Ruby on rails 3 Rails中关联的空对象模式

Ruby on rails 3 Rails中关联的空对象模式,ruby-on-rails-3,null-object-pattern,Ruby On Rails 3,Null Object Pattern,尽管在这里看到了一些关于rails中空对象的答案,但我似乎无法让它们正常工作 class User < ActiveRecord::Base has_one :profile accepts_nested_attributes_for :profile def profile self.profile || NullProfile #I have also tried @profile || NullProfile #but it didn't work ei

尽管在这里看到了一些关于rails中空对象的答案,但我似乎无法让它们正常工作

class User < ActiveRecord::Base
  has_one :profile
  accepts_nested_attributes_for :profile

  def profile
    self.profile || NullProfile #I have also tried
    @profile || NullProfile #but it didn't work either
  end
end

class NullProfile
  def display #this method exists on the real Profile class
    ""
  end
end

class UsersController < ApplicationController
  def create
    User.new(params)
  end
end
class用户
我的问题是,在创建用户时,我为配置文件传入了正确的嵌套属性(profile_属性),最终在我的新用户上得到了一个null配置文件


我猜这意味着我的自定义概要文件方法在创建并返回NullProfile时被调用。如何正确处理这个空对象,使其仅在读取时发生,而不是在对象的初始创建时发生。

我正在仔细检查,如果它不存在,我想要一个干净的新对象(如果您这样做
对象。display
不会出错,可能
对象。尝试(:display)
更好)这也是我发现的:

1:别名/别名\u方法\u链

def profile_with_no_nill
  profile_without_no_nill || NullProfile
end
alias_method_chain :profile, :no_nill
但是,由于alias_method_chain已被弃用,如果您处于边缘,则必须自己手动完成该模式。。。似乎提供了更好、更优雅的解决方案

2(答案中的简化/实用版本):

它的行为不会像预期的那样,因为关联是延迟加载的(除非你告诉它在搜索中包含它),所以@profile是nil,这就是为什么你总是得到NullProfile

def profile
  self.profile || NullProfile
end

它将失败,因为该方法正在调用自身,所以它的排序类似于递归方法,您会得到
SystemStackError:stack level太深

而不是使用别名\u方法\u链,请使用以下命令:

def profile
  self[:profile] || NullProfile.new
end

我发现了一个比在接受的答案中包含私有模块更简单的选项

您可以重写reader方法,并使用
association
方法从
ActiveRecord
获取关联对象

class User < ApplicationRecord
  has_one :profile

  def profile
    association(:profile).load_target || NullProfile
  end
end # class User
class用户
根据Rails,关联方法被加载到模块中,因此重写它们是安全的

所以,有点像

def profile
  super || NullProfile.new
end
应该对你有用

class User < ApplicationRecord
  has_one :profile

  def profile
    association(:profile).load_target || NullProfile
  end
end # class User
def profile
  super || NullProfile.new
end