2011-08-19 19 views
5

tengo tres modelos ActiveRecord: Socio, MembershipChannel (que es un modelo STI, heredando de Canal) y ChannelMembership (yo no era responsable de nombrar estos modelos ...)¿Por qué mi has_many a través de un registro asociado (a veces) de solo lectura?

Cuando cargo un ChannelMembership través de la asociación de socios, que a veces (!) terminan con un registro de solo lectura. Esto está en Rails 3.0.9. El mismo código no se comportó de esta manera en 2.3.11.

> p = Partner.first 
> p.channel_memberships.map(&:readonly?) 
# => [false, false, false, false, false, false] 
> p.reload.channel_memberships.limit(1).first.readonly? 
# => false 
> p.reload.channel_memberships.first.readonly? 
# => true 

¿Por qué es readonly? cierto cuando first se llama en la asociación, pero no en la relación de limit?

Entiendo que readonly se activa si utilizo fragmentos de SQL para encontrar un registro, pero este no es el caso aquí. Es simplemente una simple has_many a través de la asociación. La única complicación es que se une a un modelo de STI. Además, mirando el SQL generado de los dos últimos ejemplos, ¡son idénticos!

Puedo obtener el comportamiento que deseo especificando :readonly => false en la asociación, pero quiero entender qué está pasando.

No hay ámbitos predeterminados en Channel, MembershipChannel o ChannelMembership. Aquí está la declaración de asociación sobre el Partner:

class Partner 
    has_many :membership_channels 
    has_many :channel_memberships, :through => :membership_channels 
end 

Aquí está el código SQL generado a partir de los registros de mi:

Partner Load (0.4ms) SELECT "partners".* FROM "partners" LIMIT 1 
    ChannelMembership Load (0.7ms) SELECT "channel_memberships".* FROM "channel_memberships" INNER JOIN "channels" ON "channel_memberships".channel_id = "channels".id WHERE (("channels".partner_id = 2) AND (("channels"."type" = 'MembershipChannel'))) 
    Partner Load (0.5ms) SELECT "partners".* FROM "partners" WHERE "partners"."id" = 2 LIMIT 1 
    ChannelMembership Load (1.0ms) SELECT "channel_memberships".* FROM "channel_memberships" INNER JOIN "channels" ON "channel_memberships".channel_id = "channels".id WHERE (("channels".partner_id = 2) AND (("channels"."type" = 'MembershipChannel'))) LIMIT 1 
    Partner Load (0.4ms) SELECT "partners".* FROM "partners" WHERE "partners"."id" = 2 LIMIT 1 
    ChannelMembership Load (0.6ms) SELECT "channel_memberships".* FROM "channel_memberships" INNER JOIN "channels" ON "channel_memberships".channel_id = "channels".id WHERE (("channels".partner_id = 2) AND (("channels"."type" = 'MembershipChannel'))) LIMIT 1 

Respuesta

2

yo era capaz de reproducir su problema a través de un has_many básica: a través de la asociación y estoy también en cuanto a lo que lo está causando

Por lo que puedo decir, solo ocurre cuando se invoca el método de recarga en el objeto original. No estoy seguro de si esto se debe a algo que la recarga está haciendo específicamente, o quizás porque ciertos indicadores de atributos se están restableciendo.

Mi segunda teoría es que tiene algo que ver con el hecho de que

p.reload.channel_memberships.limit(1) 

devuelve un ActiveRecord :: Relation través de la cual se obtiene su primera ChannelMembership y

p.reload.channel_memberships.first 

lo carga directamente de la asociación. Tal vez alguna combinación de recarga reiniciar ciertos elementos almacenados en caché (no conozco la fuente AR) está marcando la asociación como de solo lectura. Cuando aplica el alcance del límite (1), puede restablecerlos en una nueva relación y funcionar como era de esperar.

Me gustaría hojear ActiveRecord :: Persistence/Associations un poco más para la respuesta completa.

+0

Sí, creo que este sería un buen momento para hurgar en AR y AREL. He querido aprender cómo orientarme por la fuente de los raíles, de todos modos. –

Cuestiones relacionadas