Rails 6
bootstrap 4
In my books_controller.rb, I have:
def index
@books = Book.select(:id, :name)
end
def new
@book = Book.new
end
def create
@book = Book.new(book_params)
respond_to do |format|
if @book.save
format.html { redirect_to @book, notice: 'Book was successfully created.' }
format.json { render :show, status: :created, location: @book }
else
format.html { render :new }
format.json { render json: @book.errors, status: :unprocessable_entity }
end
end
end
I have a table, in my views/books/index.htmlslim, I have:
table.table.table-striped
thead
tr
th Name
tbody
- @books.each do |book|
tr
td = book.name
What I would like to do, is at the end of the table, add a form, allowing users to add a book, without going to a separate form, something like:
I tried:
= form_with url: new_book_path do |f|
.form-inputs
= f.label 'Add Book'
= f.text_field :book_name
.form-actions
= f.submit
And I also tried:
= simple_form_for(@book) do |f|
.form-inputs
= f.input :book_name
But nothing happens, when I click on submit, and I get the following message:
ActionController::RoutingError (No route matches [POST] "/bookd/new"):
I also tried:
= simple_form_for(@book || Book.new) do |f|
.form-inputs
= f.input :book_name
But. I am getting a:
ActionView::Template::Error (undefined method `book_name` for #<Book:0x000007f9cce...>);
One other thought, is to make it a link, something like:
= link_to new_book_path, :class => "btn btn-primary btn-lg"
But how do I pass the book_name parameter, and which controller action should it go to?
Here are my routes:
books GET /books(.:format) books#index
POST /books(.:format) books#create
new_book GET /books/new(.:format) books#new
edit_book GET /books/:id/edit(.:format) books#edit
book GET /books/:id(.:format) books#show
PATCH /books/:id(.:format) books#update
PUT /books/:id(.:format) books#update
DELETE /books/:id(.:format) books#destroy
In Rails you don't create resources by posting to the new
route- you post to the collection route eg. /books
. The new action is just used to create a page with a form on it.
Its still really puzzling why new_book_path
would return /bookd/new
but the error is actually correct. new_book_path
responds to GET - not POST. This is explained in Rails Routing from the Outside.
If you actually just use:
table.table.table-striped
thead
tr
th Name
tbody
- @books.each do |book|
tr
td = book.name
= simple_form_for(@book || Book.new) do |f|
.form-inputs
= f.input :name # book_name is a typo?
It will correctly create a form with action="/books" method="POST"
.
I have no idea what your trying to do with this mess:
= form_with url: new_book_path do |f|
.form-inputs
= f.label 'Add Book'
= f.text_field :book_name
.form-actions
= f.submit
= simple_form_for(@book) do |f|
.form-inputs
= f.input :book_name
But none of the HTML specifications allow nested <form>
elements and the results can be wildly unpredictable. For example a submit button may submit the inner form or the outer form.