Blog

Showing posts with label saving. Show all posts
Showing posts with label saving. Show all posts

Monday, March 17, 2008

Fundamentals: How Associations are Validated

Summary: Adding validates_associated method to your parent ActiveRecord classes will ensure both the parent and child class are valid before saving.

In this posting we will use the same model as our last post When Associations Get Saved.

Last time, we established that associated child models are automatically saved when the parent is saved. For example:


Here the associated address is saved when account is saved. But how does validation play into the saving of associations?

In this example, we have added no additional validation rules:


Although the account is valid, the address is not, it is missing the street address. When account is saved, it attempts to save the address model, but it cannot. Typically in this scenario we would prefer that the parent model is not saved if the child model in invalid and cannot be saved. How can we achieve this?

Add the following to your account model:


And observe the difference in model behavior:


As you can see an exception is raised when the account is saved as the address is invalid.

In conclusion, when a dependent model needs to be valid add the validates_associcated method to the parent model.

Sunday, December 16, 2007

Fundamentals: When Associations Get Saved (with new parent and child models)

Summary: Use the “Auto-generated methods” on the new parent object to build new associated child objects to gain the benefits of less code, encapsulation and cascading saves.

For example, do this:


Rather than this:


Details

With all the automagic and flexibility (i.e. multiple ways to do the same thing) Ruby on Rails provides, it’s easy to get confused with how the framework behaves and what the best practices are. But it is just as easily solved when you have a few rules of thumbs to follow. This is very true for ActiveRecord behaviour, specifically when saving associated records.

There is even a section dedicated to it in the Agile Web Development Book with Rails (Chapter 18, Section 7). The book looks at an existing object at one end of the association, and a new object at the other. But it does not discuss dealing with two new objects.

So let’s look at some examples how associations work. Consider the following models:


Simple stuff. For clarity sake, we will refer to the Account as the parent object, and the Address as the child object. We can consider the Address as the child object as it stores the id of the parent object. In this case the field account_id to identify the Account. So let’s create a an Account with an associated Address.

Example 1 (Recommended)


When we add a has_one relationship, a number of new methods are defined on the receiver (e.g. Account#build_address). This is true for all relationships, although the methods differ. See the ROR documentation for a complete list of Auto-generated methods.

The key observation here is, when you build a new child object via the parent object using the build method you do not need to explicitly save the child object, as the save cascades. An alternative way of doing this is:

Example 2


The first example, is preferable since it’s less code due to encapsulation.

If you assign a parent object to a child object:

Example 3


You will need to explicitly save the child object. But don’t save the parent object, because you will end up with this:


It’s always best to standardize the way you write code. When possible, when creating new objects that have an association use the following pattern:


The benefits are:

  • encapsulation, hiding the implementation of how an address is created
  • less code
  • cascading saves

Although I looked at the has_one/belongs_to association, this also works for other associations such as has_many.

For my next post, I will discuss how validating associations works in this context.

Please note this blog is no longer maintained. Please visit CivilCode Inc - Custom Software Development.