Ruby pass method (?) As a parameter?

In Ruby, I have a whole bunch of methods that return information from a database: lists of states, countries, languages, ethnic groups, etc. for application form options. I know the selected ids from the form and write methods to get names from ids:

def state_name(state_id)
  Db.states.select{ |s| s['id'] == state_id.to_i }.first['name'] 
end

def country_name(country_id)
  Db.countries.select{ |c| c['id'] == country_id.to_i }.first['name'] 
end

      

etc .. There are a lot of them. How can I simplify with 1 method that is passed in the name of the item type (state, country, etc.). I want to get a name and not repeat myself over and over again?

+3


source to share


3 answers


You can solve the metaprogramming problem:

class SomeClass
  def self.define_name_method(thing, plural)
    define_method :"#{thing}_name" do |id|
      Db.send(plural).select {|x| x['id'] == id.to_i }.first['name']
    end
  end

  define_name_method :state, :states
  define_name_method :country, :countries
end

SomeClass.new.state_name(19749387) #=> "Oregon"

      



Or with a more general method:

class SomeClass
  def thing_name(plural, id)
    Db.send(plural).select{|x| x['id'] == id.to_i }.first['name']
  end
end

SomeClass.new.thing_name(:countries, 1239394) #=> "Estonia"

      

+3


source


Well, you can use Object#public_send

to call one of the methods of the current object based on the type name you passed as a parameter:

def name(type, id)
  public_send(:"#{type}_name", id)
end

# Call like this:
name(:state, 1)

      



Or alternatively, you can drop the method definition entirely #{type}_name

and just ask the method to name

call the appropriate method on your Db object:

def name(type, id)
  Db.public_send(type).select{ |c| c['id'] == id.to_i }.first['name']
end

# Call like this:
name(:countries, 1)

      

+1


source


Something like this could work using an array of strings %w(country state)

and use define_method

both .send

to dynamically create methods and attributes calls onDb

%w(country state language).each do |entity|
  define_method("#{entity}_name") do |id|
    Db.send(entity.pluralize).select{ |o| o['id'] == id.to_i }.first['name']
  end
end

      

( require 'active_support/inflector'

if not using Rails for .pluralize

)

which dynamically creates

def state_name(id)
  Db.states.select{ |o| o['id'] == id.to_i }.first['name'] 
end

      

etc. for country_name

andlanguage_name

0


source







All Articles