Nested Attributes in Form Not showing - ruby-on-rails

I have the 3 Models, that says a Voter has many votes and i'm trying to get the voter to vote on the same form as when the voting object is created but the field in my form isn't showing.
Here are my models:
class Voter < ActiveRecord::Base
attr_accessible :email_address, :verification_code, :verified, :votes_attributes
has_many :votes, :class_name => "Vote"
accepts_nested_attributes_for :votes
end
class Vote < ActiveRecord::Base
belongs_to :entry
belongs_to :voter
attr_accessible :entry, :voter, :voter_id
end
And in my form I have:
<%= form_for(#voter) do |f| %>
<% if #voter.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#voter.errors.count, "error") %> prohibited this voter from being saved:</h2>
<ul>
<% #voter.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :email_address %><br />
<%= f.text_field :email_address %>
</div>
<div class="field">
<%= f.label :verification_code %><br />
<%= f.text_field :verification_code %>
</div>
<div class="field">
<%= f.label :verified %><br />
<%= f.check_box :verified %>
</div>
<div class="field">
<% f.fields_for :votes do |builder| %>
<fieldset>
<%= builder.label :votes, "Entry" %>
<%= collection_select(:entry, :entry_id, Entry.all, :id, :email_address, :prompt => 'Please select an Entry') %>
<% end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
But the votes field isn't showing. And I can't understand why.

In rails 3 you need to use:
<%= f.fields_for :votes do |builder| %>
This will fix the problem.

Related

Rails 4: replace / delete uploaded file in edit view form

A similar question has already been asked, but the answer is only for Rails 3, so I am taking the liberty of asking a new question.
I have a Rails 4 app, with the following models:
class User < ActiveRecord::Base
has_many :administrations
has_many :calendars, through: :administrations
end
class Calendar < ActiveRecord::Base
has_many :administrations
has_many :users, through: :administrations
has_many: :posts
end
class Administration < ActiveRecord::Base
belongs_to :user
belongs_to :calendar
end
class Post < ActiveRecord::Base
belongs_to :calendar
end
The Post model has the following attributes:
references :calendar, index: true, foreign_key: true
date :date
time :time
string :subject
string :format
text :copy
attachment :image
and the attachment was setup as follows with Paperclip in Post model:
has_attached_file :image, styles: { small: "64x64", med: "100x100", large: "200x200" }
validates_attachment :image, :content_type => { :content_type => "image/png" },
:size => { :in => 0..3000.kilobytes }
Adding an image to a Post is working fine, through the following form:
<%= form_for [#calendar, #calendar.posts.build] do |f| %>
<% if #post.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#post.errors.count, "error") %> prohibited this post from being saved:</h2>
<ul>
<% #post.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<p>
<%= f.label :date %><br>
<%= f.date_select :date %>
</p>
<p>
<%= f.label :time %><br>
<%= f.time_select :time %>
</p>
<p>
<%= f.label :subject %><br>
<%= f.text_field :subject %>
</p>
<p>
<%= f.label :format %><br>
<%= f.text_field :format %>
</p>
<p>
<%= f.label :copy %><br>
<%= f.text_area :copy %>
</p>
<p>
<%= f.label :image %><br>
<%= f.file_field :image %>
</p>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Viewing the image attached to a Post is also working well, thanks to this show view:
<h2>Post from <%= #post.date.strftime("%A, %d") %></h2>
<div>
<p><strong>Date</strong></p>
<%= #post.date.strftime("%A, %d") %>
</div>
<div>
<p><strong>Time</strong></p>
<%= #post.time.strftime("%I:%M %p") %>
</div>
<div>
<p><strong>Subject</strong></p>
<%= #post.subject %>
</div>
<div>
<p><strong>Format</strong></p>
<%= #post.format %>
</div>
<div>
<p><strong>Copy</strong></p>
<%= #post.copy %>
</div>
<div>
<p><strong>Image</strong></p>
<%= image_tag #post.image.url(:med) %>
</div>
However, when I go to the edit view, for a post where I have previously uploaded an image, I only see the field that allows me to add an image and a message saying "no file chosen".
The edit view uses (for now) the same form as the new view, as shown above.
How can I achieve the following:
Have the uploaded image appear in the edit page.
Allow users to delete this image.
Allow users to replace this image with a new one.
–––––
UPDATE: I found a way to solve item #1 above, by replacing
<p>
<%= f.label :image %><br>
<%= f.file_field :image %>
</p>
with
<p>
<%= f.label :image %><br>
<% if #post.image.exists? %>
<%= image_tag #post.image.url(:med) %>
<% else %>
<%= f.file_field :image %>
<% end %>
</p>
in my Post edit view.
I am still working on items #2 & #3 and could definitely use some help with these.
–––––
I am happy to share more code if necessary.
Any idea?
For #2 - Allow user to delete image, you might find this SO Issue helpful
OR, as per Paperclip's documentation you could simply create a dummy checkbox and, in the update method of your controller, look if the checkbox has been ticked and delete the attachment as mentioned in the documentation.
For #3 - Allow users to replace this image with a new one
Simply rework your code as follow:
<p>
<%= f.label :image %><br>
<% if #post.image.exists? %>
<%= image_tag #post.image.url(:med) %>
<% end %>
<%= f.file_field :image %>
</p>
This way, the file_field is always present (allowing user to replace or add their image)

How to save nested form data in Rails?

I have this data inside my foods and drinks table:
Foods table
ID | Name
------------
1 | Rojak
2 | Lemang
Drinks table
ID | Name
------------
1 | Barli
2 | Sirap
My model relationship is:
class Survey < ActiveRecord::Base
has_many :questions
accepts_nested_attributes_for :questions, allow_destroy: true
end
class Question < ActiveRecord::Base
belongs_to :survey
has_many :answers
accepts_nested_attributes_for :answers, allow_destroy: true
end
class Answer < ActiveRecord::Base
belongs_to :question
has_many :foods
has_many :drinks
accepts_nested_attributes_for :foods, :drinks
end
class Food < ActiveRecord::Base
belongs_to :answer
end
class Drink < ActiveRecord::Base
belongs_to :answer
end
And this is my _form.html.erb file inside app/views/surveys:
<%= form_for #survey do |f| %>
<% if #survey.errors.any? %>
<div class="error_messages">
<h2><%= pluralize(#survey.errors.count, "error") %> prohibited this survey from being saved:</h2>
<ul>
<% #survey.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<br>
<%= f.fields_for :questions do |f| %>
<fieldset>
<%= f.label :content, "Question" %><br />
<%= f.text_area :content %><br />
<% Food.all.each do |fd| %>
<fieldset>
<%= f.fields_for :answers do |f| %>
<%= f.text_field :name, :value => fd.name %>
<%= f.number_field :quantity %>
<% end %> <br>
</fieldset>
<% end %>
</fieldset>
<br>
<% end %>
<br>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
What I'm trying to do is:
List all foods name and drinks name inside foods and drinks fieldset
Give each of the foods and drinks a quantity (this quantity column is inside answers table)
Save and update it
But I got no luck. When I'm try to load the edit view (the form), I managed to list all of the foods name. But, I've no idea how to list all of the drinks name in its own fieldset.
I try to make it like this but it didn't work:
<% if :content == "Foods" %>
<%= #loads foods %>
<% else %>
<%= #loads drinks %>
<% end %>
And, when I try to save the foods/drinks name and its quantity, it didn't work too.
Demo:
How to fix this problem?
Note:
This is update method inside surveys_controller:
def update
if #survey.update(survey_params)
redirect_to #survey, notice: "Successfully updated survey."
else
render :edit
end
end
...
def survey_params
params.require(:survey).permit(:name, questions_attributes: [:id, :_destroy, :content, answers_attributes: [:id, :_destroy, :content, :quantity]])
end
Update:
This is my show.html.erb
<h1><%= #survey.name %></h1>
<ul class="questions">
<% #survey.questions.each do |question| %>
<li>
<%= question.content %>
<ol class="answers">
<% question.answers.each do |answer| %>
<li><%= answer.content %> (<%= answer.quantity %>)</li>
<% end %>
</ol>
</li> <br>
<% end %>
</ul>
<%= link_to 'Edit', edit_survey_path(#survey) %> |
<%= link_to 'Back to Surveys', surveys_path %>
You might be seeing an issue with variable scope. Each time you create a nested form with f.fields_for you pass in the variable f, even though f is the variable used in the parent.
Try calling it something different with questions and answers, such as:
<%= f.fields_for :questions do |fq| %>
<fieldset>
<%= fq.label :content, "Question" %><br />
<%= fq.text_area :content %><br />
<% Food.all.each do |fd| %>
<fieldset>
<%= fq.fields_for :answers do |fa| %>
<%= fa.text_field :name, :value => fd.name %>
<%= fa.number_field :quantity %>
<% end %> <br>
</fieldset>
<% end %>
</fieldset>
<br>
<% end %>

Rails 4 nested form not saving

I have scoured all the other questions relating to this topic here, but I am still having this problem. I have a nested form inside a nested form. Answer choices are inside questions which are inside survey. I had no problem setting up the questions, and they save fine. The Answer choices, though, are not saving, and I cannot figure out where I am going wrong.
survey.rb
class Survey < ActiveRecord::Base
belongs_to :author
has_many :questions, dependent: :destroy
has_many :forms, dependent: :destroy
has_many :answer_choices, through: :question
validates :name, uniqueness: true
accepts_nested_attributes_for :questions, reject_if: proc { |attributes| attributes['text'].blank?},
allow_destroy: true
end
question.rb
class Question < ActiveRecord::Base
belongs_to :survey
has_many :responses, dependent: :destroy
has_many :answer_choices, dependent: :destroy
accepts_nested_attributes_for :answer_choices, reject_if: proc { |attributes| attributes['content'].blank?},
allow_destroy: true
end
answer_choice.rb
class AnswerChoice < ActiveRecord::Base
belongs_to :question
end
survey_controller.rb
def new
#survey = Survey.new(author_id: session[:user_id])
#survey.questions.build
#survey.questions.each { |question| 4.times { question.answer_choices.build }}
end
def edit
#survey.questions.build
#survey.questions.each { |question| 4.times { question.answer_choices.build }}
end
def survey_params
params.require(:survey).permit(:name, :description, :author_id,
questions_attributes: [:id, :text, :required, :response_type,
:_destroy, :number])
end
_form.html.erb
<%= form_for(#survey) do |f| %>
<% if #survey.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#survey.errors.count, "error") %> prohibited this survey from being saved:</h2>
<ul>
<% #survey.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_field :description %>
</div>
<div class="field">
<%= f.hidden_field :author_id %>
</div>
<h2>Questions</h2>
<%= f.fields_for(:questions) do |ff| %>
<%= render 'questions', :f => ff %>
<% end %>
<div class="actions">
<%= f.submit 'Submit Question'%>
</div>
<div class="actions">
<%= link_to 'Finish Survey', surveys_path %>
</div>
<% end %>
_questions.html.erb
<div>
<span><%= f.index + 1 %>. </span>
<div class="field">
<%= f.hidden_field :number, value: f.index + 1 %>
</div>
<div class="field">
<%= f.label :text, "Question" %><br>
<%= f.text_field :text %>
</div>
<div class="field">
<%= f.label :response_type %><br>
<%= f.select :response_type, [["Yes/No", "yes/no"], ["Short Answer", "string"], ["Long Answer", "text"], ["Multiple Choice", "multi"]] %>
</div>
<div class="field">
<%= f.label :required %>
<%= f.check_box :required %>
</div>
<div>
<p>Answer Choices</p>
<%= f.fields_for(:answer_choices) do |ff| %>
<%= render 'answer_choices', :f => ff %>
<% end %>
</div>
<div class="field">
<%= f.label :_destroy %>
<%= f.check_box :_destroy %>
</div>
</div>
_answer_choices.html.erb
<div class="field">
<%= f.label :content %><br>
<%= f.text_field :content %>
</div>
<div class="field">
<%= f.label :_destroy %>
<%= f.check_box :_destroy %>
</div>
A few changes in your code.
Change your new method like this
def new
#survey = Survey.new(author_id: session[:user_id])
#questions = #survey.questions.build
#answer_choices = 4.times { #questions.answer_choices.build }
end
Your survey_params should look like this
def survey_params
params.require(:survey).permit(:name, :description, :author_id,
questions_attributes: [:id, :text, :required, :response_type,
:_destroy, :number, answer_choices_attributes: [:id,:content,:_destroy]])
end
And in your form code, change these lines
<%= f.fields_for(:questions) do |ff| %>
<%= f.fields_for(:answer_choices) do |ff| %>
into
<%= f.fields_for #questions do |ff| %>
<%= f.fields_for #answer_choices do |ff| %>

How to include both dynamic select menu and nested attributes together in rails?

Consider i have three tables users, countries, states. I have a page to add a new user and when i add a new user i have to list the countries in the select box and on selecting the country the multiple select box should be loaded with the states of the country and i should be able to select the desired states.
Similarly i can click on the add button to add another select box and select another country and select states that belongs to that country and so on. And i know this needs nested attributes and dynamic select menu functionality but do not know how i can use these together.
The following are the ones that i tried
Models:
class Country < ActiveRecord::Base
has_many :states
attr_accessible :name
end
and
class User < ActiveRecord::Base
serialize :state_id
has_many :user_countries
accepts_nested_attributes_for :user_countries, :allow_destroy => true
has_many :state
attr_accessible :username, :user_countries_attributes
end
and
class State < ActiveRecord::Base
belongs_to :country
attr_accessible :name, :country_id
end
and
class UserCountry < ActiveRecord::Base
serialize :state_id
belongs_to :users
attr_accessible :country_id, :user_id, :state_id
end
Also the following image shows what i am trying to accomplish clearly
UPDATE
<%= form_for(#user) do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :username %><br />
<%= f.text_field :username %>
</div>
<%= f.fields_for :user_countries do |country| %>
<%= render "user_country_fields", :f => country %>
<% end %>
<div class="add_variant"><%= link_to_add_fields "Add Country", f, :user_countries %></div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Update1:
<div class="entry_field">
<label>Country :</label>
<div id="field_country">
<%= f.collection_select :country_id, Country.all, :id, :name, :prompt => 'Select Country' %>
</div>
<div id="field_state">
<%= f.collection_select :state_id, State.all, :id, :name, {:prompt => 'Select State'}, { :multiple => true } %>
</div>
<%= link_to_remove_fields "remove", f %></div>
You can use nested_form (https://github.com/ryanb/nested_form) to achieve this in following way,
<%= nested_form_for(#user) do |f| %>
....
<%= f.fields_for :user_countries do |country| %>
<%= render "user_country_fields", :f => country %>
<% end %>
<div class="add_variant"><%= f.link_to_add "Add" :user_countries %></div>
<div class="actions">
<%= f.submit %>
</div>
Similarly, in partial
<%= f.link_to_remove "Remove" %>

Nested Form Error - ArgumentError (wrong number of arguments (0 for 1)):

I followed this screencast to make a nested model form.
http://railscasts.com/episodes/196-nested-model-form-part-1
Now, I am trying my application to include such a nested model form but I received a argument error (wrong number of arguments(0 for 1)).
I can't seem to figure out where I went wrong and would like to seek some advice on what I could try out and why some an error might have occurred.
The error happens on this line in the Subject Model.
has_many :lessons, :dependent => destroy
The other relevant codes:
Subjects Controller:
def new
#subject = Subject.new
#3 times one for lecture one for lab one for tut.
3.times{#subject.lessons.build}
respond_to do |format|
format.html # new.html.erb
format.json { render json: #subject }
format.js
end
end
Subject Model
class Subject < ActiveRecord::Base
has_many :lessons, :dependent => destroy
attr_accessible :lesson_attributes, :acad_unit, :cohort_size, :discipline, :remarks, :subject_code, :subject_name, :year_of_study
accepts_nested_attributes_for :lessons, :reject_if => lambda { |a| a[:lesson_type].blank? }, :allow_destroy => true
end
Lesson Model
class Lesson < ActiveRecord::Base
belongs_to :subject
attr_accessible :frequency, :lesson_type, :no_of_lesson, :possible_venues
end
_form.html.erb
<%= form_for(#subject,:remote=>true) do |f| %>
<% if #subject.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#subject.errors.count, "error") %> prohibited this subject from being saved:</h2>
<ul>
<% #subject.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :subject_code %><br />
<%= f.text_field :subject_code %>
</div>
<div class="field">
<%= f.label :subject_name %><br />
<%= f.text_field :subject_name %>
</div>
<div class="field">
<%= f.label :year_of_study %><br />
<%= f.text_field :year_of_study %>
</div>
<div class="field">
<%= f.label :discipline %><br />
<%= f.text_field :discipline %>
</div>
<div class="field">
<%= f.label :acad_unit %><br />
<%= f.text_field :acad_unit %>
</div>
<div class="field">
<%= f.label :cohort_size %><br />
<%= f.text_field :cohort_size %>
</div>
<div class="field">
<%= f.label :remarks %><br />
<%= f.text_field :remarks %>
</div>
<ol>
<%= f.fields_for :lessons do |builder| %>
<%= render "lesson_fields", :f => builder %>
<% end %>
</ol>
<% end %>
_lesson_fields.html.erb
<p>
<div class="field">
<%= f.label :lesson_type %><br />
<%= f.text_field :lesson_type %>
</div>
<div class="field">
<%= f.label :no_of_lesson %><br />
<%= f.text_field :no_of_lesson %>
</div>
<div class="field">
<%= f.label :frequency %><br />
<%= f.text_field :frequency %>
</div>
<div class="field">
<%= f.label :possible_venues %><br />
<%= f.text_field :possible_venues %>
</div>
</p>
I guess you wanted :
has_many :lessons, :dependent => :destroy
?
Here you'll find a nice discussion on topic.

Resources