Calling a controller's action without a named route in Rails 3 - ruby-on-rails

In Rails 3, is there a way to link to a controller's action using ajax without having a named route?
I tried <%= link_to 'Reload', '#', url_for(:action => :reload, :id => #user.id), :remote => true, :method => 'post' %>
but it returns with the error No route matches {:controller=>"users", :id=>2, :action=>"reload"}
My main concern is that I don't want the action to be called by someone typing in a route in the address bar. Is there another way to go about this?
Thanks!
Tim

if your User resource is in your routes.rb file then you need to add a route to the 7 restful actions.
resources :user, :member => {:reload => :get}
That will give you the route to work with
<%= link_to "Reload", user_reload_path(current_user)%>
and that should work for reloading your user object
rake routes
that will show you all your routes you can work with

Related

link making GET (rather than DELETE) request to wrong controller

I have a link in views/questions/show.html.erb that lets users delete tags.
<%=link_to "x",
:remote => true,
:url => remove_question_tag_path(#question, tag),
:method => :delete,
:html => { :id => "delete-#{tag.name.parameterize}"} %>
<% end %>
The remove_question_tag_path route is created by nesting the tags resource inside the questions resource.
resources :questions do
resources :answers do
member { post :vote }
end
resources :tags do
member do
delete :remove
end
end
end
Rake routes shows that this route exists as I try to use it in the url
remove_question_tag DELETE /questions/:question_id/tags/:id/remove(.:format) tags#remove
However, when I click on the link, it's making a get request to the show action of the Questions controller, rather than the remove action of the Tags controller, as rake routes indicates is the destination for the route.
Started GET "/questions/25?html%5Bid%5D=delete-outdoors&method=delete&url=%2Fquestions%2F25%2Ftags%2F2%2Fremove" for 127.0.0.1 at 2013-03-26 19:01:00 -0700
Can you explain what I might be doing wrong?
Try this:
<%= link_to "x", remove_question_tag_path(#question, tag), :remote => true, :method => :delete, :html => { :id => "delete-#{tag.name.parameterize}"} %>
Explanation: you do not specify url for link so link_to makes a hash of all given arguments except "x" and treats them as url options. Therefore, :method option is just added to GET parameters instead of generating DELETE request.

Custom action not firing using link_to with remote=true

Very new to ruby on rails and trying to get my first ajax call working. It is making the ajax call, but it always calls the #index action and seems to ignore the URL parameter. Here's the code:
class UserController < ApplicationController
def flag
logger.debug "in flag user"
respond_to do |format|
format.js { render :layout=>false }
end
end
end
In my routes.db:
resources :users do
member do
post 'flag'
get 'flag'
end
end
And then in my view I create the link like this:
<%= link_to "Flag User", :url => flag_user_path(user.id), :method => :get, :remote => true %>
the HTML source is:
Flag User
rake routes produces this:
flag_user POST /users/:id/flag(.:format) users#flag
GET /users/:id/flag(.:format) users#flag
Whenever I click on the link, the user#index method always gets executed. How do I get the user#flag method to execute?
The issue was the :url symbol. I changed:
<%= link_to "Flag User", :url => flag_user_path(user.id), :method => :get, :remote => true %>
to:
<%= link_to "Flag User", flag_user_path(user.id), :method => :get, :remote => true %>
and everything works was expected. I was incorrectly using it like link_to_remote which requires the :url symbol. Thanks everyone for their input.
The problem is in how you are defining your routes. It needs to be like this,
resources :users do
post 'flag'
get 'flag', on: :member
end
Check the rails guides for routing to get more idea.
If you run rake routes, I think you'll see that the route created with name "flag_user_path" expects "post" not "get"

link_to controller action in view

inside my routes.rb I have resources: x
but I also have another controller y, and in one of the pages I want to link to a 'new' action in controller x.
usually If I have a match statement defined in routers like
match 'signin', to: 'session#new'
I can go
<%= link_to "text", signin_path %>
but what do I do when I use resources as with controller x and need to link to the new action, without having to write match statements out in routes.rb
Thanks
<%= link_to 'New', new_controller_name_path %>
And you can view all your routes by type rake routes in your app directory.
And if you want change default path you can write in config/routes.rb smth like this:
match 'controller_name/new', :to => 'controller_name#new', :as => 'only_my_new', :via => :get
And then create link:
<%= link_to 'New', only_my_new_path %>
Try this
match '/signin' => 'session#new', :as => :new_session
now, your signin path is new_session_path
write in your view file
<%= link_to "SignIn", new_session_path %>
write in your terminal - $ rake routes
you can view your resources and other routes. for that choose your '/signin' path and write that path in your link.

Rails: Custom nested controller actions

I want to setup a custom nested controller actions but I can't figure out the routing.
I keep getting the following error
No route matches [GET] "/assets"
routes.rb
resources :companies do
resources :requests do
match :accept
end
end
index.html.rb
<% #requests.each do |request| %>
<ul class="users">
<li>
<%= full_name(request.profile) %>
<%= request.status %>
<%= link_to "Accept",
:controller => "requests", :action => "accept",
:id => request.id %>
</li>
</ul>
<% end %>
There are a couple of problems: routing to the accept action and building a URL to a nested resource.
Defining custom actions
You can add custom actions to your RESTful resources using this syntax:
resources :requests do
get 'accept', :on => :member
end
This will give you a route that looks like this:
requests/:id/accept
And you can generate paths in your views using:
accept_request_path(a_request)
The :on => :member part indicates that you're routing to a new action on each individual request, rather than the collection of all requests. If you used :on => :collection the route would be requests/accept
Nesting resources
When you nest resources:
resources :companies do
resources :requests do
get 'accept', :on => :member
end
end
You get routes that look like this, note that because the requests is nested inside companies the route includes both a company_id and an id:
companies/:company_id/requests/:id/accept
And helpers like this:
accept_company_request_path(a_company, a_request)
You could do this long-hand, as you're currently trying to do, with something like:
<%= link_to "Accept",
:controller => "requests", :action => "accept",
:id => request.id, :company_id => request.company.id %>
But it's easier to use the helpers:
<%= link_to "Accept", accept_company_request_path(request.company, request) %>
Appropriate verbs
Accept sounds a lot like something that updates your database in some way, and if that's the case you should consider using a PUT request rather than a GET request.
The HTTP/1.1 spec says that the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval (RFC2616, section 9) which has the real-world implication that non-human web clients — search engine indexers, browser extensions, etc. — are allowed to follow links (which make GET requests) but not allowed to submit forms that make other types of requests.
If you do switch to using a PUT request then the button_to helper will come in handy. As with link_to you can pass the controller, action, method, and all the parameters required by the route to button_to:
<%= button_to 'Accept',
{:controller => :requests, :action => :accept,
:company_id => request.company, :id => request},
:method => :put %>
Or you can use the helpers to generate the path which is much easier:
<%= button_to 'Accept',
accept_company_request_path(request.company, request),
:method => :put %>
More documentation
Adding more RESTful actions
Nested resources
in your route file:
match 'request/accept/:id' => 'requests#accept', :as => :accept
and in view
link_to "Accept", accept_path(request)

Devise route issue

I am using devise for authentication on my project. I created a basic controller called panel with rails. When I am at the home url the link works as it should. But for some reason the link_to in my layout file attempts to find a route that does not exist when I go to /users/sign_in, the default login for devise.
In my layout file I have this link that should always be shown.
<%= link_to "Panel", :controller => "panel", :action => "index" %>
when I attempt to access the default user login path on devise /users/sign_in it gives the error: ActionController::RoutingError in Devise/sessions#new
No route matches {:controller=>"devise/panel"} from the layout file.
routes:
get "panel/index"
get "home/index"
devise_for :users
It looks like the routes go into some sort of devise scope when I click on the link for the users/sign_in path.
Try this:
routes.rb:
get "panel/index" => 'panel#index', :as => 'panel'
In your controller:
<%= link_to "Panel", panel_path %>
get "panel/index", :as => :panel_index
<%= link_to "Panel", panel_index_path %> |
Doing the following also solves it,
<%= link_to "Panel", :controller => "/panel", :action => "index" %>
Source: https://github.com/plataformatec/devise/issues/471

Resources