有幾次我一直在想要重構某個模型的設計,並最終將更新邏輯放入遷移中。然而,據我瞭解,這不是好的做法(特別是因爲鼓勵您使用您的模式文件進行部署,而不是您的遷移)。你如何處理這些問題?在您的遷移中添加更新邏輯
爲了表達我的意思,說我有一個用戶模型。由於我認爲只有兩種用戶,即「普通」用戶和管理員,我選擇使用簡單的布爾字段來告訴用戶是否是管理員。
但是,經過一段時間後,我想我需要一些第三種用戶,也許是一個主持人或類似的東西。在這種情況下,我添加一個UserType模型(以及相應的遷移),以及從用戶表中刪除「admin」標誌的第二次遷移。問題來了。在「add_user_type_to_users」遷移中,我必須將管理標誌值映射到用戶類型。此外,爲了做到這一點,用戶類型必須存在,這意味着我不能使用種子文件,而是在遷移中創建用戶類型(也被認爲是不好的做法)。這裏有一些代表情況的虛構代碼:
class CreateUserTypes < ActiveRecord::Migration
def self.up
create_table :user_types do |t|
t.string :name, :nil => false, :unique => true
end
#Create basic types (can not put in seed, because of future migration dependency)
UserType.create!(:name => "BASIC")
UserType.create!(:name => "MODERATOR")
UserType.create!(:name => "ADMINISTRATOR")
end
def self.down
drop_table :user_types
end
end
class AddTypeIdToUsers < ActiveRecord::Migration
def self.up
add_column :users, :type_id, :integer
#Determine type via the admin flag
basic = UserType.find_by_name("BASIC")
admin = UserType.find_by_name("ADMINISTRATOR")
User.all.each {|u| u.update_attribute(:type_id, (u.admin?) ? admin.id : basic.id)}
#Remove the admin flag
remove_column :users, :admin
#Add foreign key
execute "alter table users add constraint fk_user_type_id
foreign key (type_id) references user_types (id)"
end
def self.down
#Re-add the admin flag
add_column :users, :admin, :boolean, :default => false
#Reset the admin flag (this is the problematic update code)
admin = UserType.find_by_name("ADMINISTRATOR")
execute "update users set admin=true where type_id=#{admin.id}"
#Remove foreign key constraint
execute "alter table users drop foreign key fk_user_type_id"
#Drop the type_id column
remove_column :users, :type_id
end
end
正如你可以看到有兩個有問題的部分。首先是第一個模型中的行創建部分,如果我想要在一行中運行所有遷移,那麼這是必需的,然後第二個遷移中的「更新」部分將「admin」列映射到「type_id」列。
有什麼建議嗎?
當涉及到外鍵時,我發現它們非常有用,特別是在處理buisness關鍵數據時。它可以幫助我避免懸浮數據,並檢測我是否錯過了Rails方面的應用鉤子等。雖然你是對的,但他們可能會給你一些醜陋的錯誤信息。 – 2010-05-22 07:52:34
我明白了,這是一個選擇的問題。如果超出備份的數據完整性超過了UX,fk就是要走的路。 在這種情況下,你有一個插件來管理遷移中的fk: http://agilewebdevelopment.com/plugins/foreign_key_migrations – Oinak 2010-05-22 12:51:12
好的。謝謝你的提示! – 2010-05-24 06:23:08