ruby / rails中的动态方法

时间:2017-01-19 22:01:05

标签: ruby ruby-on-rails-3

我正在使用ActiveRecord开发Rails应用程序。除其他外,我有以下型号:

class Report
  has_many :subscriptions
  has_many :custom_report_params
end

class CustomReportParam
  belongs_to :report
  # attributes are: :column_name, :variable_name, :description
end

class Subscription
  belongs_to :report
  # attributes (among others): :custom_text_field_1[,2,3], :custom_boolean_field_1[,2,3], :custom_date_field_1[,2,3]       
end

表格填充如下(例如):

reports
=======
id     name
 1     Test
 2     Test 2


custom_report_params
====================
id    report_id     column_name          variable_name     description     used
 1            1     custom_text_field1   test_param        Test Param         1

subscriptions
=============
id    report_id     custom_text_field_1
 1            1     test_param_value

鉴于此背景,我想创建动态方法,让我可以执行以下操作:

r = Report.find(1)
s = r.subscriptions.first #=> returns the subscription object above

# this is the trouble part:
s.test_param #=> should return "test_param_value"

当然,我已经做过的事情就像(过度简化)

s.send(s.report.custom_report_params.used.first.column_name) #=> returns "test_param_value"

所以..简而言之,我想在实例对象上定义动态方法,使用该对象关联来获取方法名称。

如果需要,将很乐意提供更多说明。

我对动态方法很熟悉。我已经做了类似的事情:

["text", "boolean", "date"].each do |type|
  (1..3).each do |num|
    col_name = "custom_#{type}_field_#{num}"
    method_name = "#{col_name}_display
    send :define_method, method_name do
      case type
      when "text"
        self.send(col_name)
      when "date"
        self.send(col_name).try(:to_s, :date_format) || "XXX"
      when "boolean"
        self.send(col_name) ? "Yes" : "No"
      end
    end
  end
end

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:0)

试试这个

class Subscription
  # ...

  def method_missing(mth, *args)
    all_params = self.report.custom_report_params
    col_name = all_params.find_by(used: true, variable_name: mth)

    if col_name
      seld.read_attribute(col_name)
    else
      raise NoMethodError.new("undefined method '#{mth}' for #{self}")
  end

  # ...
end