Mam trzy modele ActiveRecord: Partnerzy, MembershipChannel (który jest modelem STI, dziedziczenie z Kanału) i ChannelMembership (I nie był odpowiedzialny za nazywanie tych modeli ...)Dlaczego moje has_many przez skojarzony rekord (czasami) tylko do odczytu?
Kiedy załadować ChannelMembership przez stowarzyszenia Partner, ja czasem (!) kończy się na zapisie tylko do odczytu. To jest w Railsach 3.0.9. Ten sam kod nie zachowywał się w ten sposób w 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
Dlaczego readonly?
prawdziwe, gdy first
nazywa sprawie stowarzyszenia, ale nie w związku z limit
?
Rozumiem, że readonly
jest wyzwalane, jeśli używam fragmentów SQL podczas znajdowania rekordu, ale tak nie jest w tym przypadku. Jest to tylko zwykła kombinacja. Jedyną komplikacją jest to, że dołącza się do modelu STI. Co więcej, patrząc na wygenerowany SQL z dwóch ostatnich przykładów, są one identyczne!
Mogę uzyskać pożądane zachowanie, określając :readonly => false
na skojarzenie, ale chcę zrozumieć, co się dzieje.
Brak domyślnych zakresów w kanale, MembershipChannel lub ChannelMembership. Oto deklaracja stowarzyszenie na Partner:
class Partner
has_many :membership_channels
has_many :channel_memberships, :through => :membership_channels
end
Oto generowane SQL z moich logów:
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
Tak, myślę, że byłby to dobry czas dla mnie, aby przeglądać AR i AREL. W każdym razie chciałbym się nauczyć, jak znaleźć drogę wokół źródła szyn. –