1

在我的應用程序,我有幾個clients,並且他們有幾個elements(通過has_many_through協會)根據一定的BusinessTypeClient屬於讓,而不是手動添加所有elementsClient,我可以選擇BusinessType,並且所有內容都會自動添加(business_typeClientattr_readonly)。 BusinessType HABTM elements獲取先前HABTM值

這裏的漁獲,默認BusinessType創建後,客戶端可以更新其內容,並刪除或添加隨心所欲(主要是增加),所以我想要做的是以下幾點:

假設一個business_type具有元素[1,2,3]並被分配到一個client,然後,將以下元素手動添加到client = [4,5,6],所以它最終具有[1,2,3,4,5,6],確定一切都很好。

但是在此之後,business_type得到更新,並刪除了元素2,因此它最終成爲[1,3]。事情是這樣的,我想在客戶端通過移除2被更新,但不是[4,5,6],使其最終[1,3,4,5,6]不對應business_type問題,我使用的是after_update回調更新clients'元素,但_was方法不HABTM關係的工作(讓老business_type's元素。

我使用before_update回調先client.elements = client.elements - business_type.elements瞬間存儲在數據庫[1,2,3,4,5,6] - [1,2,3] = [4,5,6]嘗試,並在after_update做client.elements = client.elements + business_type.elements得到[4,5,6] + [1,3] = [1,3,4,5,6]但這已經有了新的價值[1,3]。怎樣才能得到舊的在before_updateafter_update的3210值?

在此先感謝您的幫助!

回答

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 

在products控制器更新方法i執行以下操作:

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內部,因爲這是一個簡單的實現。

0

您應該使用after_initialize回調來存儲以前的值。

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

請注意,在這裏,我們通過映射函數調用製作了一個關聯的副本。