Czy możesz uzyskać nazwę użytkownika DB, pw, nazwę bazy danych w Railsach?

146

Piszę zadanie rake, które wykonuje jakąś pracę DB poza Railsami / ActiveRecord.

Czy istnieje sposób na uzyskanie informacji o połączeniu z bazą danych (host, nazwa użytkownika, hasło, nazwa bazy danych) dla bieżącego środowiska, zgodnie z definicją w database.yml?

Chciałbym to zdobyć, więc mogę go użyć do połączenia w ten sposób ...

con = Mysql.real_connect("host", "user", "pw", "current_db")
Ethan
źródło

Odpowiedzi:

244

Z poziomu szyn możesz utworzyć obiekt konfiguracyjny i uzyskać z niego niezbędne informacje:

config   = Rails.configuration.database_configuration
host     = config[Rails.env]["host"]
database = config[Rails.env]["database"]
username = config[Rails.env]["username"]
password = config[Rails.env]["password"]

Zobacz dokumentację Rails :: Configuration po szczegóły.

To po prostu używa YAML :: load do załadowania konfiguracji z pliku konfiguracyjnego bazy danych ( database.yml), którego możesz użyć samodzielnie, aby uzyskać informacje spoza środowiska railsowego:

require 'YAML'
info = YAML::load(IO.read("database.yml"))
print info["production"]["host"]
print info["production"]["database"]
...
Robert Gamble
źródło
27
W nowszych Railsach nie musisz tworzyć konfiguracji, możesz ją pobrać za pośrednictwemRails.configuration
Bryan Larsen
dla rails 3.0.0, require 'yaml' i YAML :: load (IO.read ("config / database.yml")) działa dobrze!
Arivarasan L
Jeśli niektóre z nich mają wartości zerowe (w moim przypadku: host, nazwa użytkownika i hasło), jakie są wartości domyślne, których użyją Railsy?
Dennis
3
Uważaj przy używaniu YAML - nowoczesne wersje Railsów również najpierw przefiltrują zawartość pliku przez ERB.
Kelvin
@BryanLarsen mógłbyś rozwinąć? ̶ ̶ ̶R̶a̶i̶l̶s̶.̶c̶o̶n̶f̶i̶g̶u̶r̶a̶t̶i̶o̶n̶̶ to co się różnić od odpowiedź? ̶ Być może odpowiedź była edytowana od oryginału. Widzę odpowiedź @KenB.
mlt
156

Odpowiedź Bryana w powyższym komentarzu zasługuje na trochę więcej uwagi:

>> Rails.configuration.database_configuration[Rails.env]
=> {"encoding"=>"unicode", "username"=>"postgres", "adapter"=>"postgresql", "port"=>5432, "host"=>"localhost", "password"=>"postgres", "database"=>"mydb", "pool"=>5}
KenB
źródło
7
Uaktualniając do Rails 4.1 na Heroku, musiałem przełączyć tę linię na: ActiveRecord :: Base.configurations [Rails.env]
quainjn
82
ActiveRecord::Base.connection_config

zwraca konfigurację połączenia w skrócie:

=> {:adapter=>ADAPTER_NAME, :host=>HOST, :port=>PORT, 
    :database=>DB, :pool=>POOL, :username=>USERNAME, 
    :password=>PASSWORD} 

Jak tpettzauważono w ich komentarzu: to rozwiązanie uwzględnia scalanie konfiguracji zi database.ymlze zmiennej środowiskowej DATABASE_URL.

qqbenq
źródło
10
Wydaje się, że jest to jedyny, który odpowiada za scalenie database.ymlkonfiguracji ze DATABASE_URLzmienną środowiskową.
tpett
Nie mogę mówić w imieniu nikogo innego, ale to jest idealne. Chciałem dwukrotnie sprawdzić programowo, czy
wskazałem
3

Myślę, że to najprostsze rozwiązanie. Po kilku testach (przynajmniej w Railsach 5.2) spowoduje to poprawne rozwiązanie DATABASE_URL.

 ActiveRecord::Base.configurations[Rails.env]
derosm2
źródło
1

Stare pytanie, ale to był jeden z moich pierwszych przystanków w szukaniu, jak to zrobić, więc myślę, że może to pomóc komuś innemu. Zwykle mam pliki .my.cnf w katalogu domowym. Tak więc użycie klejnotu „parseconfig” i jakiejś składni ERB w moim pliku konfiguracyjnym database.yml oznacza, że ​​mam plik dynamiczny, który mogę dobrze sprawdzić w kontroli źródła, a także uprościć wdrożenia (w moim przypadku). Zwróć także uwagę na listę typowych gniazd, co ułatwia przenoszenie mojej aplikacji do różnych systemów operacyjnych, które mogą mieć inną ścieżkę gniazda Unix.

<% 
    require 'parseconfig'
    c=ParseConfig.new('../../.my.cnf') %>

mysqlevn: &mysql
  adapter: mysql 
  username: <%= c.params['client']['user'] %>
  password: <%= c.params['client']['password'] %>
  host: localhost 
  socket: <%= [ 
  '/var/run/mysqld/mysqld.sock',
  '/var/lib/mysql/mysql.sock',
  '/tmp/mysqld.sock',
  '/tmp/mysql.sock'].detect { |socket| File.exist?(socket) } %>

production:
  database: app_production
  <<: *mysql


development:
  database: app_development 
  <<: *mysql

# Do not set this db to the same as development or production.
test:
  database: app_test
  <<: *mysql

ref: http://effectif.com/articles/database-yml-should-be-checked-in

edwardsharp
źródło