The Ruby Way to build an object unless nil?

P

Peter Fitzgibbons

Hello all,

I have this :

def mymethod
a =3D someobjectreference('a')
if a.nil?
return nil
end
b =3D a.someattribute_might_be_nil
if b.nil?
return nil
end
c =3D b.someattribute_might_be_nil
if c.nil?
return nil
end
c.dosomething
end

What is the ruby way to handle the if .nil? ladder created here?

Thanks.
Peter Fitzgibbons
 
K

Kevin Ballard

I'm not sure what the ideal is, but this is certainly more terse:

def mymethod
a = someobjectreference('a')
b = a.some_attribute unless a.nil?
c = b.some_attribute unless b.nil?
c.dosomething unless c.nil?
end

If any of those are nil, the rest of the statements will evaluate to
nil as well.
 
J

Jeffrey Moss

This could be accomplished using a recursive method. It is more resource
intensive than what you have here, but it would end up being simpler and
more versatile.

def mymethod(a, count=1)
return if a.nil?
return c.dosomething if count == 3
mymethod(a.someattribute_might_be_nil, count+1)
end
 
P

Peter Fitzgibbons

I'm not sure what the ideal is, but this is certainly more terse:

def mymethod
a =3D someobjectreference('a')
b =3D a.some_attribute unless a.nil?
c =3D b.some_attribute unless b.nil?
c.dosomething unless c.nil?
end

If any of those are nil, the rest of the statements will evaluate to
nil as well.
Thank you Kevin. I knew I was missing the obvious.
 
A

Austin Ziegler

Hello all,

I have this :

def mymethod
a =3D someobjectreference('a')
if a.nil?
return nil
end
b =3D a.someattribute_might_be_nil
if b.nil?
return nil
end
c =3D b.someattribute_might_be_nil
if c.nil?
return nil
end
c.dosomething
end

One possibility:

def mymethod(a =3D nil)
a.attr1.attr2.do_something
rescue NoMethodError
return nil
end

You may want to disambiguate the NoMethod error to make sure it's not
raised in #do_something:

def mymethod(a =3D nil)
c =3D a.attr1.attr2 rescue return nil
c.do_something
end

-austin
 
J

Jeremy Kemper

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

One possibility:
def mymethod(a = nil)
a.attr1.attr2.do_something
rescue NoMethodError
return nil
end

I like that when I'm only concerned with the final value (e.g. in an
erb template)
<%= foo.bar.baz rescue nil %>

otherwise,
if a = foo and b = a.bar then b.baz end

Regards,
jeremy
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (Darwin)

iD8DBQFDVU9qAQHALep9HFYRAuVyAJ4tac4WhOCtB6zEkVY8nhr4btygUQCg2Gda
az395n6c6LrPmWlwVSlzOJ8=
=ec6D
-----END PGP SIGNATURE-----
 
G

gwtmp01

I'm not sure what the ideal is, but this is certainly more terse:
def mymethod
a = someobjectreference('a')
b = a.some_attribute unless a.nil?
c = b.some_attribute unless b.nil?
c.dosomething unless c.nil?
end

How about:

module Kernel
def send_each(*mlist)
mlist.inject(self) do |obj, mname|
return nil unless obj
obj.send(mname)
end
end
end

puts "ruby rocks".send_each:)reverse, :chop, :capitalize) # ->
"Skcor ybu"



Gary Wright
 
K

Kevin Ballard

Joby said:
class NilClass
def method_missing(method, *args)
nil
end
end

Forget the ladder... use the elevator! ;)

While that certainly works, I would advise not doing that. The problem
with this is it will hide problems that might show up elsewhere in your
code.
 
J

Joby Bednar

Well, IF you actually want to debug... true... it could cause some
problems, though you could also put in some debug logging or such
before returning nil. But, with this method (a little pun there) you
can place nil catching at major gatekeeper points in the code instead
of on every line where a nil might be returned. Especially when one
line would be broken out into numerous.

-J()by
http://jobybednar.com
 
S

Sean O'Halpin

How about:

module Kernel
def send_each(*mlist)
mlist.inject(self) do |obj, mname|
return nil unless obj
obj.send(mname)
end
end
end

puts "ruby rocks".send_each:)reverse, :chop, :capitalize) # ->
"Skcor ybu"
Nice, but your example is no different to

puts "ruby rocks".reverse.chop.capitalize

Maybe this shows off your method better:

class String
def nil_method
nil
end
end
puts "ruby rocks".send_each:)reverse, :chop, :nil_method, :capitalize)
# -> nil

Regards,

Sean
 
E

Eric Mahurin

--- Kevin Ballard said:
=20
While that certainly works, I would advise not doing that.
The problem
with this is it will hide problems that might show up
elsewhere in your
code.

I also think you shouldn't overload the semantics of "nil"
anymore. It already has enough meaning. Use another object
(like below), or just check for nil explicitly like most other
do.

What I do when I need this kind of functionality is just make a
"do nothing" object that just returns self for everything.=20
Then your callers just pass this when they want to do nothing
for that object:

Nothing =3D Class.new {
def method_missing(method, *args, &block)
self
end
}.new

An example is that I have a method that takes a buffer object
where I store results. Sometimes I don't need the buffer, so I
just pass it something like the above.



=09
__________________________________=20
Yahoo! Music Unlimited=20
Access over 1 million songs. Try it free.
http://music.yahoo.com/unlimited/
 
D

Dominik Bathon

Hello all,

I have this :

def mymethod
a =3D someobjectreference('a')
if a.nil?
return nil
end
b =3D a.someattribute_might_be_nil
if b.nil?
return nil
end
c =3D b.someattribute_might_be_nil
if c.nil?
return nil
end
c.dosomething
end

How about:

def mymethod
if
a =3D someobjectreference('a') and
b =3D a.someattribute_might_be_nil and
c =3D b.someattribute_might_be_nil
c.dosomething
else
nil
end
end

It isn't exactly the same, because it would also return nil if a, b or c =
=20
were false instead of nil.

Dominik
 
J

John Carter

def mymethod
a = someobjectreference('a')
if a.nil?
return nil
end
b = a.someattribute_might_be_nil
if b.nil?
return nil
end
c = b.someattribute_might_be_nil
if c.nil?
return nil
end
c.dosomething
end

class NilObject
def someattribute
nil
end

def dosomething
nil
end
end

def mymethod
someobjectrefence('a').someattribute.someattribute.dosomething
end


John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : (e-mail address removed)
New Zealand

Carter's Clarification of Murphy's Law.

"Things only ever go right so that they may go more spectacularly wrong later."

From this principle, all of life and physics may be deduced.
 
J

John Carter

class NilObject

Sorry, that should be NilClass



John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : (e-mail address removed)
New Zealand

Carter's Clarification of Murphy's Law.

"Things only ever go right so that they may go more spectacularly wrong later."

From this principle, all of life and physics may be deduced.
 
J

John Carter

While that certainly works, I would advise not doing that. The problem
with this is it will hide problems that might show up elsewhere in your
code.


Yes yes we have had this on out all before... The answer is nil is
overloaded to mean several things. eg. Not initialized and Not Applicable.

So how about..

class ReDuckulous
# I just Quack myself up...
def someattribute
self
end

def dosomething
self
end
end

DAFFY = ReDuckulous.new

def mymethod
a = somereference('a')
a = DAFFY unless a # What's up Doc?
a.someattribute.someattribute.dosomething
end


John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : (e-mail address removed)
New Zealand

Carter's Clarification of Murphy's Law.

"Things only ever go right so that they may go more spectacularly wrong later."

From this principle, all of life and physics may be deduced.
 
A

Adam Sanderson

Not quite a direct response, but the ||= idiom is also handy for these
things
ie:

irb(main):001:0> a = nil
irb(main):002:0> b = 4
irb(main):003:0> b ||= 7
=> 4
irb(main):004:0> b
=> 4
irb(main):005:0> a ||= b
=> 4
irb(main):006:0> a
=> 4

.adam
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
474,175
Messages
2,570,942
Members
47,489
Latest member
BrigidaD91

Latest Threads

Top