I got a view with the following code:
<%= form_for(#stock,:url=>{:action=>"buyback"},:html=>{:class=>"form-horizontal"}) do |f| %>
My routes.rb file shows:
post '/stocks/buyback'
When I click the submit button of the form, it does not trigger the method buyback of the controller but instead update.
The log file shows:
Started PUT "/stocks/buyback" for 127.0.0.1 at 2012-07-22 19:46:07 +0800
Processing by StocksController#update as HTML
Its triggering the controller method Update instead of buyback. Why?
try this
<%= form_for(#stock,:url=>{:action=>"buyback"},:method => :post, :html=>{:class=>"form-horizontal"}) do |f| %>
Related
I'm using Rails 7. I wanted to create a link using link_to that inserts some custom form fields for a many-to-many relation into a form via a hotwired frame elsewhere on the page. In order to customize the form fields generated (setting defaults etc) I need to include some custom parameters in the request:
<%= link_to "Add crew to ship",
new_crew_path(ship_id: ship.id),
data: { turbo_method: :get,
turbo_stream: true } %>
The HTML looks correct, but when clicking the link, the parameter seems to have been stripped away:
<a data-turbo-method="get" data-turbo-stream="true" href="/crews/new?ship_id=1">Add crew to ship</a>
...
Started GET "/crews/new" for 127.0.0.1 at 2023-01-24 13:49:23 +0100
Processing by CrewsController#new as TURBO_STREAM
If I remove the data map defining turbo_stream: true so it becomes a regular request, it works fine:
<%= link_to "Add crew to ship",
new_crew_path(ship_id: ship.id) %>
Started GET "/crews/new?ship_id=1" for 127.0.0.1 at 2023-01-24 13:53:26 +0100
Processing by CrewsController#new as HTML
Incoming parameters: {"ship_id"=>"1"}
Same for changing it to a POST request, so it goes to the #create action of the controller instead, that also works:
<%= link_to "Add crew to ship",
crews_path(ship_id: ship.id),
data: { turbo_method: :post,
turbo_stream: true } %>
Started POST "/crews?ship_id=1" for 127.0.0.1 at 2023-01-24 13:58:01 +0100
Processing by CrewsController#create as TURBO_STREAM
Incoming parameters: {"ship_id"=>"1"}
So I have workarounds. Nevertheless, out of curiousity, is there some way to make GET turbo requests submit the custom params? From a REST perspective it feels like the most correct request method.
When you add turbo_method: :get the link is treated as a form and GET forms overwrite url query params with form params. As a test:
// app/javascript/application.js
document.addEventListener("turbo:before-fetch-request", (event) => {
console.log(event.target)
})
// you get this "fake" form in the console, that Turbo submits instead of a link:
// <form data-turbo="true" action="http://localhost:3000/?ship_id=1" hidden="" method="get" data-turbo-stream=""></form>
If you just change the link to this:
<%= link_to "Add crew to ship",
new_crew_path(ship_id: ship.id),
data: { turbo_stream: true } %>
Now it's a regular GET turbo stream link, and query params should stay untouched.
For some extra details:
https://github.com/hotwired/turbo/pull/647
it's worth emphasizing that declaring [data-turbo-method="get"] on an
<a> element is redundant, and should be avoided
https://github.com/hotwired/turbo/pull/821
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.
I'm trying to set up a form on my index page that will pass a param myform, to the same index page via a GET request. I thought this would be relatively simple. but I'm getting an error.
I generated a controller, RecipesController, with a method called index:
class RecipesController < ApplicationController
def index
#search = params[:myform]
return #search
end
end
In this method I'm trying to get back what the user types into a textbox when a button is pressed and the GET request is fired.
Here is my view:
<h1>Recipe Finder</h1>
<%= form_tag(controller:"recipes",method:"get") do %>
<%= label_tag(:myform, "Search") %>
<%= text_field_tag(:myform) %>
<%= submit_tag("search") %>
<% end %>
Here are my routes:
Rails.application.routes.draw do
root 'recipes#index'
This shows up fine when I visit localhost:3000, but when I press the button I'm expecting the controller index method to just return whatever text i typed into the textbox. Unfortunately, I only get:
No route matches [POST] "/"
I know setting the root to recipes#index is causing the failure as my #search variable is not set when the page is opened initially.
I'm wondering if I should have a separate route and method for the GET request and should I just open the main page with the call to localhost:3000 without running any code in the controller? Is this possible?
The problem is that form_tag accepts a Hash as both its first and second argument. If you don't use brackets, it's going to interpret all of it as part of the first argument, and your method: "get" is not applied properly.
Because of this, it defaults to doing a POST request, for which there is no route.
Try this. Because the first argument is no longer a Hash, it should work properly:
<%= form_tag("/", method: "get") do %>
Alternatively, using your code, you can try this:
<%= form_tag({ controller: "recipes" }, { method: "get" }) do %>
Hi all my flash messages work in the normal fashion but there is an action in one of my controllers where the flash message does not work.
This is the view:
<%= form_tag update_status_order_path(update_status), method: :put do |f| %>
<%= select(:order, :status, [['Active', 1], ['Inactive', 0]]) %>
<%= submit_tag "Update" %>
<% end %>
This is the controller action
def update_status
if #order.update_order_status! params[:order][:status]
redirect_to show_orders_ofert_path #order.ofert, success: "Updated!."
else
redirect_to show_orders_ofert_path #order.ofert, error: "Error."
end
end
When I send the form the action is performed correctly, but the flash message is not displayed in the layout, instead is displayed in the url as a param, just after click the Update button it reloads and shows the url like this:
http://localhost:3000/oferts/48/show_orders?success=Updated!
I have tried changing put to patch but it did not worked, even changing the action to work with respons_to block but it did not work, any idea?
this problem is only happening with that specific action because with the other actions I have the flash messages are isplayed normally.
Thanks
The success and error keys are being used as parameters to the show_orders_ofert_path because there are no parenthesis. Add parenthesis around the path helper arguments:
redirect_to show_orders_ofert_path(#order.ofert), success: "Updated!."
Trying to route:
scope :shortcut do
resources :text_elems
end
Using basic scaffold with form partial
*_form.html.erb*
<%= form_for(#text_elem, :shortcut => #shortcut) do |f| %>
...
Problem is: When I call the edit action, the form html shows as:
<form ... action="/25/text_elems/25">
Note: The new action renders the form action correctly:
<form ... action="/home/text_elems">
So it appears that my :shortcut param is getting trumped by the :id param when form_for processes it's block. Now I am able to get the action to correctly route with the :shortcut param if I manually make the :url => {...} in the form_for block, but I would prefer to keep the code dry, plus I want to report this problem to rails if it is indeed a bug.
Can anyone else confirm this as a bug?
Actually, you can pass the values as a full hash, rather than trying to rely on the default to_param (which is what gets called if all you do is pass the #text_elem)
<%= form_for({:id => #text_elem.to_param, :shortcut => #shortcut}) do |f| %>
however, if this is actually a nested-resource, you could also do:
<%= form_for([#shortcut, #text_elem]) do |f| %>
I was having the same issues and none of the above answers helped.
The last answer on this page worked for me though...
https://rails.lighthouseapp.com/projects/8994/tickets/6736-problem-with-scoped-routes-and-form_for-helper