Ric*_*ard 5 null-object-pattern ruby-on-rails-3
尽管在这里看到一些关于轨道中的Null对象的答案,我似乎无法让它们工作.
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
Run Code Online (Sandbox Code Playgroud)
我的问题是在用户创建时,我为配置文件传递了适当的嵌套属性(profile_attributes),最后我的新用户使用了NullProfile.
我猜这意味着我的自定义配置文件方法在创建时被调用并返回NullProfile.我如何正确地执行此NullObject,以便这仅在读取时发生,而不是在对象的初始创建时发生.
我正在经历,如果它不存在,我想要一个干净的新对象(如果你这样做只是为了object.display
不犯错误,也许object.try(:display)
更好)这也是,这就是我发现的:
1:别名/alias_method_chain
def profile_with_no_nill
profile_without_no_nill || NullProfile
end
alias_method_chain :profile, :no_nill
Run Code Online (Sandbox Code Playgroud)
但由于 alias_method_chain 已被弃用,如果您处于边缘,您将不得不自己手动执行该模式...这里的答案似乎提供了更好、更优雅的解决方案
2(答案的简化/实用版本):
class User < ActiveRecord::Base
has_one :profile
accepts_nested_attributes_for :profile
module ProfileNullObject
def profile
super || NullProfile
end
end
include ProfileNullObject
end
Run Code Online (Sandbox Code Playgroud)
注意:您执行此操作的顺序(在链接的答案中进行了解释)
关于你尝试过的:
当你这样做的时候
def profile
@profile || NullProfile
end
Run Code Online (Sandbox Code Playgroud)
它不会按预期运行,因为关联是延迟加载的(除非您:include
在搜索中告诉它),所以 @profile 为零,这就是为什么您总是得到 NullProfile
def profile
self.profile || NullProfile
end
Run Code Online (Sandbox Code Playgroud)
它会失败,因为该方法正在调用自身,所以它有点像递归方法,你得到SystemStackError: stack level too deep