This project is archived and is in readonly mode.
Database config in Ruby
Reported by Adam Keys | June 3rd, 2008 @ 06:53 AM
This patch allows a developer to configure their database via Ruby in addition to the existing database.yml. First, one specifies the path to the Ruby file:
config.database_configuration_file = 'config/database.rb'
Then, you set up your database in @database.rb@:
Rails::DatabaseSpecGenerator.map do |db|
db.development :config =>
{:adapter => 'sqlite3',
:database => 'db/development.sqlite3',
:timeout => 5000}
db.test :config =>
{:adapter => 'sqlite3',
:database => 'db/test.sqlite3',
:timeout => 5000}
db.production :config =>
{:adapter => 'sqlite3',
:database => 'db/production.sqlite3',
:timeout => 5000}
end
This patch does not yet generate config/database.rb
by default, nor does it prevent you from using config/database.yml
.
Comments and changes to this ticket
-
Pratik June 3rd, 2008 @ 11:17 PM
- Assigned user set to Pratik
-
Cheah Chu Yeow June 4th, 2008 @ 06:08 AM
- no changes were found...
-
Cheah Chu Yeow June 4th, 2008 @ 04:11 PM
I like this!
I'm adding a patch based off Adam's one that would allow you to do something like this (I use defaults in YAML so this is needed for a Ruby version for me):
Rails::DatabaseSpecGenerator.map do |db| db.defaults :config => { :adapter => 'mysql', :encoding => 'utf8' } db.development :config => { :database => 'ryokan_development' }.merge(db.defaults) end
The syntax is not DSL-ish nor perfect but at least it's understandable ruby.
Also some minor tweaks like removing the @@@returning@@@ block and using File.extname to check for file extensions.
-
Adam Keys June 4th, 2008 @ 04:14 PM
I'm curious what advantages
db.defaults
has something like this:Rails::DatabaseSpecGenerator.map do |db| defaults = {:adapter => 'mysql', :encoding => 'utf8'} db.development :config => defaults.merge(:database => 'ryokan_development'} end
That said, I'm working on a somewhat different approach to this. Will post it here once I'm done.
-
Pratik June 4th, 2008 @ 10:30 PM
- Assigned user cleared.
-
Cheah Chu Yeow June 4th, 2008 @ 04:14 PM
- Assigned user cleared.
Ack sorry Adam you got me there. I was thinking of not doing it with a local var to stick to the DSL but I guess that's not very convincing. Looking forward to your different approach :)
-
Adam Keys June 6th, 2008 @ 07:05 AM
Just attached a reworked version. This time 'round, the database config hangs off of ActiveRecord itself. You can set it in your generic environment or a specific environment file. For example, in `config/environment.rb` :
config.active_record.configure do |db| db.development do |setup| socket = %w{/tmp/mysql.sock /var/run/mysql.sock}.detect do |f| File.exists?(f) end setup.database = "test_app_#{Rails.env}" setup.adapter = 'mysql' setup.socket = socket setup.credentials = "#{RAILS_ROOT}/config/credentials.rb" end db.production do |setup| socket = %w{/tmp/mysql.sock /var/run/mysql.sock}.detect do |f| File.exists?(f) end setup.database = "test_app_#{Rails.env}" setup.adapter = 'mysql' setup.socket = socket # setup.credentials = "#{RAILS_ROOT}/config/credentials.rb" end end
Or, in `config/environments/development.rb` :
config.active_record.configure do |db| db.development do |setup| setup.database = 'test_app_development' end end
Note you can set `credentials`. This loads a YAML or Ruby file with the database username/password information:
username: root password:
username = 'root' password = ''
You must use a credentials file in production, otherwise an exception is raised.
If this version looks good, I'll start on app generator changes.
-
Jeremy Kemper June 6th, 2008 @ 07:18 AM
Hey, that's pretty nice.
What's the advantage of a DSL here (config builder) over, say, assigning a hash? e.g.
config.active_record.databases = { :development => { :adapter => 'mysql', :socket => find_socket, :database => "#{test_app_#{Rails.env}", :credentials => "#{Rails.root}/config/credentials.rb" }, ...
The blocks let you delay execution, but I'm not sure that's needed.
-
Adam Keys June 6th, 2008 @ 01:01 PM
Jeremy: well in this case, having real methods makes it cleaner, IMHO, to do things like yell at the developer if they set a username/password in production mode. But really, I like the look of the block version better than a hash-y version.
As an aside, I would love to not delay execution, but AR isn't loaded when environments are evaluated.
-
Adam Keys June 6th, 2008 @ 02:52 PM
I went ahead and did the generators. Here's what it looks like for a fresh app generated for MySQL:
# Specify your database connections. You can partially configure your # your database here and then finish in an environment-specific file or # an initializer. config.active_record.configure do |db| # MySQL. Versions 4.1 and 5.0 are recommended. # # Install the MySQL driver: # gem install mysql # On Mac OS X: # sudo gem install mysql -- --with-mysql-dir=/usr/local/mysql # On Mac OS X Leopard: # sudo env ARCHFLAGS="-arch i386" gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config # This sets the ARCHFLAGS environment variable to your native architecture # On Windows: # gem install mysql # Choose the win32 build. # Install MySQL and put its /bin directory on your path. # # And be sure to use new-style password hashing: # http://dev.mysql.com/doc/refman/... db.development do |setup| setup.encoding = utf8 setup.username = root setup.password = setup.socket = /tmp/mysql.sock setup.adapter = mysql setup.database = foo_development end # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. db.test do |setup| setup.encoding = utf8 setup.username = root setup.password = setup.socket = /tmp/mysql.sock setup.adapter = mysql setup.database = foo_test end # You cannot specify the username and password for your database directly # here. You need to add those details to a credentials file that looks # like this: # # username = 'root' # password = '' # # Specify the path to your credentials file below. For more info see # http://rubyonrails.org/awesome_c... db.production do |setup| setup.encoding = utf8 setup.credentials = "/path/to/your/credentials.rb" setup.socket = /tmp/mysql.sock setup.adapter = mysql setup.database = foo_production end end
Looking for feedback on the code and/or copy.
-
Adam Keys June 8th, 2008 @ 05:54 PM
Updated patch to allow DRYer AR configuration. In
environment.rb
:config.active_record.configure do |db| db.encoding = utf8 db.adapter = 'mysql' db.socket = /tmp/mysql.sock db.database = 'foo_development' end
@development.rb@:
config.active_record.connection.configure do |db| db.username = 'root' db.password = '' db.database = 'foo_development' end
@production.rb@:
config.active_record.connection.configure do |db| db.database = 'foo_production' db.credentials = '/path/to/your/credentials.rb' end
environments.rb
is loaded first. Environment-specific files overwrite anything set previously. -
James Cox June 11th, 2008 @ 04:16 PM
I have to say that the credentials in a file means that rather than saving another file from getting checked in, what you are doing is just drying up database.yml - which is fine if it's an itch you want scratching :)
to be honest- it might be more interesting drying it up properly. Why not get opinionated and append _dev/_prod/_test to the name of your db- so in env, set db.name = "foo" and the name of each db is inferred, unless you override and explicitly set in each env?
-
Adam Keys June 11th, 2008 @ 04:31 PM
@James yeah its completely possible to define the whole thing in
environment.rb
like so:config.active_record.connection.configure do |db| db.adapter = 'mysql' db.encoding = 'utf8' db.database = "test_app_#{Rails.env}" db.socket = %w{/tmp/mysql.sock /var/run/mysql.sock}.detect do |f| File.exists?(f) end db.credentials = "#{RAILS_ROOT}/config/credentials.rb" end
You can then override anything you want (adapter, credentials, etc.) in environment-specific files.
-
Trevor Turk June 11th, 2008 @ 11:09 PM
I think this is a great direction, but I just wanted to note that using a hash might be more consistent with how email configuration works (e.g. config.action_mailer.smtp_settings)
-
Adam Keys June 11th, 2008 @ 11:31 PM
Trevor: indeed, I considered using a Hash. However, using a proper object makes it easier to yell at those who would explicitly set a username/password for their production database. ;)
-
Chad Woolley June 12th, 2008 @ 02:22 AM
-1
See comments on mailing list thread (which contains another -1 from another poster) for explanation.
-
Wesley Moxam June 12th, 2008 @ 11:08 PM
-1
It might make for a nice plugin for those who desire such a feature.
-
Pratik August 21st, 2008 @ 11:53 AM
- State changed from new to wontfix
- Tag set to activerecord, enhancement, patch, railties
Closing till there is any further progress.
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>