1

I am trying to use form_tag to pass the params captured by the form to my users controller. I am attempting to communicate with a Sinatra server, and so I do not have a database on the client. My view is as follows:

 <% form_tag(@user) do %>

<div class="field">
<%= label_tag :first_mame %><br />
<%= text_field_tag :first_name  %>
</div>
<div class="field">
<%= label_tag :last_name %><br />
<%= text_field_tag :last_name %>
</div>
<div class="field">
<%= label_tag :email %><br />
<%= text_field_tag "user[email]" %>
</div>
<div class="field">
  <%= label_tag :device_id %><br />
  <%= text_field_tag "user[device_id]" %>
</div>
<div class="field">
<%= label_tag :type %><br />
<%= text_field_tag "user[device_type]" %>
</div>
<div class="actions">
<%= submit_tag %>
 </div>
<% end %>

The create action on my controller is simply:

 def create
 @user = User.new(params[@user])
 @user.save

respond_to do |format|
  if @user.save
    format.html { redirect_to(@user, :notice => 'User was successfully created.') }
    format.json {render :json => @user }
    format.xml  { render :xml => @user, :status => :created, :location => @user }
  else
    format.html { render :action => "new" }
    format.xml  { render :xml => @user.errors, :status => :unprocessable_entity }
  end
end

end

Here's what I get as a result => expected an attributes Hash, got nil

Anybody know why? Thanks for the help.

Lior
  • 60
  • 10

2 Answers2

1
  1. You need to use form_for and not form_tag. form_for(@user) do
  2. In your model you need to create a schema. Without it Rails doesn't know what do with the data you enter into the form.
  3. When you pass the object into the parameter hash use :user and not @user. @user = User.new(params[:user])
Scott
  • 330
  • 3
  • 15
  • Yeah. When I do a user.save with that, it works. The parameters are passed correctly. – Lior Jul 28 '11 at 21:55
0

For your form you need to do

<%= form_for @user do |f| %>
  <div class="field">
    <%= f.label :first_name %>
    <%= f.text_field :first_name %>
  </div>

  # more fields
<% end %>

Note the:

  • <% %> --> <%= %>
  • form_tag(@user) do --> form_for(@user) do |f|
  • label_tag --> f.label
  • text_field_tag --> f.text_field

In you controller:

@user = User.new(params[:user])

Update:

  • <% %> --> <%= %>: This is just the convention in rails3, when ever you want to write something in the response you should use later(with = sign). Earlier still works but is deprecated.

  • form_tag(@user) do --> form_for(@user) do |f|

    • form_tag(@user) do: form_tag is used to for simple forms which are not tied with any model. You can have the tags inside form_tag named so that they resemble form for, but then why wouldn't you use form_for directly. Apparently the first parameter to the helper is target url, and in this particular case rails magically identifies the url from @user and you didn't notice any bug
    • form_for(@user) do |f|: form_for is used to create a form for a model, and ties up the form with the instance of the model passed to it. The block for form_for receives a form_builder object, which has equivalents of text_field_tag, label_tag etc. as text_field, label
  • label_tag --> f.label: first is the common tag which just creates a label tag with no magic attached to it.The later is related with the model object and follows different naming and id conventions, than former. It also ties up with the value of the field, i.e. if the field has an error(failed validation), your label will be surrounded by a div tag with class fields_with_error or something, I can't remember the class name.

  • text_field_tag --> f.text_field: Former will create a field with name first_name with no magic attached. The later follows a naming convention, the input field will be named user[first_name], so that when you do params[:user] you get a first_name parameter there. It also ties up with the value of the field with the html input, i.e. you get the same error functionality as label and you also get the input automatically prefilled with whatever the value field has in the model instance.

rubish
  • 10,887
  • 3
  • 43
  • 57
  • Could you go into more detail and explain why these changes are necessary please? – Ryan Bigg Jul 22 '11 at 00:09
  • Thanks for the response. I tried form_for before, as you described above, but the form gets pre-populated with '{}' and the params hash associated with the model puts the entire hash into every key. For example, :first_name => {:first_name . . . :last_name . . .:email . . . etc). The last_name key, email key, etc. all have the same hash inside when using form_for to capture the params. This only happens with ActiveResource. What do you suggest? Thanks for your feedback btw. – Lior Jul 22 '11 at 13:43
  • Apparently this is because params[:user] with activeresource dumps everything into a big array. I need to be able to flatten the array and convert it into a hash so that only the keys and info I need can be extracted so that it plays nicely with Json. – Lior Jul 22 '11 at 21:30
  • Going to ask another question because I was able to get the attributes into a hash, but I can't save the hash. @rubish – Lior Jul 22 '11 at 22:47
  • can you post the parameters you are receiving? – rubish Jul 22 '11 at 23:16
  • This is the console response when I create a new user:#"stop", "last_name"=>"eating", "email"=>"your", "device_id"=>"feet", "device_type"=>"sisi"}, #@prefix_options={}> , but when Sinatra sees this when I try to save the object, it only sees nil. So, I thought I would turn it into a hash that JSon could understand. Apparently, I can't save a hash (I'm kind of a Ruby newbie). PS, the # in the code above is just so that I don't get errors posting to this response regarding "post author." @Rubish – Lior Jul 23 '11 at 13:44