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| %>
Related
I have a User model as below,
class User < ActiveRecord::Base
devise :database_authenticatable, :registerable
has_many :company_users
accepts_nested_attributes_for :company_users, :allow_destroy => true
has_many :companies, :through => :company_users
has_many :roles, :through => :company_users
end
and its associated model CompanyUser as below,
class CompanyUser < ActiveRecord::Base
belongs_to :user
belongs_to :company
belongs_to :role
end
I am trying to build the associations as below but it seems like not working
# GET /users/new
def new
#user = User.new
#user.company_users.build
end
View file is as follows,
<%= form_for(#user) do |f| %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :email %><br>
<%= f.text_field :email %>
</div>
<h3>Companies and Roles</h3>
<div class="field">
<% f.fields_for :company_users do |cu| %>
<p>
<%= cu.label :company_id %>
<%= cu.text_field :company_id%>
<%= cu.label :role_id %>
<%= cu.text_field :role_id %>
<%= cu.check_box :_destroy %>
<%= cu.label :_destroy, 'delete' %>
</p>
<% end %>
<p>
<%= f.submit 'Add to user', :name => "add_company_user" %>
<%= f.submit 'Delete from user', :name => "remove_company_user" %>
</p>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I am trying to figure out where it is going wrong.
You are missing a =, therefore the fields_for block isn't rendered to the page. Change this line
<% f.fields_for :company_users do |cu| %>
to
<%= f.fields_for :company_users do |cu| %>
I am learning RoR and i am trying to find how to set a fields_for in another one with has_one models like this:
class Child < ActiveRecord::Base
belongs_to :father
accepts_nested_attributes_for :father
end
class Father < ActiveRecord::Base
has_one :child
belongs_to :grandfather
accepts_nested_attributes_for :grandfather
end
class Grandfather < ActiveRecord::Base
has_one :father
end
I used Nested Model Form Part 1 on Railscasts to get these:
In children_controller.rb:
def new
#child = Child.new
father=#child.build_father
father.build_grandfather
end
def child_params
params.require(:child).permit(:name, father_attributes:[:name], grandfather_attributes:[:name])
end
And my form:
<%= form_for(#child) do |f| %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
mother:<br>
<%= f.fields_for :father do |ff| %>
<%= ff.label :name %>
<%= ff.text_field :name %><br>
grand mother:<br>
<%= f.fields_for :grandfather do |fff| %>
<%= fff.label :name %>
<%= fff.text_field :name %>
<% end %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I am trying to retrieve the datas with:
<%= child.father.name %>
<%= child.father.grandfather.name %>
but the grandfather's name won't work.
I cannot find the mistake(s)...anyone to help on this?
Thanks!
Try switching:
<%= f.fields_for :grandfather do |fff| %>
to:
<%= ff.fields_for :grandfather do |fff| %>
And switching:
params.require(:child).permit(:name, father_attributes:[:name], grandfather_attributes:[:name])
To:
params.require(:child).permit(:name, father_attributes:[:name, grandfather_attributes:[:name]])
according to http://guides.rubyonrails.org/getting_started.html, I have below relationship models,
class Tag < ActiveRecord::Base
belongs_to :post
attr_accessible :name
end
class Post < ActiveRecord::Base
attr_accessible :context, :title, :tags_attributes
validates :title, :presence => true
validates :context, :presence => true, :length => {:minimum => 5}
has_many :comments
has_many :tags
accepts_nested_attributes_for :tags, :allow_destroy => :true,
:reject_if => proc {|attrs| attrs.all? {|k,v| v.blank?} }
end
normally below code could work well when I sent a edit request,these existing tags are listed as editable elements on the page.
<%= form_for(#post) do |post_form| %>
<%= post_form.fields_for :tags do |tag_form|%>
<div class="field">
<%= tag_form.label :name, 'Tag:' %>
<%= tag_form.text_field :name %>
</div>
<% unless tag_form.object.nil? || tag_form.object.new_record? %>
<div class="field">
<%= tag_form.label :_destroy, 'Remove:' %>
<%= tag_form.check_box :_destroy %>
</div>
<% end %>
<% end %>
but now,refer to below instance code on http://guides.rubyonrails.org/form_helpers.html
<%= form_for #person, :url => { :action => "create" } do |person_form| %>
<%= person_form.text_field :name %>
<%= fields_for #person.contact_detail do |contact_details_form| %>
<%= contact_details_form.text_field :phone_number %>
<% end %>
<% end %>
then I change the statement with fields_for to below format, why it always always prompt
undefined method `model_name' for Array:Class
<%= fields_for #post.tags do |tag_form|%>
at last, I make it work with below update
<% #post.tags.each do |tag| %>
<%= post_form.fields_for tags,tag do |tag_form|%>
<div class="field">
<%= tag_form.label :name, 'Tag:' %>
<%= tag_form.text_field :name %>
</div>
<% unless tag_form.object.nil? || tag_form.object.new_record? %>
<div class="field">
<%= tag_form.label :_destroy, 'Remove:' %>
<%= tag_form.check_box :_destroy %>
</div>
<% end %>
<% end %>
<% end %>
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.
I'm having real trouble getting my head around editing attributes in has_many through join models. I've set up a very simple app to experiment with; Recipes, Ingredients and Recipe_Ingredients (the join).
Can anyone help with making this work as it should? As it is, it'll pulling through 'qty' from the join model, but not the actual ingredient.
I've put a public repo up that anyone can download to play with: https://github.com/EssentialMusic/Recipes
The models:
class Ingredient < ActiveRecord::Base
attr_accessible :name
has_many :recipe_ingredients, :dependent => :destroy
has_many :recipes, :through => :recipe_ingredients
end
class Recipe < ActiveRecord::Base
attr_accessible :author, :description, :name, :recipe_ingredients_attributes, :ingredients_attributes
has_many :recipe_ingredients, :dependent => :destroy
has_many :ingredients, :through => :recipe_ingredients
accepts_nested_attributes_for :ingredients, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => :true
accepts_nested_attributes_for :recipe_ingredients
end
class RecipeIngredient < ActiveRecord::Base
belongs_to :recipe
belongs_to :ingredient
attr_accessible :measure, :qty, :special_instructions
end
The form
<%= form_for(#recipe) do |f| %>
<% if #recipe.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#recipe.errors.count, "error") %> prohibited this recipe from being saved:</h2>
<ul>
<% #recipe.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>
<div class="field">
<%= f.label :author %><br />
<%= f.text_field :author %>
</div>
<div class="field">
<%= f.label :description %><br />
<%= f.text_area :description %>
</div>
<div>
<%= f.fields_for :recipe_ingredients do |ri| %>
<%= ri.text_field :qty %> -
<%= ri.fields_for :ingredients do |i| %>
<%= i.text_field :name %><br>
<% end %>
<% end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Cheers!!
Substitute the ri with f in the second nested fields_for like this:
<%= f.fields_for :recipe_ingredients do |ri| %>
<%= ri.text_field :qty %> -
<%= **f**.fields_for :ingredients do |i| %>
<%= i.text_field :name %><br>
<% end %>
<% end %>