Ruby on rails RubyonRails:如何动态创建关联模型?
我有以下型号:Ruby on rails RubyonRails:如何动态创建关联模型?,ruby-on-rails,ruby-on-rails-3,Ruby On Rails,Ruby On Rails 3,我有以下型号: class Product < ActiveRecord::Base belongs_to :brand belongs_to :model accepts_nested_attributes_for :brand, :model ... end class Brand < ActiveRecord::Base has_many :products has_many :models ... end class Model < Ac
class Product < ActiveRecord::Base
belongs_to :brand
belongs_to :model
accepts_nested_attributes_for :brand, :model
...
end
class Brand < ActiveRecord::Base
has_many :products
has_many :models
...
end
class Model < ActiveRecord::Base
has_many :products
belongs_to :brand
accepts_nested_attributes_for :brand
...
end
我得到了以下错误:
Mysql2::Error: Column 'brand_id' cannot be null: INSERT INTO `models` ...
因为型号有一个外键品牌id
,未设置。我无法设置它,因为品牌(如模型)是在产品创建时动态创建的。我不想在产品之前创建品牌,因为如果产品出现错误,我需要删除创建的品牌
然后我尝试更改参数[:product]
如下:
"brand_attributes"=>{"name"=>"my_new_brand",
"model_attributes"=>{"model_no"=>"my_new_model"}}
但我最终得出的结论是:
unknown attribute: model_attributes
处理这个问题的正确方法是什么?首先,如果在事务中包装保存,事务中任何一点的失败都会回滚所有写入,因此您的品牌等不会受到影响
Product.transaction do
@product.save
end
你可以试试这个:
before_create :save_associated
validates_associated :brand, :model
def save_associated
brand.save if brand.new_record?
model.save if model.new_record?
end
当你创建一个产品记录时,它会验证自己,然后验证附加的品牌和型号。如果一切顺利,它将转到您的before_save回调,它将保存您的关联模型,然后您的产品模型将被保存。如果这三个模型中的任何一个无效,您将永远无法进行相关的save_
,如果您感到异常偏执,您可以如上所述将save包装到事务中,以便在save的任何部分失败时自动回滚任何更改。1。)您应该避免将Model用作模型名称(我认为您可以理解为什么这会导致错误,尽管我不认为这是您的问题)
2.)引用的循环模式太多。产品有模型,模型有品牌。为什么你的产品属于一个模型和一个品牌??我建议进行以下设置:
class Product < ActiveRecord::Base
belongs_to :model
accepts_nested_attributes_for :model
end
class Brand < ActiveRecord::Base
has_many :models
end
class Model < ActiveRecord::Base
has_many :products
belongs_to :brand
accepts_nested_attributes_for :brand
end
问题不在于rails——尽管你的解决方案(我认为)会解决他的问题。问题是数据库设置没有意义。他在循环中自引用表,这不允许嵌套属性。我没有仔细阅读这个问题来推断。哈哈。我不得不这么做,因为我不明白他为什么要这么做。。。我已经试着在我的回答中解决了他潜在的问题谢谢你的建议!谢谢,这很有道理。我试试看:)
before_create :save_associated
validates_associated :brand, :model
def save_associated
brand.save if brand.new_record?
model.save if model.new_record?
end
class Product < ActiveRecord::Base
belongs_to :model
accepts_nested_attributes_for :model
end
class Brand < ActiveRecord::Base
has_many :models
end
class Model < ActiveRecord::Base
has_many :products
belongs_to :brand
accepts_nested_attributes_for :brand
end
Product < Model <> Brand
# schema
create_table :products do |t|
t.string :name
t.references :model
end
create_table :brands do |t|
t.string :name
end
create_table :models do |t|
t.string :name
t.references :brand
end