Ruby alias_method chain of responsibility and problems

I am trying to implement a chain of responsibility in Ruby and ActiveRecord for a polymorphic object. I have a problem's.

  • Sometimes I get an error that the method is not defined when I try to use alias_method, I think it is because the class is not loaded or something else, so I will explain what to send the request to get the method
  • I get a bunch of endless chains where the aliased (original_method) function calls a method that calls the original_method method. I am wondering if this is due to the fact that when you use an alias that has already been overwritten, you essentially make an "original_method" copy of the smoothed method.
  • I am currently working on this with a chained function, returning a subclass of the Customization class with all the defined methods, but it is curious why the class had so many problems with alias_method.

Here is an example:

class Hospital
  has_one :setting, :as => :settable
  belongs_to :administrative_area

  def next_link
    adminstrative_area
  end

  def usable_setting
    setting ? setting : next_link.usable_setting
  end
end

Then I have a Setting object:

class Setting < ActiveRecord::Base

belongs_to :settable, :polymorphic => true

def chained
  %w(api_key active_days).each do |method|

    # this is here because otherwise the method isn't defined,
    # it almost as while it going up, the metaclass doesn't have the columns
    # until it loads, probably will be fixed if we cache classes
    self.send method.to_sym

    (class << self; self; end).class_eval do

      define_method method do |*args|
        alias_method "original_#{method}", method
        my_setting = send("original_#{method}")
        if my_setting.nil? or my_setting.empty?
          settable.next_link.usable_setting.chained.send(method)
        else
          return my_setting
        end
      end
    end
  end
  self
end
end
+3
source share
1 answer

You seem too embarrassed. It seems you are trying to see if api_key and active_days exist, and if not, get it from somewhere else.

Here's the right way to do this, assuming api_key and active_days are the columns in your table:

class Setting < ActiveRecord::Base

  belongs_to :settable, :polymorphic => true

  def api_key
    super || settable.next_link.usable_setting.api_key
  end

  def active_days
    super || settable.next_link.usable_setting.active_days
  end
end

You can reorganize it a bit to maintain clarity and remove duplication.

class Setting < ActiveRecord::Base

  belongs_to :settable, :polymorphic => true

  def api_key
    super || next_usable_setting.api_key
  end

  def active_days
    super || next_usable_setting.active_days
  end

  private
  def next_usable_setting
    settable.next_link.usable_setting
  end
end

, - api_key/active_days, . Otehrwise, usable_setting next_link. api_key/active_days, , usable_setting next_link. Etc.

+1

Source: https://habr.com/ru/post/1752387/


All Articles