Parameter ID changes with custom controller - ruby-on-rails

When the form_for is as so:
<%= form_for #reservation, remote: true do |f| %>
I get the following params:
Parameters: {"utf8"=>"✓", "reservation"=>{"party_size"=>"1",
"persons_attributes"=>{"0"=>{"first_name"=>"Big Name",
"last_name"=>"test", "meal_id"=>"1", "id"=>"24"},
"1"=>{"first_name"=>"", "last_name"=>"", "meal_id"=>"1"}},
"address"=>"test", "city"=>"Test", "state"=>"te", "zip"=>"te"},
"commit"=>"submit", "id"=>"24"}
But when I put a custom controller onto the form_for, as so
<%= form_for #reservation, url: {controller: 'static_pages'}, remote: true do |f| %>
I get the following params:
Parameters: {"utf8"=>"✓", "reservation"=>{"party_size"=>"1",
"persons_attributes"=>{"0"=>{"first_name"=>"Big Name",
"last_name"=>"test", "meal_id"=>"1", "id"=>"24"},
"1"=>{"first_name"=>"", "last_name"=>"", "meal_id"=>"1"}},
"address"=>"test", "city"=>"Test", "state"=>"te", "zip"=>"te"},
"commit"=>"submit", "id"=>"index"}
How do I ensure that the params[:id] remains the same? All I need is the standard form_for with a different controller called (the same for is used for both new\ create and edit\ update).

'form_for' with an active record object tries to identify the URL from the object. If it has an ID, it uses the update route, otherwise it uses the create route. Initially it identifies it as something like
/reservation/1
But when you explicitly pass something as the URL it will override it. Now our URL looks like
/reservation/index
I recommend looking into the 'form_for' documentation, but what could really solve your problem would be to explicitly pass the whole URL, instead of just the controller. That way you could get the ID in the right place

In the form you can place the following line of code which will pass the :id to the controller in the POST request.
<%= hidden_field_tag(:id, params[:id]) %>
You might have to add a method to convert it to an integer within the controller.
params[:id].to_i
Depending on how you have your db setup.

Related

Nested form to route to proper controller action

The routes define
resources :interruptions do
collection do
post :pause
post :restart
end
end
However, within an intervento_controller show action, where #interruption = Interruption.new is declared, a form to create a related record
<%= form_for #interruption, url: pause_interruptions_path do |f| %>
<%= f.hidden_field :intervento_id, value: #intervento.id %>
<%= submit_tag "Pausa", name: 'pausa_intervento' %>
<% end %>
rails is routing to the intervento action, not the one stated in the form_for url declaration.
Started PATCH "/interventos/32" for ::1 at 2017-01-17 13:04:49 +0100
Processing by InterventosController#update as HTML
Parameters: {"utf8"=>"✓", [...] "interruption"=>{"intervento_id"=>"32"}, "pausa_intervento"=>"Pausa", "id"=>"32"}
The model Intervento does allow accepts_nested_attributes_for :interruptions, however I expected this not be necessary as the form declares the action to be routed to. Also, only one record is being created or edited at a time.
How can this be achieved?
Your pause action is defined on collection, i.e /interventos/post,
however, your form is defined for an interruption instance.
You think you meant to do
resources :interruptions do
member do
post :pause
# post :restart
end
end
and you also need to change pause_interruptions_path accordingly.
Also try use f.submit
submit_tag seems being treated as a input field.

Ruby on Rails get paramenter from URL on View

I'd like to get the paramenter from the URL on my view/html.
For example, I'm showing an specific item from my data base, and the URL is like this: "http://localhost:3000/menus/index.%23%3CMenu::ActiveRecord_Relation:0x007f50ed153250%3E?id=6"
What I want is: when I click on the New Button of that specific item, the form opens with the URL "http://localhost:3000/menus/new", but I want somehow pass that id=6 to this NEW view.
I am using this code on the html to open the form: <%= link_to 'Novo', new_menu_path %>
I also tried: <%= link_to 'Novo', new_menu_path(#menus, :id) %>, but the id param is always null/empty.
How do I do that?
Thank you
To pass an extra param to an url when you define a link_to
<%= link_to 'Novo', new_menu_path(id: #menu.id, other_param: "hello") %>
will generate http://localhost:3000/menus/new?id=6&other_param=hello
this will add the following to the params hash
Parameters: {"id"=>"6", "other_param"=>"hello"}
well :id is just a symbol, you need to tell the route helper what to bind to it. For example
<%= link_to 'Novo', new_menu_path(id: params[:id]) %>
which should give you something like /menus/new?id=6

Rails params, params.merge error

In order to keep params filter and filter_type through a ajax form submit, I pass them in as hidden fields in my article form which as a result gives me this params hash:
{"utf8"=>"✓", "_method"=>"patch", "article"=>{"filter"=>"xxx", "filter_type"=>"xxxx", ....actual fields of the model that got updated...}, "commit"=>"Update Article", "controller"=>"articles", "action"=>"update", "id"=>"xxx"}
Which means I can access them through params[:article]["filter"].
When I, in my controller's update method, call params.merge(filter: params[:article]["filter"]) nothing gets appended. When I try params = params.merge(filter: params[:article]["filter"]) I get this error NoMethodError (undefined method '[]' for nil:NilClass):
and here comes the weird part: When I do #foo = params.merge(filter: params[:article]["filter"]) I also don't get anything added until I actually output #foo in the view. As soon as I have the <%= #foo %> in my view, the params get properly merged. Can somebody explain why that is?
I think it is better for you to not pass them as articles child. Instead of using f.hidden_field :filter you could use hidden_field_tag :filter, so you will receive the params like: { filter: "filter", article: {}}. This way there is no need to merge.

Rails Button_to not passing model param

I have the following in my products index page:
<%= button_to "Add", user_order_orderitems_path(user_id: current_user.id, item_id: x.id, order_id: current_user.group.current_order.id), class: "btn btn-mini" %>
Which I can see from the logs is being picked up by my Orderitems#create action in my controller ok. This looks like:
def create
#orderitem = Orderitem.new(orderitem_params)
if #orderitem.save
redirect_to items_path
else
redirect_to items_path
end
end
private
def orderitem_params
params.require(:orderitem).permit(:user_id, :order_id, :item_id)
end
end
The params specified in the button_to call are being created and are showing up in the logs as:
Started POST "/users/1/orders/1/orderitems?item_id=2264" for 127.0.0.1 at 2013-07-03 22:45:24 +0100
Processing by OrderitemsController#create as HTML
Parameters: {"authenticity_token"=>"blah=", "item_id"=>"2264", "user_id"=>"1", "order_id"=>"1"}
Fnally - the problem - my strong_params method can't process these params as the three params I care about are not nested in a hash with 'Orderitem's as a key. I would expect, for my create action to work, I need something like:
Parameters: {"authenticity_token"=>"blah=", "orderitems"=>{"item_id"=>"2264", "user_id"=>"1", "order_id"=>"1"}}
but I can't for the life of me work out how, with button_to I am able to do this - I have tried a form_for, but this also failed to work. Banging my head on a brick wall for a couple of days on this one...So, how can post my three ids to my OrderItemsController create action from an index view for Products but bypassing any form_for or new actions? Is it possible?
Please let me know if I am approaching this scenario (adding an item to a basket) in completely the wrong way.
This way you can treat a standard hash as one supported by strong parameters
raw_parameters = {"authenticity_token"=>"blah=", "item_id"=>"2264", "user_id"=>"1", "order_id"=>"1"}
parameters = ActionController::Parameters.new(raw_parameters)
parameters.permit(:user_id, :order_id, :item_id)

Pass Parameters in Link_to

I would like to pass a parameter through a link_to method in Rails. I know there is a way to do it via the URL but I really don't want to do that. Is there any way to pass a param via a link without adding it to the link itself?
I know in PHP you can post and then retrieve that value by using the post variable. Is there something similar in Rails?
link_to signature looks as follows:
link_to(body, url_options = {}, html_options = {})
So, POST would look like (lets say you want to POST user's data):
link_to "Link text", some_path(:foo => "bar", :baz => "quux"), user: #user, :method => :post
User's data can be retrieved in the controller using params[:user]
Here's how you can pass a parameter around via the link_to method in order to, say, create a new object with the passed parameter. This strategy would allow you to pass variables among actions in your controller and create objects with predefined attributes:
Say in your show view, you have a variable called #foo that you want to pass to your new controller action. In which case, in your show view, you can have
<%= link_to "Link Text", new_widget_path(:foo => #foo) %>
which would store #foo in params[:foo], allowing you to use params[:foo] in your controller. Which controller action you get directed to depends upon *new_widget_path*. In this case, you get directed to the new action in WidgetController.
Clicking on Link Text will direct Rails to the new action of your WidgetController. You can have
def new
#widget = Widget.new(:foo => params[:foo])
end
Then, in your new.html.erb view file, you can allow the user to create a new Widget object with this pre-defined foo attribute already filled out via a hidden form field:
<%= form_for(#widget) do |f| %>
<%= f.label :other_attribute %><br />
<%= f.text_field :other_attribute %>
<%= f.hidden_field :foo %>
<%= f.submit %>
<% end %>
Allowing the user to create a new widget with the foo attribute already filled out!
Passing information through a web request can be done either by the URL: http://example.com/foo?bar=blah in a GET request which is what link_to does, or through a POST operation which usually requires a form. The form could have hidden elements if you just want a submit button:
<form method="POST" action="http://example.com/foo">
<input type="hidden" name="bar" value="blah">
<input type="submit">
</form>
There are various rails helpers to help build the form if needed.
Lastly, if you really want a link, you could either CSS style that button, or you could use javascript to observe a link and then POST the info. (the method Simon Bagreev posted does this with javascript)
What sort of parameter? If it's a key for a GET request, convention would dictate using the url (e.g. params[:id] or a an active record path variable). If you want to POST something, you should be using a form. Otherwise, you could write a helper method to set a session variable or something, but think about your architecture and what you're semantically trying to do, and I'm sure someone here can help you out.

Resources