2012-07-19 39 views
1

這裏的交互有點複雜,請耐心等待。 我正在使用Spree。 Spree在其一些模型中使用了delegate_belongs_to,包括「Spree :: Variant」。 'delegate_belongs_to:product,:available_on(...)'在原始類體中被調用。我如何重寫一個寶石添加到ActiveRecord :: Base的類方法(在我的裝飾器中)

我希望變體能夠擁有自己的available_on日期。 delegate_belongs_to被注入本身就像這樣:

module DelegateBelongsTo 
    extend ActiveSupport::Concern 
    module ClassMethods 
    #... 
    def delegate_belongs_to(association, *attrs)  
     #... 
    end 
    end 
end 

ActiveRecord::Base.send :include, DelegateBelongsTo 

我寧願不重寫整個variant類刪除此一個參數。這是我最近的嘗試之一:

Spree::Variant.class_eval do 
    class << self 
    alias_method :original_dbt, :delegate_belongs_to 

    def delegate_belongs_to(association, *attrs) 
     attrs.delete [:available_on] 
     original_dbt(association, attrs) 
    end 
    end 

    attr_accessible :available_on 
    #... 
end 

我已經嘗試了一些這方面的變化。我不確定是否它是因爲它在class_eval中,如果執行順序有問題,或者是什麼,但我似乎無法重寫此方法。我在這裏無法理解什麼?

謝謝。

+0

我正在研究迄今爲止提供的解決方案。一個注意,在軌道控制檯'Spree :: Product.method(:delegate_belongs_to).source_location '給了我原來的位置,'Spree :: Variant.method(:delegate_belongs_to).source_location'給了我在我的裝飾器中的定義線。方法中的斷點雖然沒有做任何事情。 – 2012-07-19 21:04:42

回答

0

這是不是一個真正的答案,我指出我曾嘗試

,我不知道有多少,這將有所幫助,但我把你的代碼,並簡化了一點,看是否覆蓋該方法可以正常工作,這意味着你的方法是正確的,如果你直接覆蓋類,那麼它會調用新的方法。

module DelegateBelongsTo 

    module ClassMethods 
    def delegate_belongs_to(association, *attrs)  
     p "METHOD INSIDE MODULE" 
    end 
    end 

    def self.included(base) 
    base.extend(ClassMethods) 
    end 
end 

module Spree 
    class Variant 
    include DelegateBelongsTo 

    def self.some_method 
     delegate_belongs_to("foo", "bar") 
    end 
    end 
end 

Spree::Variant.some_method #METHOD INSIDE MODULE 


Spree::Variant.class_eval do 
    class << self 
    alias_method :original_dbt, :delegate_belongs_to 
    def delegate_belongs_to(association, *attrs) 
     p "OVERWRITTEN METHOD" 
     original_dbt(association, *attrs) 
    end 
end 
end 

Spree::Variant.some_method # "OVERWRITTEN METHOD", "METHOD INSIDE MODULE" 
0

我通常在lib中執行它,所以我確定我的更改是在所有初始化器之後進行評估的。

  1. 允許負載LIB文件中application.rb

    # ... 
    module App 
        class Application < Rails::Application 
        # ...   
        config.autoload_paths += %W(#{config.root}/lib) 
        # ... 
        require 'spree_variants' 
        end 
    end 
    
  2. 創建文件lib/spree_variants.rb與內容

    require 'spree_core' 
    
    module SpreeOldPriceProducts 
        class Engine < Rails::Engine 
        def self.activate 
         Variant.class_eval do 
         alias_method :original_dbt, :delegate_belongs_to 
    
         def delegate_belongs_to(association, *attrs) 
          attrs.delete [:available_on] 
          original_dbt(association, attrs) 
         end 
         end 
        end 
    
        config.to_prepare &method(:activate).to_proc 
        end 
    end 
    

我做類似的東西,大約2個月前導軌3.0。 9和spree_core 0.60.1所以我的回答對你來說可能沒用,但也許會給你一些方向。

+0

delegate_belongs_to是從Variant類的正文中調用的方法(如'has_many'或'belongs_to')。我仍然在嘗試使用這種方法。問題在於,舊的delegate_belongs_to在被切換之前至少被調用一次,並且正在進行無法調用的修改。我想我可能不得不重寫整個變體類來刪除這一個參數。 – 2012-07-19 21:39:52

1

我不認爲我完全理解您的問題,但每當看到有人使用class_eval或alias_method時,我認爲必須有更好的方法。你有沒有嘗試覆蓋你的課堂上的方法,只是調用超級?

class MyModel < ActiveRecord::Base 
    def self.delegate_belongs_to(association, *attrs) 
    attrs.delete [:available_on] 
    super(association, attrs) 
    end 
end 
+0

是的,它似乎沒有任何影響。我使用的是class_eval,因爲他們推薦將其用於擴展Spree功能:http://guides.spreecommerce.com/logic_customization.html – 2012-07-19 21:15:03

+0

您是否在使用它之前嘗試覆蓋它? – 2012-07-19 21:18:32

1

我結束了剛剛覆蓋Spree :: Variant在我自己的應用程序/模型目錄。

我真的不希望這樣做是爲了刪除一個參數,但事實上,spree模型似乎在實例化中加載到內存中,並且由於Ruby具有可執行類體,原始的delegate_belongs_to調用被觸發(並觸發一些副作用),然後才能切換出來。

該方法正在被覆蓋,我可以證實,但到時候已經太遲了。我嘗試設置一個初始化程序來解決這個問題並不成功。

據我所知,任何面臨類似情況的人都必須替換整個班級。如果有人有更好的解決方案,我想留下這個問題。感謝您的迴應。

0

對於任何尋找工作解決方案的人來說,移除getter和setter會恢復到ActiveRecord關聯。

`DATETIME_add_to_variant.rb`: 
class AddToVariant < ActiveRecord::Migration 
    def change 
     add_column :spree_variants, :description, :text 
     add_column :spree_variants, :available_on, :datetime 
    end 
end 

`variant_decorator.rb`: 
Spree::Variant.class_eval do 
    remove_method :description 
    remove_method :description= 

    remove_method :available_on 
    remove_method :available_on= 
end 
相關問題