jeudi 19 janvier 2017

Dynamic methods in ruby/rails

I'm developing a Rails application with ActiveRecord. Among other things, I have the following models:

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

The tables are populated as below (for example):

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

Given this background, I want to create dynamic methods that will let me do the following:

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"

What I can already do, of course, is something like (over-simplified)

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

So.. in short, I want to define dynamic methods on an instance object using that objects associations to get the method names.

Will be happy to provide more clarification if needed.

I'm sort of familiar with dynamic methods. I already do something like:

["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

Any help would be appreciated.

Aucun commentaire:

Enregistrer un commentaire