动态添加到Ruby类方法

时间:2016-05-17 12:17:36

标签: ruby

我试图为第三方应用程序创建一个插件类型的东西。

应用程序有一个类似的类:

class foo < ActiveRecord::Base

  def random_properties
    @random_properties = nil
  end

  def self.thing_i_want_to_change
    %w(
      itemone
      itemtwo
    )
  end

end

它也有类似的类:

class bar
  ARR_CONST = [ :otherstuff, :blah ]
end

我已经能够使用:

动态添加到数组常量(来自我的插件)
class bar
  ARR_CONST += [ :my_param ]
end

我有没有办法添加到foo.thing_i_want数组?

我希望能为foo.thing_i_want做类似的事情,例如:

class foo
 def self.thing_i_want_to_change
   foo.thing_i_want_to_change + ["newitem"]
 end
end

但是,那是行不通的

3 个答案:

答案 0 :(得分:1)

我不确定我是否完全理解这个问题,但是如果您想要从foo.thing_i_want访问bar,则需要某种类继承:

class Bar < Foo
  ARR_CONST = [ :otherstuff, :blah ]
end

然后,当您稍后重新打开该类时,它将保持继承:

rb(main):043:0> class Bar < Foo
irb(main):044:1> ARR_CONST = [ :otherstuff, :blah ]
irb(main):045:1> end
=> [:otherstuff, :blah]
irb(main):046:0> class Bar
irb(main):047:1> ARR_CONST += [ :my_param ]
irb(main):048:1> end
(irb):47: warning: already initialized constant Bar::ARR_CONST
(irb):44: warning: previous definition of ARR_CONST was here
=> [:otherstuff, :blah, :my_param]
irb(main):049:0> Bar.thing_i_want
=> ["itemone", "itemtwo"]

虽然添加修改常量是不好的做法。

如果您想修改thing_i_want,可以执行以下操作:

class Bar < Foo
  def self.thing_i_want
    super + ["itemthree"]
  end
end

通过继承,super调用允许您访问父类&#39;具有相同名称的方法,因此允许您修改父类正在执行的操作。

答案 1 :(得分:1)

要覆盖ruby中的方法,您可以在重新定义方法后重新打开它。

class Foo
    def say_hello
        puts "Hi"
    end
end

class Bar < Foo
    #Something
end

a = Bar.new
a.say_hello
# => Hi

class Bar
    def say_hello
        puts "Hello"
    end
end

a.say_hello
# => Hello

要将元素添加到foo.thing_i_want,您可以完全重新定义该方法。否则,您可以创建一个Foo实例,获取初始数组并返回更新后的数组。

答案 2 :(得分:1)

使用Module#alias_method可以重新定义新方法,保留旧行为以便重复使用。

class Foo
  def self.thing_i_want_to_change
    %w(itemone itemtwo)
  end
end

class Foo
  singleton_class.send(:alias_method, 
                       :thing_i_wanted_to_change,
                       :thing_i_want_to_change)

  def self.thing_i_want_to_change
    thing_i_wanted_to_change << 'itemthree'
  end
end