Ruby传递方法(?)作为参数?

时间:2014-12-19 20:41:14

标签: ruby

在Ruby中,我有一大堆从数据库返回信息的方法:状态,国家,语言,种族等的列表,用于申请表的选项。我知道从表单中选择的ID,并且正在编写方法来从ID中获取名称:

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

等。有很多。如何简化1方法,该方法传递项目类型(州,国家等)的名称我想得到名称,而不是一遍又一遍地重复自己?

3 个答案:

答案 0 :(得分:3)

您可以通过元编程来解决问题:

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"

或者使用更通用的方法:

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"

答案 1 :(得分:1)

好吧,您可以使用Object#public_send根据您作为参数传递的“类型名称”调用当前对象上的某个方法:

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

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

或者,您可以完全放弃#{type}_name方法的defenition,只需让您的name方法调用Db对象上的相应方法:

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

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

答案 2 :(得分:0)

使用字符串数组%w(country state)并使用define_method.send动态创建Db上的方法和调用属性

%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'如果不使用R .pluralize

动态创建

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

country_namelanguage_name