tapdancer
tapdancer

Reputation: 389

Refactor some model methods in Ruby on Rails

I have some methods in my model which I use to access stored text hashes in my views:

class CarSpec < ActiveRecord::Base

    @@fuel_type_select_data = Hash[(1..5).to_a.zip(['Petrol', 'Diesel', 'Gas/petrol', 'Hybrid', 'Electric'])]
    @@mileage_type_select_data = Hash[(1..2).to_a.zip(['km', 'miles'])]
    @@transmission_select_data = Hash[(1..3).to_a.zip(['Manual', 'Automatic', 'Tiptronic'])]
    @@wheel_drive_data = Hash[(1..3).to_a.zip(['Front', 'Rear', 'All'])]
    @@color_data = Hash[(1..8).to_a.zip(['black', 'white', 'beige', 
              'blue', 'yellow', 'green', 'red', 'silver'])]

    def text_for_fuel_type
       @@fuel_type_select_data[fuel_type] 
    end

    def text_for_mileage_type
       @@mileage_type_select_data[mileage_type] 
    end

    def text_for_transmission
       @@transmission_select_data[transmission] 
    end

    def text_for_wheel_drive
       @@wheel_drive_data[wheel_drive] 
    end

    def text_for_color
       @@color_data[color]
    end

    def text_for_interior_color
       @@color_data[interior_color] 
    end

Currently, I need to write a new method for every field. How can I refactor these methods, so that I do not need to write a new method for each field? Please include how the new method/s would be called in the view.

Upvotes: 2

Views: 44

Answers (2)

Prakash Murthy
Prakash Murthy

Reputation: 13067

Agree with @Humza: constants are better than class variables here.

The current set of methods can be defined dynamically - with some metaprogramming magic - as follows:

fields = %w{ fuel_type mileage_type transmission wheel_drive interior_color }
fields.each do |field|
  define_method("text_for_#{field}") do
    CarSpec.class_variable_get("@@#{field}_select_data").send(:[], eval(field))
  end 
end 

Note: For the above to work, the class variables for all fields will have to be consistent with the @@#{field}_select_data name; so @@wheel_drive_data should be changed to @@wheel_drive_select_data, etc.

Upvotes: 1

SHS
SHS

Reputation: 7744

Using constants instead of class variables would be much better in your case.

An example:

class CarSpec < ActiveRecord::Base
  WHEEL_DRIVE_DATA = {'Front' => 1}

  # remaining class code
end

Sample code for view:

<%= CarSpec::WHEEL_DRIVE_DATA['Front'] %>

Upvotes: 1

Related Questions