[英]Ruby on Rails: Where to define global constants?
我刚刚开始使用我的第一个 Ruby on Rails 网络应用程序。 我有一堆不同的模型、视图、控制器等等。
我想找到一个好地方来粘贴真正全局常量的定义,这些定义适用于我的整个应用程序。 特别是,它们既适用于我的模型的逻辑,也适用于我的观点做出的决定。 我找不到任何干燥的地方来放置这些定义,它们既可用于我的所有模型,也可用于我的所有视图。
举一个具体的例子,我想要一个常量COLOURS = ['white', 'blue', 'black', 'red', 'green']
。 这在模型和视图中无处不在。 我在哪里可以在一个地方定义它以便它可以访问?
我试过的:
@@COLOURS = [...]
。 但是我找不到一种合理的方法来定义它,以便我可以在我的视图中写入Card.COLOURS
而不是像Card.first.COLOURS
这样Card.first.COLOURS
东西。def colours ['white',...] end
- 同样的问题。有没有办法定义任何东西都可以从模型和视图访问? 我的意思是,我知道模型和视图应该是分开的,但是在某些领域中肯定会有时间它们需要引用相同的特定于领域的知识?
如果你的模型真的对常量“负责”,你应该把它们放在那里。 您可以创建类方法来访问它们,而无需创建新的对象实例:
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
数组。 这可以防止其他代码稍后(无意中)通过添加新元素来修改数组。 一旦一个对象被冻结,它就不能再改变了。
一些选项:
使用常量:
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
放置一个顶级常量,例如。
从 Rails 4.2 开始,您可以使用config.x
属性:
# config/application.rb (or config/custom.rb if you prefer)
config.x.colours.options = %w[white blue black red green]
config.x.colours.default = 'white'
这将作为:
Rails.configuration.x.colours.options
# => ["white", "blue", "black", "red", "green"]
Rails.configuration.x.colours.default
# => "white"
另一种加载自定义配置的方法:
# config/colours.yml
default: &default
options:
- white
- blue
- black
- red
- green
default: white
development:
*default
production:
*default
# config/application.rb
config.colours = config_for(:colours)
Rails.configuration.colours
# => {"options"=>["white", "blue", "black", "red", "green"], "default"=>"white"}
Rails.configuration.colours['default']
# => "white"
在 Rails 5 & 6 中,除了config.x
之外,您还可以直接使用configuration
对象进行自定义配置。 但是,它只能用于非嵌套配置:
# config/application.rb
config.colours = %w[white blue black red green]
它将作为:
Rails.configuration.colours
# => ["white", "blue", "black", "red", "green"]
如果在一个以上的类中需要一个常量,我将它放在 config/initializers/constant.rb 中,总是大写(下面的状态列表被截断)。
STATES = ['AK', 'AL', ... 'WI', 'WV', 'WY']
它们在整个应用程序中都可用,但在模型代码中除外:
<%= form.label :states, %>
<%= form.select :states, STATES, {} %>
要在模型中使用常量,请使用 attr_accessor 使常量可用。
class Customer < ActiveRecord::Base
attr_accessor :STATES
validates :state, inclusion: {in: STATES, message: "-- choose a State from the drop down list."}
end
对于应用程序范围的设置和全局常量,我建议使用Settingslogic 。 这些设置存储在 YML 文件中,可以从模型、视图和控制器访问。 此外,您可以为所有环境创建不同的设置:
# app/config/application.yml
defaults: &defaults
cool:
sweet: nested settings
neat_setting: 24
awesome_setting: <%= "Did you know 5 + 5 = #{5 + 5}?" %>
colors: "white blue black red green"
development:
<<: *defaults
neat_setting: 800
test:
<<: *defaults
production:
<<: *defaults
在视图中的某个地方(我更喜欢此类东西的辅助方法)或在模型中您可以获得,例如,颜色数组Settings.colors.split(/\\s/)
。 它非常灵活。 你不需要发明一辆自行车。
使用类方法:
def self.colours
['white', 'red', 'black']
end
然后Model.colours
将返回该数组。 或者,创建一个初始化程序并将常量包装在一个模块中以避免命名空间冲突。
另一种选择,如果你想在一个地方定义你的常量:
module DSL
module Constants
MY_CONSTANT = 1
end
end
但仍然使它们全局可见,而无需以完全限定的方式访问它们:
DSL::Constants::MY_CONSTANT # => 1
MY_CONSTANT # => NameError: uninitialized constant MY_CONSTANT
Object.instance_eval { include DSL::Constants }
MY_CONSTANT # => 1
放置应用程序全局常量的常见位置是config/application
。
module MyApp
FOO ||= ENV.fetch('FOO', nil)
BAR ||= %w(one two three)
class Application < Rails::Application
config.foo_bar = :baz
end
end
我的 rails 程序中通常有一个“查找”模型/表,并将其用于常量。 如果常量对于不同的环境会有所不同,这将非常有用。 此外,如果您有扩展它们的计划,假设您想在以后添加“黄色”,您可以简单地向查找表添加一个新行并完成它。
如果您授予管理员修改此表的权限,他们将不会来找您进行维护。 :) 干燥。
这是我的迁移代码的样子:
class CreateLookups < ActiveRecord::Migration
def change
create_table :lookups do |t|
t.string :group_key
t.string :lookup_key
t.string :lookup_value
t.timestamps
end
end
end
我使用seeds.rb 来预填充它。
Lookup.find_or_create_by_group_key_and_lookup_key_and_lookup_value!(group_key: 'development_COLORS', lookup_key: 'color1', lookup_value: 'red');
全局变量应该在config/initializers
目录中声明
COLOURS = %w(white blue black red green)
根据您的情况,您还可以定义一些环境变量,并通过 ruby 代码中的ENV['some-var']
获取它,该解决方案可能不适合您,但我希望它可以帮助其他人。
例如:你可以创建不同的文件.development_env
, .production_env
, .test_env
并根据您的应用程序环境中加载它,看看这个根dotenv护栏它为您自动执行此。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.