带有'类Class'的Rails lib / module和自定义attr_accessor

时间:2015-03-11 04:42:30

标签: ruby-on-rails ruby metaprogramming

我想像这样创建自己的attr_accessor:

  class Class
    def attr_accessor_with_onchange_callback(*args, &block)
      raise 'Callback block is required' unless block
      args.each do |arg|
        attr_name = arg.to_s
        define_method(attr_name) do
           self.instance_variable_get("@#{attr_name}")
        end
        define_method("#{attr_name}=") do |argument|
          old_value = self.instance_variable_get("@#{attr_name}")
          if argument != old_value
            self.instance_variable_set("@#{attr_name}", argument)
            self.instance_exec(attr_name, argument, old_value, &block)
          end
        end   
      end
    end
  end

如果我在应用初始化之前将此定义放在config/enviroment.rb中,它就可以工作。

class MyCLass < ActiveRecord::Base
  attr_accessor_with_onchange_callback :some_attr do |attr_name, value, old_value|
  end

但我认为它应该在lib /文件夹中。如果我把这个

module ModelHelpers
  class Class
    def attr_accessor_with_onchange_callback(*args, &block)
      raise 'Callback block is required' unless block
      args.each do |arg|
        attr_name = arg.to_s
        define_method(attr_name) do
           self.instance_variable_get("@#{attr_name}")
        end
        define_method("#{attr_name}=") do |argument|
          old_value = self.instance_variable_get("@#{attr_name}")
          if argument != old_value
            self.instance_variable_set("@#{attr_name}", argument)
            self.instance_exec(attr_name, argument, old_value, &block)
          end
        end   
      end
    end
  end
end

lib/model_helpers.rb和此

require 'model_helpers'
class MyCLass < ActiveRecord::Base
  include ModelHelpers
  attr_accessor_with_onchange_callback :some_attr do |attr_name, value, old_value|
end

到my_class.rb然后我收到一个错误:undefined method attr_accessor_with_onchange_callback。 我做错了什么?

1 个答案:

答案 0 :(得分:2)

尝试直接在ModelHelpers中定义方法attr_accessor_with_onchange_callback,而不使用类Class。并使用extend关键字而不是包含内部类defenition。像这样:

module ModelHelpers
  def attr_accessor_with_onchange_callback(*args, &block)
...

require 'model_helpers'
class MyCLass < ActiveRecord::Base
  extend ModelHelpers

以下是我的例子:

module ModelHelpers
    def my_method
        puts 'ModelHelpers::my_method called.'
        puts "self is #{self}"
    end
end

class MyCLass 
  extend ModelHelpers
  my_method
end

输出是:

> ruby custom_method_inside_class.rb
ModelHelpers::my_method called.
self is MyCLass