render :collection calling partial with phantom object?

I have two models with a straightforward has_many / belongs_to
relationship:

class Premise < ActiveRecord::Base
  has_many :metered_services, :dependent => :destroy
  ...
end

class MeteredService < ActiveRecord::Base
  belongs_to :premise
  ...
end

and nested routes to match:

Demo::Application.routes.draw do
  devise_for :users
  resources :premises do
    resources :metered_services
  end
  ...
end

I want to show/edit the metered services on the same page as premise
edit page, so my views/premises/edit.html.erb file has this line:

<% Rails.logger.debug("== #{@premise.address} has
#{@premise.metered_services.count} metered services") %>
<%= render :partial => "metered_services/metered_service", :collection
=> @premise.metered_services %>

and my stubbed views/metered_services/_metered_service.html.erb is just
this:

<% Rails.logger.debug("== _metered_service: metered_service =
#{metered_service.inspect}") %>

So here's what's weird: With a newly created premise -- before I've
added any metered services -- the _metered_service.html.erb partial gets
called with a metered service object whose ID is nil and whose
premise_id field is filled in with the owning premise. But there should
be ZERO metered services, not one. The console will show something
like:

== 1800 Pennsylvania Avenue has 0 metered services
  MeteredService Load (0.2ms) SELECT "metered_services".* FROM
"metered_services" WHERE ("metered_services".premise_id = 48)
== metered_service = #<MeteredService id: nil, premise_id: 48, ... >

Is this a special "feature" of render ... :collection? I can always
filter out metered_services with nil ids in the partial, but that seems
really odd. Am I doing something wrong?

- ff

maybe you have to add nested_attributes

I want to show/edit the metered services on the same page as premise
edit page, so my views/premises/edit.html.erb file has this line:

<% Rails.logger.debug("== #...@premise.address} has
#...@premise.metered_services.count} metered services") %>
<%= render :partial => "metered_services/metered_service", :collection
=> @premise.metered_services %>

and my stubbed views/metered_services/_metered_service.html.erb is just
this:

<% Rails.logger.debug("== _metered_service: metered_service =
#{metered_service.inspect}") %>

So here's what's weird: With a newly created premise -- before I've
added any metered services -- the _metered_service.html.erb partial gets
called with a metered service object whose ID is nil and whose
premise_id field is filled in with the owning premise. But there should
be ZERO metered services, not one. The console will show something
like:

== 1800 Pennsylvania Avenue has 0 metered services
MeteredService Load (0.2ms) SELECT "metered_services".* FROM
"metered_services" WHERE ("metered_services".premise_id = 48)
== metered_service = #<MeteredService id: nil, premise_id: 48, ... >

Is this a special "feature" of render ... :collection? I can always
filter out metered_services with nil ids in the partial, but that seems
really odd. Am I doing something wrong?

That sounds like you've got an unsaved metered_service somewhere (eg
by doing premise.metered_services.build)

Fred

Frederick Cheung wrote in post #984616:

That sounds like you've got an unsaved metered_service somewhere (eg
by doing premise.metered_services.build)
Fred

Yep, that's true. I based my code on the canonical blog posts /
comments example, so in views/premises/edit.html.erb, I wrote:

<%= form_for([@premise,
@premise.metered_services.build(:account_identifier => "gas")]) do |f|
%>
  <%= f.submit "add gas account" %>
<% end %>

... and it clearly calls build() whenever it renders the page. But this
leads to two questions:

* (Curiosity:) How did render(... :collection) know about the newly
created metered_service without an ID? I know that
premise.metered_services.build will create a new record, but it appears
that the new record doesn't appear on the premises.metered_services list
until it's saved.

* (Necessity:) Assume the user is looking at
views/premises/edit.html.erb. I want a button that says "add
metered_service to the current premise". What's the right way to do
that? (Clearly, I haven't made friends with form_for() just yet.)

TIA.

- ff

actually i have done somethign similiar these is my code

<%= @todo.todostags.build %>
<%= form_for(@todo) do |f| %>
  <div class="actions">
    <%= f.submit %>
  </div>
here the todo model
class Todo < ActiveRecord::Base
  has_many :todostags, :foreign_key =>"todos_id" , :primary_key =>'id'
   accepts_nested_attributes_for :todostags, :allow_destroy => :true,
        :reject_if => proc { |attrs| attrs.all? {|k,v| v.blank?}}
end

class Todostag < ActiveRecord::Base

  belongs_to :tag , :foreign_key =>"tags_id"
  belongs_to :todo , :foreign_key =>"todos_id"

end

* (Curiosity:) How did render(... :collection) know about the newly
created metered_service without an ID? I know that
premise.metered_services.build will create a new record, but it appears
that the new record doesn't appear on the premises.metered_services list
until it's saved.

build adds the record to the in memory collection

* (Necessity:) Assume the user is looking at
views/premises/edit.html.erb. I want a button that says "add
metered_service to the current premise". What's the right way to do
that? (Clearly, I haven't made friends with form_for() just yet.)

There's a railscast covering one possible approach:
http://railscasts.com/episodes/197-nested-model-form-part-2

Fred

Frederick Cheung wrote in post #984876:

There's a railscast covering one possible approach:
http://railscasts.com/episodes/197-nested-model-form-part-2

@Lorenzo: Looks good. Thanks.

@Frederick: I'm beginning to believe that "if you can imagine it, Ryan
Bates has already coded it." Thanks for the pointer. I should start
watching the railscasts regularly.

- ff