Partial loop counter override by local variable

The following is an issue I raised over in the Rails Talk group and it
was suggested that I bring it up here...

Although not documented as far as I'm aware, prior to Rails 2.1 it was
possible to pass a local variable to a partial with the same name as
the partial's internal collection counter variable, i.e.
<name>_counter, and have it take on the value that is passed. I have
found this to be extremely useful in situations where I have a
collection of items to be rendered, but also want to be able to add an
item to the page one at a time after it has initially been rendered,
in response to an ajax request, e.g. so I can allow the user to add
new fields to a form.

In a situation like this the ordinality of the new item relative to
the others may be important to how it is rendered, but of course the
internal counter disappears once the initial collection has been
rendered. What I had been doing here was to have an rjs template
invoke the same partial used for the collection but on an object, and
pass the counter in as a local to ensure that the object gets treated
the right way with respect to the items already rendered.

Unfortunately, the ability to do this appears to have disappeared in
2.1, and leaves me resorting to some pretty nasty stuff to achieve the
same effect. It appears that regardless of the value passed to the
local variable, when the partial is invoked on an object, internally
the variable is just set to zero.

This seems like a step backwards. Anyone want to explain the thinking
behind this, or suggest an elegant alternative strategy for
implementing the kind of case I described?

Unfortunately, the ability to do this appears to have disappeared in
2.1, and leaves me resorting to some pretty nasty stuff to achieve the
same effect. It appears that regardless of the value passed to the
local variable, when the partial is invoked on an object, internally
the variable is just set to zero.

Looks like it's back in edge :slight_smile:
Assuming it's desirable behaviour, sounds to me like the right thing
to do would be to add a test for it so that it doesn't get trampled on
in the future.

Fred

Just ran into the same issue as MarkMT. The code required for the
functionality he describes is fairly nasty atm.

Glad to hear the original way is back in Edge, just need the next
official release now!

Just ran into the same issue as MarkMT. The code required for the
functionality he describes is fairly nasty atm.

Glad to hear the original way is back in Edge, just need the next
official release now!

Do you have a test for this? We can merge it to 2.1 before we put out
2.1.1 (hopefully soon).

I've just tried the following on Edge;

<%= render(:partial => 'example', :collection => %w(rails-doc is
cool), :locals => {:example_counter => 5}) %>

in the 'example' partial;

<p>Element: <%= example %> (index: <%= example_counter %>)</p>

output;

Element: rails-doc (index: 0)
Element: is (index: 1)
Element: cool (index: 2)

so not only has the behaviour changed (counter starting from 0, not
1), it's still not allowing it to be overridden.

How did you check it was working, Frederick?

@Koz - I'll try and write a patch/test which allows the internal
counter to be overridden.

My bad, it does work.

<%= render(:partial => 'example', :locals => {:example_counter => 5})
%>

Which is how you'd call it from an AJAX request, works.

I'll look into whether there's a test case.

Hi Koz, added a patch for the tests to Lighthouse.

http://rails.lighthouseapp.com/projects/8994/tickets/766

Cam