Rails 3 form_for nested routes for custom action - ruby-on-rails

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.

Related

Getting "No Route matches" error when though I have a method in my controller

I’m using Rails 4.2.3. I have this in my controller file, “./app/controllers/users_controller.rb” …
def edit
#user = User.find(session["user_id"])
render 'edit'
end
def update
#user = User.find(session["user_id"])
if #user.update_attributes(user_params)
flash[:success] = "Profile updated"
end
render 'edit'
end
And I have this in my “./app/views/users/edit.html.erb” file
<%= form_for(#user) do |f| %>
…
<%= button_to "Save", { :action => "update" }, :method => :post, :class => 'button' %>
But when I visit my url “http://localhost:3000/users/edit”, I get this error
No route matches {:action=>"update", :controller=>"users"}
This is what I have in routes/config.rb so I’m not sure why its falling apart …
get "users/edit" => "users#edit"
resources :users
I believe you need to use PUT/PATCH method for the update action, while POST is used for the create action as per the Rails documentation:
<%= button_to "Save", { :controller => "users", :id => #user.id }, :method => :put, :class => 'button' %>
Also, rake routes is a really useful command for debugging routing issues that dumps all defined routes.

routing error showing that No route matches [POST] "/admin/locations/1"

I am new to ROR when i edit my location it will gives me following error
No route matches [POST] "/admin/locations/1"
here i am using rails 3.2.12
this is my location controller
class Admin::LocationsController < ApplicationController
def index
#location= Location.order("location desc")
end
def new
#location=Location.new
end
def create
#location = Location.new(params[:location])
if #location.save
# flash[:notice] = 'Location is successfully added in to list.'
redirect_to :action => 'index'
else
render :action => 'new'
end
end
def edit
#location = Location.find(params[:id])
end
def update
#location = Location.find(params[:id])
if #location.update_attributes(params[:location])
#flash[:notice] = 'Category is successfully updated.'
redirect_to :action => 'index'
else
render :action => 'index'
end
end
end
this is my edit.html.erb
<h2>Edit Location</h2>
<%= simple_form_for(:location, :url => {:action => 'update', :id => #location.id}) do |f| %>
<%= render(:partial => 'form', :locals => {:f => f}) %>
<%= submit_tag("Update",) %> <%= link_to("cancle", {:action => 'index'} )%>
<%end%>
and this is my route.rb
GuestHouse::Application.routes.draw do
devise_for :customers
namespace :admin do
resources :locations
end
and in my index.html.erb as
<%= link_to("Edit", {:action => 'edit', :id => location.id}, :class => 'btn btn-info')%>
<%= simple_form_for(:location,
:url => {:action => 'update', :id => #location.id},
:method => 'put' ) do |f| %>
Pass method in simple_form_for
For an edit form, you likely want to be using the PUT method instead of POST. It looks like you are using [SimpleForm][1], though, which normally would handle constructing the path for a given model for you. Is there any reason you are not passing your Location instance in your call to simple_form_for? I would expect something like the following:
<%= simple_form_for #location do |f| %>
...
Here your routes for admin/location like the following.
admin_locations GET /admin/locations(.:format) admin/locations#index
POST /admin/locations(.:format) admin/locations#create
new_admin_location GET /admin/locations/new(.:format) admin/locations#new
edit_admin_location GET /admin/locations/:id/edit(.:format) admin/locations#edit
admin_location GET /admin/locations/:id(.:format) admin/locations#show
PUT /admin/locations/:id(.:format) admin/locations#update
DELETE /admin/locations/:id(.:format) admin/locations#destroy
so if you want to send the form to 'update' action, you should mention the path like below.
<%= simple_form_for #location, :url => admin_location_path(#location),:html => { :method => "post"} do |f| %>

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 method "No route matches [POST]"

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.

button_to :action => 'destroy' looks for 'show'

This seems incredibly similar to a question I had answered just a few days ago, but the solution then isn't working now.
I'm building a rails app, and I am trying to have a button_to trigger a destroy in a different controller.
the code I have for the button is
<%= button_to "delete", :controller => :meals,
:action => 'destroy',
:recipe_id => recipe.id,
:method => :post >
when I click the delete button, i get a
'no matches for meals/3' which is the current meal_id.
the destroy in the meals controller looks like this
def destroy
#meal = Meal.where("current_user.id => ? AND recipe_id => ?", current_user.id, params[:recipe_id]).first
#meal.destroy
respond_to do |format|
format.html { redirect_to :controller => "user" , :action => "show" }
format.xml { head :ok }
end
end
it appears as though the button_to is completely ignoring the :action and requesting show which does not exist and shouldn't exist.
And how you part of routes.rb for that one looks like?
Because if you use map.resources then destroy has same path as show but :method => :delete(which is virtual verb implemented by form and _method=delete param).
Try this:
<%= button_to "delete", {:controller => :meals,
:action => 'destroy', :id => recipe.id }, :method => :delete %>
or if recipe is instance of Meal class then
<%= button_to "delete", #recipe, :method => :delete %>
Mind the curly brackets.
I know it is way too late for an answer but hope it may help somebody(using Rails 4).
<%= button_to "delete", meal_path(:id => recipe.id), :method => :delete %>

Resources