ActiveRecord associations


#1

Can someone clarify this for me? Suppose I have two tables like:

class Company < ActiveRecord::Base
belongs_to :category
end

class Category < ActiveRecord::Base
has_many :companies
end

I understand that the belongs_to causes related companies to be read
from the db when I ask for a category. I suspect SQL something like

select * from categories, companies
where category.id = myid
and companies.category_id = category.id

but what SQL results from the has_many?


#2

You can look at the development.log file to see all the SQL queries made
but it’s probably like the query you said:

belongs_to:
select * from categories where category_id = {company_category_id}

  • where category id is retrived from the company results

has_many:
select * from companies where category_id = {category_id}

  • where category id is the id of the retrived category

Steve


#3

On May 11, 2006, at 10:08 AM, Richard W. wrote:

I understand that the belongs_to causes related companies to be read
from the db when I ask for a category. I suspect SQL something like

select * from categories, companies
where category.id = myid
and companies.category_id = category.id

but what SQL results from the has_many?

I would say that you are thinking about this in the wrong way.
Technically the belong_to and the has_many methods don’t specifically
create SQL. What they do is create a programatic link between the two
models that is then expressed as SQL when you request specific data
from the database.

If you do: Company.find(:first), say through script/console, SQL is
generated, but no SQL specific to the belongs_to relationship.

If you do: Company.find(:first).category, you actually create two SQL
requests to the database. The first is to return the first Company
record. The second is to return the parent Category record of that
Company record.

Likewise, if you do: Category.find(:first).companies, you get 2 SQL
requests, the second of which brings back an array of child Company
records.

If you want a deeper understanding of this, there are several things
you should do. First, I recommend getting the Agile Web D.
with Rails book (http://pragmaticprogrammer.com/).

Second, you should read through the API docs on this page:
<http://rails.rubyonrails.com/classes/ActiveRecord/Associations/
ClassMethods.html>

Third, you should launch your Rails app under Development, with the
ability to see the WEBrick/lighttpd output, launch script/console and
give some find calls a try, looking at the web server output. In that
output will be the SQL generated by Rails.

-Brian


#4

On May 11, 2006, at 10:29 AM, Richard W. wrote:

select * from companies where category_id = {category_id}

  • where category id is the id of the retrived category

So I guess that if you don’t ever want to do the has_many query, i.e.
you don’t every want to get a list of categories for a particular
set of
companies you would not need to have the has_many association in
the model.

Not true, IMO. Unfortunately, while Stephen’s description is
essentially accurate, it’s too simplistic a view into what
ActiveRecord associations can do for you. If you have a relationship
where it makes sense to say one model belongs_to another model, the
“parent” model should have the appropriate has_* association
specified within it.

I believe it would technically work, if you only specified one side
of the association, you would be cutting off half (or more) of the
functionality that ActiveRecord is trying to provide. I would say
it’s actually irrelevant if the code you are currently planning to
develop only accesses the association from one side, you want to have
both sides specified so that when you need both sides, it will be there.

-Brian


#5

On Thursday, May 11, 2006, at 3:15 PM, Stephen B. wrote:

class Category < ActiveRecord::Base
but what SQL results from the has_many?


Rails mailing list
removed_email_address@domain.invalid
http://lists.rubyonrails.org/mailman/listinfo/rails

So I guess that if you don’t ever want to do the has_many query, i.e.
you don’t every want to get a list of categories for a particular set of
companies you would not need to have the has_many association in the
model.


#6

As Brian said, has_many defines a relationship - it doesn’t generate
SQL. There is more involved in this relationship that just selecting out
children, such as creating and deleting related records.

Also, the query to select children wont be run unless you try to do
something with them:

for company in @category.companies

… code

end

I also second all of Brian’s advice.

Cheers,

Steve


#7

Thanks Brian.

What I was confused about was that I never see example model where
ONLY a has_many or ONLY a belongs to is shown. Always they are shown as
a pair. I wanted to know if it is “normal” to use only one or the other
and when that would be.

I think I understand now that you can use either one independently of
the other or you can use both together as required by the application.