我正在通过控制器创建一个对象。 Foo
有很多Bar
个。 Bar
模型验证其必须具有Foo
才能生效。
在foo.rb
模型中:
has_many: bars
在bar.rb
模型中:
validates_presence_of :foo
belongs_to: foo
在foo_controller.rb
:
@foo = Booking.new(params[:foo]) # this has all the params needed to make a Foo.
@foo.create_bars(params[:bars])
在foo.rb
模型中:
def create_bars(bars)
bars.each do |t|
bar = Bar.create({name: name, email: email, foo: foo})
bar.foo = self
self.bars << bar
bar.save
puts self.bars.to_s
end
end
puts self.bars.to_s
这听起来应该是非常基本的东西,但由于db中不存在foo
,ActiveRecord是否认为它是零,这就是为什么它不能保存?我怎样才能正确写出来?
答案 0 :(得分:2)
也许试试这个:
def create_bars(bars)
bars.each do |t|
self.bars << Bar.new({name: t[:name], email: t[:email]})
end
end
&LT;&LT;用于活动记录对象的运算符自动设置关联。
不要忘记在模型中添加has_many:foos和belongs_to:bar。
答案 1 :(得分:1)
我先回答这一部分:
这听起来应该是非常基本的东西,但是从那以后 数据库中不存在foo,ActiveRecord认为它是否为零, 这就是为什么它不能保存?我怎样才能正确写出来?
不完全。验证不依赖于数据库中的任何内容,它只是在持久化之前检查模型中是否存在指定的字段(或依赖对象)。 create
方法是一种快捷方式,它不仅初始化ActiveModel对象,还同时尝试将其保存在数据库中。您的验证失败,因为您在设置foo
对象的bar
字段之前调用此方法。
你可以在这个实例中通过在你的场景中传递create
来技术上使用foo: self
,但坦率地说,我会在@ pablopablo89的答案中使用这一部分。如果您这样做,当您保存Foo
时,所有Bar
对象也将被保存。
此外,用于创建.create
个对象的Bar
方法很危险,因为您可以立即保留Bar
个独立于父Foo
的对象,如果出于某种原因您的Foo
无法保存(未通过其他验证等),最终会出现一堆孤立的Bar
个对象,无法独立于Foo
删除它们(I')我对你的系统实际工作方式做了一些假设。假设这是您系统的反映,您要记住的目标是一个对象及其所有依赖项都保存在一个原子操作中。如果一个失败,它们都会失败,并提醒用户。
更一般地回答这个问题,正如@phoet在评论中指出的那样,改变表单和使用accepts_nested_attributes_for
方法可能会好得多。这是link to the rails documentation。
在Foo
模型中,添加第accepts_nested_attributes_for :bars
行,然后在表单中使用fields_for
,如下所示:
<%= form_for @foo do |f| %>
...other stuff...
<%= f.fields_for :bars do |f_bar| %>
... bar-related stuff ...
提交的参数映射将返回:foo
键中所有与栏相关的内容,以便创建Foo
对象和所有相关{{1}一次性对象。在这种情况下,Bar
也可以使用,但我仍然倾向于单独create
和.new
,但由您决定。
.save
的This link也可能会有所帮助。
答案 2 :(得分:0)
Booking.new只是初始化一个对象。为了让foo存在,你需要保存它。保存后,创建条形对象时的验证将通过,并且应创建对象。希望这应该有用