weird issue with dirty tracking on rails 7
Closed this issue · 5 comments
Tell us about your environment
Ruby Version: 2.7.4
Rails Version: 7.0.0.alpha2
Store Attribute Version: 0.9.1
What did you do?
if i have a stored attribute in the database, change another stored attribute and then call #changes
, the already present attribute value gets removed. see example below.
this does not happen without the store_attribute gem.
# frozen_string_literal: true
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem "activesupport", "~> 7.0.0.alpha2", require: false
gem "activerecord", "~> 7.0.0.alpha2", require: false
gem "store_attribute", "0.9.1", require: false
gem "sqlite3"
gem "debug"
end
require "active_support"
require "active_record"
require "store_attribute"
require "minitest/autorun"
require "logger"
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Schema.define do
create_table :humen, force: true do |t|
t.text :meta
end
end
class Human < ActiveRecord::Base
store :meta, accessors: [ :social_credit, slave: :boolean ], coder: JSON
after_initialize { self.social_credit ||= 0.0 }
end
class BugTest < Minitest::Test
def setup
meta = { slave: true }
ActiveRecord::Base.connection.execute "DELETE FROM humen;"
ActiveRecord::Base.connection.execute "INSERT INTO humen (meta) VALUES ('#{meta.to_json}');"
end
def test_without_call_to_changes
human = Human.first
assert human.slave
human.social_credit = 1.0
human.save!
assert human.slave
end
def test_call_to_changes
human = Human.first
assert human.slave
human.changes
human.save!
assert human.reload.slave
end
end
result:
Run options: -v --seed 28294
# Running:
BugTest#test_call_to_changes = D, [2021-10-07T22:00:17.405408 #64486] DEBUG -- : (0.1ms) DELETE FROM humen;
D, [2021-10-07T22:00:17.405693 #64486] DEBUG -- : (0.1ms) INSERT INTO humen (meta) VALUES ('{"slave":true}');
D, [2021-10-07T22:00:17.406992 #64486] DEBUG -- : Human Load (0.1ms) SELECT "humen".* FROM "humen" ORDER BY "humen"."id" ASC LIMIT ? [["LIMIT", 1]]
D, [2021-10-07T22:00:17.410243 #64486] DEBUG -- : TRANSACTION (0.0ms) begin transaction
D, [2021-10-07T22:00:17.410463 #64486] DEBUG -- : Human Update (0.1ms) UPDATE "humen" SET "meta" = ? WHERE "humen"."id" = ? [["meta", "{\"social_credit\":0.0}"], ["id", 1]]
D, [2021-10-07T22:00:17.410621 #64486] DEBUG -- : TRANSACTION (0.0ms) commit transaction
D, [2021-10-07T22:00:17.411141 #64486] DEBUG -- : Human Load (0.1ms) SELECT "humen".* FROM "humen" WHERE "humen"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
0.01 s = F
BugTest#test_without_call_to_changes = D, [2021-10-07T22:00:17.414410 #64486] DEBUG -- : (0.1ms) DELETE FROM humen;
D, [2021-10-07T22:00:17.414565 #64486] DEBUG -- : (0.1ms) INSERT INTO humen (meta) VALUES ('{"slave":true}');
D, [2021-10-07T22:00:17.414959 #64486] DEBUG -- : Human Load (0.0ms) SELECT "humen".* FROM "humen" ORDER BY "humen"."id" ASC LIMIT ? [["LIMIT", 1]]
D, [2021-10-07T22:00:17.415384 #64486] DEBUG -- : TRANSACTION (0.0ms) begin transaction
D, [2021-10-07T22:00:17.415595 #64486] DEBUG -- : Human Update (0.1ms) UPDATE "humen" SET "meta" = ? WHERE "humen"."id" = ? [["meta", "{\"slave\":true,\"social_credit\":1.0}"], ["id", 2]]
D, [2021-10-07T22:00:17.415784 #64486] DEBUG -- : TRANSACTION (0.0ms) commit transaction
0.00 s = .
Finished in 0.011849s, 168.7906 runs/s, 337.5812 assertions/s.
1) Failure:
BugTest#test_call_to_changes [store_attribute_changes.rb:59]:
Expected nil to be truthy.
2 runs, 4 assertions, 1 failures, 0 errors, 0 skips
What did you expect to happen?
a call to #changes
should not change model state.
What actually happened?
it removes the slave
column value.
oh. the test case above works with 0.9.0. so 39a0859 must be the culprit.
nevermind. i'm a confused person.
looks like this only happens with json-coder attributes. was trying to come up with a patch all weekend -.-
looks like this only happens with json-coder attributes
Interesting; I wasn't able to reproduce the bug so far. If you're able to provide a PR with a failing test example, that would be really helpful.
failing test example
see above? 👀
see above?
Oops :) Thanks!
Fixed and released in 0.9.2.