开发者

What is the proper way to check for existence of objects in Rails / Ruby?

开发者 https://www.devze.com 2023-02-05 08:55 出处:网络
I have a lot of models and relations. Due to this fact, there is lot of calls in views/controllers, which look like this:

I have a lot of models and relations. Due to this fact, there is lot of calls in views/controllers, which look like this:

 @object.something.with_something.value 

Some part of the c开发者_Go百科hain can end up being nil, which is perfectly ok. What is the proper/clean/fast way to check for the existence of the terminal object?

Is calling something like:

 @object.something.with_something.value if defined? @object.something.with_something.value 

Considered ok?


Natively, you'd need to use the && operator (not defined?), but this can get very verbose, very quickly.

So instead of doing this:

(@object && @object.something && @object.something.with_something &&
  @object.something.with_something.value)

You can do this when ActiveSupport is present:

@object.try(:something).try(:with_something).try(:value)

Or install the invocation construction kit and use its guarded evaluation tools:

Ick::Maybe.belongs_to YourClass
maybe(@object) { |obj| obj.something.with_something.value }


It's best to arrange the rest of your code in order to see this problem for at most the last object in a chain.

defined? won't do what you want. Something can be defined? and nil at the same time.

When the problem is restricted to the last attribute in a chain of references:

@object.something.with_something.value if @object.something.with_something

I might take advantage of the facts that:

nil.to_a => []
nil.to_s => ''
nil.to_f => 0.0
nil.to_i => 0

So, if you know that something is either nil or an Array, often you can write better code without any conditionals at all by writing something like:

something.to_a.each do |e|
  . . .


what.you.are.doing is sometimes called a "Train wreck". It's also described as a violation of the Law of Demeter.

That being said, I think there's something called "andand" that can help with what you're doing.


Another option is to use the Null Object pattern to ensure that none of those objects is ever nil. Arguably, if your code is going to chain access in that way, then something should always be defined.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号