Out with database.yml

23 views
Skip to first unread message

Adam Keys

unread,
Jun 11, 2008, 9:39:55 AM6/11/08
to rubyonra...@googlegroups.com
In short: With the help of the friendly folks in #rails-contrib, I've
been working on a patch that provides Ruby configuration of your
database connections. I'm looking for people to test the patch and
post +1s if it works for them. You can find the patch in Lighthouse: http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/312
(its the last attachment, dry_database_config.diff)

## What's it look like?

In config/environment.rb:

> config.active_record.connection.configure do |db|
> db.adapter = 'mysql'
> db.encoding = 'utf8'
> end

In config/development.rb:

> config.active_record.connection.configure do |db|
> db.database = 'test_app_development'
> db.socket = '/tmp/mysql.sock'
> db.username = 'root'
> db.password = ''
> end

So the short of it is that you configure global stuff in
environment.rb and environment-specific stuff in the respective files.
This generates the connection-specification hashes that
ActiveRecord::Base.establish_connection expects.

## Why change?

database.yml is workable, but its a little weird at this point. There
is no other instance of YAML configuration in one's app when it runs
in production. This approach also lets you significantly DRY up your
configuration. Its even possible to specify the entire configuration
in environment.rb.

Idatabase.yml is still loaded if you don't specify the database
connection in your environment files. I wouldn't up and take it away
from you like that. :)

## Securing your database credentials

We all know its a good idea to keep your database credentials
(username/password) out of source control. This patch supports that
raising an exception if you try to set your username or password in a
production setting. Instead, you specify a credentials file like so:

> config.active_record.configure do |db|
> db.database = 'test_app_production'
> db.socket = '/var/run/mysql.sock'
> db.credentials = "#{RAILS_ROOT}/config/credentials.rb"
> end

The preferred credential format is Ruby, like so:

> username = 'root'
> password = ''

YAML is also supported:

> username: root
> password:

## Other bits and bobs

I also patched the application generator to produce an app with no
database.yml. Database config bits are added to environment.rb. The
adapter-specific comments get added in environment.rb.

## Did I mention I'm looking for +1s

Yes, the pandering is strong with this one. Grab
dry_database_config.diff from http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/312
and give it a spin.

Thanks in advance!

--
~akk
http://therealadam.com

Mislav Marohnić

unread,
Jun 11, 2008, 10:12:46 AM6/11/08
to rubyonra...@googlegroups.com
What I like with database.yml is that I don't version it and therefore I don't keep production passwords in version control. Also I can have one database in production locally and another on the remote machine.

Adam Keys

unread,
Jun 11, 2008, 11:04:34 AM6/11/08
to rubyonra...@googlegroups.com
On Jun 11, 2008, at 9:12 AM, Mislav Marohnić wrote:

> What I like with database.yml is that I don't version it and
> therefore I don't keep production passwords in version control. Also
> I can have one database in production locally and another on the
> remote machine.
>


I've done that too. You could get that effect like so:

> config.active_record.connection.configure do |db|
> case `hostname`
> when 'my_laptop'
> db.host = 'localhost'
> when 'production'
> db.host = 'db1'
> end
> end

Or you can stick with database.yml :)
--
~akk
http://therealadam.com

Mislav Marohnić

unread,
Jun 11, 2008, 12:41:57 PM6/11/08
to rubyonra...@googlegroups.com
On Wed, Jun 11, 2008 at 17:04, Adam Keys <ad...@therealadam.com> wrote:

Or you can stick with database.yml :)

I will stick with yml for sure and I guess most of experienced devs will also keep their copies because, now that we have deployment set up, there is no compelling reason for us to switch. 

But I'm worried what about new users? This pratice encourages them to version their passwords. Rails is opinionated and we have to choose which practice we will encourage. Will it be database info in ruby or YAML?

Ben Munat

unread,
Jun 11, 2008, 12:55:22 PM6/11/08
to rubyonra...@googlegroups.com

I don't understand how a Ruby config encourages versioning passwords
more than using the yaml file. Either way you can svn/git ignore the
file with the passwords.

However, the main benefit of switching to a Ruby config file seems to be
"because database.yml was the only yaml config file", which doesn't seem
like a particularly great reason.

On the other hand, I like this just because I find the Ruby syntax more
clearly indicates what you are doing, whereas the yaml is pure data that
is sucked up into some mysterious place inside Rails. So I guess that's
more than a "just because it's not yaml" reason.

Ben

Adam Keys

unread,
Jun 11, 2008, 1:03:37 PM6/11/08
to rubyonra...@googlegroups.com
On Jun 11, 2008, at 11:41 AM, Mislav Marohnić wrote:
> But I'm worried what about new users? This pratice encourages them
> to version their passwords. Rails is opinionated and we have to
> choose which practice we will encourage. Will it be database info in
> ruby or YAML?
>

I don't think this encourages new users to version their passwords any
more than they are now. In fact, because there is no username/password
generated in the production config, I think it guides them towards
_not_ versioning their *production* credentials. If you try to set
username/password directly in your production configuration, the
application won't start.

Those taking the path of least resistance will generate their app, get
something small working and then check it in. When they get to the
point where they want to deploy, they will have to either add a
credentials file to source control (the bad route) or tweak their
deploy script to symlink the credentials (the good route).

Perhaps generated applications could have more verbiage encouraging
developers to store their credentials outside of source control and
link it into the application at deploy-time? Besides that, there's
only so much vinegar and hand-holding one can apply. ;)

--
~akk
http://therealadam.com

Adam Keys

unread,
Jun 11, 2008, 1:08:42 PM6/11/08
to rubyonra...@googlegroups.com
On Jun 11, 2008, at 11:55 AM, Ben Munat wrote:
>
> On the other hand, I like this just because I find the Ruby syntax
> more
> clearly indicates what you are doing, whereas the yaml is pure data
> that
> is sucked up into some mysterious place inside Rails. So I guess
> that's
> more than a "just because it's not yaml" reason.
>

"No more YAML" is certainly the Reddit-friendly reason for this patch.
Ousting YAML+ERB tricks is just the humane thing to do. :)

However, the reason I really like this approach is that it cleans up
clever configurations. People have been using File.exists? to figure
out which MySQL socket to use within ERB blocks in database.yml for a
long time. This makes those sorts of idioms easier to read and write.
As the name of the patch implies, this approach is also considerably
DRYer. If you want, you can define everything in environment.rb and
move on.

--
~akk
http://therealadam.com

Scott Bronson

unread,
Jun 11, 2008, 5:16:13 PM6/11/08
to rubyonra...@googlegroups.com
On Wed, Jun 11, 2008 at 9:55 AM, Ben Munat <bmu...@gmail.com> wrote:
> However, the main benefit of switching to a Ruby config file seems to be
> "because database.yml was the only yaml config file", which doesn't seem
> like a particularly great reason.

That sounds like a great reason to me. Why pull in a whole different
technology just to read a 6-line file?? (maybe that's what you were
meaning when you said YAML was a mysterious place inside Rails?)


Or, easily work around wandering mysql socket locations (excuse the junk code):

config.active_record.connection.configure do |db|
db.adapter = 'mysql'

sockets = %w(/var/run/mysqld/mysqld.sock
/var/lib/mysql/mysql.sock /tmp/mysql.sock)
db.socket = sockets.find { |f| File.exist?(f) }
end


Does anyone even use YAML anymore? My projects are mostly JSON, a
little XML, and zero YAML. database.yml is an an anachronism. Why
keep this legacy inside Rails?

Great work Adam. I'll be installing your patch as I move projects to
Rails 2.1 and I sure hope it moves upstream quickly.

- Scott

Matt Palmer

unread,
Jun 11, 2008, 8:58:43 PM6/11/08
to rubyonra...@googlegroups.com
On Wed, Jun 11, 2008 at 12:08:42PM -0500, Adam Keys wrote:
> As the name of the patch implies, this approach is also considerably
> DRYer. If you want, you can define everything in environment.rb and
> move on.

I'm not sure how you're repeating yourself by putting the database config in
a separate file. Where's the repetition?

If anything, this patch is anti-DRY because it locks up the database config
in a place that can only be read by Rails. If you've got anything other
than Rails that wants to talk to the database (cron jobs, other apps,
whatever) YAML is a far better way to store your credentials than a chunk of
Rails code (it's not even plain Ruby, because you need umpteen lines of
scaffolding to evaluate it and get the values out of it). Practically
anything can parse YAML, nothing except Rails can parse Rails.

I'm -1 on this patch because it'll almost certainly make my life harder
trying to host apps that use this convention.

- Matt

--
"I invented the term object-oriented, and I can tell you I did not have C++
in mind." -- Alan Kay

Matt Palmer

unread,
Jun 11, 2008, 9:00:59 PM6/11/08
to rubyonra...@googlegroups.com
On Wed, Jun 11, 2008 at 02:16:13PM -0700, Scott Bronson wrote:
>
> On Wed, Jun 11, 2008 at 9:55 AM, Ben Munat <bmu...@gmail.com> wrote:
> > However, the main benefit of switching to a Ruby config file seems to be
> > "because database.yml was the only yaml config file", which doesn't seem
> > like a particularly great reason.
>
> That sounds like a great reason to me. Why pull in a whole different
> technology just to read a 6-line file?? (maybe that's what you were
> meaning when you said YAML was a mysterious place inside Rails?)
>
> Or, easily work around wandering mysql socket locations (excuse the junk code):

Or you can configure your MySQL installation properly, and put the socket
location in the global my.cnf file, as $DEITY intended.

- Matt

--
A friend is someone you can call to help you move. A best friend is someone
you can call to help you move a body.

Chad Woolley

unread,
Jun 11, 2008, 9:22:41 PM6/11/08
to rubyonra...@googlegroups.com
On Wed, Jun 11, 2008 at 5:58 PM, Matt Palmer <mpa...@hezmatt.org> wrote:
> If anything, this patch is anti-DRY because it locks up the database config
> in a place that can only be read by Rails. If you've got anything other
> than Rails that wants to talk to the database (cron jobs, other apps,
> whatever) YAML is a far better way to store your credentials than a chunk of
> Rails code (it's not even plain Ruby, because you need umpteen lines of
> scaffolding to evaluate it and get the values out of it). Practically
> anything can parse YAML, nothing except Rails can parse Rails.

-1

I agree. We have utilities which parse database.yml for rake tasks
and other batch jobs. An example (which we use on a daily basis) is a
utility to automatically pull and import a production database to the
local dev database, for easy testing against production data.

database.yml is metadata about an external resource. It makes sense
to put that metadata in a DRY, easily-parsable format which can be
used by things other than the Rails app itself.

As the previous poster mentioned, I can imagine this approach making
life harder for many rails hosting providers as well. I don't think
this is a good approach to encourage or propogate.

-- Chad

Scott Bronson

unread,
Jun 11, 2008, 9:22:52 PM6/11/08
to rubyonra...@googlegroups.com
On Wed, Jun 11, 2008 at 5:58 PM, Matt Palmer <mpa...@hezmatt.org> wrote:
> If anything, this patch is anti-DRY because it locks up the database config
> in a place that can only be read by Rails...

The beauty of this patch is that now the database config can be read
from anywhere.

If you still want to read your config from a YAML file, nothing's
stopping you. I presume you could do something like this:

require 'yaml'
db.merge(YAML::load(File.open('database.yml')))

And it's just as easy to store your database config in XML, CSV, LDAP,
or another database. Your deployment options are wide open. Really,
this patch frees the database config. Where's the downside?

- Scott

Chad Woolley

unread,
Jun 11, 2008, 9:25:01 PM6/11/08
to rubyonra...@googlegroups.com
On Wed, Jun 11, 2008 at 6:22 PM, Scott Bronson <bro...@rinspin.com> wrote:
> And it's just as easy to store your database config in XML, CSV, LDAP,
> or another database. Your deployment options are wide open. Really,
> this patch frees the database config. Where's the downside?

Because then it is nonstandard (again, making it hard for hosting
companies to provide standardized auto-deployment).

Convention over configuration.

-- Chad

Ryan Bigg (Radar)

unread,
Jun 11, 2008, 9:55:01 PM6/11/08
to rubyonra...@googlegroups.com
- 1

How about we store the configuration in a c program, which rails has to compile and then execute in order to read the correct data?

What I'm trying to say is that this process doesn't seem dryer at all. The YAML file has become the standard and many, many tutorials reference this. Do you not remember the uproar about scaffolding?

Please, for the sake of sanity, do not change this from the old way unless you have a better reason than "It's DRYer"

Matt Palmer

unread,
Jun 11, 2008, 10:55:54 PM6/11/08
to rubyonra...@googlegroups.com

It's different to every piece of documentation that is already out there,
and it breaks Rails' motto of convention over configuration.

- Matt

--
"The user-friendly computer is a red herring. The user-friendliness of a
book just makes it easier to turn pages. There's nothing user-friendly about
learning to read."
-- Alan Kay

DHH

unread,
Jun 11, 2008, 10:56:05 PM6/11/08
to Ruby on Rails: Core
> Please, for the sake of sanity, do not change this from the old way unless
> you have a better reason than "It's DRYer"

I think that's a perfectly valid reason. Not just that it's more dry,
but that it unifies configuration of the database along side the
configuration of everything else. The special treatment for
database.yml is completely unnecessary and sticks out like a wart to
me these days.

This change isn't going in for 2.1.x but either for 2.2 or 3.0
(whichever the next big release will be, my guess is 3.0). And it's
not going to change anything for existing applications. And it
encourages the good form of separating your credentials from your
configuration.

So it's all cheers from me to Adam for finally cleaning up this piece
of my personal indulgence with "let's try to use YAML for something".

Frederick Cheung

unread,
Jun 12, 2008, 4:00:31 AM6/12/08
to rubyonra...@googlegroups.com

On 12 Jun 2008, at 03:56, DHH wrote:

>
>> Please, for the sake of sanity, do not change this from the old way
>> unless
>> you have a better reason than "It's DRYer"
>

Just for the sake of argument, yaml configs don't have to be repetitive:

defaults: &defaults
adapter: mysql
encoding: utf8
username: rota
password:
host: localhost

development:
<<: *defaults
database: rota_development

test:
<<: *defaults
database: rota_test

but this is quite underused (making the default generated database.yml
look like this was discussed a while back)

Fred

Rick Olson

unread,
Jun 12, 2008, 6:47:46 AM6/12/08
to rubyonra...@googlegroups.com
> Just for the sake of argument, yaml configs don't have to be repetitive:
>
> defaults: &defaults

That's also a lot harder to read and write, especially for newbies. I
definitely support an all-ruby approach. Supporting some generic hash
merging, as Scott suggested, might not be a bad idea though.

In a similar vein: last night at the Baltimore ruby group, John
Trupiano suggested some way of merging the yml files from the
geminstaller gem with Rails' gem configurations.

--
Rick Olson
http://lighthouseapp.com
http://weblog.techno-weenie.net
http://mephistoblog.com

Chad Woolley

unread,
Jun 12, 2008, 10:28:47 AM6/12/08
to rubyonra...@googlegroups.com
On Thu, Jun 12, 2008 at 3:47 AM, Rick Olson <techno...@gmail.com> wrote:
> In a similar vein: last night at the Baltimore ruby group, John
> Trupiano suggested some way of merging the yml files from the
> geminstaller gem with Rails' gem configurations.

I've wanted to provide a non-YAML config option for GemInstaller for a
while, but it is down on the priority list. And, as pointed out, if
the config is in Ruby (as it is with config.gems), then it's still
easy to parse a YAML file (such as geminstaller.yml) to generate that
config. That's probably the best approach to support what John
wanted, and would be cool to have in Rails by default (patch
someone?!?)

After reading this thread, I'm convinced that both Ruby and YAML
config should be supported (so I retract my -1 if that will be the
case). All-ruby config is cool and nice, but for metadata describing
external dependencies (Gems, Databases), there should be a
STANDARDIZED, easily parsable, non-Ruby format supported as well.

So, I hope Rails still natively supports the old YAML format after
this patch, to support old tutorials, and to provide a standardized
option when it is needed, such as Rails parsing geminstaller.yml if it
exists, or a hosting company parsing geminstaller.yml or database.yml
to auto-configure whatever...

Also, I still don't think either option is DRY-er than the other,
because YAML supports reuse, as was just pointed out.

-- Chad

John Trupiano

unread,
Jun 12, 2008, 10:45:02 AM6/12/08
to Ruby on Rails: Core
Considering Rick referenced me, and I've made nary an appearance on
this particular list, I figured I'd chime in. I like YAML as a
portable format. It's not uncommon (especially for us) to have
solutions that aren't completely ruby/rails, and where it's helpful to
have portable configuration.

That said, I wouldn't be opposed to adding a config hook as
suggested....just as long as that config hook allowed me to specify
that I wanted my configuration read from a YAML file.

This is, in fact, the same idea Rick mentioned that I proposed. I
suggested moving gem configuration out into a YAML file (or at least
adding a hook for this). Why? Because then capistrano could read in
that file and ensure that deployment environments have the proper
versions of gems, etc. In other words, I could stop a sure-to-fail
deployment before I actually re-deploy. (There's a lot more to this,
but not so much core-related) I had proposed a config extension along
the lines of:

config.gem_file "config/gems.yml"

This would just parse the the gems and basically iteratively run
config.gem on each of them. So how is this helpful? Well my gem
configuration is in one place outside of the scope of Rails. Consider
the scenario where a company is managing dozens (or hundreds) of
apps. You could write a simple script that would inspect all of these
YAML files. This would allow you to react to new releases of major
gems (oh crap, there's a new haml for instance). You could then have
a handle of which apps are falling behind w.r.t. maintenance, etc.

Ultimately, I'm just reiterating the desire to have
"configuration" (which is what this ugly crap is, and something
convention surely can't solve) in portable formats.

I'd be happy to continue any non-core specific discussions in #rails-
contrib if anyone's interested. I should be back in this afternoon.

-John

Sam Granieri

unread,
Jun 12, 2008, 11:07:48 AM6/12/08
to rubyonra...@googlegroups.com
Why was yaml used in the first place?

Adam Keys

unread,
Jun 12, 2008, 11:58:06 AM6/12/08
to rubyonra...@googlegroups.com
On Jun 12, 2008, at 5:47 AM, Rick Olson wrote:
>> That's also a lot harder to read and write, especially for
>> newbies. I
> definitely support an all-ruby approach. Supporting some generic hash
> merging, as Scott suggested, might not be a bad idea though.
>

Something like this is ugly, but does the job:

config.active_record.connection.configure do |db|
YAML.load(ERB.new(File.read('config/database.yml').result))
[Rails.env].each_pair do |key, value|
db.send("#{key}=", value)
end
end

--
~akk
http://therealadam.com

Adam Keys

unread,
Jun 12, 2008, 12:00:14 PM6/12/08
to rubyonra...@googlegroups.com
On Jun 12, 2008, at 9:28 AM, Chad Woolley wrote:
>
> So, I hope Rails still natively supports the old YAML format after
> this patch, to support old tutorials, and to provide a standardized
> option when it is needed, such as Rails parsing geminstaller.yml if it
> exists, or a hosting company parsing geminstaller.yml or database.yml
> to auto-configure whatever...
>

To clarify, my patch tries to load database.yml if you don't set
anything in your environment.

> Also, I still don't think either option is DRY-er than the other,
> because YAML supports reuse, as was just pointed out.


I was perhaps overzealous in declaring Ruby DRYer than YAML. That
said, I think more people know how to DRY up Ruby than YAML. ;)

--
~akk
http://therealadam.com

Chad Woolley

unread,
Jun 12, 2008, 12:02:13 PM6/12/08
to rubyonra...@googlegroups.com
On Thu, Jun 12, 2008 at 7:45 AM, John Trupiano <jtru...@gmail.com> wrote:
> This is, in fact, the same idea Rick mentioned that I proposed. I
> suggested moving gem configuration out into a YAML file (or at least
> adding a hook for this). Why? Because then capistrano could read in
> that file and ensure that deployment environments have the proper
> versions of gems, etc. In other words, I could stop a sure-to-fail
> deployment before I actually re-deploy. (There's a lot more to this,
> but not so much core-related) I had proposed a config extension along
> the lines of:
>
> config.gem_file "config/gems.yml"

Totally off topic at this point, sorry, but anyway...

John and I hacked on this a bit this morning. The conclusion is that
there is no reason to do what he said above. GemInstaller.autogem
already does everything you want if you desire to manage your gems
from YAML. See:

http://geminstaller.rubyforge.org/faq.html#rails_config_gems
http://geminstaller.rubyforge.org/documentation/tutorials.html#integrating_geminstaller_into_ruby_on_rails

Thanks!
-- Chad

James Adam

unread,
Jun 12, 2008, 12:40:37 PM6/12/08
to rubyonra...@googlegroups.com
On Wed, Jun 11, 2008 at 2:39 PM, Adam Keys <ad...@therealadam.com> wrote:
> ## What's it look like?
>
> In config/environment.rb:
>
>> config.active_record.connection.configure do |db|
>> db.adapter = 'mysql'
>> db.encoding = 'utf8'
>> end
>
> In config/development.rb:
>
>> config.active_record.connection.configure do |db|
>> db.database = 'test_app_development'
>> db.socket = '/tmp/mysql.sock'
>> db.username = 'root'
>> db.password = ''
>> end
>

I don't really mind dropping the YAML configuration, but is there any
reason you aren't just using a regular Hash? i.e.

## environment.rb

config.active_record.connection = {
:adapter => 'mysql',
....
}


## environments/development.rb

config.active_record.connection.merge {
:database => 'my_app_dev',
:username => 'dev',
:password => 'password'
}


(note the merge in specific environments)

I guess this boils down to - why generate the Hash, when just writing
the Hash is pretty much equally readable? Do we get some benefit using
the block/DSL-style syntax? If not, the implementation could perhaps
be simpler.

--
* J *
~

Adam Keys

unread,
Jun 12, 2008, 1:01:42 PM6/12/08
to rubyonra...@googlegroups.com
On Jun 12, 2008, at 11:40 AM, James Adam wrote:
>
> I guess this boils down to - why generate the Hash, when just writing
> the Hash is pretty much equally readable? Do we get some benefit using
> the block/DSL-style syntax? If not, the implementation could perhaps
> be simpler.
>

Running it through a proxy makes it easier to yell at the user when
they try to set username/password in production. Also, credentials is
handled differently from the other attributes. One could do all that
with a Hash, but why apply behavior to data when you can bundle the
data with the behavior?

--
~akk
http://therealadam.com

DHH

unread,
Jun 12, 2008, 3:38:08 PM6/12/08
to Ruby on Rails: Core
> Why was yaml used in the first place?

Because I thought dammit, we gotta use YAML for something -- aka not a
good reason at all ;)

Duncan Beevers

unread,
Jun 12, 2008, 3:54:14 PM6/12/08
to rubyonra...@googlegroups.com
Reading the database configuration in for use in the db:console will
now require loading the entire framework! Sweet!

Ezra Zygmuntowicz

unread,
Jun 12, 2008, 4:13:48 PM6/12/08
to rubyonra...@googlegroups.com


I have to chime in here and plead for you to leave the database.yml
alone. Or if you must use ruby config, please leave the db.yml
working. If the credentials/config is only in ruby and in the local
variable format you showed earlier, then other tools from other
languages are going to not be able to read this stuff in easily. Heck
in that format even ruby cannot read the credentials in without
loading rails and using eval hackery to make the local variables
available outside of the file they are in.

I see significant downsides to the pure ruby config:

1. cannot read from non ruby languages.
2. now we have to load the entire rails environment just to get all
the db config, this adds needless overhead to what is currently an
easy task
3. ruby config spread out over multiple environment files as well as a
credential file is going to hamper server automation in a serious way.
4. there are countless daemons and plugins that read the database.yml
to get the db config info. how will these daemons now get said info
without loading all of the rails environment?

I thought rails was all about not breaking backwards compatibility
unless there is a very good reason? What is the very good reason to
make deployment more difficult? What does this gain us must be weighed
against what we lose with the ruby config.

-1

Thanks

- Ezra Zygmuntowicz
-- Founder & Software Architect
-- ez...@engineyard.com
-- EngineYard.com

Adam Keys

unread,
Jun 12, 2008, 4:25:55 PM6/12/08
to rubyonra...@googlegroups.com
On Jun 12, 2008, at 3:13 PM, Ezra Zygmuntowicz wrote:
> I have to chime in here and plead for you to leave the database.yml
> alone. Or if you must use ruby config, please leave the db.yml
> working. If the credentials/config is only in ruby and in the local
> variable format you showed earlier, then other tools from other
> languages are going to not be able to read this stuff in easily. Heck
> in that format even ruby cannot read the credentials in without
> loading rails and using eval hackery to make the local variables
> available outside of the file they are in.
>

*The patch leaves database.yml alone.* If no database configuration is
done in the environment, Rails still looks in database.yml.

> I see significant downsides to the pure ruby config:

It seems there are a lot of deployment-time concerns here. Would it
help if there was a Rake task to dump database.yml for a given
environment?

> I thought rails was all about not breaking backwards compatibility
> unless there is a very good reason? What is the very good reason to
> make deployment more difficult? What does this gain us must be weighed
> against what we lose with the ruby config.

What part of deploying a typical Rails app is made more difficult? If
anything, I'd think the external credential file makes things easier
than it was before.

--
~akk
http://therealadam.com

Lance Carlson

unread,
Jun 12, 2008, 4:53:10 PM6/12/08
to rubyonra...@googlegroups.com
I am also skeptical about this switch. It works as is, and supporting
both methods will just confuse people. Ezra's point about formatting
is also a good point. Most other languages have a yaml parsing
library, but if they have to parse a ruby config, it's not really an
elegant solution. If we are going to do this for sure, I'd say a rake
task is essential, but even then I think the yaml file alone is
perfect for what it does.

-1

Jack Danger Canty

unread,
Jun 12, 2008, 5:03:15 PM6/12/08
to rubyonra...@googlegroups.com
>       I see significant downsides to the pure ruby config:

It seems there are a lot of deployment-time concerns here. Would it
help if there was a Rake task to dump database.yml for a given
environment?

The assumption here is that all servers in a given environment are configured with the same db credentials.  That's usually but not always true.

The database.yml file is a pure configuration file and it covers a very specific domain.  It doesn't make sense to me that it would be rubified just to be consistent with the rest of the initialization process.

Has anyone actually needed this ruby database configuration functionality?

 -1

::Jack Danger

Sam Granieri, Jr

unread,
Jun 12, 2008, 5:12:10 PM6/12/08
to rubyonra...@googlegroups.com
Duncan Beevers wrote:
> Reading the database configuration in for use in the db:console will
> now require loading the entire framework! Sweet!

I think Duncan has a good, albeit snarky, point. If we do switch to the
ruby-based config we have to make sure that we dont slow other parts of
the framework.

Sam Granieri, Jr

unread,
Jun 12, 2008, 5:30:00 PM6/12/08
to rubyonra...@googlegroups.com
Ezra Zygmuntowicz wrote:
>
> I see significant downsides to the pure ruby config:
>
> 4. there are countless daemons and plugins that read the database.yml
> to get the db config info. how will these daemons now get said info
> without loading all of the rails environment?
>
> I thought rails was all about not breaking backwards compatibility
> unless there is a very good reason? What is the very good reason to
> make deployment more difficult? What does this gain us must be weighed
> against what we lose with the ruby config.
>
> -1

On further thought, I think we should just stay with the yaml file.

I have to give a -1 to the possiblity of using both the ruby and yaml
methods. It isnt DRY.

I think DHH unintentionally did the right thing when he kept the db
config out of ruby.

matthew deiters

unread,
Jun 12, 2008, 6:10:32 PM6/12/08
to rubyonra...@googlegroups.com
-1

If the database credentials reside in the ruby environment files then
we would be committing our database passwords into the repository.
Anyone with read access to the source code now has credentials to the
db. I'm skeptical of overly paranoid security measures, but this to me
this just seems blatantly a bad practice.

Chad Woolley

unread,
Jun 12, 2008, 6:23:14 PM6/12/08
to rubyonra...@googlegroups.com
On Thu, Jun 12, 2008 at 1:25 PM, Adam Keys <ad...@therealadam.com> wrote:
> It seems there are a lot of deployment-time concerns here. Would it
> help if there was a Rake task to dump database.yml for a given
> environment?

This ALMOST sounds like a good idea, but this really would be non-DRY,
in a dangerous way. Is the database.yml I dumped (or someone else
dumped) up-to-date? How do I know? When do I re-dump? Who re-dumps?

Scott Bronson

unread,
Jun 12, 2008, 6:37:45 PM6/12/08
to rubyonra...@googlegroups.com
On Thu, Jun 12, 2008 at 3:10 PM, matthew deiters <mdei...@gmail.com> wrote:
> If the database credentials reside in the ruby environment files then
> we would be committing our database passwords into the repository.

There's no reason to keep the database credentials in environment.rb.
Just throw them in a separate file, say database.rb, and ignore that
the way you currently do database.yml.

What's nice about this patch is that you can put the global configs in
environment.rb (UTF8, db host, database name) and leave just the
sensitive ones out of source control (username, password).

And, of course, many databases don't have any sensitive credentials to
worry about, like sqlite3.

- Scott

matthew deiters

unread,
Jun 12, 2008, 6:47:02 PM6/12/08
to rubyonra...@googlegroups.com
Awesome - so I get to distribute the concept of database configuration
into multiple files. Best yet each rails project can come up with it's
own conventions on what it should call this file and what should go in
it.

Scott Bronson

unread,
Jun 12, 2008, 6:54:55 PM6/12/08
to rubyonra...@googlegroups.com
On Thu, Jun 12, 2008 at 3:47 PM, matthew deiters <mdei...@gmail.com> wrote:
> Awesome - so I get to distribute the concept of database configuration
> into multiple files.

You do currently. Is that a problem?


> Best yet each rails project can come up with it's
> own conventions on what it should call this file and what should go in
> it.

Yep! Because each rails project best understands its own needs and
requirements.

I expect most Rails devs will continue to use database.yml the way
they currently do. There's no reason to break backward compatibility
but there's every reason to allow forward progress.

- Scott

Lawrence Pit

unread,
Jun 12, 2008, 7:04:15 PM6/12/08
to rubyonra...@googlegroups.com

> What's nice about this patch is that you can put the global configs in
> environment.rb (UTF8, db host, database name) and leave just the
> sensitive ones out of source control (username, password).
>

This argument has been given a few times. Am I the only one who
considers the db host en database name to be just as security sensitive
as the username and password? Why would I tell anyone that the safe is
located behind the Van Gogh painting I've got hanging here?

Lawrence

Jack Danger Canty

unread,
Jun 12, 2008, 7:11:20 PM6/12/08
to rubyonra...@googlegroups.com
On Thu, Jun 12, 2008 at 3:37 PM, Scott Bronson <bro...@rinspin.com> wrote:

On Thu, Jun 12, 2008 at 3:10 PM, matthew deiters <mdei...@gmail.com> wrote:
> If the database credentials reside in the ruby environment files then
> we would be committing our database passwords into the repository.

What's nice about this patch is that you can put the global configs in
environment.rb (UTF8, db host, database name) and leave just the
sensitive ones out of source control (username, password).

Is there a real use case for the Ruby config?  Anyone have a story of something they could do with the .rb and not do with the .yml?

::Jack Danger

Scott Bronson

unread,
Jun 12, 2008, 7:15:23 PM6/12/08
to rubyonra...@googlegroups.com
On Thu, Jun 12, 2008 at 4:04 PM, Lawrence Pit <lawren...@gmail.com> wrote:
>> What's nice about this patch is that you can put the global configs in
>> environment.rb (UTF8, db host, database name) and leave just the
> This argument has been given a few times. Am I the only one who
> considers the db host en database name to be just as security sensitive
> as the username and password? Why would I tell anyone that the safe is
> located behind the Van Gogh painting I've got hanging here?

To keep this discussion on track, forget I said that abou the db host
and db name. :) But there's no reason to keep the adaptor, encoding,
or socket location secret.

(In theory, if your safe is secure, it doesn't matter if the thief
knows where it is. It doesn't even matter if he knows how it's built.
In practice, I agree that every little bit helps, even the most
incidental bit of obscurity.)

- Scott

Lawrence Pit

unread,
Jun 12, 2008, 7:53:26 PM6/12/08
to rubyonra...@googlegroups.com

> To keep this discussion on track, forget I said that abou the db host
> and db name. :) But there's no reason to keep the adaptor, encoding,
> or socket location secret.
>
>

I don't want you to know /anything/ about the databases I'm using.
Including the adapter and socket location(s) (if I have them at all,
which I won't tell you ;).

> (In theory, if your safe is secure, it doesn't matter if the thief
> knows where it is. It doesn't even matter if he knows how it's built.
> In practice, I agree that every little bit helps, even the most
> incidental bit of obscurity.)
>

It does matter, because you can damage the safe without actually
cracking the code making the safe inaccessible to the owner.

My point is that I don't want /any/ info wrt the production databases
under source control. I don't see how moving stuff into ruby code adds
any value. It's not like there's something dynamic going on for which
you need the power of ruby.

Lawrence

Lawrence Pit

unread,
Jun 12, 2008, 8:10:54 PM6/12/08
to rubyonra...@googlegroups.com

Btw, what about email credentials? Currently the only way to define the
smtp_settings for ActionMailer::Base is via ruby code. If we're sticking
to database.yml, shouldn't we have an email.yml as well?


sure, I can do e.g.:

ActionMailer::Base.smtp_settings = YAML::load(ERB.new(IO.read(RAILS_ROOT
+ "/config/email.yml")).result)[env]

in my environment.rb, but then I can do that for database.yml as well if
that was what's needed.


Lawrence

Michael Schoen

unread,
Jun 12, 2008, 8:17:32 PM6/12/08
to rubyonra...@googlegroups.com

On Jun 12, 2008, at 1:13 PM, Ezra Zygmuntowicz wrote:
> I see significant downsides to the pure ruby config:
>
> 1. cannot read from non ruby languages.

I concur with Ezra on this. It's very nice to have the database config
in a single place that other applications in other languages can
easily reference.


Ryan Bigg (Radar)

unread,
Jun 12, 2008, 8:26:37 PM6/12/08
to rubyonra...@googlegroups.com
Sure you can.

It'll just be a larger pain in the ass.
--
Appreciated my help?
Recommend me on Working With Rails
http://workingwithrails.com/person/11030-ryan-bigg

zilkey

unread,
Jun 13, 2008, 3:44:18 AM6/13/08
to Ruby on Rails: Core
http://slantwisedesign.com/rdoc/yaml_mail_config/ puts email config in
yaml, ferret and backgroundrb store their info in yml and on occasion
I've stored environment-specific config code in yaml.

Is the ruby config released as a gem? If not, I suggest that you
release it as a gem. Bonus points if it has a generator that creates
the necessary files (newgem rocks for creating things like that).

I think will_paginate should be in core, but it's not, and I have to
config.gem it to every app I have, but I don't mind since it's so
hip. If people think ruby database configs are hip, they won't mind
adding a line to each new app they have and running a generator.

Personally I don't see the need for it, and I probably wouldn't
install the gem. Further, if rails shipped with it I'd probably opt
to keep using yaml just because I've got several apps with capistrano
recipes and backup scripts that I like to keep them up to date with
the latest released version of rails.

James Adam

unread,
Jun 13, 2008, 5:27:04 AM6/13/08
to rubyonra...@googlegroups.com

If the behaviour you mean is simply to ensure that production
credentials are loaded from an external file, there are surely simpler
ways of doing this than building a Ruby DSL (loathe as I am to use
that word, but you get what I mean).

My concern is that this is *too much solution*, even for the benefits
that it claims, and keeping Rails lithe and slim should be a priority.

The problems with the current setup need to be much clearer -
"database.yml is workable, but its a little weird at this point" isn't
sufficient reason to change, IMHO. Weird how? I'm not suggesting that
it isn't weird, but we should have some explicit reasons or examples.

Likewise, "there is no other instance of YAML configuration in one's
app when it runs
in production" is a bit misleading: the database is the *only common
external dependency* in a Rails application. It is a description of
something outside of the Ruby process (unlike any ruby libraries or
frameworks you might be loading). If every Rails application had to
also interface with, say, Solr, we'd probably have a config/solr.yml
file too.

As Frederick Cheung points out, another solution to the "DRY" concern
is using YAML in a smarter way. Rick suggested that "[it's] a lot
harder to read and write, especially for newbies", but we could solve
that by providing comments in the file to educate. Making the change
to a ruby-based configuration will still confuse newbies, thanks to
Google and all the tutorial pages that won't be updated.

In a nutshell, lets be sure that we're solving genuine problems and/or
providing tangible benefits, before we make the framework that little
bit more complicated.

Neil Wilson

unread,
Jun 13, 2008, 5:46:28 AM6/13/08
to Ruby on Rails: Core
I can see where you are coming from with this patch, but while we're
at it wouldn't it be better to support the standard credential
mechanisms for the database in question as well.

For example with mysql there is a file called ~/.my.cnf that can hold
the credentials necessary for the 'mysql' tool to log onto the
database. It is a simple ini file. Similarly with postgres there is
the ~/.pgpass file

I would really like to see a three layer system here

- Use the database tool set credential storing mechanism if it has
one.
- Override with credential details from database.yml for backward
compatibility.
- Override with ruby config credential details from the environments,
if specified.

That way you can keep your credentials out of Rails completely if you
want *and* have it DRY with the toolset you are using.

On Jun 12, 5:00 pm, Adam Keys <a...@therealadam.com> wrote:

> To clarify, my patch tries to load database.yml if you don't set  
> anything in your environment.

Neil Wilson

unread,
Jun 13, 2008, 6:16:21 AM6/13/08
to Ruby on Rails: Core
Right so we're back to a single file containing the database logon
details, only this time we've scattered some of the config in four
other files as well rather than keeping it all nicely together.

Struggling to see how that helps anybody.

Your change moves the database details from one file for all
environments to separate specifications in the environment files as
well as changing the format. So there are two separate debates here.

- moving away from the yml format. We could simply go for
'database.rb' containing a details hash per environment. Essentially
replicating the existing structure in Ruby format.
- moving away from the single file to the multiple environment file
approach. But then you want to put an exception in forcing people to
source credentials from some other file. I don't see the benefit in
that. Just do it in one place.

I can see the advantage of getting rid of YML for the database
connection specification, but I think your "don't version control the
credentials" opinionation sort of torpedoes the 'put the database
details directly in the environment files' idea.

To go the whole hog surely we need a 'development_database.rb',
'test_database.rb' and 'production_database.rb' set of files in config/
environments where the differences between the environments can be
expressed *and* excluded from version control. This way you still get
the advantage of factoring the common stuff into the main
'environment.rb' file - something that is less than can be done in
YAML but only if you know the incantation.

Rails will than look for a <environment>.rb and
<environment>_database.rb file when it loads the environment.

On Jun 11, 2:39 pm, Adam Keys <a...@therealadam.com> wrote:
> ## Securing your database credentials
>
> We all know its a good idea to keep your database credentials  
> (username/password) out of source control. This patch supports that  
> raising an exception if you try to set your username or password in a  
> production setting. Instead, you specify a credentials file like so:

James H.

unread,
Jun 13, 2008, 7:28:41 AM6/13/08
to Ruby on Rails: Core
I definitely agree with Matt's sentiments. You can count me in for a
-1. Good effort though.

James

On Jun 11, 8:58 pm, Matt Palmer <mpal...@hezmatt.org> wrote:
> On Wed, Jun 11, 2008 at 12:08:42PM -0500, Adam Keys wrote:
> > As the name of the patch implies, this approach is also considerably  
> > DRYer. If you want, you can define everything in environment.rb and  
> > move on.
>
> I'm not sure how you're repeating yourself by putting the database config in
> a separate file.  Where's the repetition?
>
> If anything, this patch is anti-DRY because it locks up the database config
> in a place that can only be read by Rails.  If you've got anything other
> than Rails that wants to talk to the database (cron jobs, other apps,
> whatever) YAML is a far better way to store your credentials than a chunk of
> Rails code (it's not even plain Ruby, because you need umpteen lines of
> scaffolding to evaluate it and get the values out of it).  Practically
> anything can parse YAML, nothing except Rails can parse Rails.
>
> I'm -1 on this patch because it'll almost certainly make my life harder
> trying to host apps that use this convention.
>
> - Matt
>
> --
> "I invented the term object-oriented, and I can tell you I did not have C++
> in mind."  -- Alan Kay
Reply all
Reply to author
Forward
0 new messages