2012-07-19 1 views
1

상호 작용은 약간 복잡하므로 부담해야합니다. 저는 Spree와 함께 일하고 있습니다. Spree는 'Spree :: Variant'를 포함한 일부 모델에서 delegate_belongs_to를 사용합니다. '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 

나는이 하나 개의 인자를 제거하는 전체 변형 클래스를 오버라이드 (override)하지 않으려는 것입니다. 나는이에 변화의 숫자를 시도했습니다

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'이라는 원래 위치가 내 데코레이터의 정의 라인을 제공합니다. 메소드의 중단 점은 아무 것도하지 않습니다. –

답변

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. 콘텐츠 나는 레일 3.0 약 2 개월 전 그런 짓을했다

    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 
    

와 파일 lib/spree_variants.rb을 만들 application.rb

# ... 
module App 
    class Application < Rails::Application 
    # ...   
    config.autoload_paths += %W(#{config.root}/lib) 
    # ... 
    require 'spree_variants' 
    end 
end 
  • 에로드 라이브러리 파일을 할 수 있습니다. 9 and spree_core 0.60.1 그래서 내 대답은 당신에게 쓸모가 없지만 아마도 당신에게 줄 수 있습니다. 어떤 방향.

  • +0

    delegate_belongs_to는 Variant 클래스 본문 내에서 호출되는 메서드입니다 (예 : 'has_many'또는 'belongs_to'). 나는 여전히이 접근법에 변형을 시도하고있다. 문제는 이전 delegate_belongs_to가 전환되기 전에 적어도 한 번 이상 확실히 호출되고 있으며 호출 할 수없는 수정 작업을 수행하고 있다는 것입니다. 나는이 하나의 인수를 제거하기 위해 전체 변형 클래스를 오버라이드해야 할 수도 있습니다. –

    1

    나는 당신의 문제를 완전히 이해한다고 생각하지 않지만, class_eval 또는 alias_method를 사용하는 누군가를 볼 때마다 나는 더 나은 방법이 있어야한다고 생각한다. 클래스의 메서드를 재정의하고 super를 호출하려고 시도 했습니까?

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

    예, 효과가없는 것 같습니다. 그것은 Spree 기능을 확장하기 위해 권장하기 때문에 class_eval을 사용하고 있습니다 : http://guides.spreecommerce.com/logic_customization.html –

    +0

    사용하기 전에 무시하려고 했습니까? –

    1

    나는 내 자신의 app/models 디렉토리에서 Spree :: Variant를 재정의했다.

    하나의 인수를 제거하기 위해이 작업을 수행하지 않는 것이 좋겠지 만, 그 이유는 실행 모델이 인스턴스화시 메모리에로드되는 것처럼 보이기 때문이며 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