Rails Metaprogramming: how to add instance methods at runtime?

I define my own AR class in Rails, which will include dynamically created instance methods for user fields 0-9. User fields are not stored directly in db, they will be serialized together since they will be used infrequently. Is the best way to do this? Alternatives?

Where should the startup code be run to add methods from?

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 
+4
source share
2 answers

One good way, especially if you can have more than 0..9 custom fields, would be to use 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 

If you prefer to define methods:

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

Using method_missing very difficult to maintain and not necessary. Another alternative using define_method is better, but leads to poor code execution. The following 1 liner is all you need:

 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 
+4
source

Source: https://habr.com/ru/post/1305479/


All Articles