How to create a delete form with RESTful routes in Rails. - ruby-on-rails

I am trying to create a form that serves as confirmation for the destroy method on a controller. In my routes I have:
resources :leagues do
get 'delete', :on => :member
end
In my delete.html.erb, I have the following for:
<% form_for current_league, :html => {:method => :delete} do |form| %>
<%= form.submit 'Yes' %>
<%= form.submit 'No', :name => 'cancel' %>
<% end %>
current_league is a helper function defined by:
def current_league
#current_league ||= League.find_by_id(params[:id])
end
So the problem is that the form that is generated only edits the league model, as seen by the form method="post".
<form accept-charset="UTF-8" action="/leagues/1" class="edit_league" id="edit_league_1" method="post">
<div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" />
<input name="_method" type="hidden" value="delete" />
<input name="authenticity_token" type="hidden" value="abcdefg" />
</div>
<input id="league_submit" name="commit" type="submit" value="Yes" />
<input id="league_submit" name="cancel" type="submit" value="No" />
</form>
How can I fix this?

I think that will already work. As in rails guide http://guides.rubyonrails.org/form_helpers.html#how-do-forms-with-patch-put-or-delete-methods-work-questionmark
However, most browsers don’t support methods other than “GET” and “POST” when it comes to submitting forms.
Rails works`around this issue by emulating other methods over POST with a hidden input named "_method", which is set to reflect the desired method:
as you see in the output form there is
<form accept-charset="UTF-8" action="/leagues/1" class="edit_league" id="edit_league_1" method="post">
....
<input name="_method" type="hidden" value="delete" />
....
</form>
When reading this variable, rails understood that this is a DELETE method, not a POST method. even though the form it self is a POST.

Related

rails form_with check_box is not rendering value of object on page refresh

The following form allows the changing of an attribute vie UJS, the returning block of HTML is rendered correctly
<% #product.productviews.each do |productview| %>
<%= form_with(url: update_productview_products_path(productview_id: productview.id), method: :patch) do |form| %>
<%= productview.active %> <%= form.check_box :active %>
<%= form.submit t('update') %>
<% end %>
<% end %>
Class Product is a parent of has_many :productviews. context: rails 6.1.3
However when refreshing the page the check_box is invariably set to false, notwithstanding the value of the attribute:
<form action="/products/update_productview?productview_id=1" [...]
true <input name="active" type="hidden" value="0" /><input type="checkbox" value="1" name="active" id="active" />
<form action="/products/update_productview?productview_id=2" [...]
true <input name="active" type="hidden" value="0" /><input type="checkbox" value="1" name="active" id="active" />
<form action="/products/update_productview?productview_id=3" [...]
true <input name="active" type="hidden" value="0" /><input type="checkbox" value="1" name="active" id="active" />
<form action="/products/update_productview?productview_id=4" [...]
false <input name="active" type="hidden" value="0" /><input type="checkbox" value="1" name="active" id="active" />
Which is unexpected. Rails guides specify that Array parameters do not play well with the check_box helper. This instance is not a case of array parameters, although it is an array of forms.
However switching to <%= form.check_box_tag "active" %> or <%= form.check_box_tag :active %> will return
undefined method `check_box_tag' for #<ActionView::Helpers::FormBuilder:
which again seems contrary to what the Rails guides purport
Can check_box be used in an array of forms? How can this checkbox show the value of the attribute on page load?
you need to pass the model to the form
<%= form_with(url: update_productview_products_path(productview_id: productview.id), method: :patch, model: productview) do |form| %>
if this does not work you can pass a checked into the check_box input but I advise to use the first option if its working
<%= form.check_box :active, checked: productview.active %>

Rails Turbolinks does not render response from submitted form

Submitting a basic xhr-form in a turbolinks-activated rails project (5.1), does trigger the correct server-side response but the client (turbolinks) discards the response. Neither get nor post do work. Tested in Firefox and Chromium. Forms with redirection work as intended.
Here's a simple test page that fails for me
test.html.erb:
<h1><%= #value %></h1>
<%= form_with url: 'test' do |f| %>
<%= f.check_box :anything %>
<%= f.submit %>
<% end %>
controller:
def test
if request.post?
#value = 'post'
else
#value = 'get'
end
end
routes:
post '/test', to: 'controller#test'
get '/test', to: 'controller#test'
rails response payload:
<h1>post</h1>
<form action="test" accept-charset="UTF-8" data-remote="true" method="post"><input name="utf8" type="hidden" value="✓" /><input type="hidden" name="authenticity_token" value="X1sh+tc/Jx4P0rdDqc2CD1RetKQKr+lVh4fD29JOMY/b+PdPNgw1qyzoyv6t3I2I+6jV1mmn6voXN+YySaUISw==" />
<input name="anything" type="hidden" value="0" /><input type="checkbox" value="1" name="anything" />
<input type="submit" name="commit" value="submit" data-disable-with="submit" />
</form>
</div>
The form loads like expected, but after submitting the page does not change. Inside the xhr-response the correct answer is visible, but it does not get applied to the DOM.
Is this a bug, or am I using turbolinks wrong?
I'm seeing this as well and I'm not sure how to proceed. What is nice about Turbolinks is that you don't have to create js responses for each request. This is true until you submit a form. At that point, you have no choice but to create a js.erb respone file or change the form to local: true. Am I missing something?
Try using data: { turbolinks: false } in the any links to the page containing the form.
E.g.
<%= link_to "Get in Touch", 'contact', data: { turbolinks: false } %>

Rails generate wrong method for "form_tag". How to fix that?

On on page, I have 2 forms like this:
<%= form_tag(create_car_service_settings_index_path, remote: true, method: :post) do %>
<%= hidden_field_tag "service_type", 1 %>
<%= text_field_tag "service_name", "", id: "service_name_car" %>
<%= submit_tag "Add Service" %>
<% end %>
... some HTML ...
<%= form_tag(create_car_service_settings_index_path, remote: true, method: :post) do %>
<%= hidden_field_tag "service_type", 0 %>
<%= text_field_tag "service_name", "", id: "service_name_car" %>
<%= submit_tag "Add Service" %>
<% end %>
The first form is rendered as POST, but the second one as GET; in routes.rb is following:
resources :settings do
collection do
...
post 'create_car_service'
post 'edit_car_service'
end
end
Why the second form is rendered as GET instead of POST? Stuck on this for a while.
Thanks.
EDIT:
First form:
<form action="/settings/create_car_service" accept-charset="UTF-8" data-remote="true" method="post">
...
Second form:
<form action="/settings/create_car_service" accept-charset="UTF-8" data-remote="true" method="get">
When you do bin/rails routes you should get something like this
Prefix Verb URI Pattern Controller#Action
create_car_service_settings POST /settings/create_car_service(.:format) settings#create_car_service
edit_car_service_settings POST /settings/edit_car_service(.:format) settings#edit_car_service
So that post route should be create_car_service_settings_path not create_car_service_settings_index_path that points to settings#create_car_service
But it is a strange if you get for one method GET and other POST. Can you paste the output from these forms (html)
EDIT
So using the path that you provided generated an error for me. When I use this
<%= form_tag(create_car_service_settings_path, remote: true, method: :post) do %>
I will get this for first
<form action="/settings/create_car_service" accept-charset="UTF-8" data-remote="true" method="post">
for second
<form action="/settings/create_car_service" accept-charset="UTF-8" data-remote="true" method="post"><input name="utf8" type="hidden" value="✓" />
<input type="hidden" name="service_type" id="service_type" value="0" />
<input type="text" name="service_name" id="service_name_car" value="" />
<input type="submit" name="commit" value="Add Service" data-disable-with="Add Service" />
</form>

routing form submission to different controller

problem: I have a form but the submit button doesn't do anything.
i instantiate the class the form is for in the employee_controller controller.
def employee
#body_class = "employee membership"
#employee_contact_form = CorporateContactForm.new
end
I create the form in the page the above controller action serves
= simple_form_for [#employee_contact_form] do |f|
= f.input :firstname
= f.button :submit
In my routes I set the resources for the contact forms
resources :corporate_contact_forms
I then have a controller that serves the form
class CorporateContactFormsController < ApplicationController
def create
raise
end
I am aware there is no code in the corporatecontactcontroller, but the submit button should at least fire to an error. It doesn't do anything.
This feels like such a simple problem, and surely it is.
What am I missing?
update
html output
<form>
<form accept-charset="UTF-8" action="/corporate_contact_forms" class="simple_form new_corporate_contact_form" id="new_corporate_contact_form" method="post"><div style="display:none"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="7iMwWQOuyzV3jJt4jTtr9MGvI129hPaG+m+Pe2D3YyM=" /></div> <div class="input string optional corporate_contact_form_firstname"><label class="string optional" for="corporate_contact_form_firstname">Firstname</label><input class="string optional" id="corporate_contact_form_firstname" maxlength="255" name="corporate_contact_form[firstname]" size="255" type="text" /></div>
<input class="button" name="commit" type="submit" value="Create Corporate contact form" />
</form>
</form>
According to the documetation (http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for), you can do something like this to force the form to go to CorporateContactFormsController#create
<%= simple_form_for #employee_contact_form, url: corporate_contact_forms_path, method: :post do |f| %>
# awesome code...
<% end %>
Also I'm not sure if the f.button :submit has something to do, the default for submitting is f.submit

form_tag with :remote => true does not update div, skips to separate page

I am trying to update a div based on a form submit. I am on Rails 3.1.1. I am trying to adapt someone else's recipe. My code in the view is something like this in main.html.erb:
<%= javascript_include_tag :defaults %>
<div id='seq_search'>
<%= form_tag(:remote => true, :update => 'seq_select', :action => 'select') do %>
<p>
<%= search_field_tag :query, '', :size => 45 %>
</p>
<p>
<%=submit_tag "Submit", :disable_wth => "Adding ..."%>
</p>
<% end %>
</div>
<div id='seq_select'>
</div>
The controller looks like
class SearchAjaxController < ApplicationController
def main
end
def select
render :text => '<li> '+params[:query] + ' </li>'
end
end
However, when I enter something in the text box and press submit, instead of updating the div, it goes off to another page rendering just the output of the select method of the controller.
If I look at the page source of the form, it is something like this:
<div id='seq_search'>
<form accept-charset="UTF-8" action="/search_ajax/select?remote=true&update=seq_select" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="wlOm4H7GvZAQoIVpjxPLqHAQLOIpJ4V5r0WYEpvCCrQ=" /></div>
<p>
<input id="query" name="query" size="45" type="search" value="" />
</p>
<p>
<input disable_wth="Adding ..." name="commit" type="submit" value="Submit" />
</p>
</form></div>
<div id='seq_select'>
</div>
It seems that the form is simply passing remote=true&update=seq_select as arguments to the controller's method/function. Is this what is supposed to happen?
Update:
So I tried to add to follow Mike Campbell's sugggestion and added the following code to my view (`.html.erb') file
<SCRIPT type='text/Javascript'>
$(function(){
$('#form-id').bind('ajax:success', function(xhr, data, status){
$('#seq_select').html(data);
});
}
</SCRIPT>
and also gave an id to the form:
<%= form_tag(:remote => true, :update => 'seq_select', :action => 'select', :id => 'form-id') do %>
Submitting the form still doesn't update the page. It simply skips to a new rendered view as before. The generated HTML reads:
<SCRIPT type='text/Javascript'>
$(function(){
$('#form-id').bind('ajax:success', function(xhr, data, status){
$('#seq_select').html(data);
});
}
</SCRIPT>
<div id='seq_search'>
<form accept-charset="UTF-8" action="/ajax_search/select/form-id?remote=true&update=seq_select" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /><input name="authenticity_token" type="hidden" value="wlOm4H7GvZAQoIVpjxPLqHAQLOIpJ4V5r0WYEpvCCrQ=" /></div>
<p>
<label> Search by identifiers, accessions, and gene names.. </label>
</p>
<p>
<input id="query" name="query" size="45" type="search" value="" />
</p>
<p>
<input disable_wth="Adding ..." name="commit" type="submit" value="Submit" />
</p>
</form></div>
<div id='seq_select'>
</div>
Update:
It seems that the syntax for form_tag was wrong, and the first argument has to be the name of the action. I now have <%= form_tag( 'select', :remote => true, :id => 'form_id') do %> which generates the associated HTML <form accept-charset="UTF-8" action="select" data-remote="true" id="form_id" method="post">. Which is better, but my Ajax is still not working.
I think this has to do with respond to xhr in the controller. you should specify this is a xhr request.
See here for a question on that.

Resources