简体   繁体   中英

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

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 chain 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM