简体   繁体   中英

Why Rails process link_to with :action=>methodname as ID=>methodname

I'm trying to make a link in Rails (2.1) that:

  1. Only appears for admin users
  2. When clicked, executes a method in the controller,
  3. The method executes a small shell script (eg a short sql query which outputs a text file),
  4. Prompts the user to download the output text file,
  5. Everything is done on the same page without redirecting to another page (ideally)

I tried these solutions to run a shell script from Ruby: ( 1 ), ( 2 ). In my reports_controller.rb :

  def runreport    
    #system('sh hello.sh')
    puts `whoami` # << this is just to test shell script calling
  end

And in my view/report/index.html.erb :

<% if is_logged_in? && logged_in_user.has_role?('Administrator') -%>
  <p><span class="encapsulated"><%= link_to "Download File", { :action => 'runreport' } %></span></p>
<% end -%>

(The <span class="encapsulated"> just puts the link in a nice button form). However, when I clicked the link, it returns an error:

ActiveRecord::RecordNotFound in ReportsController#show 
Couldn't find Report with ID=runreport
...
app/controllers/reports_controller.rb:100:in `show'

With Parameters:

{"id"=>"runreport"}

It looks like when the link is pointed to itself ( reports ), the default method to execute is " show ". But wasn't it specifically told to do action => 'runreport' ? I've scratched my head and looked for answers for a few hours and couldn't figure it out :( Thus, my questions are:

  1. What am I doing wrong?
  2. Why is it looking for the id=>"runreport"?
  3. How to fix the error? and if it's possible to tell it to not do redirection
  4. And what's the ideal way to deliver the file to the user after the script is done?

Thank you in advance for any help/feedback!

Cheers!

EDIT: This is how the routes.rb on reports look like:

map.resources :reports, 
:member => { :claim => :put, :close => :put, :open => :put, :baz => :post }, 
:collection => {:search => :get} do |report|
    report.resources :blah, :foo => { :bar => :post }
  end

This is on Rails 2.1, so I assume it's different from 3.x

Generally the issue is with the routes.

If you define restful routes as in

map.resources :reports

or in case of rails 3 and above

resources :reports

Its assumed that /reports/:id is the show action. So when you go to "/reports/runreport" it goes to the show action and tries to find an Report object with the Id "runreport".

Read this http://guides.rubyonrails.org/routing.html#resources-on-the-web

You may want to define collection route on reports to make this work. Read this http://guides.rubyonrails.org/routing.html#adding-more-restful-actions

I have not figured out entirely why the controller always defaults to the show method, but I've found a workaround. I just make it call my runreport method when the link is clicked (which will reload the same page), before it calls the show method.

I'm guessing, since the page is always calling the show method, which is a "member" method, it will always look for some id.

Thanks for all your help!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM