Rails: How to Pass Custom Params to a Controller Method

Rails: How do I pass custom params to a controller method?

One of the below answers is probably a better way, but to answer your question of how to pass extra params. You can just add them to the end of your url helper, so if your existing link looks like:

link_to 'Show', post_path(id)

just change it to:

link_to 'Show', post_path(id) + '?preview=true'

Ruby on rails. Passing params from view to controller

But I get undefined method 'update'for nil:NilCLass:

The error is that you have not defined @gig in your create action.

Since Rails is built on HTTP, and HTTP is stateless, you have to set the "instance" variables with each new request:

def new
@review = Review.new
@gig = Gig.find params[:gigid]
end

def create
@gig = Gig.find params[:gigid]
@review = @user.reviews.new review_params

A much better pattern for you would be to use the after_create callback in your Review model:

#app/models/review.rb
class Review < ActiveRecord::Base
belongs_to :gig #-> I presume
after_create :set_gig

private

def set_gig
self.gig.update(reviewed: true)
end
end

--

If you wanted to make the Gig update within your current setup, you'll be best sending the gig_id param through the request (not the link):

#app/views/reviews/new.html.erb
<%= form_for [@user, @review] do |f| %>
<%= f.hidden_field :gig_id, @gig.id %> #-> params[:reviews][:gig_id]
...
<% end %>

This will make params[:review][:gig_id] available in the create action, with which you'll be able to use in your code.

Passing custom params through from view to a form_with

Solution 1 - Clean Pass Through

This is the simple solution that requires the least amount of change in your current application.

You can set the attribute in the #new method of the DevicesController and pass it to the form as an hidden field like so:

class DevicesController < ApplicationController

def new
@device = Device.new(outlet_id: params[:outlet_id])
end

end

Now add a hidden field to the form. This is necessary to preserve and send the outlet_id to the form path (in this case POST /devices/:id). I leave out the error handling part for simplicity.

<%= form_with model: @device, local: true do |form| %>

<%= form.hidden_field :outlet_id %>

<p>
<%= form.label :title %><br />
<%= form.text_field :title %>
</p>

<p>
<%= form.submit %>
</p>

<% end %>

Don't forget to whitelist the new param in your DevicesController#device_params method, otherwise it won't save.

Solution 2 - Nested Resources

A better approach would be to use Nested Resources, but that would require a structural change. Firstly add a nested route in your routes.rb file:

resources :outlets do
resources :devices, shallow: true
end

This will create the following routes:

+-----------+---------------------------------+-------------------+------------------------+
| HTTP Verb | Path | Controller#Action | Named Helper |
|-----------|---------------------------------|-------------------|------------------------|
| GET | /outlets | outlets#index | outlets_path |
| GET | /outlets/:id | outlets#show | outlet_path |
| GET | /outlets/new | outlets#new | new_outlet_path |
| GET | /outlets/:id/edit | outlets#edit | edit_outlet_path |
| POST | /outlets | outlets#create | outlets_path |
| PATCH/PUT | /outlets/:id | outlets#update | outlet_path |
| DELETE | /outlets/:id | outlets#destroy | outlet_path |
| GET | /outlets/:outlet_id/devices | devices#index | outlet_devices_path |
| GET | /devices/:id | devices#show | device_path |
| GET | /outlets/:outlet_id/devices/new | devices#new | new_outlet_device_path |
| GET | /devices/:id/edit | devices#edit | edit_device_path |
| POST | /outlets/:outlet_id/devices | devices#create | outlet_devices_path |
| PATCH/PUT | /devices/:id | devices#update | device_path |
| DELETE | /devices/:id | devices#destroy | device_path |
+-----------+---------------------------------+-------------------+------------------------+

Now add a before_action callback in the controller alongside a new way of building the new instance for #new and #create:

class DevicesController < ApplicationController
before_action :set_device, on: %i[show edit update delete] # already present
before_action :set_outlet, on: %i[index new create] # new

def new
# for outlet has_many devices
@device = @outlet.devices.build
# for outlet has_one device
@device = @outlet.build_device
end

def create
# for outlet has_many devices
@device = @outlet.devices.build(device_params)
# for outlet has_one device
@device = @outlet.build_device(device_params)

# followed by your normal create stuff
end

# code...

private

def set_devise # already present
@device = Device.find(params[:id])
end

def set_outlet # new
@outlet = Outlet.find(params[:outlet_id])
end

# code ...

end

Now remove the params param and change the path of your of your button to:

<%= button_to 'Add Device', new_outlet_device_path(outlet), method: :get %>

Now the last thing to do is change the url of the form so it points to the right path for #create and #update. For this, change the form creation line to:

<%= form_with model: [@outlet, @device].compact, local: true do |form| %>

Passing an array to a form helper in Rails normally sets up nested paths. I call #compact to ensure that the form works fine when editing. Because when you edit a device @outlet is not set resulting in [nil, #<Device...>]. When calling #compact the nil values are removed from the array.

This will result in the following requests:

  • POST /outlets/:outlet_id/devices for a new device
  • PUT /devices/:id for an existing device

How do you pass parameters to a controller method when you invoke it in the Rails console?

You're getting this error because the create method doesn't receive any argument. In order to use the create action properly you need to pass the ActionController::Parameters to your controller's instance:

c = MyObjectsController.new
c.params = ActionController::Parameters.new(id: "abc")
c.create # It will not work if this controller uses authentication

How to pass a parameter to controller action from view in rails through link_to helper

  1. Do not use camel case in variable names and method names in Rails. That's not a convention and will bite you later.

  2. Use named path when you can, instead of manually assign controller and action.

For your question, suppose your named path is home_connect_to_path, then

link_to "Connect", home_connect_to_path(foo_param: 'bar_value')

The link will look like

http://localhost:3000/home/connect_to?foo_parms=bar_value

Then get it in controller

def connect_to
foo = params[:foo_param] # 'bar_value'

Rails passing params to another controller

You should build URL with parameters use Rails helper:

redirect_to test_path(param1: 'value', ...)

or specify controller and action:

redirect_to controller: 'Test', action: 'index', param1: 'value', ... 

in your case you just make redirect to '/thankyou' URL without parameters.

How Do I Pass Additional Parameters in Rails from Controller to Model

I have an association of cart and transaction in which cart has_many transactions and transaction belongs_to cart

Since that's the case and you already have a cart object, in your controller just instantiate the transaction from the cart:

transaction = cart.transactions.build app_token: params[:token]
transaction.save

cart_id will then be available to all the instance methods in the model, so there is no need to extend app_token= with additional logic unrelated to the app_token. Instead, take advantage of ActiveRecord callbacks. For example, you could use a before_save callback to implement your logic:

class Transaction < ActiveRecord::Base
belongs_to :cart
before_save :do_something_with_cart

def do_something_with_cart
# I want to add a few more lines of code here so that I can manipulate cart_id
end
end

If for some reason a callback does not fit your use casae, call the custom method directly in the controller:

transaction = cart.transactions.build app_token: params[:token]
transaction.do_something_with_cart

Custom parameters from view to controller

Add hidden filed in your form and set its value equal to @event.id

 <%= form_tag logic_giveRandomGifts_path :method => 'post' %>
<div class="form-group">
<%= collection_select(:params, :product_id, Product.all, :id, :name, :prompt => true) %>
Quantidate:
<%= text_field_tag :quantity, params[:quantity], :size => 2 %>
<%= hidden_field_tag :event_id, value: @event.id%> #add this
<%= submit_tag "GO!",params[:event_id] => @event.id,:class => 'btn btn-default' %>
</div>
<% end %>

You can use now event id in your controller as params[:event_id]

Passing Custom Form Values to a Custom Controller Action

You cannot use form_for since your form elements doesn't represent the attributes of a model. use form_tag instead

<%= form_tag(update_ordid_exchange_path, :method => :patch) do%>
<div class="field">
<%= label_tag "Order ID" %><br>
<%= text_field_tag :ordid, class: "form-control" %>
</div>
<% if @isrequestor == true %>
<%= hidden_field_tag :ordfld, "1" %>
<% else %>
<%= hidden_field_tag :ordfld, "2" %>
<% end %>
<div class="actions">
<%= submit_tag "Submit", class: "btn btn-primary" %>
</div>
<%end%>

Documentation here

form_tag vs form_for

hidden_field_tag



Related Topics



Leave a reply



Submit