On 19 Aug 2008, at 16:10, Xavier Noria wrote:

>
> I am precisely documenting associations these days.
>
> I think the problem is not related to #build itself, that method adds
> the model to the target of the proxy just fine:
>
>   [EMAIL PROTECTED]:~/tmp/test_associations$ cat test_build.rb
>   post = Post.create
>   post.comments.build
>   puts post.comments.target.empty?
>   [EMAIL PROTECTED]:~/tmp/test_associations$ script/runner test_build.rb
>   false
>
> Looks like the issue has to do with rendering collections somehow, if
> you pass the target to the helper instead it works:
>
>   <%= render :partial => "comment", :collection =>  
> @post.comments.target %>
>
> Note that target is a getter for @target, load_target is not involved.
>
> Looking further down, render_partial_collection has this line
>
>   return " " if collection.empty?
>
> empty? is equivalent to size.zero? for association collections and
> #size does some stuff, so I guess we are getting close. The branch we
> enter does take into account new records and performs a count_records
> in case there was something in the database, the result is correct. In
> fact the flow execution goes on, but *after* that line
> collection.empty? is true (so the #map call afterwards does nothing
> and no template gets rendered). My conjecture is that the call to
> #size resets the proxy somehow.
>

Size looks like this:

  def size
    if @owner.new_record? || (loaded? && [EMAIL PROTECTED]:uniq])
      @target.size
    elsif !loaded? && [EMAIL PROTECTED]:uniq] && @target.is_a? 
(Array)
      unsaved_records = Array(@target.detect { |r| r.new_record? })
      unsaved_records.size + count_records
    else
      count_records
    end
  end

Unrelated to this and maybe I'm hallucinating, but isn't that second  
branch wrong ? should it not be
unsaved_records = @target.select { |r| r.new_record? })
(since detect just returns the first element for which the block  
returns true, or nil)


If we look inside count_records we can see that your conjecture is  
correct. count_records gets the count (reads the counter cache or  
executes the relevant sql query) and then it does

@target = [] and loaded if count == 0

My reasoning is that this is an optimisatiohn: if you do foos.count  
and you get back 0 then you can assume that foos is indeed an empty  
array - there is no need to actually load the foos array. Of course in  
this case this optimisation is screwing things up.

@target ||= [] and loaded if count == 0

might be more correct.

Fred


> I may complete the walkthrough later but that's what I've got by now.
> Next target is count_records.
>
> >


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Ruby 
on Rails: Core" group.
To post to this group, send email to rubyonrails-core@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/rubyonrails-core?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to