我看过 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/