Rails 2.3.2ã§ããã¯ã®æåãå¤ãã£ã¦ãã
ãRuby on Rails 2.3.2ããªãªã¼ã¹ãããã®ã§ããã£ããã¤ã³ã¹ãã¼ã«ãã¾ãããèªåã®ä½ã£ã¦ããã¢ããªã±ã¼ã·ã§ã³ã§ãã¹ããå®è¡ãã¦ã¿ãã¨ã2.3.1ã®ã¨ãã«åºã¦ããªãã£ã"ActiveRecord::StaleObjectError: Attempted to delete a stale object"ã¨ããã¨ã©ã¼ãåºã¦ãã¾ããããã® ActiveRecord::StaleObjectError 㯠lock_version を使ったロック機能ã«ãããã®ã§ããããã¤ãã¯æ´æ°æã«èµ·ããã®ã«ãä»åã¯ã©ããã¬ã³ã¼ãã®åé¤æã«èµ·ãã¦ããããã§ããã¾ããã¨ã©ã¼ãåºãã¦ããã®ã¯ãããããã®ããã¯ã«å ãã¦ãé¢é£å ã®ã¢ãã«ã«å¯¾ã㦠counter_cache ã¨":dependent => :destroy"ã«ããé£éåé¤ãæå®ãã¦ããã¢ãã«ã®ããã§ãã
ãåå ã調ã¹ãããã«ãæ°ãã以ä¸ã®ãµãã¤ã®ã¢ãã«ãä½ãã¾ããããªããç°å¢ã¯ Mac OS X 10.5.6 㨠Ruby 1.8.7, ãã¼ã¿ãã¼ã¹ã«ã¯ SQLite ã使ã£ã¦ãã¾ãã
- app/models/user.rb
class User < ActiveRecord::Base has_many :blogs, :dependent => :destroy end
- app/models/blog.rb
class Blog < ActiveRecord::Base belongs_to :user, :counter_cache => true end
ãmigration ã¯ä»¥ä¸ã®ãããªå®ç¾©ã§ãã
class CreateUsers < ActiveRecord::Migration def self.up create_table :users do |t| t.string :name t.integer :lock_version, :default => 0 t.integer :blogs_count, :default => 0 t.timestamps end end def self.down drop_table :users end end class CreateBlogs < ActiveRecord::Migration def self.up create_table :blogs do |t| t.references :user t.string :title t.timestamps end end def self.down drop_table :blogs end end
ãmigration ãå®è¡ããå¾ãconsole ã§ã¬ã³ã¼ããæä½ãã¦ã¿ã¾ãã2.3.2ã ã¨ãããªãã¾ãã
mac:blog nabeta$ script/console Loading development environment (Rails 2.3.2) >> u = User.create(:name => 'nabeta') # Userãä½æãã => #<User id: 1, name: "nabeta", lock_version: 0, blogs_count: 0, created_at: "2009-03-16 15:09:40", updated_at: "2009-03-16 15:09:40"> >> u.blogs => [] >> u.blogs.create(:title => 'my blog') # Userã«é¢é£ã¥ããããBlogãä½æãã => #<Blog id: 1, user_id: 1, title: "my blog", created_at: "2009-03-16 15:10:00", updated_at: "2009-03-16 15:10:00"> >> u => #<User id: 1, name: "nabeta", lock_version: 0, blogs_count: 0, created_at: "2009-03-16 15:09:40", updated_at: "2009-03-16 15:09:40"> >> u.reload => #<User id: 1, name: "nabeta", lock_version: 1, blogs_count: 1, created_at: "2009-03-16 15:09:40", updated_at: "2009-03-16 15:09:40"> >> u.destroy # Userãåé¤ãããã¨ããã以ä¸ã®ã¨ãã失æãã ActiveRecord::StaleObjectError: Attempted to delete a stale object from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/locking/optimistic.rb:127:in `destroy_without_callbacks' from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/callbacks.rb:337:in `destroy_without_transactions' from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/transactions.rb:229:in `send' from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/transactions.rb:229:in `with_transaction_returning_status' from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/connection_adapters/abstract/database_statements.rb:136:in `transaction' from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/transactions.rb:182:in `transaction' from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/transactions.rb:228:in `with_transaction_returning_status' from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/transactions.rb:192:in `destroy' from (irb):6 >>
ãUser ãåé¤ãããã¨ããã¨ãåé¡ã® ActiveRecord::StaleObjectError ãçºçãã¾ãã2.3.1ã ã¨ãããªãã¾ãã
mac:blog nabeta$ script/console Loading development environment (Rails 2.3.1) >> u = User.create(:name => 'nabeta') # Userãä½æãã => #<User id: 1, name: "nabeta", lock_version: 0, blogs_count: 0, created_at: "2009-03-16 15:21:23", updated_at: "2009-03-16 15:21:23"> >> u.blogs => [] >> u.blogs.create(:title => 'my blog') # Userã«é¢é£ã¥ããããBlogãä½æãã => #<Blog id: 1, user_id: 1, title: "my blog", created_at: "2009-03-16 15:21:29", updated_at: "2009-03-16 15:21:29"> >> u => #<User id: 1, name: "nabeta", lock_version: 0, blogs_count: 0, created_at: "2009-03-16 15:21:23", updated_at: "2009-03-16 15:21:23"> >> u.reload => #<User id: 1, name: "nabeta", lock_version: 1, blogs_count: 1, created_at: "2009-03-16 15:21:23", updated_at: "2009-03-16 15:21:23"> >> u.destroy # Userãåé¤ãããã¨ããã以ä¸ã®ã¨ããæåãã => #<User id: 1, name: "nabeta", lock_version: 1, blogs_count: 1, created_at: "2009-03-16 15:21:23", updated_at: "2009-03-16 15:21:23"> >> u.blogs => [#<Blog id: 1, user_id: 1, title: "my blog", created_at: "2009-03-16 15:21:29", updated_at: "2009-03-16 15:21:29">] >> u.reload ActiveRecord::RecordNotFound: Couldn't find User with ID=1 from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.3.1/lib/active_record/base.rb:1595:in `find_one' from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.3.1/lib/active_record/base.rb:1578:in `find_from_ids' from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.3.1/lib/active_record/base.rb:616:in `find' from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.3.1/lib/active_record/base.rb:2695:in `reload_without_dirty' from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.3.1/lib/active_record/dirty.rb:94:in `reload_without_autosave_associations' from /opt/local/lib/ruby/gems/1.8/gems/activerecord-2.3.1/lib/active_record/autosave_association.rb:191:in `reload' from (irb):7 >> Blog.find(:all) => [] >>
ãUser ã¯ã¨ã©ã¼ãèµ·ãããã«åé¤ããã¦ãã¾ãã
ãããå°ã2.3.2ã®åä½ãã½ã¼ã¹ã³ã¼ãã調ã¹ã¦ã¿ãã¨ãæè¿ ActiveRecord でロックを扱っている部分に変更があったãã¨ããããã¾ãããã¾ããä¸è¨ã®ä¾ã§ã¯ counter_cache 㨠":dependent => :destroy"ã«ããé£éåé¤ã®ä¸¡æ¹ãæå®ãã¦ããã¨ãã« ActiveRecord::StaleObjectError ãçºçããã©ã¡ããçæ¹ã ãã§ã¯çºçããªããã¨ããããã¾ããã