cleaner Ruby in a rails view

P

petermichaux

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
 
S

Scott

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

petermichaux

is something like the following acceptable?


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

<% end %>
 
P

Pit Capitain

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
 
D

dblack

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

--
David A. Black ([email protected])
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
 
C

Charlie Bowman

--=-4i6pYF1ImmYtva7CEaK7
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

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.


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


Charlie Bowman
http://www.recentrambles.com

--=-4i6pYF1ImmYtva7CEaK7--
 
J

James Byrne

Charlie said:
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
 
J

James Byrne

James said:
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...
 
C

Charlie Bowman

--=-jDWCcV0MLNdX8jYwGgc/
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

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



Because it's not a container or iterator.


David


Charlie Bowman
http://www.recentrambles.com

--=-jDWCcV0MLNdX8jYwGgc/--
 
J

James Edward Gray II

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. ;)

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
 
D

dblack

Hi --

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. ;)

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 ([email protected])
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
 
C

Charlie Bowman

--=-ok629ACj2M8gOTQiv+nt
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

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.


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. ;)

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

--=-ok629ACj2M8gOTQiv+nt--
 
B

Brian Cully

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

Yukihiro Matsumoto

Hi,

In message "Re: cleaner Ruby in a rails view"

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

Charlie Bowman

--=-iYMPYMsjAJXHpxWUOUNb
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

The only time this nil problem occurs for me is with rails views. With
all other ruby (about half my time is spent in ruby and the other half
web apps) code, I never have the nil problem unless I've written bad
code. I feel like web templates should not throw errors if you pass nil
values.


Hi,

In message "Re: cleaner Ruby in a rails view"

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


Charlie Bowman
http://www.recentrambles.com

--=-iYMPYMsjAJXHpxWUOUNb--
 
D

dblack

Hi --

The only time this nil problem occurs for me is with rails views. With
all other ruby (about half my time is spent in ruby and the other half
web apps) code, I never have the nil problem unless I've written bad
code. I feel like web templates should not throw errors if you pass nil
values.

Probably the best thing is to do whatever's necessary in the
controller to make sure the template can coast. So you could, for
example, put list.items (or whatever) in @items, making sure in
advance that it's an empty array if there aren't any.


David


Hi,

In message "Re: cleaner Ruby in a rails view"

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


Charlie Bowman
http://www.recentrambles.com

--
David A. Black ([email protected])
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
 
J

James Edward Gray II

Hi --



Probably the best thing is to do whatever's necessary in the
controller to make sure the template can coast. So you could, for
example, put list.items (or whatever) in @items, making sure in
advance that it's an empty array if there aren't any.

Bingo. I think that's the perfect answer here.

Remember that you can always declare Helper methods that deal with
the nils for you too.

James Edward Gray II
 
C

Charlie Bowman

--=-vTSG3gWAsTmXvHyNeNZe
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

I think that is the best answer so far....but that seems to go against
everything that makes ruby so great. Something just doesn't feel right
about creating an object just to say that it's empty. I guess I should
ask this on the rails list, but I like this list much better :) , Is is
possible to add methods to the nil class in only the views? If so, that
would be awsome!



Charlie Bowman
Programmer
Castle Branch Inc.

--=-vTSG3gWAsTmXvHyNeNZe--
 
M

Matthew Desmarais

Charlie said:
I think that is the best answer so far....but that seems to go against
everything that makes ruby so great. Something just doesn't feel right
about creating an object just to say that it's empty. I guess I should
ask this on the rails list, but I like this list much better :) , Is is
possible to add methods to the nil class in only the views? If so, that
would be awsome!





Charlie Bowman
Programmer
Castle Branch Inc.
Hi Charlie,

I think that David's plan is a good one. I also think that his answer
has less to do with Ruby and more to do with the appropriate use of the
Model-View-Controller framework (if that's the right word).

As I understand it, the role of the controller is to be the setup guy
for the view. You really want to have as little significant Ruby code
as you can in the view, and that's what David's answer is getting at.
Make the controller ensure that the view has an Array to deal with
rather than let the view worry about what you've given it.

Hope that helps.

Regards,
Matthew
 

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

Members online

Forum statistics

Threads
474,293
Messages
2,571,500
Members
48,188
Latest member
GerardRush

Latest Threads

Top