3

ポリモーフィック オブジェクトの Ruby と ActiveRecord で一連の責任パターンを実装しようとしています。いくつか問題があります。

  • alias_method しようとすると、メソッドが定義されていないというエラーが表示されることがあります。
  • エイリアス化された関数 (original_method) が original_method を呼び出すメソッドを呼び出す無限チェーンの束を取得します。これは、既に上書きされているメソッドにエイリアスを付けると、本質的に「original_method」をエイリアス化されたメソッドのコピーにするためかどうか疑問に思っています。
  • 私は現在、「連鎖」のような関数に、定義されたすべてのメソッドを含む Setting のサブクラスを返させることでこれを回避していますが、クラス内の alias_method に非常に多くの問題があった理由に興味があります。

次に例を示します。

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

次に、Setting オブジェクトがあります。

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's almost as while it's 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
4

1 に答える 1

1

あなたは複雑化しすぎているようです。api_key と active_days が存在するかどうかを確認しようとしているようです。存在しない場合は、別の場所から入手してください。

api_key と active_days がテーブルの列であると仮定すると、これを行う正しい方法は次のとおりです。

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

少しリファクタリングして、明快さを保ち、重複を取り除くことができます。

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 が利用可能であれば、それが返されます。それ以外の場合は、next_link から available_setting をフェッチします。それが api_key/active_days を持っている場合は返され、そうでない場合は next_link から usb_setting をフェッチします。等。

于 2010-07-08T03:13:07.347 に答える