I have an application where my users can have a set of preferences. Both are stored as ActiveRecord-models as follows:
class User < AR::Base
has_one :preference_set
end
class PreferenceSet < AR::Base
belongs_to :user
end
I can now access the preferences of a user:
@u = User.first
@u.preference_set => #<PreferenceSet...>
@u.preference_set.play_sounds => true
But this fails if a preference set is not already created, since @u.preference_set will be returning nil, and I'll be calling play_sounds
on nil
.
What I want to archive is that User.preference_set always returns a PreferenceSet instance. I've tried defining it like this:
class User < ..
has_one :preference_set
def preference_set
preference_set || build_preference_set
end
end
This is causing a 'Stack level too deep'
, since it is calling itself recursively.
My question is this:
How can I ensure that @user.preference_set
returns either the corresponding preference_set-record or, if none exists, builds a new one?
I know I could just rename my association (eg. preference_set_real
) and avoid recursive calls this way, but for the sake of simplicity in my app, I'd like to keep the naming.
Thanks!
There's an elegantly simple form:
class User < ApplicationRecord
has_one :preference_set
def preference_set
super || build_preference_set
end
end
ActiveRecord intentionally enables such use of super
to override the behaviour of association methods.