{"action":"created","issue":{"url":"https://api.github.com/repos/flyerhzm/bullet/issues/302","repository_url":"https://api.github.com/repos/flyerhzm/bullet","labels_url":"https://api.github.com/repos/flyerhzm/bullet/issues/302/labels{/name}","comments_url":"https://api.github.com/repos/flyerhzm/bullet/issues/302/comments","events_url":"https://api.github.com/repos/flyerhzm/bullet/issues/302/events","html_url":"https://github.com/flyerhzm/bullet/issues/302","id":169152385,"number":302,"title":"Misrepresented ActiveRecord::Associations::CollectionProxy when Bullet is enabled","user":{"login":"danielmackey","id":15375,"avatar_url":"https://avatars.githubusercontent.com/u/15375?v=3","gravatar_id":"","url":"https://api.github.com/users/danielmackey","html_url":"https://github.com/danielmackey","followers_url":"https://api.github.com/users/danielmackey/followers","following_url":"https://api.github.com/users/danielmackey/following{/other_user}","gists_url":"https://api.github.com/users/danielmackey/gists{/gist_id}","starred_url":"https://api.github.com/users/danielmackey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/danielmackey/subscriptions","organizations_url":"https://api.github.com/users/danielmackey/orgs","repos_url":"https://api.github.com/users/danielmackey/repos","events_url":"https://api.github.com/users/danielmackey/events{/privacy}","received_events_url":"https://api.github.com/users/danielmackey/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":1,"created_at":"2016-08-03T14:56:23Z","updated_at":"2016-08-03T15:17:49Z","closed_at":null,"body":"After upgrading to Bullet v5.2.0 (with a Rails 5.0.0 app) and had some regressions with some associations that I'm not really sure how to describe, so I made an app/repo to demonstrate it (https://github.com/danielmackey/bullet-bug-has-many-through)\r\n\r\n# tl;dr\r\nin Bullet v5.2.0, some collection proxies are returned as \r\n```\r\n<Contact::ActiveRecord_Associations_CollectionProxy:0x007ffb59702388>\r\n``` \r\ninstead of \r\n\r\n```\r\n#<ActiveRecord::Associations::CollectionProxy [#<Contact id: ... >]>\r\n```\r\nthus making enumeration methods break. \r\n\r\n\r\n## Problem\r\nIt appears to be a regression between Bullet v5.1.1 and v5.2.0 ([see the diff](https://github.com/flyerhzm/bullet/compare/5.1.1...5.2.0)), as rolling back to the previous 5.1.1 version works.\r\n\r\nGiven the following models/associations\r\n```rb\r\nclass Group < ApplicationRecord\r\n  has_many :memberships\r\n  has_many :people, through: :memberships\r\nend\r\n\r\nclass Person < ApplicationRecord\r\n  has_many :memberships\r\n  has_many :groups, through: :memberships\r\n\r\n  has_many :contacts\r\nend\r\n\r\nclass Contact < ApplicationRecord\r\n  belongs_to :person\r\nend\r\n\r\nclass Membership < ApplicationRecord\r\n  belongs_to :person\r\n  belongs_to :group\r\n\r\n  has_many :contacts, through: :person\r\nend\r\n```\r\n\r\nWhen viewing a `@membership.contacts` in a view, the collection proxy is returned as `#<Contact::ActiveRecord_Associations_CollectionProxy:0x007ffb59702388>`, as opposed to a `#<ActiveRecord::Associations::CollectionProxy [#<Contact id: ... >]>` (as debugged via rails console). The bug this causes it the inability to run any enumerable methods like `#each` on the collection proxy.\r\n\r\n**in view w/ byebug**\r\n```rb\r\n(byebug) @membership\r\n#<Membership id: 1, person_id: 1, group_id: 1, created_at: \"2016-08-03 13:37:25\", updated_at: \"2016-08-03 13:37:25\">\r\n(byebug) @membership.contacts\r\n#<Contact::ActiveRecord_Associations_CollectionProxy:0x007ffb59702388>\r\n(byebug) @membership.contacts.count\r\n  CACHE (0.0ms)  SELECT COUNT(*) FROM \"contacts\" INNER JOIN \"people\" ON \"contacts\".\"person_id\" = \"people\".\"id\" WHERE \"people\".\"id\" = ?  [[\"id\", 1]]\r\n2\r\n(byebug) @membership.contacts.to_sql\r\n\"SELECT \\\"contacts\\\".* FROM \\\"contacts\\\" INNER JOIN \\\"people\\\" ON \\\"contacts\\\".\\\"person_id\\\" = \\\"people\\\".\\\"id\\\" WHERE \\\"people\\\".\\\"id\\\" = 1\"\r\n(byebug) @membership.contacts.map(&:value)\r\n*** NoMethodError Exception: undefined method `each' for #<Person:0x007ffb5ad58e98>\r\n\r\nnil\r\n```\r\n\r\n**in** `rails console`\r\n```rb\r\nirb(main):001:0> @membership = Membership.find(1)\r\n  Membership Load (0.2ms)  SELECT  \"memberships\".* FROM \"memberships\" WHERE \"memberships\".\"id\" = ? LIMIT ?  [[\"id\", 1], [\"LIMIT\", 1]]\r\n=> #<Membership id: 1, person_id: 1, group_id: 1, created_at: \"2016-08-03 13:37:25\", updated_at: \"2016-08-03 13:37:25\">\r\nirb(main):002:0> @membership.contacts\r\n  Contact Load (0.1ms)  SELECT \"contacts\".* FROM \"contacts\" INNER JOIN \"people\" ON \"contacts\".\"person_id\" = \"people\".\"id\" WHERE \"people\".\"id\" = ?  [[\"id\", 1]]\r\n=> #<ActiveRecord::Associations::CollectionProxy [#<Contact id: 1, value: \"john@acme.co\", person_id: 1, created_at: \"2016-08-03 13:37:25\", updated_at: \"2016-08-03 13:37:25\">, #<Contact id: 2, value: \"john.doe@acme.co\", person_id: 1, created_at: \"2016-08-03 13:37:25\", updated_at: \"2016-08-03 13:37:25\">]>\r\nirb(main):003:0> @membership.contacts.count\r\n   (0.2ms)  SELECT COUNT(*) FROM \"contacts\" INNER JOIN \"people\" ON \"contacts\".\"person_id\" = \"people\".\"id\" WHERE \"people\".\"id\" = ?  [[\"id\", 1]]\r\n=> 2\r\nirb(main):004:0> @membership.contacts.to_sql\r\n=> \"SELECT \\\"contacts\\\".* FROM \\\"contacts\\\" INNER JOIN \\\"people\\\" ON \\\"contacts\\\".\\\"person_id\\\" = \\\"people\\\".\\\"id\\\" WHERE \\\"people\\\".\\\"id\\\" = 1\"\r\nirb(main):005:0> @membership.contacts.map(&:value)\r\n=> [\"john@acme.co\", \"john.doe@acme.co\"]\r\n```\r\n\r\n## Setup\r\n```\r\ngit clone https://github.com/danielmackey/bullet-bug-has-many-through.git\r\ncd bullet-bug-has-many-through\r\nbin/setup\r\nrails server\r\n```\r\n\r\nThen navigate to http://localhost:3000/groups/1 and click on the link to view John/Jane Doe [with](http://localhost:3000/groups/1/memberships/1) and [without](http://localhost:3000/groups/1/memberships/1?skip_bullet=true) Bullet enabled. When Bullet is disabled (the w/o version), the collection proxy behaves normally, but when enabled, generates an error. If you add a `byebug` to `app/views/memberships/show.html.erb:6`, you can play along in the terminal to see the behavior documented above."},"comment":{"url":"https://api.github.com/repos/flyerhzm/bullet/issues/comments/237269172","html_url":"https://github.com/flyerhzm/bullet/issues/302#issuecomment-237269172","issue_url":"https://api.github.com/repos/flyerhzm/bullet/issues/302","id":237269172,"user":{"login":"danielmackey","id":15375,"avatar_url":"https://avatars.githubusercontent.com/u/15375?v=3","gravatar_id":"","url":"https://api.github.com/users/danielmackey","html_url":"https://github.com/danielmackey","followers_url":"https://api.github.com/users/danielmackey/followers","following_url":"https://api.github.com/users/danielmackey/following{/other_user}","gists_url":"https://api.github.com/users/danielmackey/gists{/gist_id}","starred_url":"https://api.github.com/users/danielmackey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/danielmackey/subscriptions","organizations_url":"https://api.github.com/users/danielmackey/orgs","repos_url":"https://api.github.com/users/danielmackey/repos","events_url":"https://api.github.com/users/danielmackey/events{/privacy}","received_events_url":"https://api.github.com/users/danielmackey/received_events","type":"User","site_admin":false},"created_at":"2016-08-03T15:17:49Z","updated_at":"2016-08-03T15:17:49Z","body":"As I mention in [this commit](https://github.com/danielmackey/bullet-bug-has-many-through/commit/95db1c456d79161a98566613e8391ae2deaa79a8), the `has_many :through` on `Membership` seems to be the case that breaks, maybe because its the 'join' model of what would be a `HABTM`. In the actual use production use case, this model has other functionality and data hung on it, so going to a straight SQL join table doesn't make sense. Other `has_many :through` cases (`Group#group_contacts`, for example) don't produce this error."}}
{"actor":{"display_login":"danielmackey"}}