Skip to content

Commit 8ec27a4

Browse files
authored
Merge pull request rails#43386 from rdimartino/dirty_store
Fix tracking previous changes for ActiveRecord::Store accessors with underlying JSON data column
2 parents 4e01a7e + eceaa38 commit 8ec27a4

File tree

5 files changed

+28
-3
lines changed

5 files changed

+28
-3
lines changed

activerecord/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
* Fix previous change tracking for `ActiveRecord::Store` when using a column with JSON structured database type
2+
3+
Before, the methods to access the changes made during the last save `#saved_change_to_key?`, `#saved_change_to_key`, and `#key_before_last_save` did not work if the store was defined as a `store_accessor` on a column with a JSON structured database type
4+
5+
*Robert DiMartino*
6+
17
* Fully support `NULLS [NOT] DISTINCT` for PostgreSQL 15+ indexes.
28

39
Previous work was done to allow the index to be created in a migration, but it was not

activerecord/lib/active_record/store.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,19 +163,19 @@ def store_accessor(store_attribute, *keys, prefix: nil, suffix: nil)
163163

164164
define_method("saved_change_to_#{accessor_key}?") do
165165
return false unless saved_change_to_attribute?(store_attribute)
166-
prev_store, new_store = saved_change_to_attribute(store_attribute)
166+
prev_store, new_store = saved_changes[store_attribute]
167167
prev_store&.dig(key) != new_store&.dig(key)
168168
end
169169

170170
define_method("saved_change_to_#{accessor_key}") do
171171
return unless saved_change_to_attribute?(store_attribute)
172-
prev_store, new_store = saved_change_to_attribute(store_attribute)
172+
prev_store, new_store = saved_changes[store_attribute]
173173
[prev_store&.dig(key), new_store&.dig(key)]
174174
end
175175

176176
define_method("#{accessor_key}_before_last_save") do
177177
return unless saved_change_to_attribute?(store_attribute)
178-
prev_store, _new_store = saved_change_to_attribute(store_attribute)
178+
prev_store, _new_store = saved_changes[store_attribute]
179179
prev_store&.dig(key)
180180
end
181181
end

activerecord/test/cases/store_test.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,23 @@ class StoreTest < ActiveRecord::TestCase
163163
assert_equal "Dallas", @john.partner_name_before_last_save
164164
end
165165

166+
test "saved changes tracking for accessors with json column" do
167+
if current_adapter?(:Mysql2Adapter, :TrilogyAdapter) && ActiveRecord::Base.connection.mariadb?
168+
skip "MariaDB doesn't support JSON store_accessor"
169+
end
170+
@john.enable_friend_requests = true
171+
assert @john.enable_friend_requests_changed?
172+
173+
@john.save!
174+
assert_not @john.enable_friend_requests_change
175+
assert @john.saved_change_to_enable_friend_requests?
176+
assert_equal [nil, true], @john.saved_change_to_enable_friend_requests
177+
# Make a second change to test key_before_last_save
178+
@john.enable_friend_requests = false
179+
@john.save
180+
assert_equal true, @john.enable_friend_requests_before_last_save
181+
end
182+
166183
test "object initialization with not nullable column" do
167184
assert_equal true, @john.remember_login
168185
end

activerecord/test/models/admin/user.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ def load(s)
2828
store :preferences, accessors: [ :remember_login ]
2929
store :json_data, accessors: [ :height, :weight ], coder: Coder.new
3030
store :json_data_empty, accessors: [ :is_a_good_guy ], coder: Coder.new
31+
store_accessor :json_options, :enable_friend_requests
3132

3233
def phone_number
3334
read_store_attribute(:settings, :phone_number).gsub(/(\d{3})(\d{3})(\d{4})/, '(\1) \2-\3')

activerecord/test/schema/schema.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
t.string :json_data_empty, null: true, default: "", limit: 1024
3939
t.text :params
4040
t.references :account
41+
t.json :json_options
4142
end
4243

4344
create_table :admin_user_jsons, force: true do |t|

0 commit comments

Comments
 (0)