Forum: Rails-ES Extraño comportamiento del sum en un Ar ray devuelto por un has_many de rails

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Fernando G. (Guest)
on 2009-01-22 03:16
(Received via mailing list)
Hola gente,

Llevo un rato dándole vueltas a este asunto y no logro encontrar donde
está el error/mal entendimiento/mal uso/bug/feature...

Resulta que extraigo todos los elementos de una relación has_many y le
quiero pasar un sum para sumar uno de los campos de los objetos del
array tal que
así:
Tengo el modelo Cart con estos has_many
  has_many :carts_events, :dependent => :destroy
  has_many :events, :through => :carts_events

Y el modelo Evento que tiene un atributo price_cents:integer

Fijaros en el through pero como veremos más abajo ocurre de igual modo
si uso el array del carts_events que no tiene through

Invoco al sum tal que
así:  cart.events.sum{ |e| e.price_events }

Y me suelta este error:
ArgumentError: wrong number of arguments (1 for 2)
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_collection.rb:368:in
`calculate'
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_collection.rb:368:in
`send'
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_collection.rb:368:in
`method_missing'
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:2003:in
`with_scope'
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_proxy.rb:202:in
`send'
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_proxy.rb:202:in
`with_scope'
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_collection.rb:366:in
`method_missing'
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_collection.rb:151:in
`sum'
  from (irb):19

Ahora un montón de comprobaciones:
>> Event.all.sum{ |e| e.price_cents }
=> 300

BIEN!

>> cart.events.class
=> Array
>> Event.all.class
=> Array

BIEN!

>> cart.events
=> [#<Event id: 491222053, name: "Event 1", permalink: "event-1",
description: "Just an Event", price_cents: 100, created_at:
"2009-01-22 00:47:38", updated_at: "2009-01-22 00:47:38">, #<Event id:
491222054, name: "Event 2", permalink: "event-2", description: "Just
another Event", price_cents: 200, created_at: "2009-01-22 00:47:38",
updated_at: "2009-01-22 00:47:38">]
>> Event.all
=> [#<Event id: 491222053, name: "Event 1", permalink: "event-1",
description: "Just an Event", price_cents: 100, created_at:
"2009-01-22 00:47:38", updated_at: "2009-01-22 00:47:38">, #<Event id:
491222054, name: "Event 2", permalink: "event-2", description: "Just
another Event", price_cents: 200, created_at: "2009-01-22 00:47:38",
updated_at: "2009-01-22 00:47:38">]

BIEN!

>> Event.all == cart.events
=> true

BIEN!


?> cart.events.ancestors
=> [Event(id: integer, name: string, permalink: string, description:
text, price_cents: integer, created_at: datetime, updated_at:
datetime), ActiveRecord::Base, ActiveRecord::Serialization,
ActiveRecord::Calculations, ActiveRecord::Reflection,
ActiveRecord::Transactions, ActiveRecord::Aggregations,
ActiveRecord::AssociationPreload, ActiveRecord::NamedScope,
ActiveRecord::Associations, ActiveRecord::Timestamp,
ActiveRecord::Observing, ActiveRecord::Callbacks, ActiveRecord::Dirty,
ActiveRecord::AttributeMethods, ActiveRecord::Locking::Pessimistic,
ActiveRecord::Locking::Optimistic, ActiveSupport::Callbacks,
ActiveRecord::Validations, Object,
ActiveSupport::Dependencies::Loadable, InstanceExecMethods,
Base64::Deprecated, Base64, Kernel]
>> Event.all.ancestors
NoMethodError: undefined method `ancestors' for #<Array:0x21da568>
  from (irb):28

OUCH!.. digo FAIL!

Para ver que el through no está causando el error:
>> cart.carts_events.sum{ |ce| ce.event.price_event }
ArgumentError: wrong number of arguments (1 for 2)
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_collection.rb:368:in
`calculate'
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_collection.rb:368:in
`send'
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_collection.rb:368:in
`method_missing'
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:2003:in
`with_scope'
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_proxy.rb:202:in
`send'
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_proxy.rb:202:in
`with_scope'
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_collection.rb:366:in
`method_missing'
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_collection.rb:151:in
`sum'
  from (irb):37

FAIL!

Pero es que además:
>> cart.events.sum
ArgumentError: wrong number of arguments (1 for 2)
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_collection.rb:370:in
`calculate'
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_collection.rb:370:in
`send'
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_collection.rb:370:in
`method_missing'
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:2003:in
`with_scope'
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_proxy.rb:202:in
`send'
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_proxy.rb:202:in
`with_scope'
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_collection.rb:366:in
`method_missing'
  from
/Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_collection.rb:153:in
`sum'
  from (irb):38

No entiendo.. recibe un argumento y esperaba 2 :?

En la línea donde peta pone esto:
  @reflection.klass.send(method, *args)

No he querido meterme ahí a debuggear por saber si esque la
soluciónla tengo delante y no la veo.

Qué me decís?

Saludos
f.
javier ramirez (Guest)
on 2009-01-22 03:57
(Received via mailing list)
>> cart.events.class
>>
> => Array
>

Aquí ActiveRecord te engaña.. te dice que te devuelve un Array, pero en
realidad te está devolviendo otra cosa (no recuerdo de memoria, pero
algo que ver con la association), así que realmente no tiene lo mismo
que un Array

En concreto, el sum es diferente y no admite un bloque, sino un nombre
de campo. Lo que tú quieres es

 cart.events.sum(:price_events)


saludos,


[1] sum de AR
http://api.rubyonrails.com/classes/ActiveRecord/Ca...

--
javier ramírez

..i do ruby on rails development in madrid, spain, at
http://www.aspgems.com
..you can find out more about me on http://formatinternet.wordpress.com
and http://workingwithrails.com/person/5987-javier-ramirez
Fernando G. (Guest)
on 2009-01-22 04:04
(Received via mailing list)
2009/1/22 javier ramirez <removed_email_address@domain.invalid>:
>
> En concreto, el sum es diferente y no admite un bloque, sino un nombre
> de campo. Lo que tú quieres es
>
>  cart.events.sum(:price_events)

Macagüen en los mil recórcholis!!

> saludos,
>
>
> [1] sum de AR
> http://api.rubyonrails.com/classes/ActiveRecord/Ca...

;)

Gracias.. trasnochador!!
Guillermo Álvarez Fernández (Guest)
on 2009-01-22 04:49
(Received via mailing list)
El 22/01/2009, a las 2:16, Fernando G. escribió:
> Invoco al sum tal que así:
>  cart.events.sum{ |e| e.price_events }

cart.events devuelve un asociation_proxy
cart.events.all devuelve todos los elementos de la asociación.

cart.events.all.sum {|e| e.price_cents} Sumas en ruby el resultado de
todos los métodos.
cart.events.sum(:price_cents) Dejas que haga la suma mysql.


> Ahora un montón de comprobaciones:
>>> Event.all.sum{ |e| e.price_cents }
> => 300

Cuidado con esto. Estás sacando todos los eventos de la aplicación.


>>> cart.events.class
> => Array
>>> Event.all.class
> => Array


Esto es cosa de la magia de ruby. Ese Array efectivamente despista
mucho.
Fijate en una cosa curiosa.

cart.events #Select * from events where cart.id = 1

Sin embargo
cart.events.first  #Select * from events where cart.id = 1 LIMIT 1

¿Adivina rails para que vas a usar y hace la consulta?

Tengo que estudiarme ese aspecto de active record. A día de hoy no se
muy bien como lo hace.

---
Guillermo Álvarez Fernández
removed_email_address@domain.invalid
http://cientifico.net
Fernando G. (Guest)
on 2009-01-22 05:01
(Received via mailing list)
El día 22 de enero de 2009 3:49, Guillermo Álvarez Fernández
<removed_email_address@domain.invalid>
escribió:>
> El 22/01/2009, a las 2:16, Fernando G. escribió:
>>
>> Invoco al sum tal que así:
>>  cart.events.sum{ |e| e.price_events }
>
> cart.events devuelve un asociation_proxy
> cart.events.all devuelve todos los elementos de la asociación.
>
> cart.events.all.sum {|e| e.price_cents} Sumas en ruby el resultado de todos
> los métodos.
> cart.events.sum(:price_cents) Dejas que haga la suma mysql.

Genial.. buena
aclaración
>> Ahora un montón de comprobaciones:
>>>>
>>>> Event.all.sum{ |e| e.price_cents }
>>
>> => 300
>
> Cuidado con esto. Estás sacando todos los eventos de la aplicación.

Sipi.. era una prueba

> cart.events #Select * from events where cart.id = 1
>
> Sin embargo
> cart.events.first  #Select * from events where cart.id = 1 LIMIT 1
>
> ¿Adivina rails para que vas a usar y hace la consulta?
>
> Tengo que estudiarme ese aspecto de active record. A día de hoy no se muy
> bien como lo hace.

Eres un estudioso :)

Qué pasa que aquí nadie duerme.. a lavarse los dientes y a la cama todol
mundo.

O esque estáis todos en el hacklab este del patio maravillas?
http://twitter.com/isaachacksimov

f.
This topic is locked and can not be replied to.