What's New in Edge Rails: Easy Join Table Conditions

Posted by ryan
at 4:38 PM on Monday, July 07, 2008

For an application with anything above a moderate level of domain complexity it’s quite likely that you’ve had to perform a query utilizing a join table:

1
2
3
4
5
6
7
8
9
10
11
class Article < ActiveRecord::Base
  belongs_to :user
end

class User < ActiveRecord::Base
  has_many :articles
end

# Get all the users that have published articles
User.find(:all, :joins => :article,
  :conditions => ["articles.published = ?", true])

It always makes me feel slightly embarrassed to have to resort to using String snippets to specify my query logic, and this little bit is no exception. Well, now we can specify conditions on a join table in a more concise manner:

1
2
3
# Get all the users that have published articles
User.find(:all, :joins => :article,
  :conditions => { :articles => { :published => true } })

Note how you’re able to specify the join-table conditions as a hash whose key corresponds to the table or association name of the join table? You can now let Rails worry about forming the correct SQL condition even across complex joins.

However, don’t let the ease of this feature make you use it over a properly associated domain-model. For instance, this join query:

1
2
3
# Get all articles for a given user
Article.find(:all, :joins => :user,
  :conditions => { :users => { :id => @user.id } })

is more appropriately represented as:


@user.articles

tags: ruby, rubyonrails

Comments

Leave a response

  1. Nathan EsquenaziJuly 08, 2008 @ 08:00 AM

    This is a cool feature. In my opinion, it should be a mission to remove as many silly string snippets from activerecord queries. This helps with join tables and in my opinion there is really only one area left that needs help and that is with advanced comparisons. For instance if I want to get all the items after a certain date, I am forced to resort to:

    Articles.all(:conditions => [ ‘published_at > ?’, some_date ])

    This would look much better as:

    Articles.all(:conditions => { :published_at.gt => some_date })

    Using the DataMapper operators.

  2. ArthurJuly 08, 2008 @ 12:36 PM

    what’s up nathan.

  3. Kazim ZaidiJuly 11, 2008 @ 02:06 PM

    I do not fully agree with you ryan. There’s nothing to be embarrassed about when using little SQL strings. In fact, ActiveRecord, like every ORM, fails to do complex optimized queries using hashes and method calls. In my applications, I do write SQL strings because otherwise AR will perform heavy operations.

    SQL is just a bit verbose. We should seek to eliminate its verbosity in trivial cases like the second example you mentioned. However, in the first example, the Ruby version of the SQL string is equally verbose and hence provides no value. In fact, using SQL string is faster since it’s just a string directly inserted into query.

    Are we just coming up with another dialect of SQL? :-P