Forum: Ruby cleaner Ruby in a rails view

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
94e31fd5108ef7932267dfc94412b668?d=identicon&s=25 unknown (Guest)
on 2006-03-02 05:03
(Received via mailing list)
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
Ee5c1f36549c4ddca2189f9c4cf36f2c?d=identicon&s=25 Scott (Guest)
on 2006-03-02 05:08
(Received via mailing list)
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.
94e31fd5108ef7932267dfc94412b668?d=identicon&s=25 unknown (Guest)
on 2006-03-02 05:13
(Received via mailing list)
is something like the following acceptable?


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

<% end %>
Cb48ca5059faf7409a5ab3745a964696?d=identicon&s=25 unknown (Guest)
on 2006-03-02 05:17
(Received via mailing list)
On Thu, 2 Mar 2006 petermichaux@yahoo.com 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
93d566cc26b230c553c197c4cd8ac6e4?d=identicon&s=25 Pit Capitain (Guest)
on 2006-03-02 11:36
(Received via mailing list)
petermichaux@yahoo.com 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
7264fb16beeea92b89bb42023738259d?d=identicon&s=25 Christian Neukirchen (Guest)
on 2006-03-02 12:38
(Received via mailing list)
petermichaux@yahoo.com 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 == []
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-03-02 15:18
(Received via mailing list)
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

--
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! http://www.manning.com/books/black
89d967359903c639d31e4cad4569f537?d=identicon&s=25 Charlie Bowman (Guest)
on 2006-03-02 16:04
(Received via mailing list)
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:

>
> David
Charlie Bowman
http://www.recentrambles.com
171ea139761951336b844e708d1547ab?d=identicon&s=25 James Byrne (byrnejb)
on 2006-03-02 16:25
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
171ea139761951336b844e708d1547ab?d=identicon&s=25 James Byrne (byrnejb)
on 2006-03-02 16:29
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...
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-03-02 16:31
(Received via mailing list)
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! http://www.manning.com/books/black
89d967359903c639d31e4cad4569f537?d=identicon&s=25 Charlie Bowman (Guest)
on 2006-03-02 16:34
(Received via mailing list)
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:

> David
Charlie Bowman
http://www.recentrambles.com
36958dd94ca666a38483df282a5214d5?d=identicon&s=25 Peter Ertl (Guest)
on 2006-03-02 16:37
(Received via mailing list)
theoretically nil is no container...
practically this could help...

class NilClass
  def each
  end
end
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2006-03-02 16:43
(Received via mailing list)
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.  ;)

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
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-03-02 16:53
(Received via mailing list)
Hi --

On Fri, 3 Mar 2006, James Edward Gray 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 (dblack@wobblini.net)
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
89d967359903c639d31e4cad4569f537?d=identicon&s=25 Charlie Bowman (Guest)
on 2006-03-02 16:53
(Received via mailing list)
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:

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


Charlie Bowman
http://www.recentrambles.com
Cbf97cb8424001f2a4a482a7e5fddfdb?d=identicon&s=25 Brian Cully (Guest)
on 2006-03-02 17:38
(Received via mailing list)
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.
36958dd94ca666a38483df282a5214d5?d=identicon&s=25 Peter Ertl (Guest)
on 2006-03-02 17:43
(Received via mailing list)
full ack [++]
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-03-02 17:49
(Received via mailing list)
Hi --

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


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! http://www.manning.com/books/black
93d566cc26b230c553c197c4cd8ac6e4?d=identicon&s=25 Pit Capitain (Guest)
on 2006-03-02 18:44
(Received via mailing list)
dblack@wobblini.net 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 :-)

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
0ec4920185b657a03edf01fff96b4e9b?d=identicon&s=25 Yukihiro Matsumoto (Guest)
on 2006-03-02 19:07
(Received via mailing list)
Hi,

In message "Re: cleaner Ruby in a rails view"
    on Fri, 3 Mar 2006 01:38:38 +0900, "Brian Cully" <bcully@gmail.com>
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.
89d967359903c639d31e4cad4569f537?d=identicon&s=25 Charlie Bowman (Guest)
on 2006-03-02 19:55
(Received via mailing list)
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.


On Fri, 2006-03-03 at 03:07 +0900, Yukihiro Matsumoto wrote:

> something like nil in Objective-C by yourself, using the combination
>     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
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-03-02 20:06
(Received via mailing list)
Hi --

On Fri, 3 Mar 2006, Charlie Bowman wrote:

> 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



>>
>>     Objective-C.
>
--
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! http://www.manning.com/books/black
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2006-03-02 20:13
(Received via mailing list)
On Mar 2, 2006, at 1:06 PM, dblack@wobblini.net wrote:

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

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
89d967359903c639d31e4cad4569f537?d=identicon&s=25 Charlie Bowman (Guest)
on 2006-03-02 20:25
(Received via mailing list)
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!


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


Charlie Bowman
Programmer
Castle Branch Inc.
0817571d150afead454f4220007042fe?d=identicon&s=25 Matthew Desmarais (Guest)
on 2006-03-02 20:38
(Received via mailing list)
Charlie Bowman wrote:
>>> 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.
>>>
>
>
> 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
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-03-02 20:40
(Received via mailing list)
Hi --

On Fri, 3 Mar 2006, Charlie Bowman wrote:

>> I wrote:
>>>
>>> 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.
> I think that is the best answer so far....but that seems to go against
> everything that makes ruby so great.

That doesn't say much for all the other answers :-)

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

I suppose you could engineer a way to do that, but it sounds awfully
fragile, and like an awful lot of trouble to go to.  I'd rather
normalize the data to an array (or whatever) and then just let each
array take care of itself.


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! http://www.manning.com/books/black
89d967359903c639d31e4cad4569f537?d=identicon&s=25 Charlie Bowman (Guest)
on 2006-03-02 21:40
(Received via mailing list)
I guess I am being a little picky.  ruby and rails both are the best at
what they do and it's hard to watch it fall short ( in my very picky
eyes ) in this one area.  I am going to work on adding a plugin to rails
that will fix the nil problem.  At least then I won't have to call a
helper method, rescue nil, or create an empty object just to display a
view.  This has been a great discussion! It's too bad that it wasn't on
the rails list...


>
>
> David


Charlie Bowman
http://www.recentrambles.com
822a498b26a2cb7d1f0f2e7e37ce61b2?d=identicon&s=25 Ed Howland (Guest)
on 2006-03-02 22:08
(Received via mailing list)
On 3/2/06, dblack@wobblini.net <dblack@wobblini.net> wrote:
> 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

Just to illustrate a point about Rails, I had a similar problem. Some
other code allowed a record to be posted to the DB w/o a good
referential link. IOW, the FK in the record pointed to a missing
record in the linked to table. The Rails view just spit out an
attribute of the linked table and that caused the app to crash because
table1.table2 was nill and table1.table2.field => 'field' was not a
valid method of nil.

So I tried the trick posted earlier and it cleaned it up nicely. I'm
sure that this problem comes up all the time, and there are probably
better ways to handle it, but this abstraction was quite nice:

In the controller's helper, I added a method_missing dispatcher:

module MycontrollerHelper
 def method_missing(methodname, *args)
   "MISSING RECORD"
 end
end

In the view: (in my case rxml)

   xml << (table1.table2 || self).field

Hopefully, you have no other need for method_missing in your view.

I'd be interested in others take on this common problem.

Ed
0817571d150afead454f4220007042fe?d=identicon&s=25 Matthew Desmarais (Guest)
on 2006-03-02 22:08
(Received via mailing list)
Charlie Bowman wrote:
>>> Something just doesn't feel right about creating an object just to
>> David
>>
>
>
> Charlie Bowman
> http://www.recentrambles.com
>
>
You know, I don't much monitor the rails list but I think that maybe
this is something that you would want to run by those folks before you
make any big design decisions.  The folks over there really do spend a
lot of time on rails-specific issues and you'll probably get more
discussion over there if not better.  I'd be curious to hear what they'd
say about this myself since I've been where (I suspect) you are before.

Regards,
Matthew
41c597a48c80e37ba68d1adc7095ea0e?d=identicon&s=25 unknown (Guest)
on 2006-03-03 06:59
(Received via mailing list)
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.
40823088cec28c3224ff4c46ced1beda?d=identicon&s=25 Seth Thomas Rasmussen (Guest)
on 2006-03-03 22:00
(Received via mailing list)
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.
40823088cec28c3224ff4c46ced1beda?d=identicon&s=25 Seth Thomas Rasmussen (Guest)
on 2006-03-03 22:00
(Received via mailing list)
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. ;)
This topic is locked and can not be replied to.