How to create a simple form without a model? - ruby-on-rails

How would I go about creating a form that takes what user input as a value and just passes it to the controller without being connected to any model?
Something simple like i.e. calculating tax based on input salary, or other calculation like that, when I show the user a form, let them fill it, and when submitting it would go to the results
<%= form_with url: 'calculator#result' do |form| %>
<%= form.number_field :value, in: 1000.0..20000.0, step: 0.5 %>
<%= form.submit %>
<% end %>
i expected something like this to pass 'value' and redirect to calculator#result when submitting, but the button doesn't really do anything. whereas a form connected to a model seems pretty smart and does it

The form_tag Helper method is usually used for forms that are not linked to a model.
I think this should work:
<%= form_tag("/calculator/result", :method => "get") do %>
<%= label_tag(:value, "Value:") %>
<%= text_field_tag(:value) %>
<%= submit_tag("Submit") %>
<% end %>

Related

How to Pass Form Field Values to a Different Controller View in Rails?

In my Rails 6 app, I have a Product and Order model.
On my products#show page, I have some fields and a button. What I need to do is send the info to the orders#new page so that this data is shown on the orders#new page.
I have tried to write some code based on Pass variables without model associations in Rails and how to pass parameters in params using form_tag method in rails, but my code seems completely wrong.
on products#show:
<%= form_tag(new_order_path do |form| %>
<%= form.input_field :comments %>
<%= form.button %>
<% end %>
With this code I get undefined method text_field' for nil:NilClass`.
I have tried adding attr_accessor :comments to both the Product and Order model, but it doesn't help.
I don't think that my approach or what I am trying to code is right. I was just trying to piece together parts from these answers.
Can someone please help me figure out the best way I can pass this data to Orders#new to show in that view?
<%= form_with url: "/search", method: :get do |form| %>
<%= form.label :query, "Search for:" %>
<%= form.text_field :query %>
<%= form.submit "Search" %>
<% end %>
from the docs
https://guides.rubyonrails.org/form_helpers.html
and the show path also requires an id

Rails simple form doen't pass params from input

I want to display a list of InvestorTypes (as a radio button) but before each type I should be able to add an explanation of that type. Here is what I've got:
<%= simple_form_for(resource, as: resource_name, url: users_user_experience_level_path(resource_name), html: { method: :put }) do |f| %>
<div class="form-inputs">
<% User::USER_EXPERIENCE_LEVEL.each do |level| %>
<b>Investor type <%= level %></b>
<%= t("user.description.#{level}") %>
<%= f.input :experience_level, collection: [level], as: :radio_buttons, label: false %>
<% end %>
</div>
<div class="form-actions">
<%= f.button :submit, 'Submit' %>
</div>
<% end %>
Which gives me expected view:
Investor type Beginner
Some explanation of what is going on
[checkobox] type Beginner
Investor type Expert
Some clarification of who is an expert and what ever you want to display here
[checkbox] type Expert
Investor type Institutional
Some clarification of who is an institutional client and some legal stuff
[checkbox] type Institutional
But when Submit button is pressed it doesn't pass input value (radio box selection which user chose) into the params:
=> #<ActionController::Parameters {"experience_level"=>""} permitted: true>
[EDIT]
class User < ApplicationRecord
USER_EXPERIENCE_LEVEL = %w[institutional beginner expert].freeze
end
It looks to me like you're using simple form wrong. The "collection" input in Simple Form is expecting to get an entire list of options, not just one option.
Looping in the way you're doing it is creating one group for each experience level, and each group only has one button in it. So it might visually look correct, but it's not functioning the way you intended. Instead you want to create one group of radio buttons for experience level such that each button changes the value of experience level.
Because you're doing this with significant customization around the appearance, it's probably not a good use of Simple Form, and instead you should fall back to the normal Rails form helpers.
You want to pass a block to f.input to get the simple form wrapper and then use the lower level rails helpers:
<%= simple_form_for(resource, as: resource_name, url: users_user_experience_level_path(resource_name), html: { method: :put }) do |f| %>
<div class="form-inputs">
# adds the simple form wrapper
<%= f.input :experience_level do %>
# iterates across the options and yields a input builder to each iteration
<%= f.collection_checkboxes(:experience_level, User::USER_EXPERIENCE_LEVEL, :value_method, :label_method) do |cb| %>
# There are three special methods available:
# object, text and value,
# which are the current item being rendered, its text and value methods, respectively.
<%= t("user.description.#{cb.text}") %>
<%= cb.check_box %>
<% end %>
<% end %>
</div>
<div class="form-actions">
<%= f.button :submit, 'Submit' %>
</div>
<% end %>
If you don't actually have a model you can use #itself to iterate across a flat array:
<%= f.collection_checkboxes(:experience_level, User::USER_EXPERIENCE_LEVEL, :itself, :itself) do |cb| %>
Or an array of pairs:
<%= f.collection_checkboxes(:experience_level, User::USER_EXPERIENCE_LEVEL.zip(User::USER_EXPERIENCE_LEVEL), :first, :last) do |cb| %>
Or even a struct.

Rails issue with access of nested hash parameter

I have in rails the following form in a view
<%= form_for (#account) do |f| %>
<%= f.label :comments,"Comments" %>
<%=f.text_area :comments %>
<%= f.submit "Confirm",:name=>"conf" %>
<%= f.submit "Reject" %>
<% end %>
When I submit the form I get the following hash in the log before the update of the database
Started PATCH "/accounts/12" for 127.0.0.1 at 2015-08-13 21:31:18 +0200
Processing by UseractionsController#answer_with_comments as HTML
Parameters: {"utf8"=>"✓", "account"=>{"comments"=>"mycomments"}, "conf"=>"Confirm", "id"=>"12"}
I am trying to access the input in the comments text area in the controller. I tried
params[:account][:comments]
but it does not seem to work. Could anyone give me the appropriate syntax? Thanks.
EDIT
This is my controller code. Right now the if loop return false and nothing is added to the database even though there is something submitted ("mycomments" see above in the param nested hash)
if params[:bankaccount][:comments]
#bankaccount.update_attribute(:comments, params[:bankaccount][:comments])
end
It is only the appropriate syntax for your view. It assumes that you have content field on your Comment model.
<%= form_for (#account) do |f| %>
<%= f.label :comments,"Comments" %>
<%= f.fields_for :comments do |ff| %>
<%= ff.text_field :content %>
<% end %>
<%= f.submit "Confirm",:name=>"conf" %>
<%= f.submit "Reject" %>
<% end %>
You also will have to declare nested attributes in your Account model and your params hash should be different.
You should watch these two Railscasts part 1 and part 2 to learn more about nested attributes.
Since you mention strong parameters as a tag you probably want to build this a bit differently.
private
def account_params
#the permit method might need to be altered depending on your model and view
params.require(:account).permit(:comments)
end
Somewhere else in your controller you would then do:
#bankaccount.update_attributes(account_params)
Please take a read: http://edgeguides.rubyonrails.org/action_controller_overview.html#strong-parameters

Rails3: How to implement multiple checkboxes in a form?

What I have now gives me a dropdown menu where I can only select one:
<%= form_for(#submission) do |f| %>
<%= f.collection_select :id, Submission::SUB_ID, :to_s, :to_s %>
<% end %>
where SUB_ID=[1,2,3] in model Submission
I want to implement a checkbox instead of a dropdown menu so that I can select multiple SUB_ID (i.e. 1&2 or 1&3 or 2&3 or 1&2&3). I tried to use this but it does not work:
<%= f.check_box :id, Submission::SUB_ID, :to_s, :to_s %>
Any idea?
Try this:
# view
<%= form_for(#submission) do |f| %>
<%= Submission::SUB_ID.each do |sub_id| %>
<%= f.checkbox 'ids[]', value: sub_id, checked: #submission.id == sub_id %>
<%= sub_id %>
<% end %>
<% end %>
# controller
params[:submission][:ids].each do |checked_sub_id|
# do your logic here
end
you have to iterate over SUB_ID
somehow like this...
<% Submission::SUB_ID.each do |ssid| %>
<%= f.check_box "ids[]", value: ssid %>
<% end %>
or you can use formtastic gem. it has :as=>:check_boxes input fields http://www.ruby-doc.org/gems/docs/n/nuatt-formtastic-0.2.3/Formtastic/Inputs/CheckBoxesInput.html
The core answer is you need to loop over each item in Submission::SUB_ID and make a checkbox for each id. Depending on how your models are set up and what you want to do - you may need to be much more involved in the form building. I hesitate to provide specific examples without know more about how you want the data to come back to the controller
<%= form_for(#submission) do |f| %>
<% Submission::SUB_ID.each do sub_id %>
<%= f.check_box_tag 'submission_ids[]', sub_id %>
<% end %>
<% end %>
Note that that will not default anything to checked and it does not come back as part of the submission parameters.
Usually when I have a similar situation I'm using nested forms to add or remove objects.
If you're using Rails 4, there is a new helper, collection_check_boxes, which helps streamline the building of your check boxes.
<%= f.collection_check_boxes :submission_ids, Submission::SUB_ID, :to_s, :to_s %>
Documentation:
Form builder version - which wraps...
...the general form options helper
If you look at the documentation in the second link, you'll also find how to use the optional block syntax to customise the HTML structure for each check box.

Difference between form_for , form_tag?

What is the difference between form_for and form_tag? Is anything different for form_remote_for and form_remote_tag?
You would use form_for for a specific model,
<% form_for #person do |f| %> # you can use f here
First name: <%= f.text_field :first_name %>
Last name : <%= f.text_field :last_name %>
<% end %>
Form_tag create basic form,
<%= form_tag '/person' do -%>
<%= text_field_tag "person", "first_name" %>
<% end -%>
form_for prefers, as its first arg, an activerecord object; it allows to easily make a create or edit form (to use it in a "new" view you should create an empty instance in controller, like:
def new
#foo = Foo.new
end
It also passes a form variable to the block, so that you don't have to repeat the model name within the form itself. it's the preferred way to write a model related form.
form_tag just creates a form tag (and of course silently prepare an antiforgery hidden field, like form_for); it's best used for non-model forms (I actually only use it for simple search forms or the like).
Similarly, form_remote_for and form_remote_tag are suited for model related forms and not model related forms respectively but, instead of ending in a standard http method (GET, POST...), they call an ajax method.
All this and far more are available for you to enjoy in the FormHelper and PrototypeHelper reference pages.
EDIT 2012-07-13
Prototype has been removed from rails long ago, and remote forms have completely changed. Please refer to the first link, with reguard to the :remote option of both form_for and form_tag.
These should be similar:
<% form_for #person do |f| %>
<%= f.text_field :name %>
<% end %>
and:
<%= form_tag '/person' do %>
<%= text_field_tag "person[name]" %>
<% end %>
If you want to submit the same params to the controller, you would have to define this explicitly.

Resources