我需要在我的Rails應用程序的現有表中添加一個新的整數列。該列只能有值1,2,3,所以我想爲表/列添加一個檢查約束。如何在Rails遷移中指定此約束?如何在Rails遷移中添加檢查約束?
回答
Rails的遷移不提供任何方法來添加約束,但你仍然可以通過遷移,但是通過將實際的SQL執行()
創建遷移文件做到這一點:
ruby script/generate Migration AddConstraint
現在,遷移文件:
class AddConstraint < ActiveRecord::Migration
def self.up
execute "ALTER TABLE table_name ADD CONSTRAINT check_constraint_name CHECK (check_column_name IN (1, 2, 3))"
end
def self.down
execute "ALTER TABLE table_name DROP CONSTRAINT check_constraint_name"
end
end
我剛剛通過獲取PostgreSQL CHECK約束來工作。
Nilesh的解決方案並不完整; db/schema.rb文件將不包含約束,因此測試和任何使用db:setup的部署都不會獲得約束。按照http://guides.rubyonrails.org/migrations.html#types-of-schema-dumps
雖然在遷移,您可以執行自定義SQL語句時, 模式自卸車無法重建從數據庫中那些語句。 如果您正在使用這樣的功能,那麼您應該將架構 格式設置爲:sql。
即,在配置/ application.rb中設置
config.active_record.schema_format = :sql
不幸的是,如果你使用PostgreSQL裝載產生的轉儲時,你可能會得到一個錯誤,請參閱ERROR: must be owner of language plpgsql討論。我不想在這個討論中關注PostgreSQL配置路徑;再加上在任何情況下,我喜歡有一個可讀的db/schema.rb文件。所以這爲我排除了遷移文件中的自定義SQL。
Valera建議的寶石https://github.com/vprokopchuk256/mv-core似乎很有前途,但它只支持一組有限的約束(當我嘗試使用它時,我得到了一個錯誤,雖然這可能是由於與我包括的其他寶石不兼容) 。
我想要的解決方案(hack)是讓模型代碼插入約束條件。由於它是kindof就像一個驗證,這就是我所說的那樣:
class MyModel < ActiveRecord::Base
validates :my_constraint
def my_constraint
unless MyModel.connection.execute("SELECT * FROM information_schema.check_constraints WHERE constraint_name = 'my_constraint'").any?
MyModel.connection.execute("ALTER TABLE my_models ADD CONSTRAINT my_constraint CHECK (...the SQL expression goes here ...)")
end
end
當然這並各個驗證之前一個額外的選擇;如果這是一個問題,解決方法是將它放在「連接後」猴子補丁中,如How to run specific script after connected to oracle using rails?(您不能簡單地緩存select的結果,因爲驗證/約束添加發生在可能獲得的事務中回滾,所以你需要檢查每一次。)
你可以使用Migration Validators gem。查看詳情這裏:https://github.com/vprokopchuk256/mv-core
隨着創業板,你就可以在數據庫級別定義包含驗證:
def change
change_table :table_name do |t|
t.integer :column_name, inclusion: [1, 2, 3]
end
end
而且您能夠定義如何驗證這應該定義,甚至錯誤消息應顯示:
def change
change_table :posts do |t|
t.integer :priority,
inclusion: { in: [1, 2, 3],
as: :trigger,
message: "can't be anything else than 1, 2, or 3" }
end
end
你甚至可以提升等級從遷移該驗證正確的模型:
class Post < ActiveRecord::Base
enforce_migration_validations
end
,然後驗證遷移定義也將被定義爲加載ActiveModel驗證您的模型:
Post.new(priority: 3).valid?
=> true
Post.new(priority: 4).valid?
=> false
Post.new(priority: 4).errors.full_messages
=> ["Priority can't be anything else than 1, 2, or 3"]
您可以使用Sequel
寶石https://github.com/jeremyevans/sequel
Sequel.migration do
change do
create_table(:artists) do
primary_key :id
String :name
constraint(:name_min_length){char_length(name) > 2}
end
end
end
我剛剛出版了寶石本:active_record-postgres-constraints。由於README有描述,您可以用DB/schema.rb文件中使用它,並把它添加支持的遷移下面的方法:
create_table TABLE_NAME do |t|
# Add columns
t.check_constraint conditions
# conditions can be a String, Array or Hash
end
add_check_constraint TABLE_NAME, conditions
remove_check_constraint TABLE_NAME, CONSTRAINT_NAME
注意,在這個時候,Postgres的唯一支持。
- 1. Laravel遷移 - 添加檢查約束表
- 2. 檢查DataRow約束添加
- 3. 如何使用Laravel的遷移將約束添加到表中?
- 4. 運行rails遷移時無法添加外鍵約束錯誤
- 5. Rails的遷移:刪除約束
- 6. Ruby on Rails:如何使用遷移向現有列添加非空約束?
- 7. 在遷移中的唯一索引列上添加空約束
- 8. 如何在實體框架中爲JSON添加檢查約束?
- 9. SQL添加外鍵約束與檢查
- 10. 如何向表中添加檢查約束?
- 11. 如何添加約束檢查表中的列值
- 12. 改變表添加約束與改變表添加檢查約束
- 13. 添加約束在Xcode 6中查看
- 14. Django遷移下降,並重新添加相同的約束
- 15. 使用Laravel遷移添加外鍵約束
- 16. 通過遷移不起作用添加唯一約束
- 17. Laravel「無法添加外鍵約束」 - 遷移
- 18. 添加CHECK約束在SQL Server:添加約束VS添加復
- 19. 檢查約束
- 20. 檢查約束
- 21. 檢查約束
- 22. 檢查約束
- 23. 檢查約束
- 24. 檢查約束
- 25. 如何添加檢查約束日期列
- 26. 在APEX中添加電子郵件檢查約束
- 27. 在postgres中添加雙精度類型的檢查約束
- 28. Django遷移。如何檢查表是否存在於遷移中?
- 29. 如何在Rails遷移中添加主鍵?
- 30. 如何使用Rails 5遷移中的級聯刪除約束創建外鍵?
另外請注意,如果你添加一個約束,你必須在`config/application.rb`中將`config.active_record.schema_format =:sql`設置爲[「`db/schema.rb`不能表達數據庫特定項目,如觸發器,存儲過程或檢查約束。「](http://edgeguides.rubyonrails.org/active_record_migrations.html#types-of-schema-dumps)。 – 2017-02-13 01:30:25
現在有一個支持在`db/schema.rb`中存儲約束的gem:[active_record-postgres-constraints](https://github.com/on-site/active_record-postgres-constraints)。查看我的答案瞭解更多詳情。目前,只支持postgres。 – 2017-03-17 13:51:14