How Do I Pass A Parameter From link_to To A Controller? - ruby-on-rails

Building a project with Rails 3.1
I would like to provide a link in a parent model's show page that passes the parent model's id to a child object controller's create method.
I'm guessing this will require a custom route, but have no idea how to build it.
Is this possible? Or would I be breaking a Rails convention? I don't want to use a multiple model form if I can avoid it.
Thanks!

You can just pass them in as arbitrary values:
link_to my_path(:extra_attribute => value, :foo => 'bar')

Related

ruby on rails 4.2 - ActionController::UrlGenerationError in Prodotti#new

I'm following the tutorial http://guides.rubyonrails.org/getting_started.html but i'm stuck on section 5.2 'the first form'
The error is after i put prodotti_path
<%= form_for :prodotto, url: prodotti_path do |f| %>
my rake routes:
Prefix Verb URI Pattern Controller#Action
welcome_index GET /welcome/index(.:format) welcome#index
prodotti_index GET /prodotti(.:format) prodotti#index
POST /prodotti(.:format) prodotti#create
new_prodotti GET /prodotti/new(.:format) prodotti#new
edit_prodotti GET /prodotti/:id/edit(.:format) prodotti#edit
prodotti GET /prodotti/:id(.:format) prodotti#show
PATCH /prodotti/:id(.:format) prodotti#update
PUT /prodotti/:id(.:format) prodotti#update
DELETE /prodotti/:id(.:format) prodotti#destroy
root GET / welcome#index
but when i refresh the page http://localhost:3000/prodotti/new/ the rails say:
ActionController::UrlGenerationError in Prodotti#new
Why? i'm new to ruby and ror, sorry !
Firstly, welcome to the Rails community!
Here's what you need to do:
#app/controllers/prodottis_controller.rb
class ProdottisController < ApplicationController
def new
#prodotti = Prodotti.new
end
def create
#prodotti = Prodotti.new prodotti_params
end
private
def prodotti_params
params.require(:prodotti).permit(:x, :y, :z)
end
end
Then in your view:
#app/views/prodotti/new.html.erb
<%= form_for #prodotti do |f| %>
<%= f.text_field :attribute_name %>
<%= f.submit %>
<% end %>
OOP
The problem you have is you're using a symbol in your form_for. Whilst this does work, it is not the best way to get it working, especially for a beginner.
Without going into too much detail, I'll explain that form_for is what's known as a helper method. If you pass this certain credentials, it will construct an HTML form for you:
Typically, a form designed to create or update a resource reflects the
identity of the resource in several ways: (i) the url that the form is
sent to (the form element's action attribute) should result in a
request being routed to the appropriate controller action (with the
appropriate :id parameter in the case of an existing resource), (ii)
input fields should be named in such a way that in the controller
their values appear in the appropriate places within the params hash,
and (iii) for an existing record, when the form is initially
displayed, input fields corresponding to attributes of the resource
should show the current values of those attributes.
In Rails, this is usually achieved by creating the form using form_for
and a number of related helper methods. form_for generates an
appropriate form tag and yields a form builder object that knows the
model the form is about. Input fields are created by calling methods
defined on the form builder, which means they are able to generate the
appropriate names and default values corresponding to the model
attributes, as well as convenient IDs, etc.
This basically means that you're meant to pass objects to the form_for helper - objects which have been built in your model and assigned in your controller.
The objects in Ruby are used by Rails throughout your application. Indeed, as Ruby is object orientated, all the things you do with the language, and frameworks, are meant to revolve around objects too.
Rails is object orientated in its own way. Remember, Rails is a framework which sits on top of Ruby. Thus, anything you do has to have objects at the center of the flow:
Models construct the objects in Rails.
Everything from your routes to controller actions take the idea that your models will be invoking data objects -- making it that each "helper" method in Rails (such as form_for) can be used with the corresponding objects you've built.
This is why I recommended setting the appropriate variable and passing it to your form helper. This will tie into your routes and controller actions, and should work for you.

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
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.

Rails form parameters: params[:controller][:variable] or params[:variable]?

In a Rails controller receiving a form POST, is it better to refer to parameters as params[:controller][:variable] or simply params[:variable]?
Rails' form helpers appears to name some fields as controller[variable] in the view, but the the controller somehow knows how to find the value when the controller uses params[:variable]. In other cases, it doesn't seem to know, particularly when I use a different controller name (e.g. form_for(#model, :as => :othercontroller, :url => :othercontroller_path(#model)).
The Rails documentation indicates that params[:variable] is sufficient, but this doesn't seem to be the case?

Custom name for params hash from Rails form_for

Ordinarily, using form_for(#foo) means that on the back end of the form's action, you'll have the form data in params[:foo], but in my case I'd like to have a custom namespace applied to these params, i.e. params[:bar], not params[:foo].
I'm not talking about making the namespace longer by supplying the :namespace argument to the form_for method. To the contrary, my current name is overlong, and I want to shorten it. More importantly, I'm actually swapping a new model in place of an existing one, so the controller is filled with calls to params[:quoter], whereas our new model supplies params[:company_quoter_intf_quoter]. Any ideas?
Specs: Ruby 1.9.3, Rails 3.2.3
What you are looking for is:
form_for(#foo, :as => :bar)
The documentation for this can be found at:
http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html

Dynamically generating method names in rails

I need to generate links in my views using the url helpers such as user_path(#user), the catch is, in some cases I don't know what model I am creating this link for i.e. whether it is a user or a store or someting else
I would like to be able to determine this on the fly and call the appropriate view helper, currently I am doing the following, but I am wondering if there is a drier way of doing it.
if object.class == "Store"
store_path(object)
elsif object.class == "User"
user_path(object)
...etc
Sure, use send to dynamically choose the method name
send("#{object.class.name.downcase}_path", object)
url_for(object) does what you need:
If you instead of a hash pass a record
(like an Active Record or Active
Resource) as the options parameter,
you‘ll trigger the named route for
that record. The lookup will happen on
the name of the class. So passing a
Workshop object will attempt to use
the workshop_path route.
If you are using link_to, then you can just pass the object as the URL:
<%= link_to 'Title', object %>

Resources