{"action":"created","issue":{"url":"https://api.github.com/repos/rails/rails/issues/26122","repository_url":"https://api.github.com/repos/rails/rails","labels_url":"https://api.github.com/repos/rails/rails/issues/26122/labels{/name}","comments_url":"https://api.github.com/repos/rails/rails/issues/26122/comments","events_url":"https://api.github.com/repos/rails/rails/issues/26122/events","html_url":"https://github.com/rails/rails/issues/26122","id":170672165,"number":26122,"title":"Rails 5 ActiveRecord::Attribute stack level too deep error on save","user":{"login":"johnathanludwig","id":1262078,"avatar_url":"https://avatars.githubusercontent.com/u/1262078?v=3","gravatar_id":"","url":"https://api.github.com/users/johnathanludwig","html_url":"https://github.com/johnathanludwig","followers_url":"https://api.github.com/users/johnathanludwig/followers","following_url":"https://api.github.com/users/johnathanludwig/following{/other_user}","gists_url":"https://api.github.com/users/johnathanludwig/gists{/gist_id}","starred_url":"https://api.github.com/users/johnathanludwig/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/johnathanludwig/subscriptions","organizations_url":"https://api.github.com/users/johnathanludwig/orgs","repos_url":"https://api.github.com/users/johnathanludwig/repos","events_url":"https://api.github.com/users/johnathanludwig/events{/privacy}","received_events_url":"https://api.github.com/users/johnathanludwig/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/needs%20feedback","name":"needs feedback","color":"ededed"}],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":2,"created_at":"2016-08-11T15:19:07Z","updated_at":"2016-08-14T20:17:04Z","closed_at":"2016-08-14T20:17:04Z","body":"If you make a _lot_ of assignments to an ActiveRecord object, you will get a a `SystemStackError` during save. In our case we are calculating some stats on reports we generate by incrementing various counters. In some cases we have large reports where one field could be incremented more than 10k times.\r\n\r\n### Steps to reproduce\r\n1. Make an assignment on the same attribute of an object at least 10,050 times.\r\n2. Attempt to save the object.\r\n\r\n### Expected behavior\r\nThe object should be saved.\r\n\r\n### Actual behavior\r\nA stack level too deep error is raised. Here is the trace:\r\n\r\n```\r\nSystemStackError: stack level too deep\r\nactiverecord-5.0.0/lib/active_record/attribute.rb:44:in `original_value'\r\nactiverecord-5.0.0/lib/active_record/attribute.rb:44:in `original_value'\r\n... 10027 levels...\r\nactiverecord-5.0.0/lib/active_record/attribute.rb:44:in `original_value'\r\nactiverecord-5.0.0/lib/active_record/attribute.rb:123:in `changed_from_assignment?'\r\nactiverecord-5.0.0/lib/active_record/attribute.rb:55:in `changed?'\r\nactiverecord-5.0.0/lib/active_record/attribute_mutation_tracker.rb:25:in `changed?'\r\nactiverecord-5.0.0/lib/active_record/attribute_mutation_tracker.rb:9:in `block in changed_values'\r\nactiverecord-5.0.0/lib/active_record/attribute_mutation_tracker.rb:8:in `each'\r\nactiverecord-5.0.0/lib/active_record/attribute_mutation_tracker.rb:8:in `each_with_object'\r\nactiverecord-5.0.0/lib/active_record/attribute_mutation_tracker.rb:8:in `changed_values'\r\nactiverecord-5.0.0/lib/active_record/attribute_methods/dirty.rb:83:in `changed_attributes'\r\nactivemodel-5.0.0/lib/active_model/dirty.rb:146:in `changed'\r\nactiverecord-5.0.0/lib/active_record/attribute_methods/dirty.rb:127:in `keys_for_partial_write'\r\nactiverecord-5.0.0/lib/active_record/attribute_methods/dirty.rb:123:in `_create_record'\r\nactiverecord-5.0.0/lib/active_record/callbacks.rb:302:in `block in _create_record'\r\nactivesupport-5.0.0/lib/active_support/callbacks.rb:126:in `call'\r\nactivesupport-5.0.0/lib/active_support/callbacks.rb:126:in `call'\r\nactivesupport-5.0.0/lib/active_support/callbacks.rb:506:in `block (2 levels) in compile'\r\nactivesupport-5.0.0/lib/active_support/callbacks.rb:455:in `call'\r\nactivesupport-5.0.0/lib/active_support/callbacks.rb:455:in `call'\r\nactivesupport-5.0.0/lib/active_support/callbacks.rb:101:in `__run_callbacks__'\r\nactivesupport-5.0.0/lib/active_support/callbacks.rb:750:in `_run_create_callbacks'\r\nactiverecord-5.0.0/lib/active_record/callbacks.rb:302:in `_create_record'\r\nactiverecord-5.0.0/lib/active_record/timestamp.rb:68:in `_create_record'\r\nactiverecord-5.0.0/lib/active_record/persistence.rb:534:in `create_or_update'\r\nactiverecord-5.0.0/lib/active_record/callbacks.rb:298:in `block in create_or_update'\r\nactivesupport-5.0.0/lib/active_support/callbacks.rb:126:in `call'\r\nactivesupport-5.0.0/lib/active_support/callbacks.rb:126:in `call'\r\nactivesupport-5.0.0/lib/active_support/callbacks.rb:506:in `block (2 levels) in compile'\r\nactivesupport-5.0.0/lib/active_support/callbacks.rb:455:in `call'\r\nactivesupport-5.0.0/lib/active_support/callbacks.rb:455:in `call'\r\nactivesupport-5.0.0/lib/active_support/callbacks.rb:101:in `__run_callbacks__'\r\nactivesupport-5.0.0/lib/active_support/callbacks.rb:750:in `_run_save_callbacks'\r\nactiverecord-5.0.0/lib/active_record/callbacks.rb:298:in `create_or_update'\r\nactiverecord-5.0.0/lib/active_record/persistence.rb:125:in `save'\r\nactiverecord-5.0.0/lib/active_record/validations.rb:44:in `save'\r\nactiverecord-5.0.0/lib/active_record/attribute_methods/dirty.rb:22:in `save'\r\nactiverecord-5.0.0/lib/active_record/transactions.rb:319:in `block (2 levels) in save'\r\nactiverecord-5.0.0/lib/active_record/transactions.rb:395:in `block in with_transaction_returning_status'\r\nactiverecord-5.0.0/lib/active_record/connection_adapters/abstract/database_statements.rb:232:in `block in transaction'\r\nactiverecord-5.0.0/lib/active_record/connection_adapters/abstract/transaction.rb:189:in `within_new_transaction'\r\nactiverecord-5.0.0/lib/active_record/connection_adapters/abstract/database_statements.rb:232:in `transaction'\r\nactiverecord-5.0.0/lib/active_record/transactions.rb:211:in `transaction'\r\nactiverecord-5.0.0/lib/active_record/transactions.rb:392:in `with_transaction_returning_status'\r\nactiverecord-5.0.0/lib/active_record/transactions.rb:319:in `block in save'\r\nactiverecord-5.0.0/lib/active_record/transactions.rb:334:in `rollback_active_record_state!'\r\nactiverecord-5.0.0/lib/active_record/transactions.rb:318:in `save'\r\nactiverecord-5.0.0/lib/active_record/suppressor.rb:41:in `save'\r\n```\r\n\r\n### System configuration\r\n**Rails version**: 5.0.0\r\n\r\n**Ruby version**: 2.4.4\r\n\r\n### Test Case\r\n```ruby\r\nbegin\r\n  require \"bundler/inline\"\r\nrescue LoadError => e\r\n  $stderr.puts \"Bundler version 1.10 or later is required. Please update your Bundler\"\r\n  raise e\r\nend\r\n\r\ngemfile(true) do\r\n  source \"https://rubygems.org\"\r\n  gem \"rails\", github: \"rails/rails\"\r\n  gem \"sqlite3\"\r\nend\r\n\r\nrequire \"active_record\"\r\nrequire \"minitest/autorun\"\r\nrequire \"logger\"\r\n\r\n# This connection will do for database-independent bug reports.\r\nActiveRecord::Base.establish_connection(adapter: \"sqlite3\", database: \":memory:\")\r\nActiveRecord::Base.logger = Logger.new(STDOUT)\r\n\r\nActiveRecord::Schema.define do\r\n  create_table :stats, force: true do |t|\r\n    t.integer :count, default: 0\r\n  end\r\nend\r\n\r\nclass Stat < ActiveRecord::Base\r\nend\r\n\r\nclass BugTest < Minitest::Test\r\n  def test_association_stuff\r\n    stat = Stat.new\r\n\r\n    10_050.times { stat.count += 1 }\r\n\r\n    assert stat.save\r\n  end\r\nend\r\n```"},"comment":{"url":"https://api.github.com/repos/rails/rails/issues/comments/239694345","html_url":"https://github.com/rails/rails/issues/26122#issuecomment-239694345","issue_url":"https://api.github.com/repos/rails/rails/issues/26122","id":239694345,"user":{"login":"sgrif","id":1529387,"avatar_url":"https://avatars.githubusercontent.com/u/1529387?v=3","gravatar_id":"","url":"https://api.github.com/users/sgrif","html_url":"https://github.com/sgrif","followers_url":"https://api.github.com/users/sgrif/followers","following_url":"https://api.github.com/users/sgrif/following{/other_user}","gists_url":"https://api.github.com/users/sgrif/gists{/gist_id}","starred_url":"https://api.github.com/users/sgrif/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sgrif/subscriptions","organizations_url":"https://api.github.com/users/sgrif/orgs","repos_url":"https://api.github.com/users/sgrif/repos","events_url":"https://api.github.com/users/sgrif/events{/privacy}","received_events_url":"https://api.github.com/users/sgrif/received_events","type":"User","site_admin":false},"created_at":"2016-08-14T20:17:04Z","updated_at":"2016-08-14T20:17:04Z","body":"So yes. This is a legitimate consequence of the current implementation. That said, I'm reasonably comfortable just saying: Don't assign the same attribute 10000+ times."}}
{"actor":{"display_login":"sgrif"}}