Cleaner Ruby in a rails view

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

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.

just return an empty array when 'cart_item_option_values' is nil

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

regards.

-a

···

On Thu, 2 Mar 2006 petermichaux@yahoo.com wrote:

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

--
judge your success by what you had to give up in order to get it.
- h.h. the 14th dali lama

petermichaux@yahoo.com schrieb:

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?

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

petermichaux@yahoo.com writes:

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?

How about this:

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

# nil.to_a ==

···

Thanks,
Peter

--
Christian Neukirchen <chneukirchen@gmail.com> http://chneukirchen.org

Hi all,

Interesting discussion... I'll just add that the following:

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

Can be:

<%= render :partial => 'foo', :collection =>
item.cart_item_option_values %>

_foo.rhtml would contain the markup used to render each item in the
collection. Sometimes I also like to do this, however:

<%= render :partial => 'foos', :object => some_collection %>

And then in _foos.rhtml have logic like:

<% if foos -%>
  <ul> <!-- or whatever parent container is appropriate -->
    <%= render :partial => 'foo', :collection => foos %>
  </ul>
<% end -%>

In the latter example, you also might want to forego the collection
rendering capability and use ERb tags to do an each() block, simple
because too many levels of partials becomes cumbersome.

Either way, it's generally more pleasing (if not outright useful, say,
for less savvy designers) to remove more complicated logic from the
'root level' view templates. The reason being, I think, because once
you get to a certain point, you're logic is solid, but you're markup
structure and flow might demand tweaking.

is something like the following acceptable?

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

<% end %>

Forgot to add that with the second example, you'd probably want an <%
else -%> clause to output something useful in that event, but you're a
clever bunch. :wink:

Hi --

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

···

On Thu, 2 Mar 2006, petermichaux@yahoo.com wrote:

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! Ruby for Rails

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, dblack@wobblini.net wrote:

Hi --

On Thu, 2 Mar 2006, petermichaux@yahoo.com 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

Charlie Bowman
http://www.recentrambles.com

Charlie Bowman 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

···

--
Posted via http://www.ruby-forum.com/\.

Hi --

···

On Fri, 3 Mar 2006, Charlie Bowman 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 (dblack@wobblini.net)
Ruby Power and Light (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! Ruby for Rails

I think the "and-call" operator discussed recently would be a very very
very nice addition, especially since in Rails Views (or any
presentation layer on most any framework in most languages) has the
ever-so-common "obj ? obj.value : nil" mini-pattern.

Of course it doesn't really apply in this specific case since there's
an empty array available, but:

item.cart_item_option_values &? each do { |ov| blah }

Would be nice.

James Byrne 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...

···

--
Posted via http://www.ruby-forum.com/\.

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, dblack@wobblini.net wrote:

Hi --

On Fri, 3 Mar 2006, Charlie Bowman 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

Charlie Bowman
http://www.recentrambles.com

theoretically nil is no container...
practically this could help...

class NilClass
  def each
  end
end

···

--- Ursprüngliche Nachricht ---
Von: Charlie Bowman <charlie@castlebranch.com>
An: ruby-talk@ruby-lang.org (ruby-talk ML)
Betreff: Re: cleaner Ruby in a rails view
Datum: Fri, 3 Mar 2006 00:33:53 +0900

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, dblack@wobblini.net wrote:

> Hi --
>
> On Fri, 3 Mar 2006, Charlie Bowman 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

Charlie Bowman
http://www.recentrambles.com

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 Gray II

···

On Mar 2, 2006, at 9:33 AM, Charlie Bowman 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?

Hi --

···

On Fri, 3 Mar 2006, James Edward Gray II wrote:

On Mar 2, 2006, at 9:33 AM, Charlie Bowman 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?

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 (dblack@wobblini.net)
Ruby Power and Light (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! Ruby for Rails

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 Gray II wrote:

On Mar 2, 2006, at 9:33 AM, Charlie Bowman 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 Gray II

Charlie Bowman
http://www.recentrambles.com

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.