Updating state in ruby on rails - ruby-on-rails

I'm using the AASM gem to manage states on one of my models. Right now, I'm using a form_for in a javascript popup to change the state, but it's not working:
<h2>Set the state:</h2>
<%= form_for(#tracker) do |f| %>
<% if #tracker.errors.any? %>
<div id="error_explanation">
<h2>Uh-oh. We've got some problems</h2>
<% #tracker.errors.full_messages.each do |msg| %>
<%= msg %><br />
<% end %>
</div>
<% end %>
This tracker is currently: <%= #tracker.state %><br />
<%= select_tag :state, options_for_select(Tracker::STATEDESCRIPTIONS.map { |event| [event.to_s.humanize, event]}) %>
<%= f.submit %>
<% end %>
What I'd really like to do, though, is contain the form all in a single button, but I'm not sure what to use for that? button_to?

You should use f.select instead of select_tag. That way, the resulting select HTML tag will be associated with the form_for(#tracker), and the chosen state will be correctly mapped to #tracker in the controller action in question.

Related

Rails form_for check_box

I'm trying to create a basic survey app. On my take survey page I'm looping through and displaying each answer option as a radio button or checkbox as a form_for to create a user's choice. The choices are working great for the questions that are single choice (or radio buttons), but they aren't saving for multi select questions. I'm pretty sure this has to do with the form I have for the checkbox.
It seems like I should do
<%= f.check_box :answer_id, answer.id %> <%= answer.title %> <br>
similar to how I'm creating the radio button but that throws an error
undefined method `merge' for 14:Fixnum
Here's my code that displays:
<h3>Questions:</h3>
<ul><% #survey.questions.each do |question| %>
<li><p><%= question.title %></p></li>
<% choice = question.choices.build %>
<% if question.single_response == true %>
<%= form_for [question, choice] do |f| %>
<% question.answers.each do |answer| %>
<%= f.radio_button :answer_id, answer.id %> <%= answer.title %><br>
<% end %>
<%= f.hidden_field :survey_id, value: #survey.id %>
<%= f.submit %>
<% end %>
<br />
<% else %>
<%= form_for [question, choice] do |f| %>
<% question.answers.each do |answer| %>
<%= f.check_box :answer_id %> <%= answer.title %> <br>
<%= f.hidden_field :survey_id, value: #survey.id %>
<% end %>
<%= f.submit %>
<% end %>
<br />
<% end %>
<% end %>
</ul>
Any idea what I need to do to get it to save the answer_id to the choice so that it actually creates the choice?
Thanks!
This question is a few years old but I think it deserves a better answer. Since you are using form_for (a model backed form), then you probably want to use the form_for check_box method that you originally tried to use. In your case, it would look like this:
<%= f.check_box :choice, { :multiple => true }, answer.id, false %>
Here is the doc on this.
For checkboxes, you actually want to return an array as the parameter. There is a little funny syntax to this because we don't actually want to use the form builder methods. It should look something like this (adapt to your specific model names and methods)
<%= check_box_tag 'choice[answer_ids][]', answer.id %>
Using this syntax should tell Rails to compile all of the checked checkbox values into an array.
This Railscast goes over the topic.

Concatenate multiple fields on submit into a single array/field

I have two models: QuestionnaireResult and QuestionnaireOption.
The options are dynamic.
QuestionnaireResult has two columns: date_submitted and results. I want the results column to be some sort of array of the QuestionnaireOption and their value...
i.e.
option_id / value
1 / 50
2 / false
3 / true
I submit data using this form, however it's not complete and not working because I don't know what name to give the text_fields (undefined method 'not_sure_what_to_name_this' for #<Admin::QuestionnaireResult:0x4a5ef9>):
<%= form_for(#questionnaire_result) do |f| %>
<% if #questionnaire_result.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#questionnaire_result.errors.count, "error") %> prohibited this questionnaire_result from being saved:</h2>
<ul>
<% #questionnaire_result.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<% #questionnaire_options.each do |questionnaire_option| %>
<% if questionnaire_option.field_type == 'Textbox' %>
<div class="field">
<%= f.label questionnaire_option.option %><br />
<%= f.text_field :not_sure_what_to_name_this %>
</div>
<% elsif questionnaire_option.field_type == 'Checkbox' %>
<div class="field">
<%= f.label questionnaire_option.option %><br />
<%= f.check_box :not_sure_what_to_name_this %>
</div>
<% end %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
What name do I give text_field and how do I go about saving the results and storing them in a column as an array? Or is there better ways of going about this?
Check out this reference, where it says:
2.2 Binding a Form to an Object
While this is an increase in comfort it is far from perfect. If Person
has many attributes to edit then we would be repeating the name of the
edited object many times. What we want to do is somehow bind a form to
a model object, which is exactly what form_for does.
It goes on to show examples and elaborate on the discussion. So, the fields you use in the form_for are that model's fields. To show an example, in:
<%= form_for Feed.new, id: "feed_add" do |f| %>
<%= f.submit "Add Feed", class: 'formlabel' %>
<%= f.text_field :feed_url, class: 'forminput', :autocomplete => :off %>
<% end %>
the model is Feed and the text_field is :feed_url, so this updates Feed.feed_url. It is returned to the controller in params[:feed]['feed_url'].
If you can show your model, I can advise further.
To follow up on the other part of your question, "how do I go about saving the results and storing them in a column as an array? Or is there better ways of going about this?", that's a bit different.
If what you want to do is build an array, you might want to use form_tag instead of form_for. form_for is specifically for models. form_tag is a more generalized interface for objects not necessarily models. You can see that in the same reference. To show an example:
<%= form_tag feeds_path, method: 'get', id: "feed_search" do %>
<%= submit_tag " Search ", feed_url: nil, class: 'formlabel' %>
<%= text_field_tag :search, params[:search], class: 'forminput', :autocomplete => :off %>
<% end %>
Here, the value of :search is returned in params[:search].
Regarding how to do it, you should return this information to your controller where it can process it. Views are for display. The controller can easily build and process the array so that it can be used in its decisions and/or routing.

How to submit multiple, duplicate forms from same page in Rails - preferably with one button

In my new views page I have:
<% 10.times do %>
<%= render 'group_member_form' %>
<% end %>
Now this form contains the fields: first_name, last_name, email_address and mobile_number. Basically I want to be able to fill in the fields of all the forms in one click which then submits each into the database as a unique row/id.
What would be the easiest way to accomplish this?
Note: The number of times do is called from a variable. Any advice welcome, thanks!
You should have only one form (you should put only fields in the group_member_form partial). In your view you should have something like:
<%= form_tag "/members" do %>
<% 10.times do %>
<%= render 'group_member_form' %>
<% end %>
<%= submit_tag "Submit" %>
<% end %>
and in _group_member_form.html.erb you should have
<%= text_field_tag "members[][first_name]" %>
<%= text_field_tag "members[][last_name]" %>
<%= text_field_tag "members[][email_address]" %>
<%= text_field_tag "members[][mobile_number]" %>
This way, when the form submits, params[:members] in the controller will be an array of member hashes. So, for example, to get the email adress from the fourth member after submitting the form, you call params[:members][3][:email_adress].
To understand why I wrote _group_member_form.html.erb like this, take a glance at this:
http://guides.rubyonrails.org/form_helpers.html#understanding-parameter-naming-conventions.
You can also use accepts_nested_attributes_for in your model, and use fields_for on your form.
Submitting multiple forms, afaik, only javascript, if the forms are remote: true, and you run through each of them and then submit.
$("form.class_of_forms").each(function() {
$(this).submit();
});
Alternatively a more up to date approach using form_with and fields_for, without removing the form into a partial, could be written like this:
<%= form_with (url: end_point_path), remote: true do |form| %>
<% (1..5).each do |i| %>
<%= fields_for 'cart_items'+[i].to_s do |fields|%>
<%= fields.text_field :first_name %>
<%= fields.text_field :last_name %>
<%= fields.email_field :email_address %>
<%= fields.number_field :phone_number %>
<% end %>
<% end %>
<%= form.submit "Submit" %>
<% end %>

Rails 3.0 - form_for and fields outside of the current model

When I submit a Photo to a Rails 3.0 photo gallery site. In addition to being able to upload the file, select Album from a drop down list, I need to be able to pass along a list of comma delimited tags. I'm confused about the proper use of form_for. note: this is in the new.html.erb view (and new method of the PhotoController)
<%= form_for(#photo) do |f| %>
<% if #photo.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#photo.errors.count, "error") %> prohibited this photo from being saved:</h2>
<ul>
<% #photo.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<%= f.label :album_id %>
<%= select "photo", "album_id", #albums.map {|a| [a.name,a.id]} %><br />
<%= f.label :name %>
<%= f.text_field :name %><br />
<%= f.label :photofile %>
<%= f.file_field :photofile %><br />
<%= f.label :tags %>
<%= f.text_field :tags %><br />
<%= f.submit %>
<% end %>
I'm confused about the proper way that I can (1) upload a file - am I headed down the right path with f.file_field. photofile isn't really a property of the Photo object. And (2) similar question with :tags - tags isn't a property on the Photo object so should it be f.text_field (3) I'm assuming the way I am doing the Album dropdown is correct (I hope?)
Remember you can create any fields inside the form_for, just like any other form.
The form for just helps you by generating fields with names like photo[name]
but you can use a text_field_tag :tags and on the controller retrieve it with params[:tags] without a problem.
If the field is not from your model, you shouldn't use the f.<helper> just use another helper like text_field_tag appropriate for your data or even pure html if you'd like.
Firstly, you need to say :multipart => true in your form_for call. This says that the form has attachment. Then, for attachments, use a gem like paperclip or carrierwave. Checkout these railscasts for a nice introduction on how to use paperclip and carrierwave.
For tagging this railscast is a useful resource.

Rails Nested Attributes Doesn't Insert ID Correctly

I'm attempting to edit a model's nested attributes, much as outline here, replicated here:
<%= form_for #person do |person_form| %>
<%= person_form.text_field :name %>
<% for address in #person.addresses %>
<%= person_form.fields_for address, :index => address do |address_form|%>
<%= address_form.text_field :city %>
<% end %>
<% end %>
<% end %>
In my code, I have the following:
<%= form_for(#meal) do |f| %>
<!-- some other stuff that's irrelevant... -->
<% for subitem in #meal.meal_line_items %>
<!-- # Edit 2: I need to display information here about the subitem
Which I can't find a way to pass it to the partial, or work in
this manner for existing items
-->
<%= subitem.food.name %>
<%= subitem.food.calories %>
<%= f.fields_for subitem, :index => subitem do |line_item_form| %>
<%= line_item_form.label :servings %><br/>
<%= line_item_form.text_field :servings %><br/>
<%= line_item_form.label :food_id %><br/>
<%= line_item_form.text_field :food_id %><br/>
<% end %>
<% end %>
<%= f.submit %>
<% end %>
This works great, except, when I look at the HTML, it's creating the inputs that look like the following, failing to input the correct id and instead placing the memory representation(?) of the model. As a result, an update fails:
<input type="text" value="2" size="30" name="meal[meal_line_item][#<MealLineItem:0x00000005c5d618>][servings]" id="meal_meal_line_item_#<MealLineItem:0x00000005c5d618>_servings">
EDIT:
The reason I'm attempting to do it in this method is that I need to gather some information on associations for existing meal_line_items. For example, in the area where I took out code, I have some code to the effect of:
<%= subitem.food.name %>
<%= subitem.food.calories %>
Getting this information won't work if I am using a form builder with partials, at least, not in my trials.
Edit 2:*
See the edit in the code. Here's my MealLineItem
class MealLineItem < ActiveRecord::Base
# Associations ---------------------
belongs_to :food
belongs_to :meal
end
And meal accepts_nested_attributes for the model. As you can see it belongs to both food and meal model. For the existing meal_line_item I need to do something like:
meal_line_item.food.name
Is there f. missing from <%= fields_for?
--edit
Have you tried:
<%= f.fields_for 'meal[meal_line_item][]', subitem do |line_item_form| %>
--edit
Docs say that it should work without loop too:
<%= form_for(#meal) do |f| %>
<!-- some other stuff that's irrelevant... -->
<%= f.fields_for :meal_line_items do |line_item_form| %>
<%= line_item_form.label :servings %><br/>
<%= line_item_form.text_field :servings %><br/>
<%= line_item_form.label :food_id %><br/>
<%= line_item_form.text_field :food_id %><br/>
<% end %>
<%= f.submit %>
<% end %>
Have to test this but maybe this approach?
_form
<%= form.fields_for :meal_line_items do |meal_line_item_form| %>
<% #meal.meal_line_items.each do |meal_line_item| %>
<%= render :partial => "meal_line_items/meal_line_item", :locals => { :meal_line_item_form => meal_line_item_form, :meal_line_item => meal_line_item } %>
<% end %>
<% end %>
meal_line_items/_meal_line_item.erb
<%= meal_line_item_form.label :servings %><br/>
<%= meal_line_item_form.text_field :servings %><br/>
<%= meal_line_item_form.label :food_id %><br/>
<%= meal_line_item_form.text_field :food_id %><br/>
EDIT
here's a link to an example for setting the formbuilder iterator directly (Rails 2.3.8 though). The associations between Outbreak -> Incidents -> Location should be similiar to the ones for Meal -> Meal_line_items -> Food.
AJAX update of accepts_nested_attributes_for partials
After searching high and low, I found the error. Although I was modifying the partial and was receiving a NameError it's because I was calling the partial from a helper method - exactly the same problem as stated in the following question:
rails fields_for render partial with multiple locals producing undefined variable

Resources