1

我正在通过控制器创建一个对象。AFoo有很多Bars。该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

这听起来应该是非常基本的东西,但由于foodb 中不存在,ActiveRecord 是否认为它为零,这就是它不保存的原因?我怎样才能正确地写这个?

4

3 回答 3

2

也许试试这个:

def create_bars(bars)
  bars.each do |t|
    self.bars << Bar.new({name: t[:name], email: t[:email]})
  end
end

<< 用于活动记录对象的运算符自动设置关联。

不要忘记在模型中添加 has_many :foos 和 belongs_to :bar。

于 2013-10-11T13:17:34.040 回答
1

我先回答这部分:

这听起来应该是非常基本的东西,但是由于 foo 在数据库中不存在,ActiveRecord 是否认为它为零,这就是它不保存的原因?我怎样才能正确地写这个?

不完全的。验证不依赖于数据库中的任何内容,它只是在持久化之前检查指定的字段(或依赖对象)是否存在于模型中。该create方法是一种快捷方式,它不仅可以初始化 ActiveModel 对象,还可以同时尝试将其保存在数据库中。您的验证失败,因为您在设置对象的foo字段之前调用了此方法bar

在这种情况下,您可以通过传入您的场景在技术上使用,但坦率地说,我会接受@pablopablo89 关于这部分的回答。如果你这样做,当你保存时,所有的对象也会被保存。createfoo: selfFooBar

此外,.create创建Bar对象的方法很危险,因为由于您立即Bar独立于 parent 持久化对象Foo,如果由于某种原因您Foo无法保存(其他验证失败等),您最终会得到一堆孤立的Bar对象无法独立于 a 删除它们Foo(我对您的系统实际工作方式做了一些假设)。假设这是您系统的反映,您要记住的目标是对象及其所有依赖项都保存在一个原子操作中。如果一个失败,它们都会失败,你会提醒用户。

为了更笼统地回答这个问题,正如@phoet 在评论中指出的那样,更改表单并使用该accepts_nested_attributes_for方法可能会好得多。这是rails 文档的链接

Foo模型中,添加 line 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对象和所有相关Bar对象。在那种情况下,create也可以工作,虽然我仍然倾向于做单独的.newand .save,但这取决于你。

这个关于如何使用的链接fields_for也可能会有所帮助。

于 2013-10-13T05:44:18.613 回答
0

Booking.new 只是初始化一个对象。为了 foo 存在,您需要保存它。保存后,创建条形对象时的验证将通过并且应该创建对象。希望这应该工作

于 2013-10-13T05:16:59.153 回答