Has render_component changed?


#1

I have an application that worked fine, but after the recent updates
has broken in some calls to render_component from views. I might be
missing something but as far as I remember Rails updates is the only
thing I’ve done in between. See the log:

*** START LOG SNIPPET

Start rendering component ({:params=>
{:center_id=>10, :id=>25}, :action=>“supervisory_commissions_widget”}):

Processing EmployeeController#supervisory_commissions_widget (for
127.0.0.1 at 2006-04-10 22:07:27) [GET]
Session ID: 94a1e0400481a317fcd235c1360c82ac
Parameters: {“action”=>“supervisory_commissions_widget”,
“id”=>nil, “controller”=>“employee”, “center_id”=>10}

*** END LOG SNIPPET

The “id” goes from 25 in the view to nil in the controller. Does
anybody know why?

– fxn

PS: I should have frozen rails there.


#2

On Apr 10, 2006, at 22:15, Xavier N. wrote:

The “id” goes from 25 in the view to nil in the controller. Does
anybody know why?

Indeed, I froze 1.0 under vendor and everything is working again.

I would like to understand what has changed in render_component
anyway if anyone knows it. My guess is that something happens with
parameters called “id”, the rest seems to travel just fine.

– fxn


#3

One thing I do know is that :id need not be passed inside
:params–just pass it directly.

Ed Frederick - edwardfrederick.com


#4

Hello Xavier,

:action=>“supervisory_commissions_widget”})

The “id” goes from 25 in the view to nil in the controller. Does
anybody know why?

Indeed, I froze 1.0 under vendor and everything is working again.

I would like to understand what has changed in render_component
anyway if anyone knows it. My guess is that something happens with
parameters called “id”, the rest seems to travel just fine.

Well, it seems it’s due to r3563 when bitsweat committed performances
patches from Stefan K. :

in trunk/actionpack/lib/action_controller/components.rb
module method #request_for_component was modified,
especially these lines, from :

(options[:params] || {}).merge({ “controller” => options[:controller],
“action” => options[:action], “id” => options[:id]
}).with_indifferent_access

to :

(options[:params] || {}).with_indifferent_access.regular_update(
“controller” => controller_name, “action” => options[:action], “id”
=> options[:id])

In your situation, you’ve got in options hash :

:params=> {:center_id=>10, :id=>25},
:id => nil

so after the merge, you’ve got this temporary hash :

{:center_id=>10, :id=>25, “controller” =>“employee”,
:action"=>“supervisory_commissions_widget”, “id” => nil }

since option[:id] is nil.

When a HashWithIndifferentAccess object is created from
a Hash, if there’s collision between :foo and ‘foo’, I can’t figure
out how it works, but in your case the (:id, 25) pair wins.

So ‘id’ => 25 is fine in the request.

After r3563, the HashWithIndifferentAccess object is created first
so you’ve got :

{ ‘center_id’ =>10, ‘id’ =>25 }

Then the (id, 25) pair is overwritten by (id, nil) by the
#regular_update
call. so you’ve got ‘id’ => nil in the request.

As Edward wrote, pass :id directly and it should work.

-- Jean-François.

#5

On Apr 11, 2006, at 2:08, Jean-François wrote:

As Edward wrote, pass :id directly and it should work.

Excellent analysis. Looks like a bug then, I’ll report it.

Why is :id looked for in options in the first place? From the docs I
would expect params to contain all parameters, nothing special is
said about :id.

– fxn