routing form submission to different controller - ruby-on-rails

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

Related

Adding new option to select in Rails

I currently have a vendor, which can have any number of tags attached to it. However, I also want the user to be able to add extra tags on the form. I had previously done this with fields_for and text fields in the form, and accepts_nested_attributes in the controller, but this led to tags getting duplicated when a tag with the same name was added to two different vendors. I know this happened because each vendor could only see the tags that it owned, so it did not know the IDs of the other tags.
Now, I have switched to a select, which lists all possible tags, and pass in a list of ownership IDs to the controller. However, I cannot add new tags anymore, since it cannot find the IDs of the new tags if they aren't added to the database first. It seems that I cannot use fields_for to build the options within the select, so I'm kind of stuck on how to handle this. I've looked into using AJAX to create the tag using the remote: true option inside form_for, but it seems that forms within forms are not supported.
Here are the basic model relationships:
class Vendor < ActiveRecord::Base
has_many :vendor_ownerships
has_many :ownerships, through: :vendor_ownerships
end
class Ownership < ApplicationRecord
has_many :vendor_ownerships
has_many :vendors, through: :vendor_ownerships
end
class VendorOwnership < ApplicationRecord
belongs_to :vendor
belongs_to :ownership
end
Here is my form partial (simplified). It currently tries to use nested forms, but it does not work.
= form_for #vendor do |f|
#form_elements_div
.form_group.element_div
= f.label :name
= f.text_field :name
#ownerships.element_div
= f.collection_select :ownership_ids, Ownership.all, :id, :name, {}, {multiple: true}
#new_ownerships.element_div
-# How do I add the new tag/ownership here?
= form_for :ownership, url: ownerships_path, remote: true do |ff|
= ff.text_field :new_ownership_field
= ff.submit
#submit_div.form_group
= f.submit class: 'btn btn-success'
Theoretically, the nested form for adding a new tag would trigger the controller action create inside the Ownership model, but the submit button for that form always triggers the create for the outer Vendor model.
Edit: Here is the HTML body currently created by my code.
<body>
<body id='vendorsBody'>
<div id='form_div'>
<h2>Edit Vendor</h2>
<form class="edit_vendor" id="edit_vendor_1" action="/vendors/1" accept-charset="UTF-8" method="post">
<input name="utf8" type="hidden" value="✓" />
<input type="hidden" name="_method" value="patch" />
<input type="hidden" name="authenticity_token" value="PzG968HknJ5wCYt37g7RL8J4/00rmcnIO6T02owt5HBh9FUsXfWd00WZW1k/vM+o4RktfbKPBEcWk4BdCfYnhg==" />
<div id='form_elements_div'>
<div class='form_group element_div'>
<label for="vendor_name">Name</label>
<input type="text" value="Vendor 1" name="vendor[name]" id="vendor_name" />
</div>
<div class='element_div' id='ownerships'>
<input name="vendor[ownership_ids][]" type="hidden" value="" />
<select multiple="multiple" name="vendor[ownership_ids][]" id="vendor_ownership_ids">
<option selected="selected" value="1">Type 1</option>
<option selected="selected" value="2">Type 2</option>
<option selected="selected" value="3">Type 3</option>
</select>
</div>
<div class='element_div' id='new_ownerships'>
<form action="/ownerships" accept-charset="UTF-8" data-remote="true" method="post">
<input name="utf8" type="hidden" value="✓" />
<input type="text" name="ownership[new_ownership_field]" id="ownership_new_ownership_field" />
<input type="submit" name="commit" value="Save Ownership" data-disable-with="Save Ownership" />
</form>
</div>
<div class='form_group' id='submit_div'>
<input type="submit" name="commit" value="Update Vendor" class="btn btn-success" data-disable-with="Update Vendor" />
<button class='btn btn-danger' id='cancel_button' onclick='confirmVendorCancel()' type='button'>Cancel</button>
</div>
</div>
</form>
</div>
</body>
</body>

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 } %>

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.

How to create a delete form with RESTful routes in 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.

Is there any way to create a form with formtastic without a model?

I would like to use formtastic to create form but I don't have a model associated with that (login form with username, password and openid URL).
Of course I could create a model to do that but that model was just a hack without any useful code in it.
You can pass a string instead of a model, which will be used to generate the field names:
<% semantic_form_for 'user', :url => 'login' do |f| %>
<% f.inputs :name => 'Login Details' do %>
<%= f.input :username %>
<%= f.input :password %>
<% end %>
<% end %>
Which will produce something like:
<form action="/login" class="formtastic user" method="post"><div style="margin:0;padding:0;display:inline"><input name="authenticity_token" type="hidden" value="E/NksKRd7Twh4nGp1Qc8jBQNfqYDn8gg6sWdTdCtl+g=" /></div>
<fieldset class="inputs"><legend><span>Login Details</span></legend><ol>
<li class="string required" id="user_username_input"><label for="user_username">Username<abbr title="required">*</abbr></label><input id="user_username" name="user[username]" size="50" type="text" /></li>
<li class="password required" id="user_password_input"><label for="user_password">Password<abbr title="required">*</abbr></label><input id="user_password" name="user[password]" size="50" type="password" /></li>
</ol></fieldset>
</form>
But you will need to be more specific with your options as formtastic won't be able to work out what types of fields it should use, all will default to textfields (although it automatically makes fields named like password password type fields).
A better way to do this though would be with a sessions model, have a look at the way authlogic (http://github.com/binarylogic/authlogic) works for more info.

Resources