Hendro Febrian
Hendro Febrian

Reputation: 222

Can't insert data to db in ruby on rails

I just learn RoR and confuse now how to insert data to db. Here's my code:

book_insert.html.erb

<%= content_for :helloworld do %>
    <%= form_tag("/insert", method: "post") do %>
        <%= label_tag(:title, "Title") %>
        <%= text_field_tag(:title) %><br>
        <%= label_tag(:price, "Price") %>
        <%= number_field_tag(:price) %><br>
        <%= label_tag(:subject_id, "Subject ID") %>
        <%= number_field_tag(:subject_id) %><br>
        <%= label_tag(:description, "Description") %>
        <%= text_field_tag(:description) %><br>
        <br>
        <%= submit_tag("Submit") %> 
    <% end %>
<% end %>

book_controller.rb

class BookController < ApplicationController
    def insert
        @book = Book.new(book_params)
        @book.save
        render :book_page
    end

    def book_params
        params.require(:books).permit(:title, :price, :subject_id, :description)
    end

    def showinsert
        render :book_insert
    end
end

It returns error:

Completed 400 Bad Request in 4ms (ActiveRecord: 0.0ms) ActionController::ParameterMissing (param is missing or the value is empty: books):

Please help. Thanks

Upvotes: 0

Views: 282

Answers (3)

Pavan
Pavan

Reputation: 33542

form_tag normally used to submit non-model actions to the mapped controller#action. You probably need to use form_for and its corresponding helpers inside the form

<%= content_for :helloworld do %>
  <%= form_for Book.new, url: "/insert", method: "post" do |f| %>
    <%= f.label :title %>
    <%= f.text_field :title %><br>
    <%= f.label :price %>
    <%= f.number_field :price %><br>
    <%= f.label :subject_id %>
    <%= f.number_field :subject_id %><br>
    <%= f.label :description %>
    <%= f.text_field :description %><br>
    <br>
    <%= f.submit "Submit" %> 
  <% end %>
<% end %>

With the above code, the params would be passed inside :book => {} hash, so you need to change the book_params to below

def book_params
  params.require(:book).permit(:title, :price, :subject_id, :description)
end              #^ 

Upvotes: 2

max
max

Reputation: 101891

The params.require method requires that the key books is present in the hash - if not it raises an ActionController::ParameterMissing exception.

To nest inputs you need to name them accordingly:

<%= form_tag("/insert", method: "post") do %>
  <%= label_tag("Title") %>
  <%= text_field_tag("books[title]") %><br>
  <%= label_tag("Price") %>
  <%= number_field_tag("books[price]") %
  ...
  <%= submit_tag("Submit") %> 
<% end %>

This will give the params hash:

{ books: { title: 'Life & Times of Michael K', price: 99 } }

However thats pretty tedious. A better way is to use the forms helpers and setup your routes and controller according to the conventions:

# config/routes.rb
resources :books

# app/views/books/new.html.erb
<%= form_for(@book) do |f| %>
  <div class="field">
    <%= f.label :title %>
    <%= f.text_field :title %>
  </div>
  # ...
  <%= f.submit %>
<% end %>

# app/controllers/books_controller.rb
class BooksController < ApplicationController
  # this renders the form to create a new book
  # GET /books/new
  def new
    @book = Book.new
  end

  # In Rails its called create - not insert
  # POST /books
  def create
    @book = Book.new(book_params)
    if @book.save
      redirect_to @book
    else
      render :new
    end
  end

  # This is the path to show a book
  # its also where we redirect after creating the book
  # GET /books/:id
  def show
    @book = Book.find(params[:id])
  end

  # ...

  private 
    def book_params
      # note thats its book singular - not plural
      params.require(:book).permit(:title, :price, :subject_id, :description)
    end
end

Upvotes: 2

John Baker
John Baker

Reputation: 2398

You should do book in the book_params method instead of books:

def book_params
    params.require(:book).permit(:title, :price, :subject_id, :description)
end

Upvotes: -1

Related Questions