为我的Rails应用程序创建自定义配置选项的最佳方法?


133

我需要为我的Rails应用程序创建一个配置选项。对于所有环境,它都可以相同。我发现如果将其设置为environment.rb,则在我的视图中可用,这正是我想要的...

environment.rb

AUDIOCAST_URI_FORMAT = http://blablalba/blabbitybla/yadda

效果很好。

但是,我有点不安。这是一个好方法吗?有没有一种更时髦的方式?

Answers:


191

对于不需要存储在数据库表中的常规应用程序配置,我想config.ymlconfig目录中创建一个文件。对于您的示例,它可能看起来像这样:

defaults: &defaults
  audiocast_uri_format: http://blablalba/blabbitybla/yadda

development:
  <<: *defaults

test:
  <<: *defaults

production:
  <<: *defaults

此配置文件从config / initializers中的自定义初始化程序加载:

# Rails 2
APP_CONFIG = YAML.load_file("#{RAILS_ROOT}/config/config.yml")[RAILS_ENV]

# Rails 3+
APP_CONFIG = YAML.load_file(Rails.root.join('config/config.yml'))[Rails.env]

如果您使用的是Rails 3,请确保不要在相对配置路径中意外添加斜杠。

然后,您可以使用以下方法检索值:

uri_format = APP_CONFIG['audiocast_uri_format']

有关完整详细信息,请参见此Railscast


1
您可能需要YAML::ENGINE.yamler = 'syck'使用它才能工作stackoverflow.com/a/6140900/414220
evanrmurphy 2012年

45
只是供参考,在Rails的3.x中,你需要更换RAILS_ENVRails.envRAILS_ROOTRails.root
JeanMertz

5
对于Rails 3+,您应该加入相对路径,而不是绝对路径。不要在配置目录前加斜杠。
2014年

10
不确定以前的版本,但是可以在Rails 4.1中执行Rails.application.config.whatever_you_want = YAML.load_file(Rails.root.join('config', 'config.yml'))[Rails.env]
d4rky 2014年

2
@ iphone007确实有可能从config目录加载任意yaml文件。请参阅下面的smathy的答案,我认为现在应该是被接受的答案。
omn​​ikron

82

Rails 3版本的初始化代码如下(不推荐使用RAILS_ROOT和RAILS_ENV)

APP_CONFIG = YAML.load_file(Rails.root.join('config', 'config.yml'))[Rails.env]

另外,Ruby 1.9.3使用Psych使得合并键区分大小写,因此您需要更改配置文件以将其考虑在内,例如

defaults: &DEFAULTS
  audiocast_uri_format: http://blablalba/blabbitybla/yadda

development:
  <<: *DEFAULTS

test:
  <<: *DEFAULTS

production:
  <<: *DEFAULTS

3
你不需要"#{Rails.root.to_s}"; "#{Rails.root}"作品。
David J.

3
我建议Rails.root.join('config', 'config.yml')而不是"#{Rails.root.to_s}/config/config.yml"
David J.

2
而且,我建议使用:AppName::Application.config.custom
-David J.

1
大卫,您的前两个注释是最佳实践,我将修改代码,但是最后一个将被删除,因为这意味着您需要记住每次使用此代码时都要更改AppName。
David Burrows 2012年

53

导轨> = 4.2

只需YAMLconfig/目录中创建一个文件即可,例如:config/neo4j.yml

的内容neo4j.yml可能如下所示(为简单起见,我在所有环境中均使用默认值):

default: &default
  host: localhost
  port: 7474
  username: neo4j
  password: root

development:
  <<: *default

test:
  <<: *default

production:
  <<: *default

config/application.rb

module MyApp
  class Application < Rails::Application
    config.neo4j = config_for(:neo4j)
  end
end

现在,可以如下访问您的自定义配置:

Rails.configuration.neo4j['host'] #=>localhost
Rails.configuration.neo4j['port'] #=>7474

更多信息

Rails官方API文档将config_for方法描述为:

为当前的Rails env加载config / foo.yml的便利。


如果您不想使用yaml文件

正如Rails官方指南所说:

您可以通过Rails配置对象使用该config.x属性下的自定义配置来配置自己的代码。

config.x.payment_processing.schedule = :daily
config.x.payment_processing.retries  = 3
config.x.super_debugger = true

然后,可以通过配置对象使用以下配置点:

Rails.configuration.x.payment_processing.schedule # => :daily
Rails.configuration.x.payment_processing.retries  # => 3
Rails.configuration.x.super_debugger              # => true
Rails.configuration.x.super_debugger.not_set      # => nil

config_for方法的官方参考 | 官方Rails指南


25

步骤1:建立config / initializers / appconfig.rb

require 'ostruct'
require 'yaml'

all_config = YAML.load_file("#{Rails.root}/config/config.yml") || {}
env_config = all_config[Rails.env] || {}
AppConfig = OpenStruct.new(env_config)

步骤2:建立config / config.yml

common: &common
  facebook:
    key: 'asdjhasxas'
    secret : 'xyz'
  twitter:
    key: 'asdjhasxas'
    secret : 'abx'

development:
  <<: *common

test:
  <<: *common

production:
  <<: *common

步骤3:在代码中的任何位置获取常量

facebook_key = AppConfig.facebook['key']
twitter_key  = AppConfig.twitter['key']

我们如何读取config.yml中的ENV变量,我的配置是相同的..i在bashrc中添加了变量,我试图使用以下键在config.yml中读取该变量:<%= ENV [URL]%> ...无法正常工作
shiva

@shiva查看Figaro gem中的ENV变量。此配置设置适用于不需要从源代码控制中隐藏的值。
Shadoath

17

我只是想针对Rails 4.2和5中的最新功能进行更新,现在可以在任何config/**/*.rb文件中执行此操作:

config.x.whatever = 42

(这就是其中的文字x,即config.x.文字必须是该文字,然后您可以在之后添加任何内容x

...这将在您的应用中显示为:

Rails.configuration.x.whatever

在此处查看更多信息:http : //guides.rubyonrails.org/configuring.html#custom-configuration


3
最初给我带来麻烦的澄清;x并不是您要放入的任何内容的占位符,它确实需要是字母x
tobinibot

好点@tobinibot-我已经在回答中添加了澄清说明,谢谢。
smathy

有趣的是,指南实际上并未提及“ x”,但我可以证明,从Rails 5.0开始,它仍然是必需的
Don

你说得对,唐,这很奇怪-我敢肯定它曾经说过。
smathy's

1
来自当前的rails文档:You can configure your own code through the Rails configuration object with custom configuration under either the config.x namespace, or config directly. The key difference between these two is that you should be using config.x if you are defining nested configuration (ex: config.x.nested.nested.hi), and just config for single level configuration (ex: config.hello).来源:guides.rubyonrails.org/configuring.html#custom-configuration
David Gay

6

关于此主题的一些额外信息:

APP_CONFIG = YAML.load_file(Rails.root.join('config', 'config.yml'))[Rails.env].with_indifferent_access

“ .with_indifferent_access”允许您使用字符串键或等效的符号键访问哈希中的值。

例如。
APP_CONFIG['audiocast_uri_format'] => 'http://blablalba/blabbitybla/yadda' APP_CONFIG[:audiocast_uri_format] => 'http://blablalba/blabbitybla/yadda'

纯粹是方便的事情,但是我更喜欢将键表示为符号。


5

我使用类似于John for Rails 3.0 / 3.1的东西,但是我先erb解析了该文件:

APP_CONFIG = YAML.load(ERB.new(File.new(File.expand_path('../config.yml', __FILE__)).read).result)[Rails.env]

这使我可以根据需要在配置中使用ERB,例如阅读heroku的redistogo url:

production:
  <<: *default
  redis:                  <%= ENV['REDISTOGO_URL'] %>

2
我认为我不是每天都需要这样做,但是对于那些确实需要它的时代来说,这是一个非常酷的解决方案。我想我可以将文件名更改为config.yml.erb,以匹配rails约定。
安德鲁·伯恩斯

2

Rails 4

要创建自定义配置yaml并加载它(并使其对您的应用可用),类似于how database_configuration

创建您的*.yml,以我为例,我需要一个redis配置文件。

config/redis.yml

default: &default
  host: localhost
  port: 6379

development:
  <<: *default

test:
  <<: *default

production:
  <<: *default
  host: <%= ENV['ELASTICACHE_HOST'] %>
  port: <%= ENV['ELASTICACHE_PORT'] %>

然后加载配置

config/application.rb

module MyApp
  class Application < Rails::Application

    ## http://guides.rubyonrails.org/configuring.html#initialization-events
    config.before_initialize do
      Rails.configuration.redis_configuration = YAML.load_file("#{Rails.root}/config/redis.yml")
    end

  end
end

访问值:

Rails.configuration.redis_configuration[Rails.env]类似于您如何database.yml通过Rails.configuration.database_configuration[Rails.env]


您也可以只为当前环境进行设置,从而节省一些时间,这大概是您唯一需要的设置:Rails.configuration.redis_configuration = YAML.load_file("#{Rails.root}/config/redis.yml")[Rails.env]。但是,在Rails 4.2及更高版本中,smathy的答案可能是更简单的方法。
omn​​ikron

1

在Omer Aslam优雅的解决方案的基础上,我决定将键转换为符号。唯一的变化是:

all_config = YAML.load_file("#{Rails.root}/config/config.yml").with_indifferent_access || {}

然后,您可以通过符号作为键来引用值,例如

AppConfig[:twitter][:key]

在我看来这看起来更整洁。

(由于我的声誉不够高,无法对Omer的回复发表评论,因此发布为答案)




0

我更喜欢通过全局应用程序堆栈访问设置。我避免在局部范围内使用过多的全局变量。

config / initializers / myconfig.rb

MyAppName::Application.define_singleton_method("myconfig") {YAML.load_file("#{Rails.root}/config/myconfig.yml") || {}}

并使用它。

MyAppName::Application.myconfig["yamlstuff"]

0

我在Rails初始化之前加载设置的方法

允许您在Rails初始化中使用设置并根据环境配置设置

# config/application.rb
Bundler.require(*Rails.groups)

mode = ENV['RAILS_ENV'] || 'development'
file = File.dirname(__FILE__).concat('/settings.yml')
Settings = YAML.load_file(file).fetch(mode)
Settings.define_singleton_method(:method_missing) {|name| self.fetch(name.to_s, nil)}

您可以通过两种方式获取设置: Settings ['email']Settings.email


0

我最好的自定义配置方式,缺少setting.yml时会引发信息。

从config / initializers / custom_config.rb中的自定义初始化程序加载

setting_config = File.join(Rails.root,'config','setting.yml')
raise "#{setting_config} is missing!" unless File.exists? setting_config
config = YAML.load_file(setting_config)[Rails.env].symbolize_keys

@APP_ID = config[:app_id]
@APP_SECRET = config[:app_secret]

在config / setting.yml中创建一个YAML

development:
  app_id: 433387212345678
  app_secret: f43df96fc4f65904083b679412345678

test:
  app_id: 148166412121212
  app_secret: 7409bda8139554d11173a32222121212

production:
  app_id: 148166412121212
  app_secret: 7409bda8139554d11173a32222121212
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.