我已经看了好几次 Sandi Metz 的 nothing is something 演讲。我意识到我在 Rails 项目中的所有地方都进行了 nil 检查,但我不知道如何避免 nil 检查以及如何在涉及关联时以面向对象的方式进行检查。
考虑这些关联:
#app/models/user.rb
class User < ActiveRecord::Base
belongs_to :blog
end
#app/models/blog.rb
class Blog < ActiveRecord::Base
belongs_to :hash_tag
has_one :user
end
#app/models/hash_tag.rb
class HashTag < ActiveRecord::Base
has_one :blog
end
我捕获了一个用户:
@user = User.find(1)
我想找到他的博客:
@user.blog
=> nil
它在此处返回
nil
,因为此 user
碰巧没有关联的 blog
,因此如果我对此 user
执行类似操作,以下代码将破坏应用程序:@user.blog.title
=> undefined method `title' for nil:NilClass
简单的解决方法是使用非面向对象的方式,只做一个 nil 检查(但这是我们想要避免的,否则 nil 检查在应用程序中绝对无处不在):
@user.blog.title if @user.blog
进行 nil 检查会变得越麻烦和程序越深入,如下所示:
@user = User.find(1)
if @user.blog && @user.blog.hash_tag #checking for nil twice
@user.blog.hash_tag.tag_name
end
避免对关联进行 nil 检查的面向对象方法是什么?
我知道 rails 的 try method ,尽管 Metz 似乎不推荐
try
方法。也许当涉及到 rails 中的关联时:try
是最好的选择? 最佳答案
有一个名为 The Law of Demeter 的编程设计指南
这是将它应用到 Rails 模型的方法:
#app/models/user.rb
class User < ActiveRecord::Base
belongs_to :blog
delegate :title, to: :blog, prefix: true, allow_nil: true
# then you can call user.blog_title
delegate :tag_name, to: :blog, prefix: true, allow_nil: true
# follow LoD
end
#app/models/blog.rb
class Blog < ActiveRecord::Base
belongs_to :hash_tag
delegate :tag_name, to: :hash_tag, allow_nil: true
has_one :user
end
现在你可以这样做:
@user = User.find(1)
@user.blog_title # no error even if there is no associated blog
@user.tag_name # no error even if there is no associatd blog or no associated hash_tag object
请阅读以下链接以获取引用:
关于ruby-on-rails - 在 Rails 中对关联进行 nil 检查的面向对象方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32961073/