2017-01-19 5 views
1

Я разрабатываю приложение Rails с ActiveRecord. Помимо всего прочего, у меня есть следующие модели:Динамические методы в рубинах/рельсах

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 

Любая помощь будет оценена.

+0

так что вы хотите 'test_param' метод возвращает значение в этих' custom_columns'? –

+0

Да. test_param - это нулевой столбец variable_name, и я хочу, чтобы он возвращал значение соответствующего настраиваемого столбца в модели подписки. – Adnan

+0

Ruby (и Rails) определенно позволит вам это сделать, но вы повеситесь на веревке, которую вы используете было дано. Отделите свои данные от кода; пусть модели представляют собой структуру данных, а не значения. – coreyward

ответ

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