1

在我的应用程序中,我有几个clients,并且它们有几个elements (通过has_many_through关联),具体取决于某个属于BusinessType哪个Client,因此我无需手动将所有的添加elementsClient,我只需选择BusinessType并自动添加所有内容(business_typeClientis 中attr_readonly)。BusinessTypeHABTM elements

这是一个问题,在使用 default 创建后BusinessType,客户端可以更新他们的元素并根据需要删除或添加(主要是添加),所以我想要做的是以下内容:

假设 onebusiness_type有元素[1,2,3]并分配给 one client,然后,将以下元素手动添加到client=[4,5,6]所以它最终有[1,2,3,4,5,6],好的,这里一切都很好。

但在此之后,business_type更新并2删除了元素,所以它最终成为[1,3]. 这是交易,我希望通过删除客户端来更新客户端2,但不是[4,5,6]那些与问题不对应的客户端,business_type以便它结束[1,3,4,5,6],我正在使用after_update回调来更新clients'元素,但该_was方法不适用于HABTM 关系(获取旧business_type's元素。

我已经尝试使用before_update回调 first toclient.elements = client.elements - business_type.elements暂时存储在 DB[1,2,3,4,5,6] - [1,2,3] = [4,5,6]中,并在 after_updateclient.elements = client.elements + business_type.elements中获取[4,5,6] + [1,3] = [1,3,4,5,6],但这已经具有[1,3]. 如何获得orbusiness_type.elements中的旧值?before_updateafter_update

在此先感谢您的帮助!

4

2 回答 2

1

我在应用程序中遇到了类似的问题,我能想出的唯一解决方案是在控制器中执行 update_attributes 之前存储值。

示例代码:

楷模

class Product < ActiveRecord::Base
  has_and_belongs_to_many :categories, :join_table => "categories_products"

  def remember_prev_values(values)
    @prev_values = values
  end

  def before_update_do_something
    puts @prev_values - self.category_ids # Any categories removed?
    puts self.category_ids - @prev_values # Any categories added?
  end
end

class Category < ActiveRecord::Base
  has_and_belongs_to_many :products, :join_table => "categories_products"
end

在产品控制器的更新方法中,我执行以下操作:

class ProductsController < ApplicationController
  ...

  def update
    @product.remember_prev_values(@product.category_ids)
    if @product.update_attributes(params[:product])
      flash[:notice] = "Product was successfully updated."
      redirect_to(product_path(@product))
    else
      render :action => "edit"
    end
  end

  ...

end

这并不理想,但是可以在执行 habtm 插入/删除之前“捕获”它们。

我确实认为可以在回调中进行,但您可能需要“破解”ActiveRecord。

我没有花太多时间尝试深入研究 ActiveRecord 的内部结构,因为这是一个有效的简单实现。

于 2013-09-03T20:50:42.950 回答
0

您应该使用 after_initialize 回调来存储以前的值。

after_initialize do @previous_elements = elements.map{|x| x} end

请注意,这里我们通过 map 函数调用来制作关联的副本。

于 2015-12-09T07:10:37.610 回答