mattmccray

 
« 28 Years Progress | Home | Supporting Themes In … »

Simple Row Style Alternator

» Published October 20, 2005 under Rails, Software

In your view (rhtml):

[code lang="xml"] <% for user in @users %> <% end %>
Name
<%= user.name %>
[/code]

In your helper (rb): Updated!

[code lang="ruby"] def row_style @row_index ||= 0 @row_index += 1 @row_index % 2 == 0 ? "Even" : "Odd" end [/code]

10 comments

10.21.05 @ 05:24 Odo said...
Small and useful. Thanx.
10.21.05 @ 07:27 Forrest said...
Could you re-write the first line of your helper method as such?

@row_index |= 0

Just trying to firm up some of my understanding of Ruby.
10.21.05 @ 08:04 Jason said...
Forrest,

Almost – you’ll want two pipes, as in ||=

irb(main):001:0> foo = 0 if !foo
=> 0
irb(main):002:0> foo = 1 if !foo
=> nil
irb(main):003:0> foo
=> 0
irb(main):004:0> bar ||= 0
=> 0
irb(main):005:0> bar ||= 1
=> 0

I’m still trying to learn Ruby, too – I think it works as follows:

a |= 0 expands to a = a | 0.
b ||= 0 expands to b = b || 0.

The | operator evaluates the two operands as boolean values and returns true if either is true (not short-circuiting). Seems most anything except nil and false eval to true here, including 0. I’m pretty sure on this, but can’t find a reference to corroborate it.

The || operator returns the first operand if it evaluates to true; otherwise it returns the second operand. So, given b = b || 0, if b is nil, (b || 0) returns 0.

Can a Ruby expert step in and confirm/clarify?
10.21.05 @ 08:23 Forrest said...
Jason,

You are correct. The ||= performs what I was thinking of. I didn’t even run |= through irb. Guess I should do that from now on :o) The ||= operator is also explained in the “Agile Web Development With Rails” book on page 479. Thanks for the correction and help.
10.21.05 @ 11:03 M@ said...
Nice! Thanks for the suggestion, I’ll update the post to show this approach.
10.21.05 @ 11:49 protocool said...
Good idea for a helper.

Alack, there’s a hidden gotcha if you happen to have more than one zebra list in the current scope. I know, I know, it’s seems strange to have more than one list on a page but hey, I’m sure somebody is doing it :-p

Anyhow the gotcha is that you can’t reset @row_index to 0 except for in the template itself and that exposes the guts of your helper function in unpleasant ways.

How about something like this:

def row_style(opt = :row_style)
case opt
when Fixnum
return opt % 2 0 ? 'Even' : 'Odd'
when Symbol
val = instance_variable_get("@#{opt.id2name}_counter") || 1
instance_variable_set("@#{opt.id2name}_counter", val + 1)
return val % 2 0 ? ‘Even’ : ‘Odd’
else
raise ArgumentError, “row_style: descriptive error message here”
end
end
10.22.05 @ 00:35 Stephen Waits said...
def row_style
row_index = 1 - (row_index ||= 0)
@row_index == 0 ? “Even” : “Odd”
end
10.27.05 @ 13:36 Will Rogers said...
Re: protocool

You are thinking too hard.

def row_style(key = :default)
row_indices ||= {}
row_indices[key] = 1 – (row_indices[key] ||= 0)
row_indices[key] == 0 ? “even” : “odd”
end

with thanks to Stephen for the clever linecount compression ;)
01.20.06 @ 14:06 Ben Marini said...
There’s a rails function for this now:

“>
01.20.06 @ 14:07 Ben Marini said...
Whoops.

cycle(‘even’,‘odd’) is what I meant to say. Check it out in the rails api.

No trackbacks

Trackback link:

Please enable javascript to generate a trackback url


You may use Textile, or simple html tags (B,I). Feel free to use Emoticons too. Oh, and please limit yourself to only five links per comment. Anything more and you'll probably get detained by the spam police.