Automatically initialize associations in your Rails 3 models.
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.
Add auto_build
to your Gemfile:
gem "auto_build"
And run bundle install
.
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.
Works the same as the has_one
association:
class User
belongs_to :directory
auto_build :directory
end
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.
- Watch out for fields with
reject_if
. Since the AutoBuild callback will be added as anafter_initialize
hook this might overwrite the validations done inreject_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.
auto_build
works by adding an after_initialize
callback per association to your model.
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.