我有一个应用程序,我的用户可以有一组偏好。两者都如下存储的ActiveRecord的模型:
class User < AR::Base
has_one :preference_set
end
class PreferenceSet < AR::Base
belongs_to :user
end
现在我可以访问用户的喜好:
@u = User.first
@u.preference_set => #<PreferenceSet...>
@u.preference_set.play_sounds => true
但是,这是否偏好设置尚未创建,因为@ u.preference_set将返回nil我会在play_sounds
调用nil
失败,。
我想存档是User.preference_set总是返回PreferenceSet实例。我试着将其定义是这样的:
class User < ..
has_one :preference_set
def preference_set
preference_set || build_preference_set
end
end
这是造成'Stack level too deep'
,因为它是递归调用本身。
我的问题是这样的:
我怎样才能确保@user.preference_set
要么返回相应preference_set记录或者,如果不存在,建立一个新的?
我知道我可以只重命名我的协会(如preference_set_real
),并避免递归调用此方法,但在我的应用程序简便起见,我想保持命名。
谢谢!
那么要做到这一点的最好办法是,当你创建主之一创建相关记录:
class User < ActiveRecord::Base
has_one :preference_set, :autosave => true
before_create :build_preference_set
end
这将设置它,以便每当创建User
,所以是一个PreferenceSet
。如果您需要初始化带参数的相关记录,然后调用before_create
这就要求build_preference_set(:my_options => "here")
不同的方法,然后返回true
。
然后,您可以仅仅通过遍历任何没有PreferenceSet
,并通过调用#create_preference_set
建立一个规范所有现有的记录。
如果你只想创建PreferenceSet
时是绝对需要它,那么你可以这样做:
class User < ActiveRecord::Base
has_one :preference_set
def preference_set_with_initialize
preference_set_without_initialize || build_preference_set
end
alias_method_chain :preference_set, :initialize
end
或者干脆
class User < ApplicationRecord
has_one :preference_set
def preference_set
super || build_preference_set
end
end
这工作,因为ActiveRecord的定义一个mixin的关联方法。