Ruby on rails 在rails中对关联进行零检查的面向对象方法
我已经看了桑迪·梅茨的演讲好几次了。我意识到我在rails项目中到处都在进行零检查,但我不知道如何避免零检查,以及在涉及关联时如何以面向对象的方式进行零检查 以这些关联为例:Ruby on rails 在rails中对关联进行零检查的面向对象方法,ruby-on-rails,ruby,Ruby On Rails,Ruby,我已经看了桑迪·梅茨的演讲好几次了。我意识到我在rails项目中到处都在进行零检查,但我不知道如何避免零检查,以及在涉及关联时如何以面向对象的方式进行零检查 以这些关联为例: #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
#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.blog
=> nil
它在此处返回nil
,因为该用户
恰好没有关联的博客
,因此如果我对该用户
执行类似操作,则以下代码将中断应用程序:
@user.blog.title
=> undefined method `title' for nil:NilClass
简单的解决方法是以非面向对象的方式执行,只需执行nil检查(但这是我们想要避免的,因为否则nil检查在应用程序中绝对无处不在):
通过以下关联越深入,执行零检查就越麻烦,程序也就越复杂:
@user = User.find(1)
if @user.blog && @user.blog.hash_tag #checking for nil twice
@user.blog.hash_tag.tag_name
end
什么是避免关联零检查的面向对象方法
我知道rails’,尽管Metz似乎不推荐使用
try
方法。也许当谈到rails中的关联时:try
是最好的选择?我认为这可能是一种选择
我会使用:rescue
method注意:此方法捕获异常并相应响应;如果您需要以不同的方式响应异常,请不要使用此选项。我希望你能理解 例如:
2.1.1 :001 > var1 = nil
=> nil
2.1.1 :002 > my_val = var1.some_method
NoMethodError: undefined method `some_method' for nil:NilClass
from (irb):2
from /home/shiva/.rvm/rubies/ruby-2.1.1/bin/irb:11:in `<main>'
2.1.1 :003 > my_val = var1.some_method rescue ''
=> ""
try在调用nil时返回nil,无论它是否响应该方法:
nil.try(:to_i) # => nil, rather than 0
有一个漂亮的gem
和
,我在这种情况下使用它。通常,您需要写:
@user.blog && @user.blog.title
and
gem实现了通用的空模式And
使用方法And
扩展对象,该方法返回调用它的对象,除非该对象为nil。在nil的情况下,对于使用方法\u的所有方法调用,都返回NullPatern对象以返回nil
@user.blog.andand.title
当您需要检查更多情况时,它的功能更强大:
@user.blog && @user.blog.title && @user.blog.title.capitalize
变成:
@user.blog.andand.title.andand.capitalize
有一个编程设计指南叫做 以下是如何将其应用于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.blog
,您可以将它放入一个变量中,如@user\u blog=@user.blog
,并在需要时检查它是否存在,如:@user\u blog.present?
我查看了和gem,发现和gem与rails中的try
方法完全相同try
在2010年的版本2.3.2中为rails推出。最初发布的和gem是在2008年发布的,所以我认为和是一个很好的选择,直到try
出现并内置到rails中。太好了,你自己修复了它
@user.blog.andand.title
@user.blog && @user.blog.title && @user.blog.title.capitalize
@user.blog.andand.title.andand.capitalize
#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