Could you tell me whats the best practice to create has_one relations?
f.e. if i have a user model, and it must have a profile...
How could i accomplish that?
One solution would be:
# user.rb
class User << ActiveRecord::Base
after_create :set_default_association
def set_default_association
self.create_profile
end
end
But that doesnt seem very clean... Any suggests?
If this is a new association in an existing large database, I'll manage the transition like this:
so that existing user records gain a profile when asked for it and new ones are created with it. This also places the default attributes in one place and works correctly with accepts_nested_attributes_for in Rails 4 onwards.
There is a gem for this:
https://github.com/jqr/has_one_autocreate
Looks like it is a bit old now. (not work with rails3)
Your solution is definitely a decent way to do it (at least until you outgrow it), but you can simplify it:
Probably not the cleanest solution, but we already had a database with half a million records, some of which already had the 'Profile' model created, and some of which didn't. We went with this approach, which guarantees a Profile model is present at any point, without needing to go through and retroactively generate all the Profile models.
Best practice to create has_one relation is to use the ActiveRecord callback
before_create
rather thanafter_create
. Or use an even earlier callback and deal with the issues (if any) of the child not passing its own validation step.Because:
How to do it:
Here's how I do it. Not sure how standard this is, but it works very well and its lazy in that it doesn't create extra overhead unless it's necessary to build the new association (I'm happy to be corrected on this):
This also means that the association is there as soon as you need it. I guess the alternative is to hook into after_initialize but this seems to add quite a bit of overhead as it's run every time an object is initialized and there may be times where you don't care to access the association. It seems like a waste to check for its existence.