2008-11-28 56 views
2

我想验证一个参数是Rails的一个特定的类的实例:Rails的:调用模型类在库

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

我在一个库班这样做(文件是在lib/),我得到一个未初始化的恒定的飞机错误。飞机是一个模型类,与相应的aircraft.rb文件在应用程序/模型

我可以在库中使用模型类和实例吗?怎么样?


错误上下文:

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

回答

3

这会给你访问到飞机模型:

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

[编辑]

丹尼尔带来了有关上下文好点。如果您使用的是rake任务确保您加载的环境:

task :my_task => :environment do 
    # something happens... 
end 
4

您可以使用Rails的库文件,模型类,你在完全正确的方式做这件事。提到时,Rails应该自动载入班级飞机。

所以我们需要更多的上下文来弄清楚它为什么会失败。是否有可能在没有Rails环境的情况下加载lib /文件?

解决此问题的一种方法是明确要求模型文件aircraft.rb。然而,你会发现这种方法很快就会导致疯狂,因为它会以微妙而令人惊讶的方式打破Rails自动加载器。如果您使用Rails类加载器,而不是针对它,Rails会更容易。

更新

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

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

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

ruby script/generate rspec 
+0

啊,非常感谢!你指出了正确的方向:它在浏览器中运行得非常好。我没有尝试它,因为我在做TDD:它在RSpec中断。我会修改这个问题。 – 2008-11-29 13:37:50

0

不得不尝试这一个: if arg.is_a? ::Aircraft

1

Daniel的答案是正确的,但请考虑:为什么库类引用模型类?库代码不应该知道实际的模型类,尽管它可能知道它们提供的接口。

另一个考虑:为什么#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工作。