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"
Related
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.
A put custom action approve was added to our rails 3.1.3 app in sourcing controller for updating 3 parameters. Custom route was added in routes.rb and link_to was called with :method => :put. However the parameters are not reset by the 'approve'.
Here is the link_to in sourcing index.html.erb:
<% #sourcings.each do |src| %>
...
<%= link_to 'Approve', approve_project_sourcing_path(#project, src), :method => :put if need_approve?(src) %>
<% end >
need_approve? is a method defined in sourcings controller to see if the sourcing needs to be approved.
Here is the rake routes output for approve:
approve_project_sourcing PUT /projects/:project_id/sourcings/:id/approve(.:format) {:action=>"approve", :controller=>"sourcings"}
Here is the approve in sourcing controller:
def approve
#project = Project.find(params[:project_id])
#sourcing = #project.sourcings.find(params[:id])
if vp_eng?
#sourcing.update_attributes!(:approved_by_vp_eng => true, :approve_vp_eng_id => session[:user_id],
:approve_date_vp_eng => Time.now, :as => :role_update)
elsif ceo?
#sourcing.update_attributes(:approved_by_ceo => true, :approve_ceo_id => session[:user_id],
:approve_date_ceo => Time.now, :as => :role_update)
end
redirect_to project_sourcing_path(#project, #sourcing)
end
Is anything we missed in the code above? Thanks so much.
The problem is with the way to call update_attributes. With hash parameters, the correct syntax is :
#sourcing.update_attributes({:approved_by_vp_eng => true, :approve_vp_eng_id => session[:user_id],:approve_date_vp_eng => Time.now}, :as => :role_update)
A brace bracket is needed for the hash parameters.
If I defined in the routes.rb
map.resources :cars
Then in my view, if I define a form like following;
<% form_for :car, #car, :url => cars_url(#car), :html => {:method => :put} do |form|%>
...
<% end %>
When I submit the form, I notice that the update method inside cars_controller.rb is executed.
Is it because of the HTML "PUT" verb defined in :html => {:method => :put} in the form_form which hints the rails to run update method in controller ?
Yes. This is a standard RESTful practice.
The idea is that every car has a unique id. if you "put" to that id - then you are "putting new information in that car object".
I'm making a form_tag panel that contains information (checkboxes) specific to a controller action. This action is set up in "routes.rb" as follows:
resources :students do
collection do
get :send_student_report_pdf
end
end
This setup works perfectly when I call the action from a link_to:
<%= link_to "Download PDF Report", :action => 'send_student_report_pdf', :controller => 'students'%>
However when I used it in a form_tag, it keeps giving me this error:
Routing Error
No route matches "/students/send_student_report_pdf"
The form_tag code I have is here:
<%= form_tag :controller => 'students', :action => 'send_student_report_pdf', :method => 'get' do %>
<%= label_tag "Include columns" %> <br>
<%= check_box_tag "first_name", params[:first_name], checked = true %> <%= label_tag "First Name" %><br>
<%= submit_tag "Download PDF Report", :action => 'send_student_report_pdf', :controller => 'students'%>
<% end %>
I have tried giving it the url, path like:
<%= form_tag send_student_report_pdf_students_path, :method => 'get' do %>
But it has been consistently giving me the same Route error (as if the action doesn't exist at all in routes.rb, even though it works perfectly using link_to instead of form_tag submit
Here is the code for the action in the controller, it basically sends back a file.
def send_student_report_pdf
#students = search_sort_and_paginate
puts "params[:first_name] = ", params[:first_namea]
send_data(generate_pdf_report(#students), :filename => "report.pdf", :type => 'application/pdf')
end
If you see that I'm missing something here, please help me.
Thank you very much,
Regards,
The :method => 'get' part in your form_for is in the url_for_options hash, not the options hash, so Rails will be putting it onto the url as cgi params instead. Try changing it to this:
form_tag url_for(:controller => 'students', :action => 'send_student_report_pdf'), :method => 'get' do ...
The reason you can't use the named route is because you didn't name it in your routes. If you name it in your routes and use the named route in your form_tag, you won't need to use url_for...
resources :students do
collection do
get :send_student_report_pdf, :as => :send_student_report_pdf
end
end
You can check whether your routes are as you expect by running rake routes
Something is seriously not adding up here.. My page just refreshes, nothing happens, it never touches any of my debuggers hanging out on all my methods except for index.
my html:
<%- for image in #images %>
<%= image.attachment_file_name %>
<%-# link_to_delete image, :url => destroy_image_admin_wysiwyg_path(image.id) %>
<%= link_to 'delete', { :url => destroy_image_image_path(image.id) },
#:confirm => 'Are you sure?',
:post => true
%>
<br />
<% end %>
my controller
def destroy_image
debugger
#img = Image.find(params[:id])
#img.destroy
respond_to do |format|
format.html { redirect_to admin_image_rotator_path }
end
end
My routes:
map.resources :images, :member => { :destroy_image => :post }
My disgusting hack that works that I will replace as soon as I find something better
I moved the action over to a simpler controller I built myself.
Changed my routes to :
admin.resources :wysiwygs, :member => { :destroy_image => :post }
Changed my html :
<%= link_to 'delete', :controller => "wysiwygs", :action => "destroy_image" %>
But when I clicked on the link..it brought up.. the show action ?? fffffffffuuuuuuu
I retaliated by just moving my action to the show action, and passing a hidden field in my html..
<%= link_to 'delete', :controller => "wysiwygs", :action => "destroy_image", :hidden_field => {:value => image.id} %>
def show
# this was previously in destroy_image
#img = Image.find(params[:hidden_field][:value])
#img.destroy
respond_to do |format|
format.html { redirect_to admin_image_rotator_path }
end
end
It seems you're going down the wrong path here. If a before_filter is blocking your action, figure out why. Use skip_before_filter :filter_name if the filter is not needed.
Don't use show actions or HTTP GET for deletes. Even if it works, it will confuse things down the road. Use a DELETE verb:
map.resources :images, :member => { :destroy_image => :delete }
pass it in the link helper:
<%= link_to "delete", destroy_image_image_path(image), :method => :delete %>
And use ImagesController#destroy_image to perform the action. Better yet, consider using the standard RESTful ImagesController#destroy which map.resources gives you for free.
Not sure what was wrong in the first place, but in your second, working solution, i think you should write your link_to as follows:
link_to 'delete', :controller => "wysiwygs", :action => "destroy_image", :id => image.id
That at least would send you to the correct action.
Depending on your routes, you will have to make this a method => :post or not.
Check your rake routes output, it will show you what are the possible routes, and also what names they got, which in turn you can use as a method (add _path or _url at the end). Then it should be even easier to write something like:
link_to 'delete', wysiwygs_destroy_image_path(image)
Good luck!
You're doing a POST but your resource says that :destroy_image is only available via GET. Try changing your route to:
map.resources :images, :member => { :destroy_image => :post }
Also, take a look at your link_to. The second parameter takes a URL, not a hash that has a :url key. As mentioned elsewhere, depending on your Rails version you may need :method => :post instead of :post => true. In Rails 2.3.8, you would want this line instead:
<%= link_to 'delete', destroy_image_image_path(image), :method => :post %>