{"action":"created","issue":{"url":"https://api.github.com/repos/rails/rails/issues/31395","repository_url":"https://api.github.com/repos/rails/rails","labels_url":"https://api.github.com/repos/rails/rails/issues/31395/labels{/name}","comments_url":"https://api.github.com/repos/rails/rails/issues/31395/comments","events_url":"https://api.github.com/repos/rails/rails/issues/31395/events","html_url":"https://github.com/rails/rails/issues/31395","id":280935969,"number":31395,"title":"Anonymous ActiveRecord classes leak memory","user":{"login":"ebeigarts","id":8155,"avatar_url":"https://avatars3.githubusercontent.com/u/8155?v=4","gravatar_id":"","url":"https://api.github.com/users/ebeigarts","html_url":"https://github.com/ebeigarts","followers_url":"https://api.github.com/users/ebeigarts/followers","following_url":"https://api.github.com/users/ebeigarts/following{/other_user}","gists_url":"https://api.github.com/users/ebeigarts/gists{/gist_id}","starred_url":"https://api.github.com/users/ebeigarts/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ebeigarts/subscriptions","organizations_url":"https://api.github.com/users/ebeigarts/orgs","repos_url":"https://api.github.com/users/ebeigarts/repos","events_url":"https://api.github.com/users/ebeigarts/events{/privacy}","received_events_url":"https://api.github.com/users/ebeigarts/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":5,"created_at":"2017-12-11T08:45:39Z","updated_at":"2017-12-13T08:51:11Z","closed_at":null,"author_association":"CONTRIBUTOR","body":"Anonymous ActiveRecord classes (`Class.new(ActiveRecord::Base)`) are not garbage collected.\r\n\r\n```\r\nrails c\r\nLoading development environment (Rails 5.1.4)\r\n[1] pry(main)> nil; 1000.times { Class.new(ActiveRecord::Base) }; GC.start(full_mark: true); ActiveRecord::Base.descendants.size\r\n1003\r\n[2] pry(main)> nil; 1000.times { Class.new(ActiveRecord::Base) }; GC.start(full_mark: true); ActiveRecord::Base.descendants.size\r\n2003\r\n[3] pry(main)> nil; 1000.times { Class.new(ActiveRecord::Base) }; GC.start(full_mark: true); ActiveRecord::Base.descendants.size\r\n3003\r\n```\r\n\r\nI have now discovered that anonymous classes are not supported #9002, but I can still create those classes without calling `establish_connection` on the child class.\r\n\r\n```\r\n> k = Class.new(ActiveRecord::Base); k.table_name = \"users\"; k.count\r\n(1.0ms)  SELECT COUNT(*) FROM \"users\"\r\n3216\r\n```\r\n\r\nA lot of rails test cases use anonymous classes, and this is the place I have learned to use them.\r\n\r\n```\r\ncd rails\r\nack 'Class.new\\(ActiveRecord::Base\\)' | wc -l\r\n     125\r\n```\r\n\r\nSuggestions:\r\n\r\n1. Do not use anonymous AR classes in rails test suite to avoid people learning to use them.\r\n2. Raise exceptions when executing queries on anonymous classes, not just `establish_connection`.\r\n3. Document this somewhere in the guides.\r\n\r\nOr maybe we can fix the leak? Maybe someone already knows the place where it leaks?\r\n"},"comment":{"url":"https://api.github.com/repos/rails/rails/issues/comments/351324348","html_url":"https://github.com/rails/rails/issues/31395#issuecomment-351324348","issue_url":"https://api.github.com/repos/rails/rails/issues/31395","id":351324348,"user":{"login":"ebeigarts","id":8155,"avatar_url":"https://avatars3.githubusercontent.com/u/8155?v=4","gravatar_id":"","url":"https://api.github.com/users/ebeigarts","html_url":"https://github.com/ebeigarts","followers_url":"https://api.github.com/users/ebeigarts/followers","following_url":"https://api.github.com/users/ebeigarts/following{/other_user}","gists_url":"https://api.github.com/users/ebeigarts/gists{/gist_id}","starred_url":"https://api.github.com/users/ebeigarts/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ebeigarts/subscriptions","organizations_url":"https://api.github.com/users/ebeigarts/orgs","repos_url":"https://api.github.com/users/ebeigarts/repos","events_url":"https://api.github.com/users/ebeigarts/events{/privacy}","received_events_url":"https://api.github.com/users/ebeigarts/received_events","type":"User","site_admin":false},"created_at":"2017-12-13T08:51:11Z","updated_at":"2017-12-13T08:51:11Z","author_association":"CONTRIBUTOR","body":"> That seems to be the course of action but that doesn't prevents you to create anonymous > classes and do not do any queries. So, I'd define a inherited hook in ActiveRecord::Base and raise an exception when inheriting without name. But that will only cause a source of memory leak since any class that extend DecendentTracker will have this problem.\r\n\r\nWouldn't it be better then to modify `DescendantsTracker#inherited`?\r\n\r\n```diff\r\n  module ActiveSupport\r\n    module DescendantsTracker\r\n      def inherited(base)\r\n+      warn \"Tracking descendants for anonymous classes can cause memory leaks\" unless name\r\n       DescendantsTracker.store_inherited(self, base)\r\n       super\r\n     end\r\n  end\r\n```\r\n\r\nMaybe it would be better to just skip tracking for anonymous classes? Because anonymous classes is a nice ruby feature and I would like to use them also for AR classes.\r\n\r\n```diff\r\n  module ActiveSupport\r\n    module DescendantsTracker\r\n      def inherited(base)\r\n-      DescendantsTracker.store_inherited(self, base)\r\n+      DescendantsTracker.store_inherited(self, base) if name\r\n       super\r\n     end\r\n  end\r\n```"}}
{"actor":{"display_login":"ebeigarts"}}