繁体   English   中英

Rails Metaprogramming:如何在运行时添加实例方法?

[英]Rails Metaprogramming: How to add instance methods at runtime?

我在Rails中定义自己的AR类,其中包括为用户字段0-9动态创建的实例方法。 用户字段不直接存储在数据库中,它们将被序列化在一起,因为它们不经常使用。 以下是最好的方法吗? 备择方案?

从哪里调用添加方法的启动代码?

class Info < ActiveRecord::Base

end

# called from an init file to add the instance methods
parts = []
(0..9).each do |i|
   parts.push "def user_field_#{i}"     # def user_field_0
   parts.push   "get_user_fields && @user_fields[#{i}]"
   parts.push "end"
end

Info.class_eval parts.join

一个很好的方法,特别是如果你有超过0..9个用户字段,将使用method_missing

class Info
  USER_FIELD_METHOD = /^user_field_(\n+)$/
  def method_missing(method, *arg)
    return super unless method =~ USER_FIELD_METHOD
    i = Regexp.last_match[1].to_i
    get_user_fields && @user_fields[i]
  end

  # Useful in 1.9.2, or with backports gem:
  def respond_to_missing?(method, private)  
    super || method =~ USER_FIELD_METHOD
  end
end        

如果您更喜欢定义方法:

10.times do |i|
  Info.class_eval do
    define_method :"user_field_#{i}" do
      get_user_fields && @user_fields[i]
    end
  end
end

使用method_missing非常难以维护和不必要。 使用define_method的另一种方法更好,但会导致代码性能不佳。 您只需要以下1个班轮:

class Info
end

Info.class_eval 10.times.inject("") {|s,i| s += <<END}
  def user_field_#{i}
    puts "in user_field_#{i}"
  end
END

puts Info.new.user_field_4

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM