Cleaner Ruby in a rails view


#1

Hi,

I think this is a pure Ruby question. I seem to be writing this nested
structure constantly

<% unless item.cart_item_optional_variations.empty? %>
<% item.cart_item_option_values.each do |ov| %>

<% end %>
<% end %>

Is there a way to write this in one steps so i am not doing nil.each?

Thanks,
Peter


#2

You can make sure that item.cart_item_optional_values is always equal
to an array, be it empty or full, that way you’re .each wont fail, it
just wont have anything to enumerate over with an empty array.


#3

is something like the following acceptable?

<% ( item.cart_item_option_values || [] ).each do |ov| %>

<% end %>


#4

removed_email_address@domain.invalid schrieb:

Is there a way to write this in one steps so i am not doing nil.each?
Hi Peter, since empty? isn’t a method of NilClass, it seems that your
arrays never are nil, so you can just remove the empty? test.

Regards,
Pit


#5

removed_email_address@domain.invalid writes:

Is there a way to write this in one steps so i am not doing nil.each?

How about this:

<% item.cart_item_option_values.to_a.each do |ov| %>
<% end %>

nil.to_a == []


#6

Hi –

On Thu, 2 Mar 2006, removed_email_address@domain.invalid wrote:

is something like the following acceptable?

<% ( item.cart_item_option_values || [] ).each do |ov| %>

<% end %>

If you get the right-hand side of that, it means the left-hand side
was nil or false – in which case calling #empty? on it will raise an
error. (Actually in your original post you had _values once and
_variations once, but I’m assuming that was an error.)

On the other hand, if you’re sure you can call #empty? on it, that
suggests you know it will be an array, in which case you can just call
#each on it and let it iterate zero times if it’s empty.

David


David A. Black (removed_email_address@domain.invalid)
Ruby Power and Light (http://www.rubypowerandlight.com)

“Ruby for Rails” chapters now available
from Manning Early Access Program! http://www.manning.com/books/black


#7

On Thu, 2 Mar 2006 removed_email_address@domain.invalid wrote:

Is there a way to write this in one steps so i am not doing nil.each?

Thanks,
Peter

just return an empty array when ‘cart_item_option_values’ is nil

<% (item.cart_item_option_values || []).each do |ov| %>

regards.

-a


#8

Charlie B. wrote:

As a side thought. Why doesn’t the nil class have an each method that
returns nothing. It seems that this problem comes up quite often.

irb(main):001:0> a = nil
=> nil
irb(main):002:0> a.to_a
=> []
irb(main):003:0> a.to_a.each {|n| puts “The index is: #{n.index}”}
=> []
irb(main):004:0>

Does this suit?

Regards,
Jim


#9

James B. wrote:

irb(main):003:0> a.to_a.each {|n| puts “The index is: #{n.index}”}

should be:

a.to_a.each {|n| puts “The index is: #{a.to_a.index(n)}”}

sigh…


#10

Hi –

On Fri, 3 Mar 2006, Charlie B. wrote:

As a side thought. Why doesn’t the nil class have an each method that
returns nothing. It seems that this problem comes up quite often.

Because it’s not a container or iterator.

David


David A. Black (removed_email_address@domain.invalid)
Ruby Power and Light (http://www.rubypowerandlight.com)

“Ruby for Rails” chapters now available
from Manning Early Access Program! http://www.manning.com/books/black


#11

As a side thought. Why doesn’t the nil class have an each method that
returns nothing. It seems that this problem comes up quite often.

On Thu, 2006-03-02 at 23:18 +0900, removed_email_address@domain.invalid wrote:

David
Charlie B.
http://www.recentrambles.com


#12

theoretically nil is no container…
practically this could help…

class NilClass
def each
end
end


#13

On Mar 2, 2006, at 9:33 AM, Charlie B. wrote:

I know this is the ruby list and not the rails list but it would be
nice
if we didn’t have to add code to our views to rescue nils. I guess
you
could add the method each if you to the nil class right?

You can, sure. Whether or not it is a good idea is the question. :wink:

Currently, when you call each() on nil, it explodes. This is a good
thing, because it takes you right to the problem. You were expecting
to have an Enumerable, but you really have a nil.

If we take that away, Ruby will start silently accepting what are
most likely mistakes. While that may keep you from typing (enum ||
[]).each… in some places, it will prevent Ruby from catching real
errors in others. Better that we explicitly state that nil is okay
in this case, and let Ruby watch our back for us the rest of the
time, don’t you think?

James Edward G. II


#14

Hi –

On Fri, 3 Mar 2006, James Edward G. II wrote:

Enumerable, but you really have a nil.

If we take that away, Ruby will start silently accepting what are most likely
mistakes. While that may keep you from typing (enum || []).each… in some
places, it will prevent Ruby from catching real errors in others. Better
that we explicitly state that nil is okay in this case, and let Ruby watch
our back for us the rest of the time, don’t you think?

Yes, definitely. Almost every time I get one of these “undefined
method `x’ for nil” messages, it’s a message I’m glad I got because it
shows me something was wrong. It may be something wrong with my code,
or it may just be that something somewhere else returns nil rather
than [] (or whatever) on failure, and I hadn’t realized it.

David


David A. Black (removed_email_address@domain.invalid)
Ruby Power and Light (http://www.rubypowerandlight.com)

“Ruby for Rails” chapters now available
from Manning Early Access Program! http://www.manning.com/books/black


#15

I know this is the ruby list and not the rails list but it would be nice
if we didn’t have to add code to our views to rescue nils. I guess you
could add the method each if you to the nil class right?

On Fri, 2006-03-03 at 00:29 +0900, removed_email_address@domain.invalid wrote:

David
Charlie B.
http://www.recentrambles.com


#16

In lisp, nil is the empty set, and can be enumerated in the standard
ways.

In ObjC, and, I believe, Smalltalk, nil swallows all messages and
returns nil.

This is /exceedingly/ useful in writing very small amounts of code, and
I am highly irritated that ruby didn’t get this right, because it leads
to tons and tons of small error checks that are otherwise un-needed.

“Catches more errors” isn’t supposed to be the answer in the ruby
idiom, it’s just another case of relying on static type checks instead
of proper testing, which is exactly what we’re not supposed to be
doing, right? Otherwise we’d all be using java because rigid typing
“catches more errors”.

I would love for ruby’s nil to behave properly, as it does in lisp and
objc. You can ask nil anything, but all you’re going to get back is nil.


#17

I’m not so sure. I’ve been using perls Template-Toolkit for the last
several years and I love the fact that my template doesn’t care weather
or not I actually passed it a variable. It allows me to avoid all the
problems that rails users (me included ) keep having. I try to re-use
my views with as many actions as possible, and this creates a lot of
rescue nil code. Maybe it’s just personal preference or maybe I’m just
used to TT but I definitely would rather have my views just skip over
any nil values than throw an error.

On Fri, 2006-03-03 at 00:43 +0900, James Edward G. II wrote:

Currently, when you call each() on nil, it explodes. This is a good
James Edward G. II

Charlie B.
http://www.recentrambles.com


#18

full ack [++]


#19

removed_email_address@domain.invalid schrieb:

On Fri, 3 Mar 2006, Brian Cully wrote:

I would love for ruby’s nil to behave properly, as it does in lisp and
objc.

A bit of a conversation-stopper, but we’ll just agree to disagree :slight_smile:

FWIW: +1 for David’s view.

IMO, if you have problems getting nil from a method that is supposed to
return an enumerable you should change the method, not the nil object.

Regards,
Pit


#20

Hi,

In message “Re: cleaner Ruby in a rails view”
on Fri, 3 Mar 2006 01:38:38 +0900, “Brian Cully” removed_email_address@domain.invalid
writes:

|I would love for ruby’s nil to behave properly, as it does in lisp and
|objc. You can ask nil anything, but all you’re going to get back is nil.

Which one behave more properly? Lisp, or Objective-C? Since they
have different behavior for nil[1]. For your information, you can
define
something like nil in Objective-C by yourself, using the combination
of BlankSlate and method_missing. Or you can even hack the
interpreter to make nil behave “properly”[2]. It’s pretty easy.

						matz.

[1] Try (1+ nil) in your Lisp REPL. In Lisp, nil is just a (), not
that something which returns nil for every request, like one in
Objective-C.
[2] But I’m sure you will soon find out making nil behave like you
want is a pretty bad idea. Trust me. I did it 10 years ago. It
swallowed so many errors, and made my debugging horrible. Perhaps
a separated special value dedicated for the purpose might be
better.