Why use an extension on config/database.yml? - ruby-on-rails

I'm inheriting a project that uses config/database.yml.sqlite and config/database.yml.psql instead of config/database.yml.
Why is this done and how should I use it?
If I just run rake db:create rails is looking for a config/database.yml. I've tried looking for a way to specify the name of the config file but no luck.
I could just ask the people I'm inheriting the code from but after a bit of googling around I see this pattern in other projects and think that it'd be nice if SO had an answer.

It is often quite normal to add database.yml to your .gitignore file, because it can contain passwords etc, and so ought to be kept out of the Git repo.
In this case, it is useful to keep an example database.yml file in the repo, showing the settings you would want for, say a Postgres database if you are going to use that, or a Sqlite database if you prefer that for your development work. Then you can get set up quickly once you've cloned the repo.
All you have to do is run:
cp config/database.yml.psql config/database.yml
then add your own passwords for your local development database into database.yml, which will then stay out of the repo and not be shared with any other developers working on the same project.

I've actually never seen that pattern. It sounds to me that those other YAML files are pre-encoded for the target database - pre-configured so to speak.
The same result could be achieved by a single YAML file with extensive documented blocks - "here is a sqlite block, here is a Postgres block", etc.

Related

How do you make rake db:schema:dump have the charset and collation of the fields in schema.rb?

One of our fields needs to be case sensitive. We can write a migration to change the collation which works fine but this change is not reflected in schema.rb. It will create issues for example when running tests and the cloned test database will not have the collation we want for that field.
We use mysql.
I have searched for a way to make this happen with no results..
I managed to find this on github but not sure how this was accomplished https://github.com/cantino/huginn/blob/db792cdd82eb782e98d934995964809d9e8cb77d/db/schema.rb
I think there is no "official" way (provided by Rails or ActiveRecord gems) to accomplish that kind of dump. Following the git history, on the Huginn repo itself, you can find the code you need to achieve this dump. Take a look to this commit: https://github.com/cantino/huginn/commit/db792cdd82eb782e98d934995964809d9e8cb77d
The most relevant code is currently here: https://github.com/cantino/huginn/blob/master/lib/ar_mysql_column_charset/main.rb
So if you need this feature, you'll probably need to copy/paste this extension into your project.
UPDATE
I made a deeper review of Huginn repo (git history and issues), and as you can read in this comment, this functionality was extracted into a gem: https://github.com/kamipo/activerecord-mysql-awesome.
As mentioned in #house9's comment, you can use structure.sql instead. Add this to your project's application.rb:
config.active_record.schema_format = :sql
Then run bundle exec rake db:structure:dump to generate the actual SQL structure. This retains charsets and collations (which should ideally be there in schema.rb, but alas).
"structure" is by nature less portable than "schema", but it's usually a good thing for all team members and environments to be using the same database and version anyway.

Is it ok to store DB password for the production environment in the config/database.yml file

Is it ok to store DB password for the production environment in the "config/database.yml" file? Or is there any more correct way to do it (maybe environment variables)?
Thanks in advance.
It's not a good idea! One main reason is that the config/database.yml file will probably be included in some kind of source control, like a git repository. Even if the repo is private currently, you can't know for sure it won't be made public in the future and then you would have a problem on your hands!
In addition, if anyone ever gains read-access to your application's files or just a copy of your application's source, they now have your database password.
A typical solution is to set an environment variable like you suggested and then read it in the .yml file:
password: <%= ENV['DATABASE_PASSWORD'] %>
If you're using a PaaS like Heroku, this is the standard way to do things. But even this isn't a perfect solution, so evaluate your options carefully.

Why is config/database.yml included in the .gitignore file by default for my Rails app?

Why would config/database.yml be included in the .gitignore file by default? This small item cost me an hour or two.
The way I stumbled into this trouble:
I thought I was confused about how git handled reset and revert.
I had been experimenting with code changes that affected config/database.yml
I didn't like the result, so I abandoned the changes.
It was odd, because it seemed I could not checkout an unedited version of config/database.yml
I then spent way too much time trying to figure out if I was misunderstanding git's reset and merge commands.
Turns out config/database.yml was included in the .gitignore file by default.
Not sure why. Cost me an hour or so of fiddling with reset and merge options, when it turns out I wasn't even tracking the file. As I write this, I realize I am not entirely sure when .gitignore was written/modified to include config/database.yml
Is there some reason it should be there?
That file usually won't contain much interesting content for tracking in a version control system.
But, it will often contain passwords for connecting to a database server, which should not be made public.
It will also often contain information which needs to differ between different working copies, different user or database names for a database server, different paths to a SQLite file. These differences would make it impossible to track this file in the version control system.
If you are seeing a file for which 'git reset' and 'git revert' don't seem to have any effect, you may find the file is listed in the .gitignore file in your project root.

Ignoring .gitignore

My brother and I are collaborating on an app from two different computers -- one mac and one pc. I can't for the life of me get Postgres to work on his computer, and after a whole bunch of hours, I decided to just have his computer run sqlite3 for development (which is easy as pie), and basically have all the production stuff happen on my mac, while still allowing him to make functional changes from his pc. And merge them to github.
The trouble is, this involves having two different database.yml files, two different db/schema.rb files (I think), and different gemfiles, one with sqlite and the other with pg.
My thought was just to do all that on his computer and add those files to the gitignore file. But if THAT isn't ignored, then when I pull back to my mac, won't I be merging his incorrect configurations to my machine?
At any rate, that's why I was thinking of adding .gitignore to .gitignore. Will this work? Will it create universe-bending paradoxes? Is there a better way to do this that I don't know about?
Are those two schemas really different? They usually aren't.
If they aren't then just ignore config/database.yml and create contig/database_sqlite_example.yml and contig/database_ppostgresql_example.yml. That way, when someone clones repo, he can use SQLite or PostgreSQL by simply copying example file to database.yml (which will be ignored)
No, don't ignore .gitignore
I've always liked the idea of creating local branches for this. I actually go a little local branch crazy... but that's a different issue all together.
If you want to have a private little work bubble then keep your branch local only. You control what gets merged into master (or whatever your development branch is) and you can commit everything in your local branch to git for history sake.
If you want to share what you are working on then just share your branch out. But this way you can keep your environment setups isolated while sharing the local branch so that it is visible for collaboration.
There's plenty of good documentation on Git Branching and Sharing so I'll leave that to you instead of clouding the post with links that surely will get broken.
I'm not sure any of us "really want to" be working directly in the master anyway, especially in collaboration efforts such as yours.

How to efficiently handle the changes between production and development when updating from the repository

I have inherited a project with a local development environment that has code specific to that machine, and which is different for the production server. Even though the majority of it is contained in constants and the rest is in the tests, every time I commit from development and update in production I'm going to have to make the same changes in production. Fortunately this is an internal tool with low volume.
I guess I could write a script to automate it but I'm hoping there's a better solution. Anyone else solved this problem?
These questions are similar but not asking the same thing, just so you know I looked:
(1) make changes to a production database
(2) transferring changes from dev to prod
Edit: Nelson LaQuet put me on what I believe is the right track, which led me to Configuring Rails Applications. However, I am unsure how to reference my FormController < ApplicationController constants, such as MyExternalCodeDir, in config/environments/production.rb and config/environments/development.rb.
Also I do not want to be required to change every reference to MyExternalCodeDir to something like config.MyExternalCodeDir.
You abstract all environment settings (database connection/pathing/URIs) into a single file. Let's call it "config.ini"
Then you simply commit a "template" called "config.ini.template" that contains the structure of the config file clearly documenting what is expected at each value - and sensable defaults. You then commit this file.
After you do that, delete the current config.ini file that is specific to your location, and add it to svn:ignore. Now, when you copy and paste config.ini.template to config.ini, and change your settings, it is not going to be committed to the repository.
It adds an extra step per deployment, but must be done only once (unless you add/remove config options). This is the best and most standard way of accomplishing what you want.
I would move the constants' values that are environment specific in a configuration file, which would make it easier to handle. I would also keep the code in just one repository in the version-control system and manage the build outputs in two separate repositories: one for the test environment and one for production. That way I can manage my code base however I choose, and when I want to deploy I'll first commit to test, and then merge from test to production and at that point just diff the configuration file and keep the correct configuration for the production environment.

Resources