Rails - Best-Practice: How to create dependent has_one relations

Viewed 41771

What's the best practice to create has_one relations?

For example, 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 doesn't seem very clean... Any suggestions?

8 Answers

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.

alias_method :db_profile, :profile
def profile
  self.profile = Profile.create(:user => self) if self.db_profile.nil?
  self.db_profile
end

I had an issue with this and accepts_nested_attributes_for because if nested attributes were passed in, the associated model was created there. I ended up doing

after_create :ensure_profile_exists
has_one :profile
accepts_nested_attributes_for :profile


def ensure_profile_exists
  profile || create_profile
end

If you need the has_one association to exist before saving the object (when testing, for instance), you should use the after_initialize callback instead. Here is how it could be applied to your use case:

class User < ActiveRecord::Base
  has_one :profile
  after_initialize :build_profile, unless: :profile
end
Related