This project is archived and is in readonly mode.

#2281 ✓wontfix
Jason Arora

value_changed? helper method

Reported by Jason Arora | March 17th, 2009 @ 11:21 PM | in 2.x

Added a new helper method to TextHelper called value_changed?, also includes test cases and documentation.

value_changed? tracks the value passed in and returns true whenever the value changes from its previous setting. It can be useful when iterating through a set of data that is organized in subsets to display a new title for each subset.


# Assuming people has been sorted by occupation...
<% @people.each do |person| %>
  <%= "<h2>#{person.occupation.pluralize}</h2>" if value_changed?(person.occupation) %>
  <%= person.name %><br/>
<% end %>

This produces:


<h2>Doctors</h2>
Jane Doe
John Smith
<h2>Programmers</h2>
Rails Rules

This little bit of code replaces the common pattern of:


<% previous_value = nil %>
<% @people.each do |person| %>
  <% if previous_value != person.occupation %>
    <% previous_value = person.occupation %>
    <h2><%= person.occupation.pluralize %></h2>
  <% end %>
  <%= person.name %><br/>
<% end %>

Also, value_changed? accepts a name parameter to support nesting in loops (by default, the value is named "default").

I hope this is useful for others. It sure has been handy in my projects. Thanks!

Comments and changes to this ticket

  • Ian Terrell

    Ian Terrell March 18th, 2009 @ 04:35 PM

    Are there other use cases?

    Do you see this as much better than using Enumerable#group_by? (http://api.rubyonrails.org/class...)

    
    <% @people.group_by(&:occupation).each do |occupation, peeps| %>
      <h2><%= occupation %></h2>
      <% peeps.each do |person| %>
        <%= person.name %>
      <% end %>
    <% end %>
    
  • Jason Arora

    Jason Arora March 21st, 2009 @ 02:01 AM

    Thanks for posting, Ian. You are correct, Enumerable#group_by is the best way to handle this pattern when ordering by a model attribute.

    However, the value_changed? method works really well for dynamic cases, such as:

    
    <% @people.each do |person| %>
      <%= "<h2>#{person.name.first}</h2>" if value_changed?(person.name.first) %>
      <%= person.name %><br/>
    <% end %>
    
    # => <h2>A</h2>
    # => Alan
    # => Amy
    # => <h2>B</h2>
    # => Barry
    # => ...
    

    Is this more acceptable? Thanks again for the feedback.

    Regards, Jason

  • Ian Terrell

    Ian Terrell March 21st, 2009 @ 08:12 PM

    For this use case, Enumerable#group_by still seems best. The &:symbol syntax is shorthand for a block; you can spell it out for cases where you wish to group by something that isn't a method:

    
    <% @people.group_by{|person|person.name.first}.each do |initial, peeps| %>
      <h2><%= initial %></h2>
      <% peeps.each do |person| %>
        <%= person.name %>
      <% end %>
    <% end %>
    
  • Jeremy Kemper

    Jeremy Kemper March 22nd, 2009 @ 01:42 AM

    • State changed from “new” to “wontfix”

    Nice patch, but agreed that group_by is a better choice for the problem it's solving

  • Jason Arora

    Jason Arora March 22nd, 2009 @ 05:55 AM

    Duh. :-P

    You're totally right, Ian. Thanks!

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Pages