# Populating array of text\_fields from an array of model objec

**URL:** <https://www.ruby-forum.com/t/populating-array-of-text-fields-from-an-array-of-model-objec/60974>\
**Category:** Rails\
**Created:** [May 18, 2006, 11:27pm UTC](https://www.ruby-forum.com/t/populating-array-of-text-fields-from-an-array-of-model-objec/60974 "2006-05-18T23:27:53Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![random52k](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/7bcc69/32.png) [@random52k](https://www.ruby-forum.com/u/random52k)\
**Post date:** [May 18, 2006, 11:27pm UTC](https://www.ruby-forum.com/t/populating-array-of-text-fields-from-an-array-of-model-objec/60974/1 "2006-05-18T23:27:53Z")

</div>

I have in my view the following:

\<% 0.upto(@num\_performances) do |idx| -%\>  
\<%= text\_field ‘performance’, ‘city’, :index =\> idx, %\>  
\<%= text\_field ‘performance’, ‘venue’, :index =\> idx, %\>  
\<% end -%\>

and in my controller I have:

@performance = [Performance.new(“city” =\> “Toronto”, “venue” =\> “Opera  
House”),  
Performance.new(“city” =\> “Toronto”, “venue” =\>  
“The Rivoli”),  
Performance.new(“city” =\> “Toronto”, “venue” =\>  
“The Gladstone”)]

but when I try to view this page, rails gives me the exception:

undefined method `city’ for #Array:0x8dac4f4

so it looks like rails is trying to send the “city” method to the  
entire @performance array, rather than the element at the given index.  
When I comment out the above @performance line, my view is rendered  
and I get:

So I can post from this form to an action and I receive the following:

Parameters: { performance"=\>{“0”=\>{“city”=\>“Toronto”, “time”=\>"",  
“date”=\>"", “venue”=\>“The Opera House”, “city\_id”=\>""},  
“1”=\>{“city”=\>“Toronto”, “time”=\>"", “date”=\>"", “venue”=\>“The  
Social”, “city\_id”=\>""}, “2”=\>{“city”=\>"", “time”=\>"", “date”=\>"",  
“venue”=\>"", “city\_id”=\>""}}, … }

which I can easily turn into an array of Performance objects… But the  
problem is, say the user posts this form and it has errors - I need to  
re-populate the form fields, but I’m not sure how to get rails to take  
an array of Performance objects and insert the appropriate elements  
back into the corresponding text fields. I thought that by providing  
an :index parameter to the text\_field declaration, rails would realize  
that it should send the method (such as ‘city’, or ‘venue’) to the  
element of the array at that index, and not the entire array…

Of course I could just change my view so that I manually pull out the  
information from the @performance array by iterating over it, but I  
just wanted to check to see if there’s something I’m doing wrong  
before going that route. Any information is greatly appreciated,  
thanks.

Mike

---

<div class="post-metadata">

**Author:** ![random52k](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/7bcc69/32.png) [@random52k](https://www.ruby-forum.com/u/random52k)\
**Post date:** [May 19, 2006, 3:08am UTC](https://www.ruby-forum.com/t/populating-array-of-text-fields-from-an-array-of-model-objec/60974/2 "2006-05-19T03:08:29Z")

</div>

Mike G. wrote:

> House"),  
> Performance.new(“city” =\> “Toronto”, “venue” =\>  
> “The Rivoli”),  
> Performance.new(“city” =\> “Toronto”, “venue” =\>  
> “The Gladstone”)]
> 
> but when I try to view this page, rails gives me the exception:
> 
> undefined method `city’ for #Array:0x8dac4f4

Pluralize your controller variable (@performances = …), then in  
your view write:

\<% @performances.each\_with\_index do |@performance, idx| -%\>  
\<%= text\_field ‘performance’, ‘city’, :index =\> idx %\>  
\<%= text\_field ‘performance’, ‘venue’, :index =\> idx %\>  
\<% end -%\>

–  
We develop, watch us RoR, in numbers too big to ignore.

---

<div class="post-metadata">

**Author:** ![random52k](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/7bcc69/32.png) [@random52k](https://www.ruby-forum.com/u/random52k)\
**Post date:** [May 19, 2006, 5:50pm UTC](https://www.ruby-forum.com/t/populating-array-of-text-fields-from-an-array-of-model-objec/60974/3 "2006-05-19T17:50:50Z")

</div>

On 5/18/06, Mark Reginald J. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > @performance = [Performance.new(“city” =\> “Toronto”, “venue” =\> "Opera  
> > Pluralize your controller variable (@performances = …), then in  
> > your view write:
> 
> \<% @performances.each\_with\_index do |@performance, idx| -%\>  
> \<%= text\_field ‘performance’, ‘city’, :index =\> idx %\>  
> \<%= text\_field ‘performance’, ‘venue’, :index =\> idx %\>  
> \<% end -%\>

thanks for the reply Mark. Although, isn’t the above simply iterating  
over the elements of the @performances array, and then having  
text\_field call the corresponding method on the element? Shouldn’t  
rails do this automatically if you specify the :index parameter to  
text\_field? ie, if text\_field notices that you’re passing :index =\>  
1, then it should understand that the @performances ivar is an array,  
and that we should send the ‘city’ method (for example) to element 1  
of the array, rather than the array itself.

The problem appears to be inside the following method in  
ActionView::Helpers::InstanceTag

```
  def value_before_type_cast
    unless object.nil?
      object.respond_to?(@method_name + "_before_type_cast") ?
        object.send(@method_name + "_before_type_cast") :
        object.send(@method_name)
    end
  end

```

instead of sending the method to object[index], it sends it directly  
to object, which is not what we want if an index parameter is being  
given to text\_field. I changed this behaviour by adding the following  
to a file called “additions.rb” which I put in the lib directory of my  
rails project, and then included inside environment.rb:

module ActionView  
module Helpers  
class InstanceTag #:nodoc:  
include Helpers::TagHelper

```
  alias :__to_input_field_tag :to_input_field_tag

  # by default, if we pass :index => n to text_field, it doesn't 

```

send the  
# method to the element at index n of the given array, but instead  
# sends the method to the entire array, which is not what we want.  
We  
# modify this by checking to see if the user has passed an  
"index parameter  
# and if so, we send the method to the object at the given element  
def to\_input\_field\_tag(field\_type, options = {})  
options = options.stringify\_keys  
options[“size”] ||= options[“maxlength”] ||  
DEFAULT\_FIELD\_OPTIONS[“size”]  
options = DEFAULT\_FIELD\_OPTIONS.merge(options)  
if field\_type == “hidden”  
options.delete(“size”)  
end  
options[“type”] = field\_type

```
    # if the user has given the :index => n parameter, then we try 

```

to obtain  
# the value of the element at the given index of the array  
if options.has\_key?(“index”)  
options[“value”] ||=  
value\_before\_type\_cast\_with\_index(options[“index”]) unless field\_type  
== “file”  
else  
options[“value”] ||= value\_before\_type\_cast unless  
field\_type == “file”  
end

```
    add_default_name_and_id(options)
    tag("input", options)
  end

  def value_before_type_cast_with_index(index)
    unless object.nil? || object[index].nil?
      object[index].respond_to?(@method_name + "_before_type_cast") 

```

?  
object[index].send(@method\_name + “\_before\_type\_cast”) :  
object[index].send(@method\_name)  
end  
end

```
end #InstanceTag

```

end #Helpers  
end #ActionView

this seems to do the trick for now, but I’m not sure what problems I  
may run into in the future (perhaps there was a reason that they  
didn’t implement it this way). Of course this will fail if you pass  
an :index parameter to your text\_field options, but don’t actually  
have an array of values to pass it from your controller (but then, why  
else would you be using the :index parameter…).

Anyways, thanks for the help, and of course if you or anyone else have  
any suggestions, advice, comments, criticism, etc on the above, please  
let me know.

Mike

---

<div class="post-metadata">

**Author:** ![random52k](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/7bcc69/32.png) [@random52k](https://www.ruby-forum.com/u/random52k)\
**Post date:** [May 20, 2006, 12:47pm UTC](https://www.ruby-forum.com/t/populating-array-of-text-fields-from-an-array-of-model-objec/60974/4 "2006-05-20T12:47:46Z")

</div>

Mike G. wrote:

> text\_field? ie, if text\_field notices that you’re passing :index =\>  
> 1, then it should understand that the @performances ivar is an array,  
> and that we should send the ‘city’ method (for example) to element 1  
> of the array, rather than the array itself.

Yes, I was also originally under the impression that the index option  
worked the way you suggest. It’s a natural assumption, given the name  
of the option.

The advantage of the way it’s been done is that the index doesn’t have  
to be an index into an array, but can be a hash key or object attribute  
(such as the id attribute, for which the [] notation can instead be  
used).

Changing the index option to work in the way you suggest would break too  
many apps, but perhaps a new option can be added. As you can see, it’s  
not  
hard to make the existing option work with arrays, but the non-intuitive  
way it works is going to keep tripping people up.

–  
We develop, watch us RoR, in numbers too big to ignore.
