Ruby on Rails: 在哪里定义全局常量?
Ruby on Rails: 在哪里定义全局常量?
我刚开始使用Ruby on Rails来开发我的第一个Web应用。我有很多不同的模型,视图,控制器等等。
我想找一个很好的地方存放真正全局且适用于我的整个应用的常量定义。特别是,它们在我的模型的逻辑中和我的视图中的决策中都适用。我找不到任何DRY的地方来放置这些定义,使它们无论在我的模型中还是在我的视图中都可以使用。
以具体的例子为例,我想要一个常量COLOURS = [\'white\', \'blue\', \'black\', \'red\', \'green\']
。这个常量在很多地方都被使用,包括模型和视图。我应该在哪里定义它,让它可以被访问?
我已经尝试过:
- 在与它们最相关的model.rb文件中定义常量类变量,例如
@@COLOURS = [...]
。但我找不到一个合理的方法来定义它,以便我可以在我的视图中编写Card.COLOURS
,而不是什么笨拙的东西像Card.first.COLOURS
。 - 在模型上定义一个方法,如
def colours [\'white\',...] end
- 同样的问题。 - 在application_helper.rb中定义一个方法-这是我目前正在做的,但这些helpers只能在视图中访问,而不能在模型中访问
- 我想我可能在application.rb或environment.rb中尝试过某些东西,但那些似乎不太合适(它们似乎也不起作用)
难道就没有办法在模型和视图中定义并使用相同的特定于领域的知识吗?我是说,我知道模型和视图应该是分开的,但在某些领域中,它们肯定需要引用相同的特定于领域的知识吧?
一些选项:
使用常量:
class Card COLOURS = ['white', 'blue', 'black', 'red', 'green', 'yellow'].freeze end
使用类实例变量进行延迟加载:
class Card def self.colours @colours ||= ['white', 'blue', 'black', 'red', 'green', 'yellow'].freeze end end
如果它是真正的全局常量(尽管应该避免此类全局常量),您还可以考虑将顶层常量放在config /initializers/my_constants.rb
中。
如果您的模型真正"负责"常量,应该将它们粘贴在那里。您可以创建类方法来访问它们,而不需要创建新的对象实例:
class Card < ActiveRecord::Base def self.colours ['white', 'blue'] end end # accessible like this Card.colours
另外,您可以创建类变量和访问器。但是,这种做法不被鼓励,因为类变量可能在继承和多线程环境中表现出意外的行为。
class Card < ActiveRecord::Base @@colours = ['white', 'blue'].freeze cattr_reader :colours end # accessible the same as above Card.colours
上述两种选项允许您在每次调用访问器方法时更改返回的数组(如果需要)。如果您有一个真正不可更改的常量,您也可以在模型类上定义它:
class Card < ActiveRecord::Base COLOURS = ['white', 'blue'].freeze end # accessible as Card::COLOURS
您还可以创建全局常量,在初始化器中从任何地方都可以访问它们,如下例所示。如果您的颜色确实是全局的,并在多个模型上下文中使用,则可能是最好的地方。
# put this into config/initializers/my_constants.rb COLOURS = ['white', 'blue'].freeze # accessible as a top-level constant this time COLOURS
注意:当我们定义以上常量时,通常我们想要freeze
该数组。这样可以防止其他代码后来(无意中)通过添加新元素而修改该数组。一旦对象被冻结,就无法再更改。