Update method "No route matches [POST]" - ruby-on-rails

Having a bit of trouble with the following ruby on rails code snippet - I have books and would like to update a book's name, here is how I try to do it:
<h1>Edit the book "<%= #book.name %>"</h1>
<%= form_tag action: :update, id: #book do %>
<p>
<label for="book_name">Name</label>
<%= text_field :book, :name %>
<%= submit_tag 'Save changes' %>
</p>
<% end %>
This is what I do in the books controller:
def edit
#book = Book.find(params[:id])
end
def update
#book = Book.find(params[:id])
if #book.update_attributes(params[:book])
redirect_to :action => 'show', id => #book
else
#subjects = Subject.find(:all)
render :action => 'edit'
end
end
These are my routes:
root to: 'authors#index'
resources :books, :authors
When I click the submit button in the form, it gives me No route matches [POST] "/books/5" and directs to localhost:3000/books/5 instead of staying and localhost:3000/books/5/edit
What am I doing wrong here? Shouldn't there be a put method for updating stuff somewhere rather than a post method?

Updates should use put not post.
<%= form_tag( { :controller => :books, :action => :update, :id => #book.id }, { :method => :put } ) do %>
or better yet use form_for
<%= form_for #book do |f| %>
On your console run "rake routes" and it will print out all available routes.

Please try this:
We need to specify match in routes file.
match "/books/:id" => "books#update"

resources :books should do the job. you dont have to explicitly use "match".
def edit
#book = Book.find(params[:id])
end
form.html
form_for #book, :method => :put do |f|
def update
#book = Book.find(params[:id])
#book.update_attributes(params[:book])
end
this should do the job.

I had this issue before. Everything was right but still getting the error then I found out it was
gem 'rails-api'
Removed it and it all worked fine.

Related

Making a link in Ruby on Rails

I'm really really newbie in Ruby on Rails...
I'm trying to make a link to another page in my project, where it's listed the posts that belong to an escuela.
This is what I did:
In posts_controller.rb I wrote:
def postesc
#posts = Post.where(:escuela_id => params[:id])
respond_to do |format|
format.html # postesc.html.erb
format.json { render json: #posts }
end
end
In config/routes.rb I wrote:
match 'postesc' => 'posts#postesc'
In view/escuelas/listaesc.html.erb I wrote the link:
<%= link_to "Escuelas", :controller => "posts", :action => "postesc" %>
And in view/escuelas/postesc.html.erb I want to make a list of the matching posts.
But this page appears just blank, with only the layout.
Please, some help?
First make the association between post and escuela, then you can find it just by
Escuela.find(params[:id]).posts
Change your routes to -
resources :posts do
get 'postesc', :on => :collection
end
View :
<%= link_to "List posts", postesc_posts_path %>
make a change in routes.rb as
get 'postesc' => 'posts#postesc'
try...<%= link_to "Escuelas", postesc_path %>
OR
<%= link_to "Escuelas", { :controller => "posts", :action => "postesc" } %>
you're missing to add an ID for the Escuela to be selected - as you're doing in your Controller#postesc Action (as in words: where: escuela_id => params[:id]).
<%= link_to "Escuela", :controller => "posts", :action => "postesc", :id => 1 %>
but you could use the object-link method using the following syntax (by changing your routes a litte):
# in routes.rb
match 'postesc' => 'posts#postesc', on: :collection, as: 'esc_index'
# in your view
<%- for escuela in #escuelas do %>
<%= link_to "Escuela", esc_index(escueal) %>
<% end %>

Update database using 'update_attributes' through 'has_many'

I'm having a problem getting my first app (I'm a total newbie) to save a new associated record. I have two models (users and pictures) with a has_many/belongs_to association. I have set up the userController so that it can create a new picture as below:
def new_picture
#user = User.find(current_user.id)
#picture = #user.pictures.build
end
def create_picture
#user = User.find(params[:id])
#picture = #user.pictures.build(params[:picture])
if #picture.save
flash[:notice] = "Your picture was successfully added."
redirect_to :action => 'show', :id => #user.id
else
render :template => "new_picture"
end
end
and I use
<%= link_to("add picture", :action => 'new_picture', :id => #user.id) if current_user %>
to add a new one. But I'd also like to be able to edit. So I updated the usercontroller with some new code:
def edit_picture
#user = User.find(current_user.id)
#picture = #user.pictures.find(params[:id])
end
# When the user clicks the save button update record
def update_picture
#user = User.find(current_user.id)
#picture = #user.pictures.find(params[:picture])
respond_to do |format|
if #picture.update_attributes(params[:picture])
flash[:notice] = "Your picture was successfully updated."
redirect_to :action => 'show', :id => #user.id
else
render :template => "new_picture"
end
end
end
and added the edit link to show.erb:
<%= link_to("edit picture", :action => 'edit_picture', :id => picture.id) if current_user %>
It loads the edit form fine, with the data all in the right place, but on save all it's doing is giving me the error 'ArgumentError in UsersController#update_picture' with a bunch of Unknown key(s) from my pictures table.
Could somebody explain why? I feel like there is one piece of the jigsaw I haven't quite understood here....
Thanks in advance!
UPDATE: View code is as follows:
<h1>New picture for <%= #user.name %></h1>
<% form_for :picture, #picture, :html => { :multipart => true }, :url => {:action => 'update_picture', :id => #user.id} do |f| %>
Can't seem to see your problem in the view code, however you can do the same thing more elegantly (RESTful) as a nested route. That way you might be able to see the problem more clearly.
config/routes.rb:
resources :users do
member do
resources :pictures
end
end
app/controllers/pictures_controller.rb:
class PicturesController < ApplicationController
before_filter :find_picture, :only => [:edit, :update]
def edit
end
def update
if #picture.update_attributes params[:picture]
flash[:notice] = "Your picture was successfully updated."
redirect_to user_path(current_user)
else
render :edit
end
end
protected
def find_picture
#picture = current_user.pictures.find params[:id]
end
end
app/views/pictures/edit.html.erb:
<%= form_for [current_user, #picture] do |f| %>
<!-- some stuff -->
<% end %>
and to link to your edit form:
<%= link_to_if current_user, 'edit picture',
edit_user_picture_path(:user => current_user, :id => picture) %>
I suggest adding 'accepts_nested_attributes_for :pictures to the user model, and then do
<%= form_for #user do |form| %>
.. user fields
<%= form.fields_for :pictures do |picture_form| %>
.. picture fields
<% end %>
<%= form.submit %>
<% end %>
in the view.
Another option is to create a new controller for the pictures. That may be simpler.

Rails 3 form_for nested routes for custom action

My setup: Rails 3.0.9, Ruby 1.9.2
I added a custom action to a nested resource task.
routes.rb
resources :tasks
resources :projects do
resources :tasks, :constraints => { :protocol => "http" } do
put :cancel, :on => :member
end
end
rake routes shows
cancel_project_task PUT /projects/:task_id/tasks/:id/cancel(.:format) {:protocol=>"http", :action=>"cancel", :controller=>"tasks"}
In my controller,
tasks_controller.rb
def cancel
#task = Task.find(params[:id])
respond_to do |format|
if #task.cancel
format.html { redirect_to(#task, :notice => 'Task was successfully canceled.') }
else
format.html { render :action => "edit" }
end
end
end
I need to define a form to perform the action, here's what I have currently
_form.html.erb for subscription
<%= form_for [#project, #task], :url => { :action => 'cancel' } do |f| %>
<%= f.submit "Cancel your task"%>
<% end %>
It throws an error
No route matches {:action=>"cancel", :controller=>"tasks"}
I also tried adding :method => "put" with the same error
_form.html.erb for subscription
<%= form_for [#project, #task], :url => { :action => 'cancel', :method => "put" } do |f| %>
<%= f.submit "Cancel your task"%>
<% end %>
Anyone knows the correct form_format syntax to accomplish this?
In case anyone wants the answer, here's what I had to do
<%= form_for [#project, #task], :url => cancel_project_task_path(#project, #task) do |f| %>
It took me way too long to figure this out, hopefully this helps the next unsuspecting developer.

Ruby on Rails: Why "edit" action does not work?

In views/products/edit.html.erb I use:
<%= form_for(:product, :url => {:action => 'update', :id => #product.id}) do |f| %>
which generates:
<form method="post" action="/aircons/8" accept-charset="UTF-8">
and I get the following error:
The action '8' could not be found for ProductsController
when trying to update a product with id=8.
I think that form's method should be put. Is that right ? How should I fix this ?
Some controller code:
def edit
#product = Product.find(params[:id])
end
def update
update_params_with_new_values(params)
#product = Product.find(params[:id])
if #product.update_attributes(params[:product])
flash[:notice] = "Product updated successfully."
redirect_to(:product => 'index')
else
render('edit')
end
end
def update_params_with_new_values(params)
params[:product][:shop_id] = Shop.create(:name => params[:new_shop]).id if params[:product][:shop_id] == "new_shop"
params[:product][:brand_id] = Brand.create(:name => params[:new_brand]).id if params[:product][:brand_id] == "new_brand"
end
routes.rb contains only the following two lines:
root :to => "products#index"
resources :products
Why don't you just use:
<%= form_for #product do |f| %>
?
If it won't work, please add your routes to question.
try using this
<% form_for #product %>
#code goes here
<% end %>
you need not do all the things that you are trying. If you have created this Product model using scaffolding mechanism you must have its entry in the config/routes.rb file this will give you a path variable as below
GET /products/:id/edit edit return an HTML form for editing a photo
PUT /products/:id update update a specific photo
you can get the edit path as edit_product_path for more info on this have a look at this
Hope you understand it better now.

Routing is using ID has action and action has ID after submitting a form

I have a model User that has_one user_profile and a User_Profile belongs_to user
in the User controller I have:
def personal
#user = User.find_by_id(params[:id])
#user_profile = #user.user_profile
#user_profile ||= #user.build_user_profile
end
def update_personal
#user = User.find_by_id(params[:id])
if #user.user_profile.update_attributes(params[:user_profile])
flash[:notice] = "OK"
redirect_to #user
else
flash[:notice] = "Fail"
render :action => 'update_personal'
end
end
In my personal.html.erb view I have:
<% semantic_form_for #user_profile, :url => { :action => "update_personal"} do |form| %>
<%= form.inputs %>
<%= form.buttons %>
<%end%>
And on the rountes I have:
map.resources :users, :member => {
:personal => :get,
:update_personal => :put
}
Now the strange thing is that I can do:
users/1/personal
to see the form but when I submit I get this error:
Unknown action
No action responded to 1.
It's trying to find an action with the name 1.
Can anyone point me out on the right direction?
I just got the problem again, and finally understood the problem and found the solution.
This time i was using an ajax call using getJason.
Because the call was a get, and in my routes I had a update_xxxxxx => :put,
the route was ignored and the default :controller/:action/:id was used.
I just had to put the update_xxxx => :get and the problem was solved.
Maybe this will help someone.

Resources