在rails模型中扩展现有属性getter

时间:2010-01-12 17:58:54

标签: ruby-on-rails plugins model methods extensibility

我在使用acts_as_textiled和has_foreign_language插件时遇到问题。

TextElement 我的应用中的模型

class TextElement < ActiveRecord::Base
    has_foreign_language :value
    acts_as_textiled :value

HasForeignLanguage

def has_foreign_language(*args)
    args.each do |field|
        # Define the Getter
        define_method(field.to_s) do
        .
        .
        .

ActsAsTextiled

def acts_as_textiled(*attributes)
.
.
.
  attributes.each do |attribute|
    define_method(attribute) do |*type|
.
.
.

两个插件都使用define_method,并且我会在TextElement中调用mixins,后者会覆盖先前定义的getter。

有没有办法保存现有的getter并在新定义的getter中调用它?类似于使用super,如果它们是遗传的。

我已经分叉了这些插件,所以在那里一切都很公平。

所有帮助表示赞赏。

2 个答案:

答案 0 :(得分:1)

或者,您可以使用alias_method_chain重写这两个。

def some_class_method_that_overrides(*columns)
  columns.each do | c |
    overriden_name = if instance_methods.include?(c)
      alias_method_chain(c.to_sym, "extra")
      "#{c}_with_extra"
    else
      c
    end
    define_method(overriden_name) do ...
    end
  end
end

答案 1 :(得分:0)

您可以尝试让其中一个插件修饰属性,而不是重新定义它们。类似的东西(我在这里扩展了Object,但你可以扩展任何需要它的人):

class Object
  def decorate!(attr)
    method = self.method(attr)
    define_method(attr) do |value|
      result = method.call(value)
      yield(result)
    end
  end
end

所以装饰!您可以在acts_as_textilized

中尝试此操作
def acts_as_textiled(*attributes)
.
  attributes.each do |attribute|
    self.decorate!(attribute) do |return_value_of_decorated_method|
    # decorate code here

或者那些东西。未经测试,你可能需要调整,但我认为基本的想法是。