ruby-on-rails - 以面向对象的方式对 Rails 中的关联进行 nil 检查

标签 ruby-on-rails ruby

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

相关文章:

ruby-on-rails - 数据抓取多个页面点击循环

ruby - 转换已经用 UTF-8 编码的 ruby​​ 字符串中的 unicode 字符

ruby-on-rails - Encoding::CompatibilityError(不兼容的字符编码:UTF-8 和 ASCII-8BIT)- 将文件上传到 Heroku 时

jquery - Rails 3 jQuery 识别 "this"对象

ruby-on-rails - Sinatra 对像 Controller 这样的 Web 服务的好处

ruby-on-rails - Ruby on Rails 错误处理、捕获错误和消息

ruby - 为什么我可以引用从未运行过的 if/unless/case 语句之外的变量?

ruby-on-rails - rails 4 : testing GET request on a namespaced controller

ruby-on-rails - 为什么我得到 NoMethodError?

ruby-on-rails - 无方法错误 : undefined method `created_at' for in Rails