2014-11-05 64 views
0

我們必須在以下格式的電話號碼一箇舊版本的MySQL數據庫字段:的ActiveRecord格式的電話號碼

(xxx) xxx-xxxx 

我想改變他們只是數字(xxxxxxxxxx)。我在下面的link上找到了解決方案,但是我想編寫一個rake文件來執行此操作。

UPDATE table_name set PhoneCol = REPLACE(PhoneCol, '(', ''); 
UPDATE table_name set PhoneCol = REPLACE(PhoneCol, ') ', '-'); 

如何運行活動記錄這些命令?我已經工作了,以

Model.update_all(phone: ???) 
+0

請看這裏:https://stackoverflow.com/questions/4483049/how-to-execute-a-raw-update-sql-with-dynamic-binding-in-rails – mcfinnigan 2014-11-05 11:58:48

+0

爲什麼你需要Rakefile?你可以使用Rails控制檯做到這一點..對嗎? – 2014-11-05 11:59:44

+0

@ User089247如果這是需要,爲什麼不修復它來自哪裏的實際來源。爲什麼雙重工作? – 2014-11-05 12:05:42

回答

0

運行原始的SQL查詢:

ActiveRecord::Base.connection.execute("UPDATE table_name set PhoneCol = REPLACE(PhoneCol, '(', '');") 
ActiveRecord::Base.connection.execute("UPDATE table_name set PhoneCol = REPLACE(PhoneCol, ') ', '-');") 

或你自己說的,使用update_all

Model.update_all("'PhoneCol' = REPLACE(PhoneCol, '(', '')") 
Model.update_all("'PhoneCol' = REPLACE(PhoneCol, ') ', '-')") 

如果你期待撤消更改,那麼你可以創建兩個耙任務:

namespace :phone_column do 
    desc "Update phone column from (xxx) -xxxx to xxx-xxxx" 
    task :update => :environment do 
    Model.update_all("'PhoneCol' = REPLACE(PhoneCol, '(', '')") 
    Model.update_all("'PhoneCol' = REPLACE(PhoneCol, ') ', '-')") 
    end 

    # NOTE: running this task can mess up the data if you have not run the previous task before 
    desc "Reverse xxx-xxxx to (xxx) -xxxx" 
    task :reverse => :environment do 
    Model.update_all("'PhoneCol' = CONCAT('(', SUBSTRING_INDEX(PhoneCol, '-', 1), ') ', SUBSTRING_INDEX(PhoneCol, '-', 2), '-', SUBSTRING_INDEX(PhoneCol, '-', -1))") 
    end 
end 

我會建議把這個與updown方法遷移文件,但是這沒有更新這樣的數據的一個很好的方式,即遷移文件應該總是處理模式的變化,而不是在你的數據庫中的數據更新。因爲,隨着項目的增長,當您創建新的遷移時,您將不會有任何其他選擇在不參考其版本號的情況下對該遷移進行回滾,並且如果您(或其他人)錯過了任何機會,您可能會面臨生產服務器上嚴重的數據丟失。這就是爲什麼你的更新腳本應該在rake任務中(這不包括保證你的數據更新是可逆的)。

+0

運作良好。但我如何撤消更改? – 2014-11-05 12:11:23

+0

@MarcoLau:查看最新版本 – Surya 2014-11-05 12:49:58

0

我覺得你應該存儲電話號碼以正確的格式,這是ITU E.164 Format。有一個名爲global_phoneGoogle’s libphonenumber紅寶石端口,它解析了各種瘋狂的輸入人物。您可以消毒在特定數據庫列的所有數字與下面的代碼片段:

Model.find_each do |model| 
    normalized_number = GlobalPhone.normalize(model.phone_number) 
    model.update_attribute('phone_number', normalized_number) 
end 

我還建議使用before_validation回調,或者,如果你需要它的許多列,這樣的創業板attribute_normalizer這將幫助你清理新記錄爲用戶輸入新號碼。然後你可以定義你自己的標準化程序,它使用global_phone Gem來標準化電話號碼。

最後,以適合用戶的格式顯示數字是視圖層的責任,您可以在其中採用全局明確的E.164格式的數字並按照您的喜好重新格式化它們,就像您使用例如,Date列。如果你想獲得真正看中的,你也可以覆蓋干將對所涉及的屬性,因此,調用model.phone_number直接返回一個解析GlobalPhone::Number對象,而不是一個字符串;通過這種方式,您可以保持對GlobalPhone.parse調用的清晰度。