Rails simple form doen't pass params from input - ruby-on-rails

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.

Related

How to create a simple form without a model?

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

Ruby on Rails, method undefined

I'm very new to ruby on rails. I'm trying to make a text field to assign one of my variables (end_date), but I keep getting this error:
undefined method `end_date' for #<Quiz:0x007fccd1e0f9c0>
Here's my code:
<%# Main Canvas where cardes places %>
<div class="column large-11" id="main">
<%= form_for #quiz do |q| %>
<%= q.label :quiz_name %>
<%= q.text_field :quiz_name %>
<%= q.label :end_date %>
<%= q.text_field :end_date %>
<%= hidden_field_tag 'selected', 'none' %>
<%= q.hidden_field :classroom_id, value: #classroom_id%>
<%= q.submit "Create Quiz", class: "expanded button" %>
<% end %>
<%= form_tag("/quiz/#{#classroom_id}/copy", method: "get") do %>
<%= label :id, "ID" %>
<%= text_field_tag "id", "" %>
<%= submit_tag "Copy Quiz By ID", class: "expanded button" %>
<% end %>
</div>
Let me break down how these different pieces relate to one-another, which hopefully will make this easier for you to troubleshoot.
<%= form_for #quiz do |q| %>
Here you are invoking form_for to create a form bound to the #quiz object. It yields a form builder object as the argument q.
<%= q.text_field :quiz_name %>
Here you are calling the text_field method on the form builder with the field named quiz_name. This means it will generate a text input, and call the quiz_name method on #quiz to find the current value.
So given that background, it should be clear why you are seeing this error:
<%= q.text_field :end_date %>
You are telling the form builder to call #quiz.end_date for the value of this field, but that method does not exist.
You have not given enough code samples for us to determine why you expect this method to exist. Perhaps this is a field you've added to the quizzes table, but haven't yet run the migration? Is this supposed to be a virtual attribute on Quiz? Or perhaps you just want to send a field that isn't connected to the Quiz model inside this form. (You can do that with a separate set of helpers, in this case text_field_tag, that give you more flexibility in where the data comes from).

Get data attribute value from the Rails form builder without using input field

I have what I hope to be a simple question. I need to display the value for an attribute on the Edit page, while keeping the input field for the same attribute. How might this be accomplished?
Well generally you can just use the original object, like you'll have an #foo that you'll have used in your form_for statement, so you can just use that directly: = #foo.the_attribute
If you're within a partial, or elsewhere where you have only the form builder instance, then you can refer to the underlying object with the .object method, eg.:
= form_for #foo do |f|
# in here, f.object == #foo
In my case, I'm working with accepts_nested_attributes_for in two models. Event accept nested objects from Speaker. And Speaker has a perfil_id attribute which could be ['Maker', 'Developer', 'Entrepreneur', ...].
The Speaker's form is a partial rendered from the principal form, Event's form:
<%= form_for(event) do |f| %>
<%= f.text_field :title %>
<%= f.label :title, 'Event name' %>
<%= f.fields_for :speakers do |builder| %>
<%= render 'events/partials/speaker_fields', f: builder %>
<% end %>
<%= f.submit %>
<% end %>
Partial
<%= builder.number_field :name %>
<%= builder.label :name %>
<% options = options_from_collection_for_select(#profiles, 'id', 'name', f.object.member_profile_id ) %>
<%= select_tag "event[speakers_attributes][profile_id]", options, prompt: 'Select a Profile' %>
When editing Event's Speakers I wanted a select_tag to select the profile name for the actual Speaker.
I could not use an input field for this. So I need to get the correct values from the builder object and I get what I need by doing this:
f.object.profile_id
Passing it as a fourth param to the select options I get this working:
<% options = options_from_collection_for_select(#profiles, 'id', 'name', f.object.profile_id ) %>
I hope it could be useful for you too!

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.

Custom form processing

I have some custom form (user reputation) that doesn't link with any model directly.
I have several reputation criteria which affects final returation value
Here is code of the form
<%= form_tag("/add_reputing",:method => "POST") do%>
<div class="reputing_column">
<p>
<b>Your feedback:</b>
</p>
<p>
<%= text_area_tag :comment,"",{:class=>"or-form-textarea"} %>
</p>
<%= submit_tag("Submit",:class=>"or-button")%>
</div>
<div class="reputing_column">
<p>
<b>Recomendation:</b>
</p>
<% #criterias.each do |c| %>
<div class="reputing_row">
<label><%= c.name%>:</label>
<div>
<% (c.rating_from .. c.rating_to).each do |i| %>
<%= radio_button_tag "reputing_#{c.id}", i%><%= (i<1)? i : "+#{i}"%>
<% end %>
</div>
</div>
<% end %>
</div>
<% end %>
In controller I need to summirize a values of "reputing_#{c.id}" fields. And then add a record to user reputation table.
How it will be better and properly to process data from this form in controller? I tried to google that problem, but found nothing.
No answers, so I'll try to clarify the dealing with, as you called them, custom forms.
Here's the form for selecting a preferred color via radio buttons.
= form_for :preferences, url: '', method: :post do |f|
- %w[black blue white green red yellow].each do |color|
= f.radio_button :color, color
= f.label :color, color.capitalize, value: color
= f.submit
The cool thing about forms in Rails that they can be used with or without a model. If you have an instance variable called #preferences then this form will respect that and will call the color method on it to determine the "current" color. This color will be selected on the generated form. If this variable doesn't exist it won't be a big deal.
In any case, after submitting the form you'll be able to access the selected color via:
params[:preferences][:color]

Resources