在Rails中实现NullObject模式

dee*_*dee 6 activerecord ruby-on-rails null-object-pattern

我是一个应用程序,Post belongs_to :user我想保留已删除用户的帖子.在查看作者被删除的帖子时,这可能会导致视图出错.我试着这样做:

class Post < ActiveRecord::Base
  belongs_to :author, class_name: 'User', foreign_key: 'user_id'

  def author
    author || NullUser.new
    super
  end
end
Run Code Online (Sandbox Code Playgroud)

这会导致"堆栈级别变深"错误.为什么?我能做到这一点:

class Post < ActiveRecord::Base
  belongs_to :user

  def author
    user || NullUser.new
  end

  def author=(user)
    self.user = user
  end
end
Run Code Online (Sandbox Code Playgroud)

但是以这种方式混淆我的协会似乎并不正确.最好的方法是什么?

Sub*_*has 14

要回答你的问题,

1. def author
2.   author || NullUser.new
3.   super
4. end
Run Code Online (Sandbox Code Playgroud)

在第1行中,您正在定义一个author方法.然后在第2行,你再次调用那个作者方法!这种情况一直在发生,并且你得到的堆栈级别太深了.正确的方法是,

def author
  super || NullUser.new
end
Run Code Online (Sandbox Code Playgroud)

所以你不再在内部调用author方法.你只是调用超类或返回NullUser.如果您在通话时遇到nil错误,请super添加额外的nil检查:

def author
  (super || NullUser.new) rescue NullUser.new
end
Run Code Online (Sandbox Code Playgroud)

救援语句将捕获所有错误,然后返回NullUser.new,因此您不必担心超级抛出错误.

编辑:

处理看起来更好的超级抛出异常的另一种方法:

def author
  (super rescue nil) || NullUser.new
end
Run Code Online (Sandbox Code Playgroud)