2012-03-15 58 views
3

[这是一个后续问题“How I can modularize Rails model?”]如何使用rails在app/modules中组织名称空间?

反正组织在app/models目录的Rails的课? 我是否必须为所有类使用单个顶级命名空间?

最初的动机是,我想将不从ActiveRecord::Base继承的业务逻辑类放入app/models目录。在这个网站上搜索可以找到很多答案,推荐将商业逻辑类放在app/models目录中。我发布了a different question,并得到了建议,可以将这些类放入lib目录。

现在我很好奇。我想将这些类放入apps/models目录中由其他人推荐的不同名称空间和目录中。可能吗?

其实,我尝试这一点,但在我看来,这就是轨道预计不会。如果我创建了这样的类(如some_mod_name/class_in_mod.rb中的SomeModName :: ClassInMod),它不会被加载。另外,我在模块中定义了常量。由于他们没有加载,我不能使用它们。其实,rspec工作没有问题,但与rails server,类不加载。我相信它与自动加载问题有关。

除了上面提到的类之外,从ActiveRecord::Base继承的类可以放入module中的某些名称空间中。我很好奇这个工作是否正常。

因此,换句话说,这样的问题:我可以让轨道高兴通过配置这些文件被加载,或不在轨道设计的方式?

回答

6

是的,你可以一个模块中定义一个ActiveRecord类。简单的方法是使用发生器:

./script/rails generate model logic/phase_logic 
./script/rails generate model logic/evaluation_logic 

请注意,Rails将另外创建一个带有模块定义的文件。在这种情况下:

# app/models/logic.rb 
module Logic 
    ... 
end 

# app/models/logic/phase_logics.rb 
class Logic::PhaseLogic < ActiveRecord::Base 
    ... 
end 

# app/models/logic/evaluation_logics.rb 
class Logic::EvaluationLogic < ActiveRecord::Base 
    ... 
end 

您与模块中定义的常量问题是由以下事实造成的,你定义的“包装”只围绕一个模型定义模块中的常量,从两个已创建。 尤其是对谁在编译语言强背景的人 - - 理解红宝石(和Rails)的一个非常重要的部分是要记住,没有编译阶段,所以有些类的定义被读取,只有当执行使用特定的类。有时候一周后应用程序服务器启动并服务了数千个请求。

因此,正如我在previous question的回答说,自动加载的问题是,有时常量的定义这是试图使用它们的定义后,读。顺序是随机的 - 如果第一个使用的对象碰巧是EvaluationLogic,那么就会出现错误。它是第一个碰巧是PhaseLogic的对象,一切都很好。

现在,当你有一个模块本身文件,并在该文件app/models/logic.rb),自动加载将能够找到并执行定义定义的任何类开始使用之前常量。我希望一切都会好起来的。

+0

谢谢。我仍然想知道为什么加载顺序与我预期的不同(你说这是随机的,我认为必须有一个触发器会导致实际的负载),但将常数放在'app/models中显然是个好主意/ logic.rb'现在会尝试改变这种方式。 – shigeya 2012-03-16 00:10:31

+0

经过测试。甚至没有必要成为'ActiveRecord :: Base'的子类在'module Logic'中放置所有常量,将它放在'app/models/logic.rb'中解决了我的问题。非常感谢你。 – shigeya 2012-03-16 00:47:20

+1

实际负载由第一个执行的代码行触发,其中使用了该类。当ruby尝试执行类似'if if; EvaluationLogic.new;否则PhaseLogic.new; end'和PhaseLogic尚未定义,然后(简化一点)自动加载机制找到文件'phase_logic.rb',执行它,并尝试再次执行该行代码。还有其他方式像STI。 – Arsen7 2012-03-16 08:32:29