Najlepszy sposób na tworzenie niestandardowych opcji konfiguracyjnych dla mojej aplikacji Rails?


133

Muszę utworzyć jedną opcję konfiguracji dla mojej aplikacji Railsowej. Może być taki sam dla wszystkich środowisk. Odkryłem, że jeśli to ustawię environment.rb, jest dostępne w moich widokach, a dokładnie tego chcę ...

environment.rb

AUDIOCAST_URI_FORMAT = http://blablalba/blabbitybla/yadda

Działa świetnie.

Jednak jestem trochę niespokojny. Czy to dobry sposób na zrobienie tego? Czy jest sposób, który jest bardziej modny?

Odpowiedzi:


191

W przypadku ogólnej konfiguracji aplikacji, która nie musi być przechowywana w tabeli bazy danych, lubię tworzyć config.ymlplik w katalogu konfiguracyjnym . Na przykład może to wyglądać tak:

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

development:
  <<: *defaults

test:
  <<: *defaults

production:
  <<: *defaults

Ten plik konfiguracyjny jest ładowany z niestandardowego inicjatora w 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]

Jeśli używasz Rails 3, upewnij się, że nie dodałeś przypadkowo początkowego ukośnika do względnej ścieżki konfiguracyjnej.

Następnie możesz pobrać wartość za pomocą:

uri_format = APP_CONFIG['audiocast_uri_format']

Zobacz ten Railscast po więcej szczegółów.


1
Być może będziesz potrzebować YAML::ENGINE.yamler = 'syck'tego do pracy stackoverflow.com/a/6140900/414220
evanrmurphy

45
Po prostu FYI, w Rails 3.x trzeba wymienić RAILS_ENVz Rails.envi RAILS_ROOTz Rails.root.
JeanMertz,

5
Dla Rails 3+ powinieneś dołączyć ścieżkę względną, a nie bezwzględną. Nie poprzedzaj katalogu konfiguracyjnego ukośnikiem.
wst

10
Nie jestem pewien co do poprzednich wersji, ale w Railsach 4.1 możesz to zrobićRails.application.config.whatever_you_want = YAML.load_file(Rails.root.join('config', 'config.yml'))[Rails.env]
d4rky

2
@ iphone007 rzeczywiście można załadować dowolne pliki yaml z katalogu konfiguracyjnego. zobacz odpowiedź smathy poniżej, która moim zdaniem powinna być teraz zaakceptowana.
omnikron

82

Wersja kodu inicjalizatora Rails 3 jest następująca (RAILS_ROOT i RAILS_ENV są ​​przestarzałe)

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

Ponadto Ruby 1.9.3 używa Psych, który rozróżnia wielkość liter w klawiszach łączenia, więc musisz zmienić plik konfiguracyjny, aby to uwzględnić, np.

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

development:
  <<: *DEFAULTS

test:
  <<: *DEFAULTS

production:
  <<: *DEFAULTS

3
Nie potrzebujesz "#{Rails.root.to_s}"; "#{Rails.root}"Pracuje.
David J.

3
Polecam Rails.root.join('config', 'config.yml')zamiast"#{Rails.root.to_s}/config/config.yml"
David J.

2
I zamiast APP_CONFIG polecam używanie:AppName::Application.config.custom
David J.

1
David, twoje pierwsze dwa komentarze to najlepsza praktyka i poprawię kod, ale ostatni pominę, ponieważ oznacza to, że musisz pamiętać o zmianie AppName za każdym razem, gdy używasz tego kodu.
David Burrows,

53

Szyny> = 4.2

Po prostu utwórz YAMLplik w config/katalogu, na przykład:config/neo4j.yml .

Treść neo4j.ymlmoże być podobna do poniższej (dla uproszczenia użyłem domyślnego dla wszystkich środowisk):

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

development:
  <<: *default

test:
  <<: *default

production:
  <<: *default

w config/application.rb:

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

Teraz Twoja niestandardowa konfiguracja jest dostępna jak poniżej:

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

Więcej informacji

Oficjalny dokument API Railsów opisuje config_formetodę jako:

Wygoda ładowania config / foo.yml dla aktualnego środowiska Railsów.


Jeśli nie chcesz używać yamlpliku

Jak mówi oficjalny przewodnik Rails:

Możesz skonfigurować własny kod za pomocą obiektu konfiguracyjnego Railsów z niestandardową konfiguracją w ramach config.x właściwości.

Przykład

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

Te punkty konfiguracji są następnie dostępne za pośrednictwem obiektu konfiguracyjnego:

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

Oficjalne odniesienie do config_formetody | Oficjalny przewodnik po Railsach


25

Krok 1: Utwórz 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)

Krok 2: Utwórz config / config.yml

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

development:
  <<: *common

test:
  <<: *common

production:
  <<: *common

Krok 3: pobierz stałe w dowolnym miejscu kodu

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

Jak odczytujemy zmienną ENV w config.yml, moja konfiguracja jest taka sama .. dodałem zmienną w bashrc i próbuję ją odczytać w config.yml za pomocą klucza: <% = ENV [URL]%> ... to nie działa
shiva

@shiva Zajrzyj do klejnotu Figaro pod kątem zmiennych ENV. Ta konfiguracja konfiguracji dotyczy wartości, które nie muszą być ukrywane przed kontrolą źródła.
Shadoath

17

Chciałem tylko zaktualizować to, aby uzyskać najnowsze fajne rzeczy w Railsach 4.2 i 5, możesz teraz zrobić to w dowolnym ze swoich config/**/*.rbplików:

config.x.whatever = 42

(i to jest tam dosłowne x, tj. config.x.dosłownie musi być to, a potem możesz dodać cokolwiek chcesz po x)

... i będzie to dostępne w Twojej aplikacji jako:

Rails.configuration.x.whatever

Zobacz więcej tutaj: http://guides.rubyonrails.org/configuring.html#custom-configuration


3
Tylko wyjaśnienie, które początkowo sprawiło mi problem; x nie jest symbolem zastępczym tego, co chcesz wstawić, naprawdę musi to być litera x.
tobinibot

Świetna uwaga @tobinibot - dodałem to wyjaśnienie do mojej odpowiedzi, dzięki.
smathy

Ciekawe, że przewodniki właściwie nie wspominają o
Don

Masz rację Don, to dziwne - na pewno to zwykło mówić.
smathy

1
Z aktualnej dokumentacji railsów : 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).Źródło: guide.rubyonrails.org/configuring.html#custom-configuration
David Gay

6

Kilka dodatkowych informacji na ten temat:

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

„.with_indifferent_access” umożliwia dostęp do wartości w skrócie za pomocą klucza ciągu lub równoważnego klucza symbolu.

na przykład.
APP_CONFIG['audiocast_uri_format'] => 'http://blablalba/blabbitybla/yadda' APP_CONFIG[:audiocast_uri_format] => 'http://blablalba/blabbitybla/yadda'

Czysto dla wygody, ale wolę, aby moje klucze były przedstawiane jako symbole.


5

Używam czegoś podobnego do Johna dla Rails 3.0 / 3.1, ale najpierw Erb parsuje plik:

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

To pozwala mi użyć ERB w mojej konfiguracji, jeśli zajdzie taka potrzeba, na przykład odczytanie adresu URL redistogo heroku:

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

2
Myślę, że nie potrzebowałbym tego codziennie, ale jest to naprawdę fajne rozwiązanie na te czasy, kiedy tego potrzebujesz. Myślę, że zmieniłbym nazwę pliku na config.yml.erb, żeby pasowała do konwencji railsów.
Andrew Burns

2

Rails 4

Aby utworzyć niestandardową konfigurację yaml i załadować ją (i udostępnić w aplikacji) w podobny sposób database_configuration .

Utwórz swój *.yml, w moim przypadku potrzebowałem pliku konfiguracyjnego redis.

config/redis.yml

default: &default
  host: localhost
  port: 6379

development:
  <<: *default

test:
  <<: *default

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

Następnie załaduj konfigurację

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

Uzyskaj dostęp do wartości:

Rails.configuration.redis_configuration[Rails.env] podobnie jak możesz mieć dostęp do swojego database.yml przezRails.configuration.database_configuration[Rails.env]


Można również zapisać się jakiś czas tylko biorąc ustawienia dla bieżącego środowiska, które są przypuszczalnie jedynymi, czego potrzeba i tak: Rails.configuration.redis_configuration = YAML.load_file("#{Rails.root}/config/redis.yml")[Rails.env]. Jednak w przypadku railsów 4.2 i nowszych odpowiedź smathy jest prawdopodobnie prostszą drogą.
omnikron

1

Opierając się na eleganckim rozwiązaniu Omer Aslam, zdecydowałem się przekształcić klucze w symbole. Jedyna zmiana to:

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

Pozwala to na odwoływanie się do wartości za pomocą symboli jako kluczy, np

AppConfig[:twitter][:key]

Wydaje mi się to ładniejsze dla moich oczu.

(Opublikowane jako odpowiedź, ponieważ moja reputacja nie jest wystarczająco wysoka, aby skomentować odpowiedź Omera)




0

Wolę uzyskiwać dostęp do ustawień za pośrednictwem globalnego stosu aplikacji. Unikam nadmiaru zmiennych globalnych w zakresie lokalnym.

config / initializers / myconfig.rb

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

I uzyskaj do niego dostęp za pomocą.

MyAppName::Application.myconfig["yamlstuff"]

0

Mój sposób na załadowanie ustawień przed inicjalizacją Railsów

Pozwala na użycie ustawień podczas inicjalizacji Railsów i skonfigurowanie ustawień dla każdego środowiska

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

Ustawienia można uzyskać na dwa sposoby: Settings [„email”] lub Settings.email


0

Mój najlepszy sposób na konfigurację niestandardową, z komunikatem o podniesieniu, gdy brakuje pliku setting.yml.

jest ładowany z niestandardowego inicjatora w 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]

Utwórz YAML w config / setting.yml

development:
  app_id: 433387212345678
  app_secret: f43df96fc4f65904083b679412345678

test:
  app_id: 148166412121212
  app_secret: 7409bda8139554d11173a32222121212

production:
  app_id: 148166412121212
  app_secret: 7409bda8139554d11173a32222121212
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.