views:

34

answers:

1

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
+2  A: 

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 :)

Jaime Bellmyer
Nope won't work. That shows and passes all nested objects to the params.
Trip
But thank you nonethless ;)
Trip
what version of rails are you using?
Jaime Bellmyer
Rails -v=2.3.5 . I think the reason its not working is because when the fields_form is called, its technically considered 'unsaved'
Trip
Sorry, I tried to give you a solution based on the docs, but I'll actually put together an example. Back in a few :)
Jaime Bellmyer
You're amazing! :D I even tried this `Referral.all.select{|ref|ref.org_name=nil}` . Even that returns them all. But! If I do `Referral.first` or `@organization.referral.first` then it only displays that one. So it does actually work for passing options, just none of the ones I need. Hey thank you so much Jaime!
Trip
Further...If I place a `-debugger` right before the fields_for statement, and I write `@organization.referrals.select{|ref|ref.new_record?}` it works just as expected. but once it hits the actual statement, every nested object shows.
Trip
Just to double-check, you're trying to get the referral form to *only* display for those referrals that are new? Because you obviously don't want people editing existing referrals. Do I have this correct, or is there anything I'm missing?
Jaime Bellmyer
I updated my answer to include all the code snippets from the example app I created for this problem. It sounds like it's still a little glitchy for you, so I hope it helps.
Jaime Bellmyer
Yes you have it correct. So strange. I bet there's some strange model instance causing this. The options params rarely responds to anything I write unless I type something like `@oragnization.find(1231)` which doesn't exist so it fails. Otherwise it doesn't respond to anything.
Trip
I wonder if it matters where I build in what controller. Now I'm doing it in the view, and I've tried in the referrals_controller as well. No difference.. I'll try making a custom collection.
Trip