Rails 3 serialized form attribute - ruby-on-rails

I have the following model:
class Deck < ActiveRecord::Base
has_many :cards
serialize :stats
attr_accessible :name, :description, :stats
end
In this, stats should be an array of strings. I want to be able to add an arbitrary number of stats to the row (using javascript to add additional "stat" input boxes, but that is outside the scope if the question.)
My question is how do I reflect this structure in the view? If I was building the form manually then it would look like:
<input type="text" name="deck[stats][]">
My view currently looks like:
<%= f.fields_for :stats, #deck.stats do |p| %>
<%= p.label :p, "Stats: " %>
<%= p.text_field :p %>
<% end %>
But this outputs:
<input type="text" name="deck[stats][p]">
I also want a counter so I can display the label as "Stat 1:", "Stat 2:", etc.
Any help is appreciated.

Posting the solution I went for to aid future readers.
#Controller
def new
#deck = Deck.new
#deck.stats = ["", ""] #include for number of times you wish to show the field.
end
#View
<%#deck.stats.each_with_index do |s,i| %>
<p>
Stat <%=i+1%>: <%=text_field "stat", i, :name => "deck[stats][]", :value => s %>
</p>
<%end%>

By defining :p you are making it think you are looking for a method on stats called p, ie stats.p
<%= f.fields_for :stats, #deck.stats do |p| %>
<%= p.label :p, "Stats: " %>
<%= p.text_field :p %>
<% end %>
Rather just try <%= p.text_field %> drop the :p

I don't know if there's a clean way of doing it, but this should work:
<% #deck.stats.each do |value|
<%= f.fields_for :stats do |fields| %>
<%= fields.text_field "", :value => value %>
<% end %>
<% end %>

= simple_form_for [:stats, #deck] do |f|
- 1.upto(4) do |i|
= f.input_field :stats, multiple: true, label: "Stat #{i}"
= f.submit

Related

rails how to pass nested parameters

I have a strong parameter like this
params.require(:survey).permit( option_booleans_attributes: [:id, :survey_id, :topic, :answer])
if I use rails f.input I got parameter like
"option_booleans_attributes"=>{"0"=>{"answer"=>"true", "id"=>"5"}, "1"=>{"answer"=>"false", "id"=>"6"}, "2"=>{"answer"=>"true", "id"=>"7"}}}
but I need to show option_booleans topic and let user fill answer
<% #survey.option_booleans.each do |question| %>
<%= question.topic %><br>
<%= radio_button "option_booleans_attributes[]", "answer[#{question.id}]", "true" %>是
<%= radio_button "option_booleans_attributes[]", "answer[#{question.id}]", "false" %>否<br>
<% end %>
But I don't know how to generate the 0 1 2 in the parameter..
about my survey.rb
class Survey < ActiveRecord::Base
has_many :option_booleans
accepts_nested_attributes_for :option_booleans
belongs_to :member
end
class OptionBoolean < ActiveRecord::Base
belongs_to :survey03
and OptionBoolean have topic:string and answer:boolean
I want to let user see the topic and update the answer
It seems you're missing several parts of your form:
#app/controllers/surveys_controller.rb
def new
#survey = Survey.new
#survey.option_booleans.build #-> creates ActiveRecord Object for your form
end
#app/views/surveys/new.html.erb
<%= form_for #survey do |f| %>
<%= f.fields_for :option_booleans do |option| %>
<% #survey.question_booleans.each do |question| %>
<%= question.topic %>
<%= f.radio_button "answer[#{question.id}]", "true" %>
<%= f.radio_button "answer[#{question.id}]", "false" %>
<% end %>
<% end %>
<% end %>
Although I don't quite understand how your system works
You have a survey with many options, but you're passing new attributes to create new options each time. Surely you'd have option_booleans as a join model, with options as an independent model, and:
#app/models/survery.rb
Class Survey < ActiveRecord::Base
has_many :option_booleans
has_many :options, through: :option_booleans
end
What I use now
<li><% #survey03.option_booleans.each do |question| %>
<%= question.topic %><br>
<%= radio_button "option_booleans_attributes[#{question.id}]", "answer", "true", :required => true %>
<%= radio_button "option_booleans_attributes[#{question.id}]", "answer", "false", :required => true %>
<% end %></li>
and in controller
params[:option_booleans_attributes].each do |option_id, attributes|
if option = OptionBoolean.find_by_id(option_id)
option.update_attributes(attributes)
end
end
and I know if I want to generate index just use
<% #survey.option_booleans.each_with_index do |question, index| %>
<%= question.topic %><br>
<%= radio_button "option_booleans_attributes[#{index}]", "answer[#{question.id}]", "true" %>
<%= radio_button "option_booleans_attributes[#{index}]", "answer[#{question.id}]", "false" %>
<% end %>
try select options like this:
#variable_with_booleans = [true, false]
<%= f.select :param, #variable_with_booleans %>
answer to your latest comment:
I don't sure, but try to edit your form
<%= form_for #question do |f| %>
<%= f.label :topic %>
<% #variable_with_booleans = [true, false] %>
<%= f.select :answer, #variable_with_booleans %>
<%= f.submit %>
<% end %>
and edit your strong params in controller,which contains this action

Sending the wrong Params on a nested form

I'm having issues with the implementation of a nested form for a model with has_many through relationship
I have 3 models: Reservation, Table and Collection (Join Model for these two)
In my Reservation Controller I have these two methods:
def new
#reservation = Reservation.new
#tables = Tables.all
#tables.size.times {#reservation.collections.build}
end
and
def reservation_params
params.require(:reservation).permit(:name, collections_attributes: [ :table_id, :units_sold],
tables_attributes: [:units, :title])
end
my form view is as following:
<%= form_for [current_user, #reservation] do |f| %>
<header>
<h1>Make Reservation</h1>
</header>
<%= f.text_field :name, placeholder: "Name" %>
<%= f.fields_for :collections do |builder| %>
<%= render 'nested_form', :f => builder %>
<% end %>
<%= f.submit "Save" %>
<% end %>
and my _nested_form.html.erb file:
<%= f.number_field :units_sold, placeholder: "Units" %>
<%= check_box_tag :table_id %>
My problem is, whenever I save a new entry on the database he assigns the same table_id to all collections association, e.g:
I want to receive the Parameters hash such as:
"collections_attributes"=>{"0"=>{"units_sold"=>"5", "table_id"=>"1"}, "1"=>{"units_sold"=>"6", "table_id"=>"2"}}}
Instead what I'm getting is:
"collections_attributes"=>{"0"=>{"units_sold"=>"5", "table_id"=>"1"}, "1"=>{"units_sold"=>"6", "table_id"=>"1"}}}
How do I fix this for it to give the correct table_id for each collection?
It would be better if you provide your models' snippet that shows their associations.
Anyway, according to your form; One Reservation has many tables through collections.
change:
<%= check_box_tag :table_id %>
to
<% #tables.each do |table| %>
<li>
<%= f.radio_button :table_id %>
<%= f.label :table_id, table.name %>
</li>
<% end %>
By this, you will be able to choose one table from all for each collection using radio button.
Hope this will help!

Select multiple categories in form (rails)

I've got this tripbuilder which i want to assign categories to. So I've set up the models as where a trip can have any(or more) categories that are in the category table in my database. However; i have no idea how i can set up the form allowing a user to select categories via checkbox. Since fields_for doesn't sound like a solid way to go in this case (Because i want to see all the categories with a checkbox and select as many categories as i want). Can anyone help me out?
I've tried this form:
<%= form_for #trip, :html => {:multipart => true} do |a| %>
<%= a.label :title, "Routetitel" %>
<%= a.text_field :title %>
<%= a.label :description, "Omschrijving" %>
<%= a.text_area :description %>
<%= a.fields_for :categories do |cat| %>
<%= cat.check_box :name %>
<% end %>
<%= a.submit 'Verstuur' %>
<% end %>
At first, you need to setup the relationship between trip and category like this:
class Trip < ActiveRecord::Base
has_and_belongs_to_many :categories
end
Then you can build the form like this:
<%= form_for #trip, :html => {:multipart => true} do |a| %>
<%= a.label :title, "Routetitel" %>
<%= a.text_field :title %>
<%= a.label :description, "Omschrijving" %>
<%= a.text_area :description %>
<% Category.all.each do |cat| %>
<%= check_box_tag "trip[category_ids][]", cat.id, #trip.catergory_ids.include?(cat.id)
<% end %>
<%= a.submit 'Verstuur' %>
<% end %>
Yes, it can be done by using select tag and multiple attribute of select tag.
<% = a.select :categories, Category.all.collect {|c| [c.name, c.id]}, :include_blank => true', :multiple => "multiple" %>
Please Modify your fields_for as described below and check !!!!
<%= a.fields_for "categories[]" do |cat| %>
<%= cat.check_box :name %>
<% end %>

How to create association for nested model in a form

In my Ruby on Rails application I want to allow the adding/editing of a nested model which itself has an associated model.
model Survey
string title
has_many questions
model Question
string question
belongs_to category
model Category
string name
For the sake of argument let's assume that the user should always have to enter a new category when entering a question (I couldn't come up with a better example, sigh).
In my model/survey/edit.html.erb I have a working setup for adding questions and saving them. However when I added the Category model to the picture, I now face the problem that when adding a new Question, there is no corresponding Category name-field displayed. I suspect this is because even though I do call Question.new, I do not call question.category.build - and I have no idea where/how to do that.
My edit.html.erb:
<h1>Editing Survey</h1>
<%= render :partial => 'form' %>
My _form.html.erb:
<% form_for(#survey) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :title %><br />
<%= f.text_field :title %>
</p>
<div id="questions">
<% f.fields_for :questions do |q| %>
<%= render :partial => 'question', :locals => { :pf => q } %>
<% end %>
</div>
<%= add_a_new_child_link("New question", f, :questions) %>
<% end %>
My _question.html.erb:
<div class="question">
<%= pf.label :question %>
<%= pf.text_field :question %>
<% pf.fields_for :category do |c| %>
<p>
<%= c.label :name, "Category:" %>
<%= c.text_field :name %>
</p>
<% end %>
</div>
A quick fix for your situation is to use virtual attributes.
EG, in your Question model:
def category_name=(new_name)
if category then
category.name = new_name
else
category = Category.new(:name => new_name)
end
end
def category_name
return category.name if category
""
end
In your _question, there no need to use nested form. Just add something like:
<%= pf.text_field :category_name %>
I didn't test it, but you probably caught the ideea.

Ruby on Rails: Drop down menu

I'm trying to create a drop down menu to allow a user to change an entry's field in my table. The user has one of three options -- hot, medium and cold.
I already have text_fields that do essentially the same thing for other fields, that all update when the user clicks on a submit_tag.
Is there an easy way to implement a drop-down box and have the result saved with the submit_tag ?
thanks,
-Chris
Here's the basic answer. The array of two element arrays is the critical part.
<% form_for #entry do |f| %>
<%= f.text_field :name %>
<%= f.select :temperature, [['Hot','hot'],['Medium','medium'],['Cold','cold']] %>
<%= f.submit %>
<% end %>
I'll assume 2 things:
That you are the <%= form_for #model_instance idiom (explained on section 2.2 of this guide).
That you want to store the "hot", "medium" and "cold" values as strings (not as numbers 1,2 and 3 or something similar) on your database.
Let's say that you have two fields, called :name and :temperature, controlled by two text_fields:
<% form_for #article do |f| %>
<%= f.text_field :name %>
<%= f.text_field :temperature %>
<%= f.submit "Create" %> <% end %>
<% end %>
Now you want to change the :temperature control to a dropdown list, accepting hot, medium and cold as values. Then you can do that this way:
<% form_for #article do |f| %>
<%= f.text_field :name %>
<%= f.collection_select :temperature, Article::TEMPERATURES, :to_s, :to_s,
:include_blank => true
%>
<%= f.submit "Create" %> <% end %>
<% end %>
You will now have to define the Article::TEMPERATURES constant in your Article model. It shouldn't be very difficult:
class Article < Activerecord::Base
TEMPERATURES = ['hot', 'medium', 'cold']
You may be wondering why I added the :include_blank part on the collection_select. This will add an "empty" option on your dropdown list. You will need that empty option when creating new objects, unless you want a "default" value to temperature.
http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html#M001730
I was working on something similar. I got this to work by simply adding either an enum or a constant(similar to what kikito said previously) in my model and then calling the select in my form.
Here's how it can work.
using the constant:
class ClassName < ActiveRecord::Base
TEMPERATURES = ['Hot', 'Medium', 'Cold']
end
bin/rails g migration add_column_to_table temperatures:string
_form.html.erb
<%= f.label :temperature %>
<%= f.select :temperature, ClassName::TEMPERATURE %>
or
using the enum:
class ClassName < ActiveRecord::Base
enum temperature: [:hot, :medium, :cold]
end
bin/rails g migration add_column_to_table temperatures:integer
_form.html.erb
<%= f.label :temperature %>
<%= f.select :temperature, ClassName.temperatures.keys %>
Hope that helps you!
You might want to consider formtastic gem which is lot less code.
<% semantic_form_for #stuff do |f| %>
<% f.inputs do %>
<%= f.input :name %>
<%= f.input :temperature, :as => :select,
:label => "Degree", :include_blank => false,
:collection => [["Hot", 1], ["Medium", 2], ["Cold", 3]] %>
<% end %>
<%= f.buttons %>
<% end %>
In accordance with all of the above answers, remember to do this last, important step:
Restart your server!
As a newbie, I was wondering why my array was not working even though I followed all the steps correctly.

Resources