Ruby Metaprogramming:基于数据库条目动态定义方法?

时间:2014-08-04 13:33:37

标签: ruby database testing metaprogramming

我有一个模型,它根据数据库内容动态定义一些方法。像这样:

class MyHelperClass
  def self.breeds
    Dogs.pluck(:breed)
  end

  breeds.each do |breed|
    class_eval <<-RUBY, __FILE__, __LINE__+1
      def #{breed}?(val)
        val == "#{breed}"
      end
    RUBY
  end
end

基本上,我想定义一个&#39;检查器&#39;每个品种的方法。它似乎工作正常,我有广泛的rspec测试,它们在本地传递,但它们在我们的持续集成服务(circleci)上失败(NoMethodError)。

我像这样填充测试数据库:

before(:all) do
  [:labrador, :dalmation, :boxer].each do |breed|
    Dogs.where(category: "large").first_or_create(
      { breed: breed }, without_protection: true
    )
  end
end

我想知道两件事:

  1. 为什么我的测试可能会失败,尽管本地传递
  2. 如果在运行期间将新品种添加到Dogs表中,是否会动态创建相应的品种方法,还是仅在服务器重新启动时才会生成?

1 个答案:

答案 0 :(得分:2)

我不知道你的测试是如何失败的,所以我只能猜测它可能与数据库连接有关,或者可能与实际的数据库内容有关,这可能与本地机器上的不同。

关于你的第二个问题 - 只有在运行代码时才创建方法,在你的情况下,它是在定义类时。如果数据库发生更改,则没有挂钩可以同步声明的方法(添加或删除它们)。

我强烈建议反对以这种方式实现它,也许您应该考虑制作一个实际检查当前breeds列表的方法,或者针对缓存副本,这是每隔几分钟刷新一次......