SitePoint Sponsor

User Tag List

Results 1 to 3 of 3
  1. #1
    SitePoint Evangelist ikeo's Avatar
    Join Date
    Oct 2004
    Location
    Austin Texas
    Posts
    591
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    error on form post

    Hi all, I wanted to run this buy you to see what I'm missing here.

    I've created the following form

    Code:
    <h1>Search#index</h1>
    <%= form_tag('/search/results') %>
        <p>Address:  <%= text_field_tag :address %></p>
        <p>City: <%= text_field_tag :city %></p>
        <p>State: <%= collection_select("city", "state" , @states, "state", "state") %></p>
        <p>Zip: <%= text_field_tag :zip %></p>
        <%= submit_tag :submit, :name => 'start_search' %>
    </form>
    but on submit, the form goes to the /search/results page, but gives me a 500 error.

    Checking through the logs, this is the error I see

    Conflicting types for parameter containers. Expected an instance of Hash but found an instance of String. This can be caused by colliding Array and Hash parameters like qs[]=value&qs[key]=value
    any ideas?

  2. #2
    SitePoint Evangelist ikeo's Avatar
    Join Date
    Oct 2004
    Location
    Austin Texas
    Posts
    591
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    okay so I figured that one out pretty quick. The

    Code:
    <%= collection_select("city", "state" , @states, "state", "state") %>
    statement was giving a lot of trouble because the select element was being named city[state] ... I don't see why this should be a problem, but whatever.

    I replaced it with this

    Code:
    <select name="state">
                <%= options_from_collection_for_select(@states, "state", "state") %>
    </select>
    but now my question is, is there an more compact way to generate the entire select statement using the hash of state names that is in @states?

  3. #3
    SitePoint Evangelist
    Join Date
    Feb 2006
    Location
    Worcs. UK
    Posts
    404
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Have a look at the select helper method. There's documentation here, and this gives:
    Code:
    select("post", "person_id", Person.find(:all).collect {|p| [ p.name, p.id ] }, { :include_blank => true })
    This shows that if you can clone your @states array and replace each element with a two element array in the form [name_to_display, data_to_be_returned] you can use:
    Code:
    select('city', 'state', @clone_of_states)
    The fact that Rails expects objects passed to form elements to be methods of parent class objects is great when creating, finding, and editing individual items. It is a bit of a pain when creating forms for things like search tools, where you don't want a part of an object passed back to the server, but just a bit of text.

    The way I've started getting around this is to use a temporary object and load this in the controller and pass that to the search form. So I'd add this class to lib:

    File name temp_object.rb
    Code:
    class TempObject
    
      def initialize(*attribute_names)
        @attribute_names = Array.new
        attribute_names.flatten.each do |a|
          create_attribute(a)
        end
      end
    
      def create_attribute(name)
        name = name.to_sym
        self.class.send(:attr_accessor, name)
        @attribute_names << name
      end
    
      def attribute_names
        @attribute_names
      end
    
      def load_data(data = {})
        @attribute_names.each do |a|
           if value = data[a.to_sym] or value = data[a.to_s]
           instance_variable_set("@#{a}", value)
        end
      end
    end
    
    end
    For your case I'd use it like this:

    controller
    Code:
    #Create a TempObject with the methods street, city, state and zip
    @address = TempObject.new(:street, :city, :state, :zip)
    #load it with data pass from form submission
    @address.load_data(params[:address].clone) if params[:address]
    The data returned by a form will then be available to the controller. For example the submitted state will be in @address.state

    The form would need to be adjusted too:

    view
    Code:
    <&#37; form_tag('/search/results') do %>
        <p>Address:  <%= text_field 'address', 'street' -%></p>
        <p>City: <%= text_field 'address', 'city' %></p>
        <p>State: <%= select('address', 'state' , @states.collect{|s| [s,s]}) -%></p>
        <p>Zip: <%= text_field 'address' :zip %></p>
        <%= submit_tag :submit, :name => 'start_search' %>
    <% end %>


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •