0

我在下面有两个模型。它们可以解释如下:

报告有一个report_detail(确定开始/结束月份)。许多报告可以具有相同的报告详细信息,但没有两个报告详细信息可以相同。

class Report < ActiveRecord::Base
  # attr: name :: String
  # attr: report_detail_id :: Integer
  belongs_to :report_detail
  accepts_nested_attributes_for :report_detail
end

class ReportDetail < ActiveRecord::Base
  # attr: duration :: Integer
  # attr: starting_month :: Integer
  # attr: offset :: Integer
end

我对 ReportDetail 的索引有一个唯一约束 [:duration, :starting_month, :offset]

我要完成的是:如果一个新报告的 ReportDetail 具有唯一的组合 attrs (:duration, :starting_month, :offset),则创建新的 ReportDetail 并正常保存。如果报表具有 ReportDetail,而现有 ReportDetail 具有相同的属性,则将报表的详细信息与此 ReportDetail 相关联并保存报表。

我通过在report_detail=使用 a时为 setter 设置别名来实现这一点,ReportDetail.find_or_create_by...但它很丑陋(而且它还通过使用 detail 属性实例化新报告来创建不必要的 ReportDetail 条目,并且由于某种原因,我无法使用 来使保存正常工作.find_or_initialize_by...)。我还尝试before_save在 ReportDetail 上说,如果我匹配其他内容,则设置self为其他内容。显然你不能这样设置自己。

对解决此问题的最佳方法有任何想法吗?

请参阅此要点以了解我当前使用别名覆盖的设置器

4

1 回答 1

1

今天刚遇到这个问题,我的解决方案是基于object_attributes=accepts_nested_attributes_for提供的方法,我认为这会减少混乱,而不是覆盖标准的关联setter方法。潜入 Rails 源代码以找到此解决方案,这里是github 链接。编码:

class Report < ActiveRecord::Base
  # attr: name :: String
  # attr: report_detail_id :: Integer
  belongs_to :report_detail
  accepts_nested_attributes_for :report_detail

  def report_detail_attributes=(attributes)
    report_detail = ReportDetail.find_or_create_by_duration_and_display_duration_and_starting_month_and_period_offset(attrs[:duration],attrs[:display_duration],attrs[:starting_month],attrs[:period_offset])
    attributes[:id]=report_detail.id
    assign_nested_attributes_for_one_to_one_association(:report_detail, attributes)
  end
end

一些解释,如果你提供一个id,将被视为更新,因此不再创建新对象。我也知道这种方法需要一个额外的查询,但我现在找不到更好的解决方案。

此外,您似乎在报告和报告详细信息之间有 has_one 关联,如果这是您的情况,您可以试试这个:

   class Report < ActiveRecord::Base
      # attr: name :: String
      # attr: report_detail_id :: Integer
      has_one :report_detail
      accepts_nested_attributes_for :report_detail, :update_only=>true
    end

根据文档,这应该对您有用。从 rails3 文档:

:update_only

允许您指定只能更新现有记录。只有在没有现有记录时才能创建新记录。此选项仅适用于一对一关联,对于集合关联将被忽略。此选项默认关闭。

于 2010-09-20T14:40:10.893 回答