Forum: Ruby on Rails acts_as_versioned with lock_version bug?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Krassimir T. (Guest)
on 2006-05-17 16:01
Hello.

The acts_as_versioned plugin works fine ... till the adjunction
of optimistic locking via the lock_version table column.

Here is the problem description:

Without optimistic locking things are fine:

    # ++++ The table creation migration ++++
    % cat db/migrate/001_create_tables.rb
    class CreateTables < ActiveRecord::Migration
      def self.up
        create_table :softwares, :force => true do |t|
          t.column :name, :string, :limit => 20, :null => false
          t.column :version, :integer, :default => 0, :null => false
        end
        Software.create_versioned_table
      end

      def self.down
        drop_table :softwares
        Software.drop_versioned_table
      end
    end

    % rake migrate
    (in /home/krassi/MyProjects/Rails/pl2)
    == CreateTables: migrating
====================================================
    -- create_table(:softwares, {:force=>true})
       -> 0.0218s
    == CreateTables: migrated (0.0589s)
===========================================

    # ++++ Using the versioned data ++++
    %  ./script/console
    Loading development environment.
    >> s = Software.create :name => "Initial name"
    => #<Software:0xb7b3c290 @new_record_before_save=true,
@errors=#<ActiveRecord::Errors:0xb7ae3ff0 @errors={},
@base=#<Software:0xb7b3c290 ...>>, @attributes={"name"=>"Initial name",
"id"=>1, "version"=>1}, @new_record=false, @changed_attributes=[]>
    >> s.version
    => 1
    >> s.save
    => true
    >> s.version
    => 2
    >> ############ WHY? THERE SHOULD BE ONLY ONE VERSION! ############
    ?>
    ?> >> s.reload
    => #<Software:0xb7b3c290 @new_record_before_save=false,
@errors=#<ActiveRecord::Errors:0xb7ae3ff0 @errors={},
@base=#<Software:0xb7b3c290 ...>>, @versions=nil,
@attributes={"name"=>"Initial name", "id"=>"1", "version"=>"2"},
@new_record=false, @changed_attributes=[]>
    >> s.version
    => 2
    >> s.name = "Changed name"
    => "Changed name"
    >> s.version
    => 2
    >> s.save
    => true
    >> s.version
    => 3
    >> s.versions
    => [#<Software::Version:0xb7a8d290 @attributes={"name"=>"Initial
name", "updated_at"=>"2006-05-16 21:25:28", "software_id"=>"1",
"id"=>"1", "version"=>"1"}>, #<Software::Version:0xb7a8d240
@attributes={"name"=>"Initial name", "updated_at"=>"2006-05-16
21:25:33", "software_id"=>"1", "id"=>"2", "version"=>"2"}>,
#<Software::Version:0xb7a8d13c @attributes={"name"=>"Changed name",
"updated_at"=>"2006-05-16 21:26:10", "software_id"=>"1", "id"=>"3",
"version"=>"3"}>]
    >> s.name = "Name changed again"
    => "Name changed again"
    >> s.save
    => true
    >> s.version
    => 4
    >> s.versions
    => [#<Software::Version:0xb7a8d290 @attributes={"name"=>"Initial
name", "updated_at"=>"2006-05-16 21:25:28", "software_id"=>"1",
"id"=>"1", "version"=>"1"}>, #<Software::Version:0xb7a8d240
@attributes={"name"=>"Initial name", "updated_at"=>"2006-05-16
21:25:33", "software_id"=>"1", "id"=>"2", "version"=>"2"}>,
#<Software::Version:0xb7a8d13c @attributes={"name"=>"Changed name",
"updated_at"=>"2006-05-16 21:26:10", "software_id"=>"1", "id"=>"3",
"version"=>"3"}>]
    >>

A question: is it normal for the first save without optimistic
locking to generate two object versions?

    % ++++ And the database content ++++
    mysql> select * from softwares; select * from software_versions;
    +----+--------------------+---------+
    | id | name               | version |
    +----+--------------------+---------+
    |  1 | Name changed again |       4 |
    +----+--------------------+---------+
    1 row in set (0.00 sec)

    +----+-------------+---------+--------------------+---------------------+
    | id | software_id | version | name               | updated_at
|
    +----+-------------+---------+--------------------+---------------------+
    |  1 |           1 |       1 | Initial name       | 2006-05-16
21:25:28 |
    |  2 |           1 |       2 | Initial name       | 2006-05-16
21:25:33 |
    |  3 |           1 |       3 | Changed name       | 2006-05-16
21:26:10 |
    |  4 |           1 |       4 | Name changed again | 2006-05-16
21:26:22 |
    +----+-------------+---------+--------------------+---------------------+
    4 rows in set (0.00 sec)

And now the same thing with optimistic locking:

    # ++++ The table creation migration ++++
    % rake migrate VERSION=0
    (in /home/krassi/MyProjects/Rails/pl2)
    == CreateTables: reverting
====================================================
    -- drop_table(:softwares)
       -> 0.0230s
    == CreateTables: reverted (0.0308s)
===========================================

    %  cat  db/migrate/001_create_tables.rb
    class CreateTables < ActiveRecord::Migration
      def self.up
        create_table :softwares, :force => true do |t|
          t.column :name, :string, :limit => 20, :null => false
          t.column :version, :integer, :default => 0, :null => false
          t.column :lock_version, :integer, :default => 0, :null =>
false
        end
        Software.create_versioned_table
      end

      def self.down
        drop_table :softwares
        Software.drop_versioned_table
      end
    end

    % rake migrate
    (in /home/krassi/MyProjects/Rails/pl2)
    == CreateTables: migrating
====================================================
    -- create_table(:softwares, {:force=>true})
       -> 0.0225s
    == CreateTables: migrated (0.0681s)
===========================================

    # ++++ Using the versioned data ++++
    % ./script/console
    Loading development environment.
    >> s = Software.create :name => "Initial name"
    => #<Software:0xb7a94290 @errors=#<ActiveRecord::Errors:0xb7a3b7e4
@errors={}, @base=#<Software:0xb7a94290 ...>>,
@new_record_before_save=true, @attributes={"name"=>"Initial name",
"lock_version"=>0, "id"=>1, "version"=>1}, @new_record=false,
@changed_attributes=[]>
    >> s.version
    => 1
    >> s.save
    => true
    >> s.version
    => 1
    >> s.reload
    => #<Software:0xb7a94290 @errors=#<ActiveRecord::Errors:0xb7a3b7e4
@errors={}, @base=#<Software:0xb7a94290 ...>>,
@new_record_before_save=false, @attributes={"name"=>"Initial name",
"lock_version"=>"1", "id"=>"1", "version"=>"1"}, @versions=nil,
@new_record=false, @changed_attributes=[]>
    >> s.version
    => 1
    >> s.name = "Changed name"
    => "Changed name"
    >> s.version
    => 1
    >> s.save
    => true
    >> s.version
    => 1
    >> s.versions
    => [#<Software::Version:0xb79e5790 @attributes={"name"=>"Initial
name", "updated_at"=>"2006-05-16 21:28:45", "software_id"=>"1",
"id"=>"1", "version"=>"1"}>, #<Software::Version:0xb79e5678
@attributes={"name"=>"Initial name", "updated_at"=>"2006-05-16
21:28:50", "software_id"=>"1", "id"=>"2", "version"=>"1"}>,
#<Software::Version:0xb79e563c @attributes={"name"=>"Changed name",
"updated_at"=>"2006-05-16 21:29:15", "software_id"=>"1", "id"=>"3",
"version"=>"1"}>]
    >> s.name = "Name changed again"
    => "Name changed again"
    >> s.save
    => true
    >> s.version
    => 1
    >> s.versions
    => [#<Software::Version:0xb79e5790 @attributes={"name"=>"Initial
name", "updated_at"=>"2006-05-16 21:28:45", "software_id"=>"1",
"id"=>"1", "version"=>"1"}>, #<Software::Version:0xb79e5678
@attributes={"name"=>"Initial name", "updated_at"=>"2006-05-16
21:28:50", "software_id"=>"1", "id"=>"2", "version"=>"1"}>,
#<Software::Version:0xb79e563c @attributes={"name"=>"Changed name",
"updated_at"=>"2006-05-16 21:29:15", "software_id"=>"1", "id"=>"3",
"version"=>"1"}>]
    >>

    % ++++ And the BAD database content ++++
    mysql> select * from softwares; select * from software_versions;
    +----+--------------------+---------+--------------+
    | id | name               | version | lock_version |
    +----+--------------------+---------+--------------+
    |  1 | Name changed again |       1 |            3 |
    +----+--------------------+---------+--------------+
    1 row in set (0.00 sec)

    +----+-------------+---------+--------------------+---------------------+
    | id | software_id | version | name               | updated_at
|
    +----+-------------+---------+--------------------+---------------------+
    |  1 |           1 |       1 | Initial name       | 2006-05-16
21:28:45 |
    |  2 |           1 |       1 | Initial name       | 2006-05-16
21:28:50 |
    |  3 |           1 |       1 | Changed name       | 2006-05-16
21:29:15 |
    |  4 |           1 |       1 | Name changed again | 2006-05-16
21:29:35 |
    +----+-------------+---------+--------------------+---------------------+
    4 rows in set (0.00 sec)

As I see, there is a mismatch between the version and the
lock_version columns usage. Or am I using the plugin incorrectly?

Thank you very much for any suggestion.
This topic is locked and can not be replied to.