我想要的是使用Rails 3.1构建以下内容:
如果A已为b_id设置了id,则不应该为c_id设置id。反过来也一样。我希望能够在迁移时从数据库级别进行操作(检查约束?)。这是否可能?还是用模型和验证更经济实惠?
我的环境: Ruby 1.9.3 Rails 3.1.3 SQLite 3.7.3
我的环境: Ruby 1.9.3 Rails 3.1.3 SQLite 3.7.3
A
属于 B
或 C
中的一个,而不是两者都属于。A
是他们的 Picture
,而 Employee
和 Product
则是您的 B
和 C
。class Picture < ActiveRecord::Base
belongs_to :imageable, :polymorphic => true
end
class Employee < ActiveRecord::Base
has_many :pictures, :as => :imageable
end
class Product < ActiveRecord::Base
has_many :pictures, :as => :imageable
end
我肯定会为此编写验证 - 从验证中向用户提供良好的错误消息更容易。我还想用数据库约束来支持它。看起来检查约束确实可以胜任这项工作。
Rails没有找到支持此功能的方法,因此您需要使用原始SQL创建表格。您还需要将模式转储器更改为:sql
,因为Rails无法生成描述此内容的schema.rb
。
我编写了这个迁移。
class CreateFoos < ActiveRecord::Migration
def change
execute <<SQL
CREATE TABLE foos (
id INTEGER PRIMARY KEY,
x_id INTEGER,
y_id INTEGER,
constraint xorit check( (x_id OR y_id) AND NOT(x_id AND y_id))
)
SQL
end
end
然后在 Rails 控制台中
Foo.create(:x_id => 1, :y_id => 1) #=> SQLite3::ConstraintException
目前的情况是,你可以创建一行没有设置 x_id 或 y_id 的数据。你可以通过更改约束条件来改变这种情况。
(x_id IS NOT NULL OR y_id IS NOT NULL ) AND (x_id IS NULL OR y_id IS NULL)
对我来说似乎有效