Лучший способ создать собственные параметры конфигурации для моего приложения Rails?


133

Мне нужно создать один вариант конфигурации для моего приложения Rails. Это может быть одинаковым для всех сред. Я обнаружил, что если я установлю его environment.rb, он будет доступен в моих представлениях, а это именно то, что я хочу ...

environment.rb

AUDIOCAST_URI_FORMAT = http://blablalba/blabbitybla/yadda

Прекрасно работает.

Однако мне немного не по себе. Это хороший способ сделать это? Есть ли способ более модный?

Ответы:


191

Для общей конфигурации приложения, которую не нужно хранить в таблице базы данных, я хотел бы создать config.ymlфайл в каталоге config . Для вашего примера это может выглядеть так:

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

45
Просто к сведению, в Rails 3.x вам нужно заменить RAILS_ENVна Rails.envи RAILS_ROOTна Rails.root.
JeanMertz

5
Для Rails 3+ вы должны присоединиться к относительному пути, а не к абсолютному. Не добавляйте к директории конфигурации префикс косой черты.
WST

10
Не уверен насчет предыдущих версий, но в Rails 4.1 вы можете это сделатьRails.application.config.whatever_you_want = YAML.load_file(Rails.root.join('config', 'config.yml'))[Rails.env]
d4rky

2
@ iphone007 действительно можно загружать произвольные файлы yaml из каталога конфигурации. см . ответ smathy ниже, который, на мой взгляд, теперь должен быть принятым ответом.
omnikron 05

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}"работает.
Дэвид Дж.

3
Я рекомендую Rails.root.join('config', 'config.yml')вместо"#{Rails.root.to_s}/config/config.yml"
Дэвид Дж.

2
И вместо APP_CONFIG я рекомендую использовать:AppName::Application.config.custom
Дэвид Дж.

1
Дэвид, ваши первые два комментария - лучшая практика, и я исправлю код, но последний, который я собираюсь пропустить, так как это означает, что вам нужно помнить, чтобы менять AppName каждый раз, когда вы используете этот код.
Дэвид Берроуз

53

Рельсы> = 4.2

Просто создайте YAMLфайл в config/каталоге, например: config/neo4j.yml.

Содержимое neo4j.ymlможет быть примерно таким, как показано ниже (для простоты я использовал default для всех сред):

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

Больше информации

Официальный документ API Rails описывает config_forметод как:

Удобство для загрузки config / foo.yml для текущей среды Rails.


Если вы не хотите использовать 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']

Как мы читаем переменную ENV в config.yml, моя конфигурация такая же ... я добавил переменную в bashrc, и я пытаюсь прочитать это в config.yml, используя ключ: <% = ENV [URL]%> ... this не работает
шива

@shiva Загляните в жемчужину Фигаро на предмет переменных ENV. Эта настройка конфигурации предназначена для значений, которые не нужно скрывать от системы контроля версий.
Шадоат 08

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
Дон

Ты прав, Дон, это странно - я уверен, что раньше это говорили.
smathy

1
Из текущих документов по рельсам: 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
Дэвид Гей

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 для 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 в моей конфигурации, если мне нужно, например, читать redistogo url heroku:

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

2
Не думаю, что мне это понадобится каждый день, но это действительно крутое решение для тех случаев, когда оно вам действительно нужно. Я думаю, что я изменил бы имя файла на config.yml.erb, хотя, чтобы соответствовать соглашению рельсов.
Эндрю Бернс,

2

Rails 4

Создать собственную конфигурацию yaml и загрузить ее (и сделать доступной для вашего приложения) аналогично тому, как это сделать 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]. Однако в рельсах 4.2 и выше ответ smathy, вероятно, является более простым способом.
omnikron

1

Основываясь на элегантном решении Омера Аслама, я решил преобразовать ключи в символы. Единственное изменение:

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

Это позволяет вам затем ссылаться на значения по символам как ключи, например

AppConfig[:twitter][:key]

Это кажется аккуратнее для моих глаз.

(Написано как ответ, поскольку моя репутация недостаточно высока, чтобы комментировать ответ Омера)



0

см. мой ответ на Где лучше всего хранить параметры приложения: базу данных, файл, код ...?

Вариант того, что у вас было, это простая ссылка на другой файл. Он видит, что environment.rb не обновляется постоянно и в нем нет кучи специфичных для приложения вещей. Хотя это и не конкретный ответ на ваш вопрос «Это путь Rails?», Возможно, там будет некоторое обсуждение этого вопроса.


0

Я предпочитаю доступ к настройкам через глобальный стек приложений. Я избегаю лишних глобальных переменных в локальной области.

конфиг / Инициализаторы / 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]

Создайте YAML в config / setting.yml

development:
  app_id: 433387212345678
  app_secret: f43df96fc4f65904083b679412345678

test:
  app_id: 148166412121212
  app_secret: 7409bda8139554d11173a32222121212

production:
  app_id: 148166412121212
  app_secret: 7409bda8139554d11173a32222121212
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.