simple_form delete method instead post method - ruby-on-rails

In simple_form is possible to use the http delete verb instead the default post verb?
<%= simple_form_for #object , method: :delete do |f| %>
<%= f.input :instance_name, as: :check_boxes, collection: #roles %>
<%= f.button :submit %>
<% end %>
It doesn't works.

Unfortunately simply stating that it doesn't work is not helpful in understanding the problem you're seeing, but I'll make a guess based on my own initial confusion with the "method:" parameter. Most browsers don't support PUT and DELETE methods, so what simple_form_for does is generate a form with a POST method, but it also adds a hidden field to pass the actual method. So:
simple_form_for #service, url: service_path, method: :delete
generates:
<form action="/services/6" method="post">
<input name="_method" type="hidden" value="delete" />
....
Rails uses that to call the correct controller method. Hope that helps.

Related

Is there a way to write a HTML form in rails?

I'm new to RoR and I've stumbled upon a problem. I'm trying to approve or deny a rent, and have been successful in doing so using the HTML form.
<form action="<%= approve_rental_url(rental) %>" method="post">
<input type="hidden" name="authenticity_token" value="<%= form_authenticity_token %>">
<input type="submit" value="Approve">
</form>
This code works without a problem and I know that it isn't the rails way of doing it. I've tried to write it in the rails way and have encountered a problem which says No route matches [POST] "/cats/2".
#Ruby code
<%= form_for approve_rental_url(rental) do |f| %>
<%= f.submit "Approve" %>
<% end %>
Here is the rails routes
Prefix Verb URI Pattern Controller#Action
approve_rental POST /rentals/:id/approve(.:format) rentals#approve
deny_rental POST /rentals/:id/deny(.:format) rentals#deny
rentals POST /rentals(.:format) rentals#create
new_rental GET /rentals/new(.:format) rentals#new
cats GET /cats(.:format) cats#index
POST /cats(.:format) cats#create
new_cat GET /cats/new(.:format) cats#new
edit_cat GET /cats/:id/edit(.:format) cats#edit
cat GET /cats/:id(.:format) cats#show
PATCH /cats/:id(.:format) cats#update
PUT /cats/:id(.:format) cats#update
root GET / cats#index
When you use form_for, you have to pass record as argument like this:
<%= form_for :person do |f| %>
First name: <%= f.text_field :first_name %><br />
Last name : <%= f.text_field :last_name %><br />
Biography : <%= f.text_area :biography %><br />
Admin? : <%= f.check_box :admin %><br />
<%= f.submit %>
<% end %>
If you need to pass URL, you need to use form_tag instead of form_for:
form_tag('/posts/1', method: :put)
But these helpers are softly deprecated. Now there is form_with helper.
You can pass to it URL or record
form_with(model: nil, scope: nil, url: nil, format: nil, **options)
Actually, since this is such a common problem, in rails you can just write
link_to 'Approve', approve_rental_url(rental), class: 'btn btn-success', method: :post
or use the button_to helper
button_to 'Approve', approve_rental_url(rental), class: 'btn btn-success'
(which will POST by default)
and both will automatically inline a form to perform the POST.

Rails - Simple Forms - undefined method `model_name' for nil:NilClass

I am trying to make a form where you select tables that you want to export. I made a simple form with a list of tables that can be exported. My plan was to allow the user to toggle check boxes for the tables they want to export and as a result they would be able to download a zip file containing the tables.
Currently, when I try to go to the page with the form, I get an error:
undefined method 'model_name' for nil:NilClass
The majority of the usage of simple forms that I see online consists of using forms to create new items to save in their models. As a result, it seems that the line simple_form_for #example would mean that when the user clicks the submit button, there is a line in the controller such as #example = SomeClass.new". My understanding is that the user input of the form is saved in #example and can be used by the controller. However, as I am not creating a new item in the model, I just want to use the values from #example, I am not sure what to put in the controller to get rid of the error so that I can code the rest of the function in the controller.
Controller:
class FormController < ApplicationController
def index
#options = []
print(#options)
end
end
The form used:
<h2>Which tables do you want to export?</h2>
<div class="well">
<% tables_in_model = %w(Table1 Table2 Table3) %>
<%= simple_form_for #selected_options, :url => form_index_path, :method => :get do |f| %>
<%= f.input :options, as: :check_boxes, collection: tables_in_model %>
<%= f.button :submit, as: :Submit %>
<% end %>
</div>
As you said correctly in your question, simple_form should be used to render forms to the user when her actions are related to the creation or edition of ActiveRecord models.
For instance, when writing down code to enable a search feature, where your goal is to simply pass a bunch of user chosen params to a controller, you should not use it. I believe you are in a similar position with the feature you described.
Simple solution though: use rails form related DSL to get your form going!
Hope it's the answer you needed. Feel free to ask for more details if needed. Cheers!
i think you are using simple_form you need to specify like
#selected_options = SelectedOptionModel.new(params)
into your controller
then it passes into View.
if you don't have any model you can use form_tag
like this:
<%= form_tag("/search", method: "get") do %>
<%= label_tag(:q, "Search for:") %>
<%= text_field_tag(:q) %>
<%= submit_tag("Search") %>
<% end %>
this will create html form like this:
<form accept-charset="UTF-8" action="/search" method="get">
<input name="utf8" type="hidden" value="✓" />
<label for="q">Search for:</label>
<input id="q" name="q" type="text" />
<input name="commit" type="submit" value="Search" />
</form>

in rails difference between form_for #article and form_for :article

im new to ruby on rails, abit confused between the usage of the following when i try to update a record:
<%= form_for #article, url:{action: "update"} do |form| %>
this one works, but i dont understand how come the submit button says 'update article'
<%= form_for :article, url:{action: "update"} do |form| %>
this one throws No route matches [POST] "/articles/2", and the submit button says 'save article'
finally:
<%= form_with(model: #article) do |form| %>
actually updates the record, but i dont understand why it's calling update, and not other methods
form_for(#article) creates a form builder which is bound to a model instance.
If #article is nil it will raise an error.
If the instance is a new record the form will use method="POST" and action="/arcticles".
If the record has been persisted it will have method="PATCH" and action="/arcticles/:article_id".
Rails derives the URL for the action attribute based on convention over configuration. So there is no need to explicitly pass the url option if you follow the conventions.
An example of this would be:
<% #article = Article.new(title: 'Hello World') %>
<%= form_for(#article) do |f| %>
<%= f.text_input :title %>
<% end %>
This will render something like:
<form action="/articles" method="POST">
<input type="text" name="article[title]" value="Hello World"/>
...
</form>
<%= form_for #article, url:{action: "update"} do |form| %> this one
works, but i dont understand how come the submit button says 'update
article'
The form builder knows it is updating an record by calling .new_record? on the the record you passed to form_with. You can change the default value of the submit button by providing translations:
# config/locales/en.yml
en:
helpers:
submit:
create: "Save new record"
update: "Save changes"
form_for(:article) creates a scoped form builder that does not wrap an object.
This creates a form builder where the inputs will be "scoped". For example:
<%= form_for(:article) do |f| %>
<%= f.text_input :title %>
<% end %>
This will render something like:
<form action="/articles" method="POST">
<input type="text" name="article[title]"/>
...
</form>
Rails derives the URL for the action attribute based on convention over configuration.
In your case <%= form_for :article, url:{action: "update"} do |form| %> causes a routing error since form_for defaults to method: "POST".
form_with is the Rails 5.1 replacement for form_for and form_tag
form_with will replace the form_for and form_tag methods which are closely related yet have very different signatures. form_for and form_tag have been soft depreciated and are slated for removal.
The idea is to provide a single method with a more consistent signature.
If you are using Rails 5.1+ this is what you should be using.
See:
Rails Guides - Action View Form Helpers
Rails API - ActionView::Helpers::FormHelper
Rails 5.1's form_with vs. form_tag vs. form_for
It all depends on #artical. If #artical is new object (id in #artical is nil) is call the create action. If #artical is existing object then it called the update method.

How to make create and update use the same route

I have a route and form that looks like this:
<%= form_for #address, url: {action: "update_contact", controller: "checkouts"}, html: {class: ""} do |f| %>
My route looks like:
post "checkouts/:cart_token/update_contact" => "checkouts#update_contact", as: "checkouts_update_contact"
For updates the form is looking for a PATCH which I haven't defined, and so I get an error when the #address model already exists i.e. updates
How can I make my form always POST no matter what?
Add method: :post
<%= form_for #address,
url: {action: "update_contact", controller: "checkouts"},
html: {class: ""},
method: :post do |f| %>
Without that Rails adds a hidden field which is used to fake a PATCH request when the form is used to update an object.
<input type="hidden" name="_method" value="patch" />

Parameters not passing in url in form

I am using rails 4 and rspec 2. I have a simple_form which sends an email.
<%= simple_form_for #student, url: create_message_pro_users_path(student_id: #student), method: :get do |f| %>
<%= f.input :subject, input_html: { size: 59 } %>
<%= f.input :message, as: :text, input_html: { class: 'text_block' } %>
<%= f.button :submit, 'Update' %>
<% end %>
In the test environment, this routes to the create_message action in the pro_users controller with params[:student_id] and params[:student], i.e. it works as I would expect.
In my development environment, this routes to the correct action with the params[:student], but does not have a params[:student_id], i.e. it does not work.
If I look at the browser source code, the relevant section is
<form novalidate="novalidate" class="simple_form edit_student" id="edit_student_1847" action="/pro_users/create_message?student_id=1847" accept-charset="UTF-8" method="get"><input name="utf8" type="hidden" value="✓" />
What is going wrong and why is it working in my tests but not the actual browser. My solution at present is to refactor the action into my student controller, where I can just use standard routing. However, I use BDD so it is disconcerting when the request spec passes but it does not work in the browser!

Resources