1

Как переопределить метод класса, определенный в модели?Как переопределить class_method в проблеме модели rails

Это немного сложно, поскольку вы действительно не переопределяете метод класса правильно? Потому что он использует проблему api для определения методов класса в блоке class_methods.

так что у меня есть опасение, что выглядит следующим образом:

module MyConcern 
    extend ActiveSupport::Concern 

    class_methods do 
    def do_something 
     #some code 
    end 
    end 

end 

В модели .. как бы я переопределить этот метод, так что я мог бы назвать это, как мы делаем с супер при использовании наследования? Поэтому в моей модели я бы хотел:

def self.do_something 
    #call module do_something 
end 

?

+0

Вы нашли решение? –

ответ

0

старый путь с помощью alias_method_chain: https://ernie.io/2011/02/03/when-to-use-alias_method_chain/

Новый путь (требуется> рубин 2.0.0), вы действительно должны использовать это, как будет Deprecation ВНИМАНИЕ при его использовании в рельсах 5.0: http://paweljaniak.co.za/2014/09/30/understanding-ruby-module-prepend-and-include/

+0

@reven это классный пост, действительно полезный на самом деле ... но не отвечает на вопрос. – andy

1

Почему бы просто не вызвать метод модуля: MyConcern.do_something?

Я не уверен, что для модулей легко сделать super (хотя я могу понять, почему это может быть полезно).

Следующее лучшее решение могло бы сделать что-то вроде вызова #included_modules и вручную переборе с #responds_to?:

def self.do_something 
    self.super_module(__method__) 
end 

def self.super_module(method) 
    self.included_modules.find { |m| m.responds_to? method }.public_send(method) 
end 
2

Если вы имеете include д MyConcern в модели, которая определяет self.do_something, вы просто должны быть в состоянии использовать super :

module MyConcern 
    extend ActiveSupport::Concern 

    class_methods do 
    def do_something 
     puts "I'm do_something in the concern" 
    end 
    end 
end 

class UsesMyConcern < ActiveRecord::Base 
    include MyConcern 

    def self.do_something 
    super 
    end 
end 

UsesMyConcern.do_something 
# => "I'm do_something in the concern" 

Если у вас есть или не хотят include MyConcern в модели, и вы хотите, чтобы вызвать do_something на модуле без создания каких-либо промежуточных объектов, вы можете изменить свою модель, чтобы:

class UsesMyConcern < ActiveRecord::Base 
    def self.do_something     
    MyConcern::ClassMethods.instance_method(:do_something).bind(self).call 
    end 
end 

UsesMyConcern.do_something 
# => "I'm do_something in the concern" 

ActiveSupport::Concern.class_methods определяет ClassMethods модуль в концерне, если есть не один уже, а вот где мы можем найти метод do_something.