如何拦截accepts_nested_attributes_for?

时间:2011-09-13 10:51:02

标签: ruby-on-rails

我有一个Rails应用程序,有两个模型:SalesTransactions和PurchaseOrders。

在PurchaseOrders模型中,使用“purchase_order_number”作为关键字段注册新条目。我使用模型的create方法来搜索先前是否已经注册了“purchase_order_number”,如果是,则重用该记录并在SalesTransaction记录中使用其id。如果该名称尚未注册,我继续执行创建,然后在SalesTransaction中使用新的PurchaseOrder记录ID(链接到相关PO的foreign_id)。

请注意,在我在create方法中查找之前,我没有现有的PurchaseOrder记录ID(所以这不是'如何使用'accepts_nested_attributes_for'来更新记录?'的问题,一旦我有了id,我就能做到。

在某些情况下,我的应用程序会记录一个新的SalesTransaction,并同时创建一个新的PurchaseOrder。它使用accepts_nested_attributes_for来创建PurchaseOrder记录。

问题似乎是当使用'accepts_nested_attributes_for'时,不会调用create,因此我的模型没有机会拦截创建,并查找'purchase_order_number'是否已经注册并处理该情况

我很欣赏有关如何拦截'accepts_nested_attributes_for'创作以允许一些预处理的建议(即,如果具有该数字的PurchaseOrder记录已经存在,则查找,如果存在,请使用它。)

并非所有销售都有PurchaseOrder,因此PurchaseTransaction中的PurchaseOrder记录是可选的。

(我看过一个涉及:reject_if的kludge,但是这不允许我在父记录中添加现有记录id作为foreign_id。)

感谢。

4 个答案:

答案 0 :(得分:1)

您可以使用validatesave回调来做您需要的事情。

假设设置:

class SalesTransaction < ActiveRecord::Base
  belongs_to :purchase_order, :foreign_key => "po_purchase_order_no", 
    :primary_key => "purchase_order_no"

  accepts_nested_attributes_for :purchase_order
end

class PurchaseOrder < ActiveRecord::Base
  has_many :sales_transactions, :foreign_key => "po_purchase_order_no", 
    :primary_key => "purchase_order_no"

  before_validation :check_for_exisitng_po # maybe only on create?

  accepts_nested_attributes_for :sales_transactions

  private

  def check_for_exisitng_po
    existing_po = PurchaseOrder.find_by_purchase_order_no(self.purchase_order_no)

    if existing_po
      self.id = existing_po.id
      self.reload # don't like this, also will overwrite incoming attrs
      @new_record = false # tell AR this is not a new record
    end

    true
  end
end

这应该再次充分利用accepts_nested_attributes_for


gist w / tests

答案 1 :(得分:0)

两个想法:你看过协会回调了吗?也许你可以在这个级别“拦截”accepts_nested_attributes_for,使用:before_add在创建新记录之前检查它是否已经在数据库中。

另一个想法是进行后期处理。在after_save / update中,您可以使用名称(应该是唯一的)查找所有记录,如果有多个记录,则将它们合并。

答案 2 :(得分:0)

我打算写一个before_save函数,但你这样说:

  

它使用accepts_nested_attributes_for来创建PurchaseOrder记录。

那么在SalesTransaction流程中,为什么要查找它?你应该让下一个可用......现在应该没有理由去搜索那些现在不存在的东西。

答案 3 :(得分:0)

好吧,我已经把这个问题暂时搁置了一段时间,并提供了赏金,但我没有得到我正在寻找的答案(尽管我非常感谢民众试图提供帮助)。

我的结论是我没有错过一些技巧,在撰写本文时,没有一个简洁的解决方案,只有解决方法。

因此,我将重写我的应用程序以避免使用accept_nested_attributes_for,并单独发布SalesTransaction和PurchaseOrder记录,因此可以在两种情况下应用创建代码。

羞耻,因为accept_nested ......非常酷,但在这种情况下它还不够完整。

我仍然喜欢Rails; - )