I am trying to use the accepts_nested_attributes_for method within my model, however I need to render the records grouped by another association. I have got this to work but the method I have used seems like a bit of a hack.
Is there a better way to structure this?
My Model
has_many :quantities
has_many :ingredients, :through => :quantities, :uniq => true
has_many :sizes, :through => :quantities, :uniq => true
has_many :photos, :as => :imageable
accepts_nested_attributes_for :quantities
My View
<%= form_for [:admin, #recipe] do |f| %>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<% #recipe.quantities.group_by(&:size).each do |size, quantities| %>
<h3><%= size.name %></h3>
<%= f.fields_for :quantities do |builder| %>
<% if builder.object.size == size %>
<p>
<%= builder.text_area :value, :rows => 1 %>
</p>
<% end %>
<% end %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
You can get rid of the if builder.object.size == size part with this :
<% #recipe.quantities.group_by(&:size).each do |size, quantities_for_size| %>
<h3><%= size.name %></h3>
<%= f.fields_for :quantities, quantities_for_size do |builder| %>
<p><%= builder.text_area :value, :rows => 1 %></p>
<% end %>
<% end %>
passing the quantities_for_size as a second argument to fields_for should make it use it instead of the whole quantities associated to the recipe. See the docs on #fields_for for more information.
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| %>
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 a three models Report,Question,Answer
Answer
belong_to :question
Question
belong_to :reports
has_many :answers, :dependent => :destroy
accepts_nested_attributes_for :answers, :allow_destroy => true
Reports
has_many :questions, :dependent => :destroy
accepts_nested_attributes_for :questions, :allow_destroy => true
While creating a new report some questions are randomly picked to be added to the report and show form in this way :
Report Form
<%= form_for #report do |f| %>
<div class="field">
<%= f.fields_for :questions do |builder| %>
<%= render "question_fields", :f => builder %>
<% end %>
</div>
<div class="actions">
<%= f.submit "Submit Report"%>
</div>
<% end %>
---Partial Question_Fields---
<h4 class="question_name">
<%= f.object.name %>
</h4>
<%= f.fields_for :answers do |answer,index| %>
<%= render 'answer_fields', :f => answer %>
<% end %>
---Partial Answer_Fields---
<%= f.text_field :name, :placeholder => "Add your answer here" %>
But when I try to edit/create a new report it fetches all the existing answers for that particular question. Whereas I want to implement something like :
---Partial Question_Fields---
<h4 class="ques_title">
<%= f.object.name %>
</h4>
<% f.object.answers_for_report(#report).each do |answer| %>
<%= render 'answer_fields', :f => answer %>
<% end %>
---Partial Question_Fields---
<b>What should be code here so that it again acts same as nested attributes and gets updated succesfully !!!</b>
Question Model
belong_to :reports
has_many :answers, :dependent => :destroy
accepts_nested_attributes_for :answers, :allow_destroy => true
def answers_for_report(#report)
self.answers.where("report_id = ? ",report.id)
end
Here is the answer to my question :
Report Form is like
<%= form_for #report do |f| %>
<div class="field">
<%= f.fields_for :questions do |builder| %>
<%= render "question_fields", :f => builder %>
<% end %>
</div>
<div class="actions">
<%= f.submit "Submit Report"%>
</div>
<% end %>
Then Question 'question_fields' is like
<%= question.fields_for :answers, question.object. answers_for_report(#report) do |answer| %>
<%= render 'answer_fields', :f => answer %>
<% end %>
This passes only a collections / set of records of answers and renders fields for those selected answers only.
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 %>
I have a basic has_many through relationship:
class Foo < ActiveRecord::Base
has_many :bars, :dependent => :destroy
has_many :wtfs :through => :bars
accepts_nested_attributes_for :bars, :wtfs
end
On my crud forms I have a builder block for the wtf, but I need the label to come from the bar (an attribute called label for instance). What's the proper method to do this?
Here's the most simple scaffold:
<h1>New foo</h1>
<% form_for(#foo) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<h2>Bars</h2>
<% f.fields_for :wtfs do |builder| %>
<%= builder.hidden_field :bar_id %>
<p>
<%= builder.text_field :wtf_data_i_need_to_set %>
</p>
<% end %>
<p>
<%= f.submit 'Create' %>
</p>
<% end %>
<%= link_to 'Back', foos_path %>
The answer was found in analyzing how the rails FormBuilder works. So in the example above where I need to access the actual wtf object so I can get a property on bar, I need to do the following:
<h2>Bars</h2>
<% f.fields_for :wtfs do |builder| %>
<%= builder.hidden_field :bar_id %>
<p>
<%= builder.label builder.object.bar.data_i_need_for_a_label %>
<%= builder.text_field :wtf_data_i_need_to_set %>
</p>
<% end %>