A melhor maneira de criar opções de configuração personalizadas para o meu aplicativo Rails?

133

Preciso criar uma opção de configuração para meu aplicativo Rails. Pode ser o mesmo para todos os ambientes. Descobri que, se eu configurá-lo environment.rb, ele estará disponível nas minhas visualizações, exatamente o que eu quero ...

environment.rb

AUDIOCAST_URI_FORMAT = http://blablalba/blabbitybla/yadda

Funciona bem.

No entanto, estou um pouco desconfortável. Essa é uma boa maneira de fazer isso? Existe uma maneira que seja mais moderna?

Ethan
fonte

Respostas:

191

Para configurações gerais de aplicativos que não precisam ser armazenadas em uma tabela de banco de dados, eu gosto de criar um config.ymlarquivo no diretório de configuração . Para o seu exemplo, pode ser assim:

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

development:
  <<: *defaults

test:
  <<: *defaults

production:
  <<: *defaults

Este arquivo de configuração é carregado a partir de um inicializador personalizado em 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]

Se você estiver usando o Rails 3, certifique-se de não adicionar acidentalmente uma barra principal ao seu caminho de configuração relativo.

Você pode recuperar o valor usando:

uri_format = APP_CONFIG['audiocast_uri_format']

Veja este Railscast para detalhes completos.

John Topley
fonte
1
Pode ser necessário YAML::ENGINE.yamler = 'syck'para que isso funcione stackoverflow.com/a/6140900/414220
evanrmurphy
45
Apenas um FYI, no Rails 3.x você precisa substituir RAILS_ENVpor Rails.enve RAILS_ROOTcom Rails.root.
JeanMertz
5
Para o Rails 3+, você deve ingressar no caminho relativo, não absoluto. Não prefixe o diretório de configuração com barra.
wst
10
Não tenho certeza sobre as versões anteriores, mas no Rails 4.1 você pode fazerRails.application.config.whatever_you_want = YAML.load_file(Rails.root.join('config', 'config.yml'))[Rails.env]
d4rky
2
@ iphone007 é realmente possível carregar arquivos yaml arbitrários do diretório de configuração. veja a resposta de smathy abaixo, que na minha opinião agora deve ser a resposta aceita.
Omnikron
82

A versão do Rails 3 do código do inicializador é a seguinte (RAILS_ROOT & RAILS_ENV estão obsoletos)

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

Além disso, o Ruby 1.9.3 usa Psych, que faz com que as chaves de mesclagem sejam sensíveis a maiúsculas e minúsculas; portanto, você precisará alterar seu arquivo de configuração para levar isso em conta, por exemplo

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

development:
  <<: *DEFAULTS

test:
  <<: *DEFAULTS

production:
  <<: *DEFAULTS
David Burrows
fonte
3
Você não precisa "#{Rails.root.to_s}"; "#{Rails.root}"trabalho.
1874 David J.
3
Eu recomendo em Rails.root.join('config', 'config.yml')vez de"#{Rails.root.to_s}/config/config.yml"
David J.
2
E, em vez de APP_CONFIG, eu recomendo usar:AppName::Application.config.custom
David J.
1
David, seus dois primeiros comentários são uma prática recomendada e eu vou alterar o código, mas o último que deixarei de fora, pois isso significa que você precisa se lembrar de alterar o AppName toda vez que usar esse código.
David Burrows
53

Trilhos> = 4.2

Basta criar um YAMLarquivo em config/diretório, por exemplo: config/neo4j.yml.

O conteúdo de neo4j.ymlpode ser algo como abaixo (para simplificar, usei o padrão para todos os ambientes):

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

development:
  <<: *default

test:
  <<: *default

production:
  <<: *default

em config/application.rb:

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

Agora, sua configuração personalizada está acessível como abaixo:

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

Mais informações

O documento oficial da API do Rails descreve o config_formétodo como:

Conveniência para carregar config / foo.yml para o ambiente atual do Rails.


Se você não quiser usar um yamlarquivo

Como o guia oficial do Rails diz:

Você pode configurar seu próprio código através do objeto de configuração do Rails com configuração personalizada sob a config.xpropriedade

Exemplo

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

Esses pontos de configuração estão disponíveis no objeto de configuração:

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

Referência oficial do config_formétodo | Guia Oficial do Rails

Ali MasudianPour
fonte
25

Etapa 1: Crie 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)

Etapa 2: Criar config / config.yml

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

development:
  <<: *common

test:
  <<: *common

production:
  <<: *common

Etapa 3: obter constantes em qualquer lugar do código

facebook_key = AppConfig.facebook['key']
twitter_key  = AppConfig.twitter['key']
Omer Aslam
fonte
Como lemos a variável ENV no config.yml, minha configuração é a mesma .. adicionei variável no bashrc e estou tentando ler isso no config.yml usando a chave: <% = ENV [URL]%> ... this não está funcionando
shiva
@shiva Veja na gema Figaro as variáveis ​​ENV. Essa configuração é para valores que não precisam ser ocultados do controle de origem.
Shadoath 8/17
17

Eu só queria atualizar isso para obter as novidades interessantes do Rails 4.2 e 5, agora você pode fazer isso em qualquer um dos seus config/**/*.rbarquivos:

config.x.whatever = 42

(e isso é literal xaqui, ou seja, o config.x.literal deve ser isso, e você pode adicionar o que quiser depois do x)

... e isso estará disponível no seu aplicativo como:

Rails.configuration.x.whatever

Veja mais aqui: http://guides.rubyonrails.org/configuring.html#custom-configuration

smathy
fonte
3
Apenas um esclarecimento que inicialmente causou um problema para mim; o x não é um espaço reservado para o que você deseja inserir, ele realmente precisa ser a letra x.
precisa saber é o seguinte
Ótimo ponto @tobinibot - adicionei esse esclarecimento à minha resposta, obrigado.
smathy
Interessante que os guias realmente não mencionar o 'x', mas posso atestar que ainda é necessário a partir de Rails 5.0
Don
Você está certo, Don, isso é estranho - tenho certeza que costumava dizer isso.
smathy
1
A partir dos documentos atuais do 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).Fonte: guias.rubyonrails.org/configuring.html#custom-configuration
David Gay
6

Apenas algumas informações extras sobre este tópico:

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

".com_indifferent_access" permite acessar os valores no hash usando uma chave de cadeia ou com uma chave de símbolo equivalente.

por exemplo.
APP_CONFIG['audiocast_uri_format'] => 'http://blablalba/blabbitybla/yadda' APP_CONFIG[:audiocast_uri_format] => 'http://blablalba/blabbitybla/yadda'

É uma questão de conveniência, mas prefiro ter minhas chaves representadas como símbolos.

foomip
fonte
5

Eu uso algo semelhante ao John for Rails 3.0 / 3.1, mas eu erb analise o arquivo primeiro:

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

Isso me permite usar o ERB na minha configuração, se necessário, como ler o URL de redistogo do heroku:

production:
  <<: *default
  redis:                  <%= ENV['REDISTOGO_URL'] %>
Jack Chu
fonte
2
Acho que não precisaria disso todos os dias, mas essa é uma solução muito legal para os momentos em que você precisa. Eu acho que mudaria o nome do arquivo para config.yml.erb, para coincidir com a convenção de trilhos.
Andrew Burns
2

Rails 4

Para criar um yaml de configuração personalizada e carregá-lo (e disponibilizar para o seu aplicativo) semelhante a como database_configuration.

Crie o seu *.yml, no meu caso, eu precisava de um arquivo de configuração redis.

config/redis.yml

default: &default
  host: localhost
  port: 6379

development:
  <<: *default

test:
  <<: *default

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

Em seguida, carregue a configuração

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

Acesse os valores:

Rails.configuration.redis_configuration[Rails.env]ao semelhante como você pode ter acesso ao seu database.ymlporRails.configuration.database_configuration[Rails.env]

twmulloy
fonte
Você também pode poupar algum tempo, tendo apenas as configurações para seu ambiente atual, que são presumivelmente os únicos que você de qualquer maneira precisa: Rails.configuration.redis_configuration = YAML.load_file("#{Rails.root}/config/redis.yml")[Rails.env]. No entanto, nos trilhos 4.2 e acima, a resposta de smathy é provavelmente um caminho mais simples.
Omnikron
1

Com base na solução elegante de Omer Aslam, decidi converter as chaves em símbolos. A única mudança é:

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

Isso permite que você faça referência a valores por símbolos como chaves, por exemplo

AppConfig[:twitter][:key]

Isso parece mais agradável aos meus olhos.

(Postado como resposta, pois minha reputação não é alta o suficiente para comentar a resposta de Omer)

Kitebuggy
fonte
0

Eu gosto de simpleconfig . Ele permite que você tenha por configuração de ambiente.

Jerry Cheung
fonte
0

Prefiro acessar as configurações através da pilha global de aplicativos. Evito excesso de variáveis ​​globais no escopo local.

config / inicializadores / myconfig.rb

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

E acesse-o com.

MyAppName::Application.myconfig["yamlstuff"]
6ft Dan
fonte
0

Minha maneira de carregar as Configurações antes da inicialização do Rails

Permite usar configurações na inicialização do Rails e definir configurações por ambiente

# 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)}

Você pode obter as configurações de duas maneiras: Configurações ['email'] ou Settings.email

greenif
fonte
0

Minha melhor maneira de configuração personalizada, com mensagem de aumento quando setting.yml está ausente.

é carregado de um inicializador personalizado em 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]

Crie um YAML em config / setting.yml

development:
  app_id: 433387212345678
  app_secret: f43df96fc4f65904083b679412345678

test:
  app_id: 148166412121212
  app_secret: 7409bda8139554d11173a32222121212

production:
  app_id: 148166412121212
  app_secret: 7409bda8139554d11173a32222121212
Marcelo Áustria
fonte