{"action":"created","issue":{"url":"https://api.github.com/repos/rails/rails/issues/26111","repository_url":"https://api.github.com/repos/rails/rails","labels_url":"https://api.github.com/repos/rails/rails/issues/26111/labels{/name}","comments_url":"https://api.github.com/repos/rails/rails/issues/26111/comments","events_url":"https://api.github.com/repos/rails/rails/issues/26111/events","html_url":"https://github.com/rails/rails/issues/26111","id":170533700,"number":26111,"title":"has_many with scope, dependent and foreign_key needs better documentation","user":{"login":"claudiob","id":10076,"avatar_url":"https://avatars.githubusercontent.com/u/10076?v=3","gravatar_id":"","url":"https://api.github.com/users/claudiob","html_url":"https://github.com/claudiob","followers_url":"https://api.github.com/users/claudiob/followers","following_url":"https://api.github.com/users/claudiob/following{/other_user}","gists_url":"https://api.github.com/users/claudiob/gists{/gist_id}","starred_url":"https://api.github.com/users/claudiob/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/claudiob/subscriptions","organizations_url":"https://api.github.com/users/claudiob/orgs","repos_url":"https://api.github.com/users/claudiob/repos","events_url":"https://api.github.com/users/claudiob/events{/privacy}","received_events_url":"https://api.github.com/users/claudiob/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/rails/rails/labels/activerecord","name":"activerecord","color":"0b02e1"},{"url":"https://api.github.com/repos/rails/rails/labels/docs","name":"docs","color":"02d7e1"},{"url":"https://api.github.com/repos/rails/rails/labels/needs%20feedback","name":"needs feedback","color":"ededed"}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2016-08-10T22:27:01Z","updated_at":"2016-08-16T09:21:52Z","closed_at":null,"body":"I found an _unexpected_ behavior in [has_many](http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many) that I illustrated with a [failing test in a gist](https://gist.github.com/claudiob/545fa683615bbc7cb6d8ddc99c4306c1).\r\n\r\nThe short version is the following. If you have these two models:\r\n\r\n```ruby\r\nclass Post < ActiveRecord::Base\r\n  has_many :comments, -> { where('text is not null') }, dependent: :destroy\r\nend\r\n\r\nclass Comment < ActiveRecord::Base\r\nend\r\n```\r\n\r\nand you call `destroy` on a post, then not all the comments of the post will be destroyed, but only the comments that match the scope  `where('text is not null')`.\r\n\r\nSome people might argue that this is the _expected_ behavior, since the Rails [documentation of has_many](http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_and_belongs_to_many-label-Scopes) states:\r\n\r\n> You can pass a second argument scope as a callable (i.e. proc or lambda) to retrieve a specific set of records or customize the generated query when you access the associated collection.\r\n\r\nThe problem is that, if `post.destroy` does not delete *all* the comments of post, then some comments might be left in the database without a corresponding post. \r\n\r\nEven worse, if you declared a foreign key between the `comments` table and the `posts` table (which is the common case for references), then you can end up with the following error, which is the result of running the referenced [gist]((https://gist.github.com/claudiob/545fa683615bbc7cb6d8ddc99c4306c1)):\r\n\r\n```sh\r\n# Comment Load (0.2ms)  SELECT \"comments\".* FROM \"comments\" WHERE \"comments\".\"post_id\" = $1 AND (text is not null)  [[\"post_id\", 1]]\r\n# SQL (0.1ms)  DELETE FROM \"comments\" WHERE \"comments\".\"id\" = $1  [[\"id\", 2]]\r\n# SQL (0.6ms)  DELETE FROM \"posts\" WHERE \"posts\".\"id\" = $1  [[\"id\", 1]]\r\n# (0.1ms)  ROLLBACK\r\n\r\nActiveRecord::InvalidForeignKey: PG::ForeignKeyViolation: ERROR:  \r\nupdate or delete on table \"posts\" violates foreign key constraint \"fk_rails_2fd19c0db7\" on table \"comments\"\r\nDETAIL:  Key (id)=(1) is still referenced from table \"comments\".\r\n: DELETE FROM \"posts\" WHERE \"posts\".\"id\" = $1\r\n```\r\n\r\nWhat do you think? Should the documentation be a little more verbose in this case?"},"comment":{"url":"https://api.github.com/repos/rails/rails/issues/comments/240050430","html_url":"https://github.com/rails/rails/issues/26111#issuecomment-240050430","issue_url":"https://api.github.com/repos/rails/rails/issues/26111","id":240050430,"user":{"login":"rafaelfranca","id":47848,"avatar_url":"https://avatars.githubusercontent.com/u/47848?v=3","gravatar_id":"","url":"https://api.github.com/users/rafaelfranca","html_url":"https://github.com/rafaelfranca","followers_url":"https://api.github.com/users/rafaelfranca/followers","following_url":"https://api.github.com/users/rafaelfranca/following{/other_user}","gists_url":"https://api.github.com/users/rafaelfranca/gists{/gist_id}","starred_url":"https://api.github.com/users/rafaelfranca/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rafaelfranca/subscriptions","organizations_url":"https://api.github.com/users/rafaelfranca/orgs","repos_url":"https://api.github.com/users/rafaelfranca/repos","events_url":"https://api.github.com/users/rafaelfranca/events{/privacy}","received_events_url":"https://api.github.com/users/rafaelfranca/received_events","type":"User","site_admin":false},"created_at":"2016-08-16T09:21:52Z","updated_at":"2016-08-16T09:21:52Z","body":"> What do you think? Should the documentation be a little more verbose in this case?\r\n\r\nYes, I agree we should have more verbose documentation about this case."}}
{"actor":{"display_login":"rafaelfranca"}}