Ruby on Rails:在哪里定义全局常量?
我刚刚开始使用我的第一个 Ruby on Rails Web 应用程序。我有很多不同的模型、视图、控制器等等。
我想找到一个好地方来保存真正全局常量的定义,这些常量适用于我的整个应用程序。特别是,它们既适用于我的模型的逻辑,也适用于我的观点所做出的决定。我找不到任何干燥的地方来放置这些定义,它们既适用于我的所有模型,也适用于我的所有视图。
举一个具体的例子,我想要一个常量COLOURS = ['white', 'blue', 'black', 'red', 'green']
。这在模型和视图中随处可见。我可以在哪里将其定义在一处以便可以访问吗?
我尝试过的方法:
- model.rb 文件中与它们最相关的常量类变量,例如
@@COLOURS = [...]
。但我找不到一种合理的方法来定义它,以便我可以在视图中编写Card.COLOURS
而不是像Card.first.COLOURS
这样的笨拙的东西。 - 模型上的方法,例如
def color ['white',...] end
- 同样的问题。 - application_helper.rb 中的方法 - 这就是我到目前为止所做的,但助手只能在视图中访问,而不是在模型中
- 访问看起来真的很正确(而且它们似乎也不起作用)
是否没有办法定义可以从模型和视图访问的任何内容?我的意思是,我知道模型和视图应该是分开的,但是在某些领域中肯定有时它们需要引用相同的特定于领域的知识?
I'm just getting started with my first Ruby on Rails webapp. I've got a bunch of different models, views, controllers, and so on.
I'm wanting to find a good place to stick definitions of truly global constants, that apply across my whole app. In particular, they apply both in the logic of my models, and in the decisions taken in my views. I cannot find any DRY place to put these definitions where they're available both to all my models and also in all my views.
To take a specific example, I want a constant COLOURS = ['white', 'blue', 'black', 'red', 'green']
. This is used all over the place, in both models and views. Where can I define it in just one place so that it's accessible?
What I've tried:
- Constant class variables in the model.rb file that they're most associated with, such as
@@COLOURS = [...]
. But I couldn't find a sane way to define it so that I can write in my viewsCard.COLOURS
rather than something kludgy likeCard.first.COLOURS
. - A method on the model, something like
def colours ['white',...] end
- same problem. - A method in application_helper.rb - this is what I'm doing so far, but the helpers are only accessible in views, not in models
- I think I might have tried something in application.rb or environment.rb, but those don't really seem right (and they don't seem to work either)
Is there just no way to define anything to be accessible both from models and from views? I mean, I know models and views should be separate, but surely in some domains there'll be times they need to refer to the same domain-specific knowledge?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(13)
如果你的模型确实对常量“负责”,你应该把它们放在那里。您可以创建类方法来访问它们,而无需创建新的对象实例:
或者,您可以创建类变量和访问器。然而,不鼓励这样做,因为类变量在继承和多线程环境中可能会表现得令人惊讶。
如果需要,上面的两个选项允许您更改每次调用访问器方法时返回的数组。如果您有一个真正不可更改的常量,您还可以在模型类上定义它:
您还可以创建可从初始化程序中的任何位置访问的全局常量,如下例所示。如果您的颜色确实是全局的并且在多个模型上下文中使用,这可能是最好的地方。
注意:当我们定义上面的常量时,通常我们想要
冻结
数组。这可以防止其他代码稍后(无意中)通过添加新元素等方式修改数组。一旦对象被冻结,就无法再更改。If your model is really "responsible" for the constants you should stick them there. You can create class methods to access them without creating a new object instance:
Alternatively, you can create class variables and an accessor. This is however discouraged as class variables might act kind of surprising with inheritance and in multi-thread environments.
The two options above allow you to change the returned array on each invocation of the accessor method if required. If you have true a truly unchangeable constant, you can also define it on the model class:
You could also create global constants which are accessible from everywhere in an initializer like in the following example. This is probably the best place, if your colours are really global and used in more than one model context.
Note: when we define constants above, often we want to
freeze
the array. That prevents other code from later (inadvertently) modifying the array by e.g. adding a new element. Once an object is frozen, it can't be changed anymore.一些选项:
使用常量:
使用类实例变量延迟加载:
如果它是真正的全局常量(尽管避免这种性质的全局常量),您也可以考虑将
例如,
config/initializers/my_constants.rb
中的顶级常量。Some options:
Using a constant:
Lazy loaded using class instance variable:
If it is a truly global constant (avoid global constants of this nature, though), you could also consider putting
a top-level constant in
config/initializers/my_constants.rb
for example.从 Rails 4.2 开始,您可以使用
config.x
属性:
可用作:
加载自定义配置的另一种方法:
在 Rails 中 5,6 ,并且 7 您可以使用
配置 对象。但是,它只能用于非嵌套配置:
它将作为以下形式提供:
Rails 6.1 引入了可以简化 YML 配置的
shared
组:As of Rails 4.2, you can use the
config.x
property:Which will be available as:
Another method of loading custom config:
In Rails 5, 6, and 7 you can use the
configuration
object directly for custom configuration, in addition toconfig.x
. However, it can only be used for non-nested configuration:It will be available as:
Rails 6.1 introduced
shared
groups which can simplify YML configs:如果多个类需要一个常量,我将它放在 config/initializers/constant.rb 中,并且始终全部大写(下面的状态列表已被截断)。
它们在整个应用程序中可用,但在模型代码中除外:
要在模型中使用常量,请使用 attr_accessor 使常量可用。
If a constant is needed in more than one class, I put it in config/initializers/constant.rb always in all caps (list of states below is truncated).
They are available through out the application except in model code as such:
To use the constant in a model, use attr_accessor to make the constant available.
对于应用程序范围的设置和全局常量,我建议使用 Settingslogic。此设置存储在 YML 文件中,可以从模型、视图和控制器访问。此外,您可以为所有环境创建不同的设置:
在视图中的某个位置(我更喜欢此类内容的辅助方法)或在模型中,您可以获得例如颜色数组
Settings.colors.split (/\s/)
。它非常灵活。而且你不需要发明自行车。For application-wide settings and for global constants I recommend to use Settingslogic. This settings are stored in YML file and can be accessed from models, views and controllers. Furthermore, you can create different settings for all your environments:
Somewhere in the view (I prefer helper methods for such kind of stuff) or in a model you can get, for ex., array of colors
Settings.colors.split(/\s/)
. It's very flexible. And you don't need to invent a bike.尝试将所有常量保留在一处,在我的应用程序中,我在初始化程序中创建了常量文件夹,如下所示:
,我通常在这些文件中保持所有不变。
在您的情况下,您可以在常量文件夹下创建文件
colors_constant.rb
colors_constant.rb
不要忘记重新启动服务器
Try to keep all constant at one place, In my application I have created constants folder inside initializers as follows:
and I usually keep all constant in these files.
In your case you can create file under constants folder as
colors_constant.rb
colors_constant.rb
Don't forgot to restart server
使用类方法:
然后 Model.colours 将返回该数组。或者,创建一个初始值设定项并将常量包装在模块中以避免命名空间冲突。
Use a class method:
Then
Model.colours
will return that array. Alternatively, create an initializer and wrap the constants in a module to avoid namespace conflicts.另一种选择,如果您想在一个地方定义常量:
但仍然使它们全局可见,而不必以完全限定的方式访问它们:
Another option, if you want to define your constants in one place:
But still make them globally visible without having to access them in fully qualified way:
放置应用程序范围的全局常量的常见位置是
config/application
内部。A common place to put application-wide global constants is inside
config/application
.我的 Rails 程序中通常有一个“查找”模型/表,并将其用于常量。如果常数对于不同的环境是不同的,这是非常有用的。此外,如果您计划扩展它们,比如说您想在以后添加“黄色”,您可以简单地向查找表添加一个新行并完成它。
如果您授予管理员修改此表的权限,他们将不会来找您进行维护。 :) 干燥。
我的迁移代码如下所示:
我使用 seeds.rb 来预填充它。
I typically have a 'lookup' model/table in my rails program and use it for the constants. It is very useful if the constants are going to be different for different environments. In addition, if you have a plan to extend them, say you want to add 'yellow' on a later date, you could simply add a new row to the lookup table and be done with it.
If you give the admin permissions to modify this table, they will not come to you for maintenance. :) DRY.
Here is how my migration code looks like:
I use seeds.rb to pre-populate it.
全局变量应该在 config/initializers 目录中声明
The global variable should be declare in
config/initializers
directory根据您的情况,您还可以定义一些环境变量,并通过 ruby 代码中的
ENV['some-var']
获取它,这个解决方案可能不适合您,但我希望它可以帮助其他人。示例:您可以创建不同的文件
.development_env
、.development_env
、.test_env
并根据您的应用程序环境加载它,检查此 gen dotenv-rails 可以自动完成此操作。According your condition, you can also define some environmental variables, and fetch it via
ENV['some-var']
in ruby code, this solution may not fit for you, but I hope it may help others.Example: you can create different files
.development_env
,.production_env
,.test_env
and load it according your application environments, check this gen dotenv-rails which automate this for your.我认为你可以使用 gem
config
https://github.com/rubyconfig/config< /a>
轻松处理和编辑
I think you can use gem
config
https://github.com/rubyconfig/config
Easy handle and edit