1

I have these relevant controller models:

class VendorsController < ApplicationController

  def vendor_params
      params.require(:vendor).permit(:id, :name, :address, :image, :latitude, :longitude)
  end

  def create
      vendor = Vendor.create(vendor_params)
      flash[:success] = "Vendor Created"
      redirect_to vendors_mgmt_path
  end

end

When I try to create a new vendor object, I get the following error:

Required parameter missing: vendor

Here is my form:

<%= form_tag({controller: "vendors", action: "create"}, method: "post", multipart: true) do %>
<%= text_field_tag :name, "Store Name" %>
<%= text_field_tag :address, "Store Address" %>
<%= file_field_tag :image %>
<%= submit_tag "Save", class: "btn btn-success" %>
<% end %>

And my migration for the Vendor table:

class CreateVendors < ActiveRecord::Migration
  def change
    create_table :vendors do |t|

    t.string :name
    t.string :address
    t.float :latitude
    t.float :longitude
    t.string :image

    t.timestamps
    end
  end
end

Does anyone see a clue as to why I might be getting this error? I don't understand how :vendor itself is a parameter... Any help is much appreciated. Thanks in advance!

Here is my updated form:

<%= form_for @vendor, multipart: true do |f| %>
<%= f.text_field :name, "Store Name" %>
<%= f.text_field :address, "Store Address" %>
<%= f.file_field :image %>
<%= f.submit "Save", class: "btn btn-success" %>
<% end %>

I'm not getting this error though:

undefined method `merge' for "Store Name":String

From the searching I've done, it sounds like the rails method merge only works on hashes, not strings. I'm not sure why it would be trying to merge this though unless my form isn't creating a hash properly?

My new action:

def new
    @vendors = Vendor.all
    @vendor = Vendor.new
end

Server Logs

Started GET "/vendors/new" for 127.0.0.1 at 2013-10-23 08:04:04 -0700
Processing by VendorsController#new as HTML
  Vendor Load (0.3ms)  SELECT "vendors".* FROM "vendors" 
Rendered vendors/new.html.erb within layouts/application (2.0ms)
Completed 500 Internal Server Error in 18ms

ActionView::Template::Error (undefined method `merge' for "Store Name":String):
    5: <h4>New Vendor Form</h4>
    6: 
    7: <%= form_for @vendor, multipart: true do |f| %>
    8: <%= f.text_field :name, "Store Name" %>
    9: <%= f.text_field :address, "Store Address" %>
    10: <%= f.file_field :image %>
    11: <%= f.submit "Save", class: "btn btn-success" %>
  app/views/vendors/new.html.erb:8:in `block in _app_views_vendors_new_html_erb__2593637676836103609_2161482240'
  app/views/vendors/new.html.erb:7:in `_app_views_vendors_new_html_erb__2593637676836103609_2161482240'


  Rendered /Users/******/.rvm/gems/ruby-2.0.0-p195/gems/actionpack-3.2.13/lib/action_dispatch/middleware/templates/rescues/_trace.erb (1.8ms)
  Rendered /Users/******/.rvm/gems/ruby-2.0.0-p195/gems/actionpack-3.2.13/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (1.4ms)
  Rendered /Users/******/.rvm/gems/ruby-2.0.0-p195/gems/actionpack-3.2.13/lib/action_dispatch/middleware/templates/rescues/template_error.erb within rescues/layout (11.9ms)
settheline
  • 3,333
  • 8
  • 33
  • 65

3 Answers3

3

The problem is that you aren't sending your params using form_for correctly. You're directly using form_tag, text_field_tag, etc which you should only do under specific circumstances because this will circumvent much of Rails' built-in functionality. You don't need to specify a value because that automatically gets populated by what's in @vendor. You can make labels to label each field as in this example:

<%= form_for @vendor, html: {multipart: true} do |f| %>
  <%= f.label :name, "Store Name" %>
  <%= f.text_field :name %>
  <%= f.label :address, "Store Address" %>
  <%= f.text_field :address %>
  <%= f.file_field :image %>
  <%= f.submit "Save", class: "btn btn-success" %>
<% end %>

In your new action make sure you instantiate an empty Vendor object so it knows what controller/action to send the form off to when it gets submitted.

If you don't want to use labels to label the fields you can use the html5 placeholder attribute to give a field hint instead:

<%= f.text_field :name, placeholder: "Store Name" %>
nzifnab
  • 15,876
  • 3
  • 50
  • 65
  • I see, that makes sense. I updated my form as above. Any idea why I'm getting thrown a `undefined method `merge' for "Store Name":String` error now? – settheline Oct 23 '13 at 14:57
  • Oh silly me ;) `f.text_field` doesn't have a "value" parameter, it gets the value from the object of the form. I've updated my answer. I don't think you needed a new question for this :p – nzifnab Oct 23 '13 at 16:27
2

Your problem is here:

<%= form_tag({controller: "vendors", action: "create"}, method: "post", multipart: true) do %>

Specifically, when you "require" params using strong params in Rails, it basically expects the params hash to be structured this way:

params{"vendor" => {"name":sdfadsf, "address": 23423}}

This can only be achieved if you use form_for @vendor in your new.html.erb view, as this is how Rails defines that initial value to the params hash. What your app is doing is setting the params hash as this:

params{"name": 234234, "address: 234324}

Solution

In your new.html.erb form, just use this code:

<%= form_for @vendor, method: "post", multipart: true) do %>
    <%= text_field_tag :name, "Store Name" %>
    <%= text_field_tag :address, "Store Address" %>
    <%= file_field_tag :image %>
    <%= submit_tag "Save", class: "btn btn-success" %>
<% end %>
Community
  • 1
  • 1
Richard Peck
  • 76,116
  • 9
  • 93
  • 147
  • That was a great answer. Good to know that about strong parameters and forms. Would you check out the error I'm getting thrown now? I've updated my question with it. – settheline Oct 23 '13 at 14:48
  • No problem! Got any more info on that error? I can't see anywhere where you call a `merge` command, and it would be good to see any other info you can provide :) – Richard Peck Oct 23 '13 at 14:51
  • I've never seen this error before, but from some research I did, it seems that it's something to do with the way Rails renders the form (it has bad syntax essentially). I actually think it's your "multipart" definition, which should be this: `<%= form_for @vendor, :html => {:multipart => true} do |f|` – Richard Peck Oct 23 '13 at 15:15
  • Hmmm...same error with the updated multipart def. I'll start a new question for this so I don't take this question off track, thanks for your help! – settheline Oct 23 '13 at 15:21
  • No problem! I'll look for you new question & see if I can help – Richard Peck Oct 23 '13 at 15:22
  • http://stackoverflow.com/questions/19546040/undefined-method-merge-for-xxxxxxstring-rails-form-for Thanks! – settheline Oct 23 '13 at 15:32
  • 1
    I think the first guy (from India) got it for you - the second parameter should be an options hash, not a value! – Richard Peck Oct 23 '13 at 15:45
0

Unless I've missed something that is not immediately obvious--

params.require(:vendor)

You are specifying that params must contain :vendor. Just remove this clause, e.g.

def vendor_params
  params.permit(:id, :name, :address, :image, :latitude, :longitude)
end

If your parameters were nested beneath :vendor then the .require(:vendor) would make sense. Take a look at your development log to see the incoming parameters (share them here if you're still having trouble).

struthersneil
  • 2,700
  • 10
  • 11
  • I originally had set up my vendor_params that way, but you run into problems if you don't require(:vendor). My understanding is: there are hidden fields by default in rails forms (like authenticity_token) that won't be permitted unless you require(:vendor). From a question I asked this week:[link](http://stackoverflow.com/questions/19486042/rails-not-updating-attribute) – settheline Oct 23 '13 at 14:56