A: 

If you just want to find the number of companies on a category all you need to do is find the category and then call the association name and size because it will return an array.

@category = Category.find(params[:id])
@category.companies.size 
Sam
I understand that, my question is aimed at understanding why join queries are considered bad. Im sorry if my question is not very clear.
Sid
I think you are making it harder than it is because quite simply joins are adding twice the work where if you stick with one model its half the work.
Sam
You should write `@category = Category.find(params[:id], :include => :companies)` or else you are hitting the database twice. Concerning your comment above: quite the opposite actually.
nathanvda
if he's looking for the size then the correct is actually doing @category.companies.count. Calling find with include will load all the companies as objects, which is not necessary.
Marcos Toledo
+1  A: 

To my knowledge, there is no such rule. The rule is to hit the database as least as possible, and rails gives you the right tools for that, using the joins.

The example Sam gives above is exemplary. Simple code, but behind the scenes rails has to do two queries, instead of only one using a join.

If there is one rule that comes to mind, that i think is related, is to avoid SQL where possible and use the rails way as much as possible. This keeps your code database agnostic (as rails handles the differences for you). But sometimes even that is unavoidable.

It comes down to good database design, creating the correct indexes (which you need to define manually in migrations), and sometimes big nested structures/joins are needed.

nathanvda
A: 

Join queries are not bad, in fact, they are good, and ActiveRecord has them at its very heart. You don't need to break into find_by_sql to use them, options like :include will handle it for you. You can stay within the ORM, which gives the readability and ease of use, whilst still, for the most part, creating very efficient SQL (providing you have your indexes right!)

Bottom line - you need to do the bare minimum of database operations. Joins are a good way of letting the database do the heavy lifting for you, and lowering the number of queries that you execute.

By the by, DataMapper and Arel (the query engine in Rails 3) feature a lot of lazy loading - this means that code such as:

@category = Category.find(params[:id])
@category.companies.size

Would most likely result in a join query that only did a COUNT operation, as the first line wouldn't result in a query being sent to the db.

Sam Phillips