How do I handle database.yml development mode configuration with multiple develpers? - ruby-on-rails

what's the standard way of dealing with development mode database config for database.yml when there are multiple developers on a project?
Should all devs have the same database setup? Is that a smart requirement?
Or should there be some type of gitignore and symlinking taking place? I did this and after branching, the database.yml disappeared :(
I've also come up with an erb solution that seems to work well enough, but not sure if there will be unintended consequences. The following will allow devs to sed environment variables in their bash_profile in case they have a different local setup than the default. This will allow our database.yml file to stay in git.
development:
adapter: postgresql
database: <%= ENV['DEV_DB_DATABASE'] || 'app_development' %>
username: <%= ENV['DEV_DB_USERNAME'] || 'postgres' %>
password: <%= ENV['DEV_DB_PASSWORD'] || '' %>
host: localhost
encoding: UTF8

Add database.yml.sample file to the rails app, also add database.yml to the .gitignore. This way all developers can have different database setups.

Related

When deploying to Heroku, is there something I need to add/change in the production entry in the database.yml?

I am using postgresql as the database in my development environment, so that means that I setup my database.yml like the code below where the username and password is my postgresql's username and password (obviously, I'm using environment variables to avoid hard-coding) and will be inherited by development and test environments:
default: &default
adapter: postgresql
encoding: unicode
# For details on connection pooling, see rails configuration guide
# http://guides.rubyonrails.org/configuring.html#database-pooling
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
host: localhost
username: <%= ENV['FOO_DATABASE_USERNAME'] %>
password: <%= ENV['FOO_DATABASE_PASSWORD'] %>
I'm just curious about the production environment, which has the code below:
production:
<<: *default
database: foo_production
username: foo
password: <%= ENV['FOO_DATABASE_PASSWORD'] %>
Unlike in the development and test environments which uses my postgresql's username and password, the production environment have different values for username and password.
My question is, do I need to change the username and password in the production environment? or should I just leave it as it is?
What you're talking about here is essentially how you can make your code work in multiple environments (development and production), with multiple different database credentials.
The way this is typically handled is through environment variables.
In your example above, it looks like you've created two environment variables for your local database:
PINTERESTING_APP_DATABASE_USERNAME
PINTERESTING_APP_DATABASE_PASSWORD
In production, I'm assuming you have some different environment variables set which contain your production Postgres credentials.
What you need to do in your code is select one of these two options, and use them everywhere.
Here's some pseudo-code I use in my applications to accomplish this:
DATABASE_HOST = ENV['LOCAL_DB_HOST'] || ENV['PRODUCTION_DB_HOST']
DATABASE_PORT = ENV['LOCAL_DB_PORT'] || ENV['PRODUCTION_DB_PORT']
DATABASE_USERNAME = ENV['LOCAL_DB_USERNAME'] || ENV['PRODUCTION_DB_USERNAME']
DATABASE_PASSWORD = ENV['LOCAL_DB_PASSWORD'] || ENV['PRODUCTION_DB_PASSWORD']
As you can see above, what I'm doing is either using my development credentials, OR my production credentials, depending on which environment variables are available.
This allows me to seamlessly switch between development and production environments by just modifying environment variables (which is what Heroku does).

fe_sendauth: no password supplied encountered with Amazon RDS

I know many others have encountered this problem, but I'm limited in the Postgres configuration I can do since I am using Amazon RDS...
Here is the relevant section of my database.yml
default: &default
host: <%= ENV["POSTGRES_HOST"] %>
username: <%= ENV["POSTGRES_USER"] %>
password: <%= ENV["POSTGRES_PASSWORD"] %>
adapter: postgis
encoding: unicode
database: <%= ENV["POSTGRES_DB"] %>
port: 5432
pool: 5
When I hard code the host, leave everything else as is, and load localhost:3000, I get fe_sendauth: no password supplied error. However, when I hard code all of the values instead of using an ENV variable, everything loads as normal with no errors.
I'm using Amazon RDS, so I have no ability to edit pg_hba.conf, but is this just a simpler problem of RoR not having access to ENV variables?
Yup, it's pretty clear that your ENV values are returning nil. Keep in mind that environment variables are loaded a bit differently on your production server than localhost. In most deployment configurations you can't simply set a Unix environment variable and have it be detectable in ENV.
I can't really tell much about how your ENV variables are being set from your provided code, but you should consider using Figaro (https://github.com/laserlemon/figaro) or dotenv (https://github.com/bkeepers/dotenv) to manage your ENV variables for you. However, it will require the extra step of having to manage an environment variable file outside of source control.

Embedded Ruby in database.yml not being parsed in RubyMine

I am using RubyMine 7.0.4 to build a Rails(4.2.0) application with Postgres as my database. I am using environment variables to hold my local configuration (DB_USERNAME and DB_PASSWORD), but RubyMine can't parse the embedded ruby in the database.yml file.
database.yml excerpt:
...
development:
<<: *default
database: my_app_development
username: <%= ENV['DB_USERNAME'] %>
password: <%= ENV['DB_PASSWORD'] %>
...
I even tried switching it to the actual credentials within the <%= %> tags, but same issue:
...
development:
<<: *default
database: my_app_development
username: <%= 'my_app' %>
password: <%= 'password' %>
...
This seems to be a RubyMine issue, since everything is executing perfectly from the command line/the application works fine. However, I like having my database integrated with the IDE, so it'd be great if I could get this working again.
Is there anything that I can do to execute the embedded ruby instead of treating it as a string?
This is a bug within RubyMine that is unfortunately still not yet fixed.
For further info please refer to https://youtrack.jetbrains.com/issue/RUBY-9223
The only fix I managed to come up with so far, is to add the database.yml to your .gitignore file (if you're pushing your project to a remote repo) and store the username and password as plain text.
The second approach could be just inputting your db_password and db_username as plain texts for development and test databases, and using ENV["DB_USERNAME"] and ENV["DB_PASSWORD"] for the production DB only.

Rails 3 - rake tasks to work with multiple database connections

Let's say I have s different database connections...
Right now for the purposes of this example let's only be concerned with development. When I run 'rake db:setup' it only creates development because from the rake task perspective the other connection is another environment. I could pass in the other connection as the RAILS_ENV to create the database. However, the problem comes in with how we've defined our database connections. I'd rather not undo this as it makes management and deployment much easier. What we've done is this...
In our database.yml we've added the following code.
databases_file = File.join(Rails.root.to_s, "config", "databases", "#{Rails.env.to_s}.yml")
IO.read(databases_file) if File.exist?(databases_file)
Then in a databases sub-folder under config we've created the different environment yml files.
So in development.yml we have...
development:
... details ...
logging:
... details ...
Now if I set RAILS_ENV to 'logging' it will never load the file since the file is called development.yml. Thus it will never find the logging connection.
If I consolidate all these settings back into the database.yml file then we're back to not checking in the database.yml into the git repo and having to manually create it on the development machines for new hires and such. We'd also have to change our deploy process to start putting the file in place on the lower environments. (Our production process already supports this)
You could use environment variables to manage these. You could have a single database.yml with things defined such as:
development:
database: ENV['DEVELOPMENT_DATABASE']
And then set the environment variables in your .bashrc/.zshrc.
We have multiple databases and we use branches heavily... so I came up with this solution to create multiple databases and tie their names to the branch being worked on...
# config/database.yml
<%=
databases_file = File.join(Rails.root.to_s, "config", "databases", "#{Rails.env.to_s}.yml")
if Rails.env.development? || Rails.env.test?
branch = ENV['BRANCH'] || `git branch --no-color 2> /dev/null`.chomp.split("\n").grep(/^[*]/).first[/(\S+)$/,1].sub("-", "_")
puts "Using databases for #{branch}"
IO.read(databases_file).gsub!("<branch>", branch) if File.exist?(databases_file)
else
IO.read(databases_file) if File.exist?(databases_file)
end
%>
And then you create a database file for each environment. In the development.yml and test.yml you use the token to let this script look for what it needs to in order to do replacement. So an example file would look like this.
# config/databases/development.yml
development:
adapter: mysql2
host: 127.0.0.1
database: <branch>_dev
username: user
password: pass
versions:
adapter: mysql2
host: 127.0.0.1
database: <branch>_versions
username: user
password: pass
reporting:
adapter: mysql2
host: 127.0.0.1
database: <branch>_reporting
username: user
password: pass
ods:
adapter: mysql2
host: 127.0.0.1
database: <branch>_ods
username: user
password: pass
I then extended the rake tasks to handle multiple databases
This is where most of the work went in. Therefore, I'm going to leave it out of the answer and make you work for it! No actually, it's just a big large mess that I'm not proud of and would love time to fix it, but haven't found any. I don't want to lead anyone down the wrong path but if you have questions just get me a message and I'll be happy to help.

rails 3: is there a way to put a gem's config params in environment.rb instead of foo.yml?

My rails app uses a gem that requires some config params to be specified in foo.yml:
development:
username: MyDevUserName
password: MyDevPassword
production:
username: MyPRODUserName
password: MyPRODPassword
I dont want the password in my source code and want to do something like:
development:
username: <%= ENV['THE_USERNAME'] %>
password: <%= ENV['THE_PASSWORD'] %>
production:
username: <%= ENV['THE_USERNAME'] %>
password: <%= ENV['THE_PASSWORD'] %>
However, for some reason that <%= ENV['XXX'] %> does work in my Settings.yml file, but does not work in my foo.yml file (I'm guessing however the foo gem loads the .yml file it does not allow interpretation).
So...
I'm wondering if Ruby/Rails has a general-purpose way to specify the variables in environment.rb instead of a foo.yml file?
Can i for example have an empty foo.yml file and add the following to environment.rb:
Foo::_something_._somethingelse =
{
:username => ENV['THE_USERNAME'],
:password => ENV['THE_PASSWORD']
}
EDIT: Since you are on Heroku...
Heroku is a different story. Your use of ENV may be conflicting with some functionality built into Heroku for handling config vars such as the ones you are working with. You need (drumroll, please)... CONFIG VARS. See this page in the Heroku Dev Center for information on how to set config vars in your Heroku deployment, how to access them from your app, and how to make it all work locally as well.
EDIT: Below is the original answer, still applicable in the general (non-heroku) case
Even if you put it in environment.rb, it will still be in your source code.
The correct way to do this is to ignore the foo.yml file in your version control (for instance, in git you would add the file to the .gitignore file). That way, you have the file locally where you need it, but it never gets committed to your repository, so your creds aren't exposed. On your deployment server, you will have to manually create that file as well, since when you deploy from source code the deployment won't have it.
If you are using capistrano for deployment, a common approach would be to put the file in [app]/shared/config/foo.yml, then add a deployment task to softlink from [sharedpath] into [releasepath]. Such a task in capistrano might look like this:
task :after_update_code do
run "ln -s #{shared_path}/config/foo.yml #{release_path}/config/foo.yml"
end

Resources