before_filter或rescue来创建新记录

时间:2010-01-25 20:13:48

标签: ruby-on-rails ruby activerecord

我有2个模特

class Room < ActiveRecord::Base
  has_many :people
  accepts_nested_attributes_for :people, :reject_if => lambda { |a| a[:person_id].blank? }, :allow_destroy => true
end

class Person < ActiveRecord::Base
  belongs_to :room
end

在'/ rooms / new'表单中,我有一个包含所有Person +一个'other'选项标签的select标签,允许用户动态地将一个人添加到select标签(新名称)。

因此,当我提交表单时,我可以让一个id = -1的人在数据库中不存在,当然,我想创建一个具有新名称的新人。

我想知道实现这一目标的最佳途径是什么?

使用'before_filter'或'rescue ActiveRecord :: RecordNotFound'或......

感谢您的帮助

2 个答案:

答案 0 :(得分:2)

作为一般惯例,我不建议使用异常处理作为功能逻辑的控件。所以我主张检查id为-1,并在那种情况下创建人,而不是在救援区之后这样做。

如果您正在寻找理由,2我认为是性能和清晰度。

例外是昂贵的,如果可以避免,你不想为他们承担处理费用。

此外,异常是指错误条件,而不是逻辑中的预期路径。通过这种方式使用它们,你正在弄脏水域,并且看起来这似乎并不意味着按照他的方式工作。通过检查前置过滤器中的非现存人员,可以更清楚地知道有时会发生这种情况,并且明确表示这会在其余的保存之前发生。

此外,如果在处理异常时执行了此逻辑,则必须重试失败的操作,通过循环或递归或以其他方式复制失败的保存,使得保存逻辑更加复杂。这也将使您的代码对于必须处理它的下一个编码器不太清楚。

答案 1 :(得分:2)

您不需要任何特殊代码。 ActiveRecord已经包含处理这种情况的逻辑。

请阅读http://github.com/rails/rails/blob/2-3-stable/activerecord/lib/active_record/nested_attributes.rb#L328http://github.com/rails/rails/blob/master/activerecord/lib/active_record/nested_attributes.rb#L332处的rdoc以获取详细信息。基本上,如果使用:id键传递Hash,则记录的属性会更新。如果记录没有:id键,则创建新记录。如果它具有:id键和带有true'ish值的:_destroy键,则该记录将被删除。

以下是2-3个稳定的分支机构文档:

# Assigns the given attributes to the collection association.
#
# Hashes with an <tt>:id</tt> value matching an existing associated record
# will update that record. Hashes without an <tt>:id</tt> value will build
# a new record for the association. Hashes with a matching <tt>:id</tt>
# value and a <tt>:_destroy</tt> key set to a truthy value will mark the
# matched record for destruction.
#
# For example:
#
# assign_nested_attributes_for_collection_association(:people, {
# '1' => { :id => '1', :name => 'Peter' },
# '2' => { :name => 'John' },
# '3' => { :id => '2', :_destroy => true }
# })
#
# Will update the name of the Person with ID 1, build a new associated
# person with the name `John', and mark the associatied Person with ID 2
# for destruction.
#
# Also accepts an Array of attribute hashes:
#
# assign_nested_attributes_for_collection_association(:people, [
# { :id => '1', :name => 'Peter' },
# { :name => 'John' },
# { :id => '2', :_destroy => true }
# ])