Here's my code for a form that contains a drop down list -
<div class="field">
<%= f.label :type, "Select profile type"%>
<%=
f.select :type, Profile::TYPES,
:prompt => "Select a profile type"
%>
</div>
The drop down menu looks fine. But, how would I check which option is selected? I want to route to a different view based on this selection.
Thanks in advance!
The logic of routing to a different view should occur in your controller. When the user submits this form, check the value of the params, and perform your logic to route to a view:
class ExampleController
def routing
case params[:example][:type]
when 'foo'
redirect_to foo_path
when 'bar'
redirect_to bar_path
end
end
You can create a custom action name, since this routing isn't one of the CRUD operations. You will need to place this route into the config/routes.rb file if it is a custom name.
Optionally, you can bind to the select's onChange event, as mentioned by others to auto-submit the form when the user changes the value. This would still send the data to the controller and perform a redirect. The advantage to this approach is that you can keep your route information out of Javascript, and in the Rail's controller.
More on Rails routing can be found here: http://guides.rubyonrails.org/routing.html
More on Javascript binding to onChange can be found here: http://www.w3schools.com/jsref/event_onchange.asp
You should be able to use jQuery or any other popular Javascript framework to achieve this -- either attach an onChange listener or set the value somewhere and check it. Events, yay, etc.
Related
I am looking for the right approach to include a preview action between new and create actions.
Let's assume I have the following:
resources :users
By default, when the form is submitted:
if new, call create action;
if edit, call update action.
In this way, I can use the same form (partial) for new and create, which is great!
How can I configure the resources to include a preview between actions. I mean, forcing new to call preview and then preview to call create.
I could add a new route/action and point the form for that action, however the same form cannot be used for new and edit.
There is a way to configure the resources to do that?
Have a look at this railscast: multibutton form, it shows a form with both a 'preview' and 'submit' button, maybe that's something you might want to do.
By the way, couldn't you use the same form by passing locals to the partial? For example:
<%= form_for #profile, url: dynamic_path do |f| %>
...
<% end %>
<%= render 'form', dynamic_path: profile_preview_path %>
you have several ways to do this:
you change the url of the form to your preview action (for which you have to add a route).
you use your create action for preview and create:
i.e. you add a parameter (like ':go_to_preview') to the form submit request. if you find it in the controller you render preview.
when the user wants to confirm the preview, you submit the data again (without that parameter) and this time create the record.
there are also 2 more dynamic possibilities:
you create the preview in real-time - if that is possible (like here on SO) - and use just the create action,
a variation of the first option: when the user submits the form, you send an ajax post request to a preview action, render a partial and include it on the page, then while your user still has the form he just filled, the user decides if she wants to modify or submit definitely.
I would suggest adding a DateTime column "finished_at", "published_on", etc... whatever is appropriate for your domain.
Using blog posts as an example:
scope :published, where("published_on IS NOT NULL")
scope :draft, where(:published_on => nil)
Use the scopes and new field where appropriate to limit the follow up actions.
This approach gives you more than you asked for :
a way to limit processing based on "state"
Data on creation times versus publishing times
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
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.
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.
I'm new to Ruby on Rails and i have an issue.
I have 2 forms which edit the same model, but in the update method I have to give a different JS response depending on the form which submitted.
How do I do that?
Just add a hidden input field to your form specifying where it comes from.
Then, in your controller, access this field through the params[:field_name].
Create the form by using something like:
<%= f.hidden_field :origin, :value => "this_form" %>
This will render as something like:
<input name="origin" type="hidden" value="foo"/>
In your controller, check which value this hidden field had, and use render to render your JS response (or whatever you specifically use). See Layouts and Rendering for more info.
if params[:origin] == "foo"
render ...
else
render ...
end
There are two different ways you could go about this:
You could put a hidden variable in the form and then check in the controller to see which form was submitted.
You could also have two different controller methods to handle the different behavior.
Without knowing more about your code it's hard to say which way would be cleaner.
I am new to Rails and don't quite understand what I'm supposed to do. Let's say, for example, I want a textbox containing a string to be passed into another controller (another page?) when the user clicks a button. How would I go about doing that?
Functions of controllers are pages, correct? Can a function take parameters just like a normal method? (E.g. sum(x,y))
For complete information, check out Rails Form helpers. Basically, you give the form_tag method a path which points to the controller and the action that you want to handle the form submission. For example,
<%= form_tag(search_path, :method => "get") do %>
<%= label_tag(:q, "Search for:") %>
<%= text_field_tag(:q) %>
<%= submit_tag("Search") %>
<% end %>
Here, the action and controller that search_path points to (defined in your routes) will receive the form submission and the value from the text field.
Your action in the controller IS a function, but it will not receive the value from the form submission as a parameter to the function. Instead, you will access it through the params hash. In the example above, you can access the value from the text field as
params[:q]
What are you doing with the string? Storing it? Using it as a parameter on another page?
I suggest you take a look at the Getting Started Guide, go through it, and pay particular attention to the What is Rails? section, where it explains MVC architecture and REST (Representational State Transfer.)
There are dozens of other Rails tutuorials out there, I'm sure if you searched this site you'd find many questions like this one:
https://stackoverflow.com/questions/2794297/how-to-learn-ruby-on-rails-as-a-complete-programming-beginner
Functions of controllers are pages, correct? Can a function take parameters just like a normal method?
Functions of controllers are pages if that's the route you've set up in your routes.rb configuration file. I suggest you run through some tutorials to understand what Rails is for and how it works.
I have a form around a list of items. I would like to check a radio button on the list and then, after clicking 'Submit', go to the 'Edit' page of the selected item.
The problem is that if I am writing something like
<%= form_tag edit_item_path %>
but Rails complains that I didn't provided a proper id, which in turn is being set on my radio buttons as the following:
<%= radio_button 'item', 'id', item.id %>
So - how would I send a form with a selected id to a given action?
Doing it the way you describe would not work, since edit_item_path by default RESTful path definitions is a GET request. You are trying to make it a POST request. If you would like to stick to the RESTful way of doing things I would recommend simply looping through your items and provide links to edit, since you are planning to edit them one at a time anyways. Otherwise, you would have to define a new route if you would prefer doing things within the form with radio buttons. If you are, than you would add something like this to your config/routes.rb: (assuming you are using rails 2.3.x)
map.resources :items, :member =>{:edit_radio_form => :post}
Than your form would look like this:
<%= form_tag edit_radio_form_item_path do |form| %>
And it should work, but it not the right way of doing things for several reasons, the most anoying one of which is that you won't get a full URL on your edit page because you got there with a POST request, so if you refresh the page, your item id param will be gone and will produce an error.