从控制器中的 application.rb 访问配置(Rails 3)
我正在尝试向我的 application.rb 添加两个额外的配置选项,以便我可以在控制器中读取它们.
I'm trying to add two extra config options to my application.rb so I can read them out in controllers.
# Extra
config.twitter.key = 'foo'
config.twitter.secret = 'bar'
我正在尝试使用三种建议的方法访问它们:
I am trying to access them using three suggested methods:
self.config.twitter.key # Should be extended through ApplicationController Base
config.twitter.key # Inherited but with different syntax
CONFIG['twitter']['key'] #some massive magical array that apparently exists somewhere
当我通过调试"方法传递它们时,它们都会给我不同类型的错误,例如:
They all give me different kinds of error when I pass them through the "debug" method, E.g:
debug self.config.twitter.key # undefined method `key' for nil:NilClass
怎么了?
我相信您对 config/application.rb 所提供的期望有一个稍微不正确的想法.ActiveRecord::Base 和 ActiveController::Base 特征类使用在 config/application.rb 中配置的 Rails::Application::Configuration 类.这些属性在继承自基类或其特征类的类中不可用.这就是您在 ApplicationController 中遇到错误的原因.
I believe you've got a slightly incorrect idea behind what your expectations for the config/application.rb is providing you. The ActiveRecord::Base and ActiveController::Base eigenclasses use the Rails::Application::Configuration class that is configured in config/application.rb. The attributes aren't available in classes that descend from either of the Base classes, nor their eigenclasses. This is why you are running into errors in ApplicationController.
通常有两种方法可以在 Rails 应用程序中进行配置初始化.第一种方法是创建一个配置模块,然后通过初始化程序将值加载到其中:
There are generally two ways to make configuration initializations in a Rails app. The first way is to create a configuration module and then load values into it via initializer:
首先,创建一个 Twiter 配置模块:
First, create a Twiter Config module:
#lib/twitter_config.rb
module TwitterConfig
def self.config
@@config ||= {}
end
def self.config=(hash)
@@config = hash
end
end
创建一个 YAML 配置文件:
Create a YAML config file:
# config/twitter.yaml
development: &base
key: "foo"
secret: "bar"
test:
<<: *base
key: "foo2"
production:
<<: *base
secret: "barbar"
或者,如果您不打算将 config/twitter.yaml 添加到您的 SCM,您可以跳过此步骤并通过环境变量设置密钥和机密.对于具有在 Heroku 上部署的公共 SCM 存储库的应用程序,这将是建议的解决方案.
Alternatively, if you don't intend to add config/twitter.yaml to your SCM, you can just skip this and set the key and secret via environment variables. This would be the suggested solution for an application with a public SCM repository deploying on Heroku.
然后通过初始化程序加载并设置值:
Then load and set the value via an initializer:
#config/initializers/01_twitter.rb
require 'twitter_config'
TwitterConfig.config = YAML.load_file("config/config.yml")[Rails.env].symbolize_keys
通常最好给初始化文件编号,因为 Rails 会根据文件名按顺序加载它们.如果您正在初始化数据存储并且这对其他步骤至关重要,那么它需要最低的数字.或者,如果您使用环境变量,这将是 init 文件:
It's generally a best practice to number your initializer files as Rails will load them in order according to their filename. If you are initializing a datastore and that is critical for other steps, then it needs the lowest number. Alternatively, if you are using environment variables, this would be the init file:
#config/initializers/01_twitter.rb
require 'twitter_config'
TwitterConfig.config[:key] = ENV['twitter_config_key']
TwitterConfig.config[:secret] = ENV['twitter_config_secret']
在整个 Rails 应用程序中,您现在可以使用 TwitterConfig.config[:key] & 访问配置值.TwitterConfig.config[:secret].您也可以包含该模块,只需注意冲突即可.
Throughout the Rails application, you now have access to the config values with TwitterConfig.config[:key] & TwitterConfig.config[:secret]. You can include the module as well, just watch out for conflicts.
您也可以将值作为全局常量加载.不过我觉得有点难看:
You can also just load the values as a global constant. It feels a bit ugly to me though:
#config/application.rb
TWITTER_CONFIG = YAML.load_file("config/twitter.yaml")[Rails.env]