Reputation: 27114
I am trying to run this..
- f.fields_for :referrals do |qf|
But I would like to pass this, @organization.referrals.select{|ref|ref.new_record?}
as well. This is so that the forms passed are exclusively new objects, and not older ones.
I've tried to do this..
- f.fields_for :referrals do |qf|
- if qf.object.new_record?
= render :partial => 'referral_fields', :locals => {:qf => qf}
Which makes it display correctly in the view, but the params are still populated with every single previously created nested object.
Which leads me to believe that I need to pass this option within the fields_for statement itself.
I have also tried this :
- f.fields_for @organization.referrals.select{|ref|ref.new_record?} do |qf|
= render :partial => 'referral_fields', :locals => {:qf => qf}
As well as this :
- f.fields_for :referrals, @organization.referrals.select{|ref|ref.new_record?} do |qf|
= render :partial => 'referral_fields', :locals => {:qf => qf}
The first example will show and only allows to pass one object. Where as my form is to allow a dynamic number of duplicate nested forms.
The second will display and pass all nested objects
App Info
#organization.rb
has_many :referrals
accepts_nested_attributes_for :referrals, :reject_if => proc { |attributes| attributes.all? { |k, v| v.blank? } }, :allow_destroy => true
#referral.rb
belongs_to :organization
#referrals_controller.rb
def new
2.times { @organization.referrals.build }
....
def create
@referral = Referral.new(params[:referral])
if @referral.valid? && @organization.referrals << @referral
flash[:notice] = "Referrals saved."
redirect_to new_organization_referrals_path(@organization)
else
render :action => :new, :layout => 'manage'
end
end
Upvotes: 1
Views: 2443
Reputation: 23307
Here's what you want:
- f.fields_for :referrals, @organization.referrals.select{|ref|ref.new_record?} do |qf|
= render :partial => 'referral_fields', :locals => {:qf => qf}
The first parameter is the association name, which rails needs in order to know how to structure the params. If your first parameter is a collection, rails can usually infer the association name from that collection.
Your collection however, has been filtered into a regular array, where the association can't be as easily inferred. So you pass the specific collection as the second parameter.
Good luck!
UPDATE
I've built out a small rails app to analyze the problem, and the solution above is working just fine for me - the edit form doesn't display existing referrals, only new ones. I'll post the relevant code, so we can see where you and I might differ. One caveat, this is all in erb since I rarely work with haml and wouldn't want a typo to mess up the solution :)
My models:
# app/models/organization.rb
class Organization < ActiveRecord::Base
has_many :referrals
accepts_nested_attributes_for :referrals
end
# app/models/referral.rb
class Referral < ActiveRecord::Base
belongs_to :organization
end
My controller's edit action:
# app/controllers/organizations_controller.rb
class OrganizationsController < ApplicationController
def edit
@organization = Organization.find(params[:id])
2.times { @organization.referrals.build }
end
end
My views:
# app/views/organizations/edit.html.erb
<h1>Editing <%= @organization.name %></h1>
<% form_for(@organization) do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :name %><br />
<%= f.text_field :name %>
</p>
<% f.fields_for :referrals, @organization.referrals.select{|ref| ref.new_record?} do |referral_fields| %>
<%= render :partial => 'referral', :locals => {:f => referral_fields} %>
<% end %>
<p>
<%= f.submit %>
</p>
<% end %>
# app/views/organizations/_referral.html.erb
<p>
<%= f.label :name, 'Referral Name' %><br />
<%= f.text_field :name %>
</p>
Of course, I just read your new comments, and maybe you don't need this anymore. Oh well, more documentation for posterity :)
Upvotes: 4