Rails - 动态方法创建

时间:2013-06-20 21:31:02

标签: ruby-on-rails ruby activerecord csv ruby-on-rails-4

我有两种方法与它们引用的ActiveRecord类完全相同:

def category_id_find(category_name)
  category = Category.find_by_name(category_name)
  if category != nil
    return category.id
  else
    return nil
  end
end

def brand_id_find(brand)
  brand = Brand.find_by_name(brand)
  if brand != nil
    return brand.id
  else
    return nil
  end
end

现在,我只知道必须有更多的Railsy / Ruby方法将它组合成某种动态创建的方法,该方法需要两个参数,即要查找的类和字符串,所以我尝试(并且失败)了一些东西像这样:

def id_find(class, to_find)
  thing = (class.capitalize).find_by_name(to_find)
  if thing.id != nil
    return thing.id
  else
    return nil
  end
end

这意味着我可以致电id_find(category, "Sports")

我必须在播种期间从包含所有数据的单个怪物CSV文件填充表格。因此,例如,我必须从CSV中获取所有不同的类别,将它们放入类别表中然后根据刚刚填充的类别表中的id分配每个项目的category_id,如果这有意义的话...... < / p>

2 个答案:

答案 0 :(得分:1)

class是Ruby中的保留关键字(它仅用于类声明),因此您不能使用它来命名方法参数。开发人员经常将其更改为klass,这样可以保留原始含义而不会与此限制发生冲突。但是,在这种情况下,您可能会将类的名称作为字符串传递,因此我将其称为class_name

Rails的ActiveSupport有许多内置的变形方法,可用于将字符串转换为常量。根据您的CSV数据的样子,最终可能会出现以下情况:

def id_find(class_name, to_find)
  thing = (class_name.camelize.constantize).find_by_name(to_find)
  ...
end

答案 1 :(得分:0)

如果使用字符串,您可以使用constantize而不是大写,并且您的代码应该有效(理论上):

thing = passed_in_class.constantize.find_by_name(to_find)

但你也可以将实际的类本身传递给方法,没有理由不:

thing = passed_in_class.find_by_name(to_find)