Ruby on Rails one to many database relationships

Using : Ruby 1.9.2, Rails 3.1.3

Please note : I’m new to all this Ruby on Rails stuff, I’m posting these articles so if I make mistakes hopefully people will point them out.

As a developer on top of the Microsoft ASP.NET and SQL Server stack you have a lot of good tools at your disposal, but a lot of these tools abstract developers away from what is really happening under the covers. Whether that is a good or bad thing I’ll leave for another post.

Creating a one to many relationship in a .NET application is as simple as:
1, Creating the database tables including necessary foreign keys
2, Add the tables and map the relationship using Linq 2 SQL or Entity Framework

…and away you go.

Ruby on Rails is quite a bit different as their is no visual designer for modeling the relationships. It is done through adding attributes to model classes. Here’s a simple walk through on how to create a simple one to many relationship where a Category can have many Products belonging to it.

First lets create a new rails app called store, in a terminal window type:

rails new store

Change into the store directory, and lets use scaffold to create our category and product application components:

rails g scaffold category name:string
rails g scaffold product name:string description:text category_id:integer

Notice that we add the foreign key field of category_id to this command.
Open up the directory in textmate and edit the model files for category and product. In category.rb add:

has_many:products

and in product.rb add

belongs_to:category

Now back in your terminal window run rake db:migrate to create your product and category tables, and run rails s to start the application.

Open a browser and navigate to http://localhost:3000/categories and add a couple of categories such as cars and books.
Now if you navigate to http://localhost:3000/products you will notice that if you try to create a new product you will have to know the exact category_id the product should belong to. What would work better is if you had a nice drop down menu to select the category. Lets do this!

Open up the products_controller.rb and find the new method below the @product = Product.new add the following line:

@categories = Category.all

Also find the edit method in the products_controller, and add the same line.

This will give us the category data to populate our drop down selection list. We now need to change the form for creating a new product. In Views/Products open the file _form.html.erb and change the line:

<%= f.text_field :category_id %>

to

<%= collection_select(:product, :category_id, @categories, :id, :name, {:prompt => false })  %>

:product – the name of the object you are setting the value for, eg in our form the object is @product set in the form helper
:category_id – the name of the property to be set by the selection
@categories – the collection of objects to display in the drop down
:id – the value property for each object displayed
:name – the display property for each object displayed
{:prompt => false} – this is optional, and is set so no prompt (such as ‘Please select an item’) is displayed.

If you save all the files now and go to create a new product you’ll notice that you get a nice drop down list of categories to chose from. Hurrah!

The final thing you may want to improve is the index.html.erb and show.html.erb views within the Views/Products folder. At the moment these two views will display the category_id number rather than the actual name of the category. If you want to fix this simply change:

<%= product.category_id %>

to

<%= product.category.name %>

in the index.html.erb and show.html.erb files.

Ruby on Rails and PostgreSQL

Using : Ruby 1.9.2, Rails 3.1.3

Please note : I’m new to all this Ruby on Rails stuff, I’m posting these articles so if I make mistakes hopefully people will point them out.

As I found out today while getting back into Ruby on Rails (for the third attempt) Heroku now uses PostgreSQL as it’s database data store. It therefore makes sense to use this database type as your local development db rather than sqlite3 so you don’t come across any issues later upon deployment.

As with all rails stuff these instructions will depend on the versions you are running with, so please take note of the date this article was published. This is also the reason I wanted to write up how I got it to work, as it seems a number of pages that show up in Google searches are a bit out of date.

1, First step is to install PostgreSQL. You can download and install it from here:

http://www.postgresql.org/

I installed it with all the defaults

2, Next install the PostgresSQL drivers for Ruby by using Ruby Gems. At a terminal prompt type

gem install pg

3, You can now go ahead and create a new rails application, but this time you want to add an extra argument to let rails know you want to use PostgreSQL:

rails new myApplication -d postgresql

4, Now you need to edit your database.yml file to let rails know how to connect to your PostgreSQL instance. This is stored in the config directory of your rails application. There will be 3 different database settings for development, test and production. Update each sections to include the username and password, here’s how the development connection will look like:

development:
adapter: postgresql
encoding: unicode
database: myApplication_development
pool: 5
username: postgres
password: ******
5, Save database.yml and go back to your terminal prompt. Now lets generate a table, model, view and controller for some product objects:

rails g scaffold products name:string description:text stock_level:integer

6, Once this has run you can use the rake command to first create the databases and then run the migration scripts

rake db:create:all
rake db:migrate

7, If you open up your pgAdmin application which PostgreSQL should have installed in Launchpad you’ll be able to see your 3 new databases. If you expand myApplication_development through the Schemas and public nodes you will be able to see that 2 tables have been created. The products table and a table for keeping track of migrations.

8, The final test to see if it is all working is to type:

rails s

and browse to http://localhost:3000/products – and try using the application!

Installing Ruby on Rails 3.1 – My Tips

Please note : I am in no way an expert – I’m just learning Ruby and Ruby on Rails and hope people may point out my mistakes by reading these posts.

Ensure you have the latest version of XCode installed. This is a big download, but ensure you get it before trying to update Ruby or install Rails.

Install RVM (Ruby Version Manager)
Simply copy the install command into a terminal window at:
http://beginrescueend.com/
to install the latest version of RVM from Github

Once RVM is installed you’ll see a long message. Read through this and notice the line you need to add into your .bash_profile file. If you are new to mac os/unix like me then .bash_profile and .bash_rc files are a bit of a mystery so I used this link to edit mine:
http://redfinsolutions.com/blog/creating-bashprofile-your-mac

Close your terminal window and open a new one. Type in:

rvm -list

to see the versions of ruby installed. If version 1.9.2 isn’t installed type in:

rvm install 1.9.2

Once it is installed, run rvm -list again just to see if there. To switch to the new version you simply type:

rvm 1.9.2

to make it the default next time you open a terminal window use:

rvm 1.9.2 –default

Now lets make sure we have the latest version of Ruby Gems. Ruby Gems is an easy way to download and manage packages – you can think of packages as .NET assemblies and libraries that you will want to use in your Ruby or Ruby on Rails apps. It is a good idea to make sure you are running the latest version of Ruby Gems by using the command:

gem update –system

Once that is done, lets install rails:

gem install rails

and then make sure we have Sqlite3 – which is a light weight database Ruby on Rails will use by default during development

gem install sqlite3

Now you should be able to get up and running with creating your first rails app!