settheline
settheline

Reputation: 3383

Required parameter missing - rails

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)

Upvotes: 1

Views: 3666

Answers (3)

nzifnab
nzifnab

Reputation: 16120

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" %>

Upvotes: 3

Richard Peck
Richard Peck

Reputation: 76784

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 %>

Upvotes: 2

struthersneil
struthersneil

Reputation: 2750

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).

Upvotes: 0

Related Questions