Why does this work?

Bryan M wrote:

@users = Array.new @employees.each do |employee|   @users.push([employee.id => employee.lname << ", " << employee.fname]) end

And in my template, I have:

<%= collection_select(:profile, :user, @employees, :id, :lname) %>

And lo and behold, I get a text box with each name formatted like "Smith, John." But I don't see how its possible, since in my collection_select statement, I reference the original @employees hash and not @users. I also only specify :lname as a parameter. But if I take out the each loop, it goes back to only listing the last name. What gives? The only explanation I can think of is if the @employees.each loop is modifying @employees hash itself.

It is. The '<<' method of String doesn't just return the new concatenated string, it actually modifies the original string as well.

So if I have

a = "Hello" a << " world"

then a will now contain "Hello world".

In your iterator, you're actually adding ", " and employee.fname to employee.lname for each employee. Good job you weren't calling employee.save anywhere in there!

If you want to concatenate strings without this side effect, you could do something like:

@users.push(employee.id => "#{employee.lname}, #{employee.fname}")

Chris

Chris Mear wrote:

Bryan M wrote: > @users = Array.new > @employees.each do |employee| > @users.push([employee.id => employee.lname << ", " << employee.fname]) > end

If you want to concatenate strings without this side effect, you could do something like:

@users.push(employee.id => "#{employee.lname}, #{employee.fname}")

Of course, if you want to be really Rubyish, you could replace that whole lot with:

@users = @employees.collect {|e| [e.id, "#{employee.lname}, #{employee.fname}"]}

Chris