views:

512

answers:

3

How do the relationships magically function when only the models are altered?

If I want a "has__and___belongs___to__many" relationship, what should I name the table (so Rails can use it) that contains the two foreign keys?

+2  A: 

This works because you are following "Convention over Configuration".

If you state that a customer model has many orders then rails expects there to be a customer_id field on the orders table.

If you have followed these conventions then rails will use them and will be able to build the necessary SQL to find all the orders for a given customer.

If you look at the development.log file when you are developing your application you will be able to see the necessary SQL being built to select all orders for a given customer.

Rails does not create tables without you asking it to. The creation of tables is achieved by generating a migration which will create/alter tables for you. The fact that you create a customer model and then state within it that it has_many :orders will not create you an orders table. You will need to do that for yourself within a migration to create an orders table. Within that migration you will need to either add a customer_id column or use the belongs_to: customer statement to get the customer_id field added to the orders table.

Steve Weet
I'll put a little more detail in the answer.
Steve Weet
+2  A: 

Short answer: You can't just tell the models that they're related; there have to be columns in the database for it too.

When you set up related models, Rails assumes you've followed a convention which allows it to find the things you wrote. Here's what happens:

  1. You set up the tables.

    Following conventions in Rails, you name the table in a particular, predictable way (a plural noun, e.g. people). In this table, when you have a relationship to another table, you have to create that column and name it in another predictable way (e.g. bank_account_id, if you're relating to the bank_accounts table).

  2. You write a model class inheriting from ActiveRecord::Base

    class Person < ActiveRecord::Base

    When you instantiate one of these models, the ActiveRecord::Base constructor looks at the name of the class, converts it to lowercase and pluralizes it. Here, by reading Person, it yields people, the name of the table we created earlier. Now ActiveRecord knows where to get all the information about a person, and it can read the SQL output to figure out what the columns are.

  3. You add relationships to the model: has_many, belongs_to or has_one.

    When you type something like, has_many :bank_accounts, it assumes a few things:

    1. The name of the model that you relate to is BankAccount (from camel-casing :bank_accounts).

    2. The name of the column in the people table which refers to a bank account is bank_account_id (from singularizing :bank_accounts).

    3. Since the relationship is has_many, ActiveRecord knows to give you methods like john.bank_accounts, using plural names for things.

Putting all of that together, ActiveRecord knows how to make SQL queries that will give you a person's bank accounts. It knows where to find everything, because you followed a naming convention that it understands when you created the table and its colums.

One of the neat things about Ruby is that you can run methods on a whole class, and those methods can add other methods to a class. That's exactly what has_many and friends are doing.

Andres Jaan Tack
So if I want a "has_and_belongs_to_many" relationship, what should I name the table (so Rails can use it) that contains the two foreign keys?
Abi Noda
The documentation is a great resource for this: http://tinyurl.com/cnfm24To paraphrase, the convention for the join table is the plural of each, in lexical order. For Master and Pet models, we would create the table `masters_pets`. The columns should be `master_id` and `pet_id`.
Andres Jaan Tack
Thanks, that's what I was looking for.
Abi Noda
A: 

The rails guide for this is pretty useful

srboisvert