Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Automatically initialize associations in your Rails models

branch: master

Release 0.5.0.

latest commit 7f1515bba2
Federico Builes authored November 20, 2012
Octocat-spinner-32 lib Release 0.5.0. November 20, 2012
Octocat-spinner-32 test Release 0.5.0. November 20, 2012
Octocat-spinner-32 .gitignore Ignore .gem files. December 11, 2011
Octocat-spinner-32 Gemfile Initial commit. December 11, 2011
Octocat-spinner-32 Gemfile.lock Release 0.5.0. November 20, 2012
Octocat-spinner-32 MIT-LICENSE Initial commit. December 11, 2011
Octocat-spinner-32 README.md Release 0.5.0. November 20, 2012
Octocat-spinner-32 Rakefile Updating Manifest. December 11, 2011
Octocat-spinner-32 auto_build.gemspec Update dependencies for Rails 3.2 January 21, 2012
README.md

AutoBuild

Automatically initialize associations in your Rails 3 models.

What

AutoBuild gives your models the option to automatically initialize (build) their associations. This is useful to skip the build_association or record.association.build calls in your models, controllers or views when working with nested fields.

Installation

Add auto_build to your Gemfile:

gem "auto_build"

And run bundle install.

Usage

has_one associations

Just call the auto_build method in your models:

 class User
   has_one :address
   has_one :phone

   auto_build :address
 end

With this in place, address will always be initialized, so you don't have to manually call build_address anywhere. If the User already has an address assigned this won't overwrite it.

You can also do:

auto_build :address, :phone,

To initialize several fields. One after_initialize callback will be created per association.

belongs_to associations

Works the same as the has_one association:

 class User
   belongs_to :directory

   auto_build :directory
 end

has_many associations

You can automatically initialize a has_many association in the same way you initialized a has_one association:

class User
  has_many :friends
  auto_build :friends
end

# User.new.friends.count == 1

The behavior will be the same, it will create a new Friend if none exists yet. If there's at least one Friend in the collection then nothing will be created.

If you want to always append a new empty object at the end of the collection, you can pass the :append => true option:

class User
  has_many :friends
  auto_build :friends, :append => true
end

# count = some_user.friends.count
# user = User.find(some_user.id)
# user.friends.count == count + 1

This will always create a new Friend instance regardless of the value of friends. It won't overwrite any existing values.

Finally, if you want to always bulk-add a number of records, you can pass the :count option with the number of records you want to add:

class User
  has_many :friends
  auto_build :friends, :count => 5
end

# count = some_user.friends.count
# user = User.find(some_user.id)
# user.friends.count == count + 5

This will always add 5 extra objects at the end of the collection. It won't overwrite any existing values.

Notes

  • Watch out for fields with reject_if. Since the AutoBuild callback will be added as an after_initialize hook this might overwrite the validations done in reject_if.
  • The option :append => true is equivalent to :count => 1.
  • None of the operations will overwrite existing objects.

Autobuilding associations means that if there's a value in the column, the object will be loaded every time you load the parent. This is problematic if you're trying to optimize your code. To get a better picture of this:

class User
  has_one :address
  auto_build :address
end

If you do User.select(:id) the resulting query will be SELECT id FROM users; plus SELECT * from addresses WHERE user_id = 42";. This happens because we're calling calling user#address every time we initialize a User object.

How it works

auto_build works by adding an after_initialize callback per association to your model.

Etc.

To report bugs or suggest new features go to the Issues tracker.

This was written by Federico. You can follow me on Twitter @febuiles. Let me know if you find this useful.

Something went wrong with that request. Please try again.