2

我正在尝试验证参数是否是 Rails 中特定类的实例:

def schedule(action, *args)
  if arg.is_a? Aircraft
    ...
  end
end

我在一个库类中执行此操作(文件位于lib/中),我得到一个未初始化的常量 Aircraft错误。Aircraft 是一个模型类,在app/models中有对应的aircraft.rb文件。

我可以在库中使用模型类和实例吗?如何?


错误上下文:

错误发生在 RSpec 测试中;该代码在浏览器中工作。我尝试在_spec.rb文件中要求模型,目前没有成功。

4

4 回答 4

4

您可以在 Rails 库文件中使用模型类,并且以完全正确的方式进行操作。Rails 应该在引用飞机类时自动加载它。

所以我们需要更多的背景来弄清楚为什么它对你来说失败了。您是否可以在没有 Rails 环境的情况下加载 lib/ 文件?

解决此问题的一种方法是明确要求模型文件飞机.rb。但是,您会发现这种方法很快就会导致精神错乱,因为它会以微妙而令人惊讶的方式破坏 Rails 自动加载器。如果您使用 Rails 类加载器,而不是反对它,Rails 会容易得多。

更新

因此,如果它在 RSpec 测试中,我们可以在规范文件中看到您用来加载环境的代码吗?它应该看起来像这样:

require File.dirname(__FILE__) + '/../spec_helper'

它需要位于文件的顶部。这是假设你已经安装了 RSpec Rails 插件(在这里)并且你有来自 RSpec 插件的默认 spec/spec_helper.rb 文件。如果没有这样的文件,请尝试运行:

ruby script/generate rspec
于 2008-11-28T19:11:29.670 回答
3

这将使您可以访问飞机模型:

require File.dirname(__FILE__) + "/../app/models/aircraft"

[编辑]

丹尼尔就上下文提出了一个很好的观点。如果您使用的是 rake 任务,请确保加载环境:

task :my_task => :environment do
  # something happens...
end 
于 2008-11-28T18:34:01.523 回答
1

丹尼尔的回答是正确的,但考虑一下:为什么库类指的是模型类?库代码不应该知道实际的模型类,尽管它可能知道它们提供的接口。

另一个考虑:为什么该#schedule方法要求模型的类?如果一个新的模型类Spaceship想要使用#schedule,则#schedule必须更改才能使用它。那没有必要。

相反,Aircraft对象和其他类的对象的处理方式有什么不同#schedule?你能把这种差异提取到自己的方法中吗?然后,您可以将这些实现移动到每个模型类中,并决定哪个由多态性使用,而不是通过分支。

例如,过去是:

def schedule(action, vehicle)
  if vehicle.is_an?(Aircraft)
    possible_days = case action
    when "travel"
      ["Mon", "Wed", "Fri"]
    when "repair"
      ["Sat", "Sun"]
    end
    possible_days.rand
  elsif vehicle.is_a?(Spaceship)
    possible_days = case action
    when "travel"
      ["Sat", "Tue", "Thu"]
    when "repair"
      ["Sun", "Mon"]
    end
    possible_days.rand
  end
end

会成为:

def schedule(action, vehicle)
  vehicle.days_action_can_be_performed(action).rand
end


class Aircraft
  def days_action_can_be_performed(action)
    possible_days = case action
    when "travel"
      ["Mon", "Wed", "Fri"]
    when "repair"
      ["Sat", "Sun"]
    end
    possible_days
  end
end

class Spaceship
  def days_action_can_be_performed(action)
    possible_days = case action
    when "travel"
      ["Sat", "Tue", "Thu"]
    when "repair"
      ["Sun", "Mon"]
    end
    possible_days
  end
end

当添加一个新类时,它只需要实现#days_action_can_be_performed,它就可以与#schedule.

于 2011-02-23T15:37:07.243 回答
0

必须尝试这个: if arg.is_a? ::Aircraft

于 2011-02-15T05:52:31.080 回答