2scottish
2scottish

Reputation: 683

Use a params[:value] to reference a controller method in Rails

I currently have a form (using form_tag). One of the fields is a dropdown list of options. Each option value matches the name of a method in my controller. What I want to do is when the form submit button is clicked, it runs the controller method corresponding directly to the value selected in the dropdown field.

I've built a work-around right now, but it feels too verbose:

def run_reports
  case params[:report_name]
    when 'method_1' then method_1
    when 'method_2' then method_2
    when 'method_3' then method_3
    when 'method_4' then method_4
    else method_1
end
# each method matches a method already defined in the controller 
# (i.e. method_1  is an existing method)

I had thought that it may work to use the dropdown option value to run the corresponding method in my controller through the form_tag action (i.e. :action => params[:report_name]), but this doesn't work because the action in the form needs to be set before the params value is set. I don't want to use javascript for this functionality.

Here is my form:

<%= form_tag("../reports/run_reports", :method => "get") do %>
  <%= select_tag :report_name, options_for_select([['--  Please Select  --',nil],['Option 1','method_1'], ['Option 2','method_2'], ['Option 3','method_3'], ['Option 4','method_4']]) %>
  <%= submit_tag "Run Report" %>
<% end %>

Any suggestions?

Can I change my controller method to look something like this - but to actually call the controller method to run? I'm guessing this won't run because the params value is returned as a string...

def run_reports
  params[:report_name]
end

Upvotes: 0

Views: 877

Answers (2)

Zach Kemp
Zach Kemp

Reputation: 11904

I think you should rethink the design of your application (based on the little I know about it). You have a controller responsible for running reports, which it really shouldn't be. The controllers are to manage the connection between the web server and the rest of your app.

One solution would be to write a new class called ReportGenerator that would run the report and hand the result back to the controller, which would run any of the possible reports through a single action (for instance, show). If you need variable views you can use partials corresponding to the different kinds of reports.

As for the ReportGenerator, you'll need to be a little creative. It's entirely possible the best solution will be to have an individual class to generate each report type.

Upvotes: 0

Jim Stewart
Jim Stewart

Reputation: 17323

WARNING: this is a terrible idea

You could call the method via a snippet of code like this in the controller:

send(params[:report_name].to_sym)

The reason this is a terrible idea is that anyone accessing the page could manually construct a request to call any method at all by injecting a request to call something hazardous. You really, really do not want to do this. You're better off setting up something to dynamically call known, trusted methods in your form.

Upvotes: 1

Related Questions