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