In this fourth part of a five-part series that delves deeply into the Active Record of the Rails framework, we'll wrap up our discussion from the previous part and then move on to take a look at applying validations. This article is excerpted from chapter five of the book Beginning Rails: From Novice to Professional, written by Jeffrey Allan Hardy, Cloves Carneiro Jr. and Hampton Catlin (Apress; ISBN: 1590596862).
Association proxy is a fancy term for the ability to “chain” together multiple calls to Active Record. We’ve been using this technique throughout the entire book, but haven’t given it any special mention. Here is a basic example of association proxies:
This will return all of the registrations for the first event returned. The secondfind(off registrations), will be automatically scoped to the event, which is to say, it will find registrations that belong to that event. If you remember,registrationsis ahas_manyrelationship on theEventmodel. The cool part is that this isn’t two queries to the database. It does all of this in one request to the database.
Scoped finders are also more secure. Imagine a multiple-user system where data owned by one user shouldn’t be accessible by another user. Simply finding an associated object, say, a document, by itsidwouldn’t restrict it to documents owned by a particular user. You could pass in thedocument_idand theuser_idas conditions, but that’s sloppy and error-prone. The correct way to do this would be to scope all find operations off the user in question. For example, assuming you had aUserobject stored in the variablecurrent_user,current_user.documents.find(1)would ensure that the document withid 1would be returned only if it belonged to thecurrent_user.
Anyone who has done database work will realize that this incredibly simple syntax is far easier than the SQL queries that need to be created to achieve similar results. If you play around with these chains, you can check out the log to see the SQL that was generated—you’ll be happy that you didn’t have to write that yourself!
This technique doesn’t just apply to finding. It can be used to automatically assign ownership withbuildandcreateconstructors by setting the appropriate foreign keys. Consider the following example where we’re creating a new document for thecurrent_user. This will automatically set the document’suser_idto that of the current user.
current_user.documents.create(:name => 'Private')
This is much better than the alternative, which would be to go through theDocumentmodel directly and set theuser_idas an attribute (Document.create(:user_id => current_user.id). As a rule, whenever you need to restrict find operations to an owner, or if you are assigning ownership, you should use the power of the association proxy.
■Tip The association proxy is one of the most commonly underused elements of Active Record. Rails core team members, Jamis Buck and Michael Koziarski, have written a great article on this topic, in which they describe several anti-patterns you should avoid. We highly recommend you read this article in full. You can find it athttp://therailsway.com/2007/3/26/association-proxies-are-your-friend.