ar_transaction_changes 1.1.3 → 1.1.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 89f3ff2a1237cc1fab8f9b2bb7b338eacb83ea97
4
- data.tar.gz: f05afe6d47540c9bfc5e7c8a80fa1277dfc03d32
2
+ SHA256:
3
+ metadata.gz: 41a85de7f78cb23d9af300f5279a909db5ecab9b3e02bca9cf2ecd4703062b8b
4
+ data.tar.gz: cc04e7f4c6e884d4db4fe94c84b8a8ef55871613c0b0d737f9956a5f69d3ebcf
5
5
  SHA512:
6
- metadata.gz: b5c64f5f5684ac7b3f06653cc6f59e855fefd51ec285fe3e8fd6f357f76201ff3d94440c272a195fcb98f5086006c672eebc743d1eff35d76abee1c6a426e4d9
7
- data.tar.gz: d4969d2850dbee065ba0711613968cbe8f4f096d4557da97b3ae82cb688b17804b6fb702dafd64a5ef72f5d625b2f0714de9943d5a6517cb4fd699b1400fc4cf
6
+ metadata.gz: 4fde634868ccbb2518edbde7841bce8ca6745a41c6ef398d1d20ce55bae6a7eefb9c35689ebecadd3ef8246200a6034bc202960457f42e430a351c56b7ef0742
7
+ data.tar.gz: d14df655313155febb0c769a2852efc8c1ce4888cfbaa05ea362ecdb3a1219bc98051b5da1b3583dd8add30ff40a6ea52f0a6ac86198cb54a4d7208520daecb4
@@ -0,0 +1,47 @@
1
+ name: CI
2
+
3
+ on:
4
+ push: {}
5
+ pull_request:
6
+ types: [opened, synchronize]
7
+
8
+ jobs:
9
+ build:
10
+ if: github.event_name == 'push' || github.event.pull_request.head.repo.owner.login != 'dylanahsmith'
11
+
12
+ runs-on: ubuntu-latest
13
+
14
+ strategy:
15
+ matrix:
16
+ entry:
17
+ - name: 'Minimum supported'
18
+ ruby: 2.4
19
+ gemfile: Gemfile.rails52
20
+ - name: "Latest released versions"
21
+ ruby: 3.0
22
+ gemfile: Gemfile
23
+ - name: "Rails main branch"
24
+ ruby: 3.0
25
+ gemfile: Gemfile.rails_head
26
+
27
+ name: ${{ matrix.entry.name }}
28
+
29
+ env:
30
+ BUNDLE_GEMFILE: ${{ matrix.entry.gemfile }}
31
+
32
+ steps:
33
+ - name: Install required packages
34
+ run: |
35
+ sudo apt-get update
36
+ sudo apt-get -y install libsqlite3-dev
37
+ - uses: actions/checkout@v2
38
+ - name: Set up Ruby
39
+ uses: ruby/setup-ruby@v1
40
+ with:
41
+ ruby-version: ${{ matrix.entry.ruby }}
42
+ - name: Install bundler and gems
43
+ run: |
44
+ gem install bundler
45
+ bundle install --jobs 4 --retry 3
46
+ - name: Run tests
47
+ run: bundle exec rake
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
+
5
+ gem 'sqlite3', '~> 1.4'
data/Gemfile.rails52 CHANGED
@@ -1,5 +1,6 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem "rails", "~> 5.2.0.beta1"
3
+ gem 'activerecord', '~> 5.2.0'
4
+ gem "sqlite3", "~> 1.3", ">= 1.3.6"
4
5
 
5
6
  gemspec
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem 'activerecord', github: 'rails/rails'
4
+ gem 'sqlite3', '~> 1.4'
5
+
6
+ gemspec
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # ArTransactionChanges
2
- [![Build Status](https://travis-ci.org/dylanahsmith/ar_transaction_changes.png?branch=master)](https://travis-ci.org/dylanahsmith/ar_transaction_changes)
2
+ [![Build Status](https://github.com/dylanahsmith/ar_transaction_changes/workflows/CI/badge.svg?branch=main)](https://github.com/dylanahsmith/ar_transaction_changes/actions?query=branch%3Amain)
3
3
 
4
4
  Store all attribute changes for active record objects during a
5
5
  transaction so that they are available in an after_commit callbacks.
@@ -11,13 +11,14 @@ Gem::Specification.new do |gem|
11
11
  gem.description = %q{Solves the problem of trying to get all the changes to an object during a transaction in an after_commit callbacks.}
12
12
  gem.summary = %q{Store transaction changes for active record objects}
13
13
  gem.homepage = "https://github.com/dylanahsmith/ar_transaction_changes"
14
+ gem.license = "MIT"
14
15
 
15
16
  gem.files = `git ls-files`.split($/)
16
17
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
18
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
19
  gem.require_paths = ["lib"]
19
20
 
20
- gem.add_dependency "activerecord", ">= 4.2.4", "< 6.0"
21
+ gem.add_dependency "activerecord", ">= 5.2.0"
21
22
 
22
23
  gem.add_development_dependency("rake")
23
24
  gem.add_development_dependency("mysql2")
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "ar_transaction_changes/version"
2
4
  require "active_record"
3
5
 
@@ -18,19 +20,62 @@ module ArTransactionChanges
18
20
  @transaction_changed_attributes ||= HashWithIndifferentAccess.new
19
21
  end
20
22
 
21
- method_name = if ActiveRecord.gem_version >= Gem::Version.new("5.2.0.beta1")
22
- "_write_attribute"
23
- else
24
- "write_attribute"
23
+ def _write_attribute(attr_name, value)
24
+ _store_transaction_changed_attributes(attr_name) do
25
+ super(attr_name, value)
26
+ end
27
+ end
28
+
29
+ if ActiveRecord.version >= Gem::Version.new('6.1.0.alpha')
30
+ def write_attribute(attr_name, value)
31
+ _store_transaction_changed_attributes(attr_name) do
32
+ super(attr_name, value)
33
+ end
34
+ end
25
35
  end
26
36
 
27
- define_method(method_name) do |attr_name, value|
37
+ private
38
+
39
+ def _store_transaction_changed_attributes(attr_name)
28
40
  attr_name = attr_name.to_s
29
- old_value = read_attribute(attr_name)
30
- ret = super(attr_name, value)
31
- unless transaction_changed_attributes.key?(attr_name) || value == old_value
32
- transaction_changed_attributes[attr_name] = old_value
41
+ old_value = _read_attribute_for_transaction(attr_name)
42
+ ret = yield
43
+ new_value = _read_attribute_for_transaction(attr_name)
44
+ if !transaction_changed_attributes.key?(attr_name) && new_value != old_value
45
+ attribute = @attributes[attr_name]
46
+ transaction_changed_attributes[attr_name] = if attribute.type.is_a?(::ActiveRecord::Type::Serialized)
47
+ attribute.type.deserialize(old_value)
48
+ else
49
+ old_value
50
+ end
51
+ elsif transaction_changed_attributes.key?(attr_name)
52
+ attribute = @attributes[attr_name]
53
+ if attribute.type.is_a?(::ActiveRecord::Type::Serialized)
54
+ new_value = attribute.type.deserialize(new_value)
55
+ end
56
+
57
+ stored_value = transaction_changed_attributes[attr_name]
58
+
59
+ if new_value == stored_value
60
+ transaction_changed_attributes.delete(attr_name)
61
+ end
33
62
  end
34
63
  ret
35
64
  end
65
+
66
+ def _read_attribute_for_transaction(attr_name)
67
+ attribute = @attributes[attr_name]
68
+ # Avoid causing an earlier memoized type cast of mutable serialized user values,
69
+ # since could prevent mutations of that user value from affecting the attribute value
70
+ # that would affect it without using this library.
71
+ if attribute.type.is_a?(::ActiveRecord::Type::Serialized)
72
+ if attribute.came_from_user?
73
+ attribute.type.serialize(attribute.value_before_type_cast)
74
+ else
75
+ attribute.value_before_type_cast
76
+ end
77
+ else
78
+ _read_attribute(attr_name)
79
+ end
80
+ end
36
81
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ArTransactionChanges
2
- VERSION = "1.1.3"
4
+ VERSION = "1.1.8"
3
5
  end
@@ -1,7 +1,3 @@
1
1
  test:
2
- adapter: mysql2
3
- database: ar_transaction_changes_test
4
- host: 127.0.0.1
5
- encoding: utf8
6
- username: root
7
- password:
2
+ adapter: sqlite3
3
+ database: ':memory:'
data/test/models/user.rb CHANGED
@@ -1,6 +1,17 @@
1
1
  class User < ActiveRecord::Base
2
2
  include ArTransactionChanges
3
3
 
4
+ class ConnectionDetails
5
+ attr_accessor :client_ip
6
+
7
+ def initialize(client_ip:)
8
+ @client_ip = client_ip
9
+ end
10
+ end
11
+
12
+ serialize :connection_details, Array
13
+ serialize :notes, Array
14
+
4
15
  attr_accessor :stored_transaction_changes
5
16
 
6
17
  after_commit :store_transaction_changes_for_tests
data/test/test_helper.rb CHANGED
@@ -1,19 +1,28 @@
1
- ENV["RAILS_ENV"] = "test"
2
1
  require 'pathname'
3
2
  require 'yaml'
4
3
  require 'ar_transaction_changes'
5
4
  require 'minitest/autorun'
6
5
 
6
+ ENV["RAILS_ENV"] = "test"
7
+
7
8
  test_dir = Pathname.new(File.dirname(__FILE__))
8
9
  config_filename = test_dir.join("database.yml").exist? ? "database.yml" : "database.yml.default"
9
10
  database_yml = YAML.load(test_dir.join(config_filename).read)
10
- ActiveRecord::Base.establish_connection database_yml['test']
11
+ database_config = database_yml.fetch("test")
12
+
13
+ if database_config.fetch('adapter') != 'sqlite3'
14
+ ActiveRecord::Base.establish_connection(database_config.except("database"))
15
+ ActiveRecord::Base.connection.recreate_database(database_config.fetch("database"))
16
+ end
17
+ ActiveRecord::Base.establish_connection(database_config)
11
18
 
12
19
  ActiveRecord::Base.connection.tap do |db|
13
- db.drop_table(:users) if db.table_exists?(:users)
14
20
  db.create_table(:users) do |t|
15
21
  t.string :name
16
22
  t.string :occupation
23
+ t.integer :age
24
+ t.text :connection_details
25
+ t.text :notes
17
26
  t.timestamps null: false
18
27
  end
19
28
  end
@@ -2,7 +2,7 @@ require 'test_helper'
2
2
 
3
3
  class TransactionChangesTest < MiniTest::Unit::TestCase
4
4
  def setup
5
- @user = User.new(:name => "Dylan", :occupation => "Developer")
5
+ @user = User.new(:name => "Dylan", :occupation => "Developer", age: 20)
6
6
  @user.save!
7
7
  @user.stored_transaction_changes = nil
8
8
  end
@@ -23,6 +23,13 @@ class TransactionChangesTest < MiniTest::Unit::TestCase
23
23
  assert_equal ["Dylan", "Dillon"], @user.stored_transaction_changes["name"]
24
24
  end
25
25
 
26
+ def test_transaction_changes_for_updating_attribute
27
+ @user[:name] = "Dillon"
28
+ @user.save!
29
+
30
+ assert_equal ["Dylan", "Dillon"], @user.stored_transaction_changes["name"]
31
+ end
32
+
26
33
  def test_transaction_changes_for_double_save
27
34
  @user.transaction do
28
35
  @user.name = "Dillon"
@@ -67,7 +74,7 @@ class TransactionChangesTest < MiniTest::Unit::TestCase
67
74
  end
68
75
 
69
76
  def test_transaction_changes_for_changing_updated_at
70
- @user.update_attributes!(updated_at: Time.now - 1.second)
77
+ @user.update!(updated_at: Time.now - 1.second)
71
78
  old_updated_at = @user.updated_at
72
79
  @user.stored_transaction_changes = nil
73
80
 
@@ -78,7 +85,7 @@ class TransactionChangesTest < MiniTest::Unit::TestCase
78
85
  end
79
86
 
80
87
  def test_transaction_changes_for_touch
81
- @user.update_attributes!(updated_at: Time.now - 1.second)
88
+ @user.update!(updated_at: Time.now - 1.second)
82
89
  old_updated_at = @user.updated_at
83
90
  @user.stored_transaction_changes = nil
84
91
 
@@ -94,4 +101,56 @@ class TransactionChangesTest < MiniTest::Unit::TestCase
94
101
  end
95
102
  refute @user.stored_transaction_changes["name"]
96
103
  end
104
+
105
+ def test_transaction_changes_type_cast
106
+ # "20" will be converted to 20 by read_attribute https://apidock.com/rails/ActiveRecord/AttributeMethods/read_attribute
107
+ @user.transaction do
108
+ @user.age = "20"
109
+ @user.save!
110
+ end
111
+ assert_empty @user.stored_transaction_changes
112
+ end
113
+
114
+ def test_serialized_attributes_value
115
+ @user.connection_details = [User::ConnectionDetails.new(client_ip: '1.1.1.1')]
116
+ @user.save!
117
+ old_value, new_value = @user.stored_transaction_changes['connection_details']
118
+ assert_equal([], old_value)
119
+ assert_equal(['1.1.1.1'], new_value.map(&:client_ip))
120
+ end
121
+
122
+ def test_serialized_attributes_mutation
123
+ details = User::ConnectionDetails.new(client_ip: '1.1.1.1')
124
+ @user.connection_details = [details]
125
+ details.client_ip = '2.2.2.2'
126
+ @user.save!
127
+ assert_equal '2.2.2.2', @user.connection_details.first.client_ip
128
+ end
129
+
130
+ def test_double_save_back_to_original_value
131
+ @user.transaction do
132
+ @user.name = "Dillon"
133
+ @user.save!(touch: false)
134
+
135
+ @user.name = "Dylan"
136
+ @user.save!(touch: false)
137
+ end
138
+
139
+ assert_empty @user.stored_transaction_changes
140
+ end
141
+
142
+ def test_double_save_back_to_original_value_for_serialized_attribute
143
+ @user.notes = ['a', 'b']
144
+ @user.save!
145
+
146
+ @user.transaction do
147
+ @user.notes = ['b', 'c']
148
+ @user.save!(touch: false)
149
+
150
+ @user.notes = ['a', 'b']
151
+ @user.save!(touch: false)
152
+ end
153
+
154
+ assert_empty @user.stored_transaction_changes
155
+ end
97
156
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ar_transaction_changes
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 1.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dylan Thacker-Smith
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-02 00:00:00.000000000 Z
11
+ date: 2021-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,20 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 4.2.4
20
- - - "<"
21
- - !ruby/object:Gem::Version
22
- version: '6.0'
19
+ version: 5.2.0
23
20
  type: :runtime
24
21
  prerelease: false
25
22
  version_requirements: !ruby/object:Gem::Requirement
26
23
  requirements:
27
24
  - - ">="
28
25
  - !ruby/object:Gem::Version
29
- version: 4.2.4
30
- - - "<"
31
- - !ruby/object:Gem::Version
32
- version: '6.0'
26
+ version: 5.2.0
33
27
  - !ruby/object:Gem::Dependency
34
28
  name: rake
35
29
  requirement: !ruby/object:Gem::Requirement
@@ -66,13 +60,11 @@ executables: []
66
60
  extensions: []
67
61
  extra_rdoc_files: []
68
62
  files:
63
+ - ".github/workflows/ci.yml"
69
64
  - ".gitignore"
70
- - ".travis.yml"
71
65
  - Gemfile
72
- - Gemfile.rails42
73
- - Gemfile.rails50
74
- - Gemfile.rails51
75
66
  - Gemfile.rails52
67
+ - Gemfile.rails_head
76
68
  - LICENSE.txt
77
69
  - README.md
78
70
  - Rakefile
@@ -84,9 +76,10 @@ files:
84
76
  - test/test_helper.rb
85
77
  - test/transaction_changes_test.rb
86
78
  homepage: https://github.com/dylanahsmith/ar_transaction_changes
87
- licenses: []
79
+ licenses:
80
+ - MIT
88
81
  metadata: {}
89
- post_install_message:
82
+ post_install_message:
90
83
  rdoc_options: []
91
84
  require_paths:
92
85
  - lib
@@ -101,9 +94,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
101
94
  - !ruby/object:Gem::Version
102
95
  version: '0'
103
96
  requirements: []
104
- rubyforge_project:
105
- rubygems_version: 2.6.14
106
- signing_key:
97
+ rubygems_version: 3.1.4
98
+ signing_key:
107
99
  specification_version: 4
108
100
  summary: Store transaction changes for active record objects
109
101
  test_files:
data/.travis.yml DELETED
@@ -1,23 +0,0 @@
1
- language: ruby
2
- sudo: false
3
-
4
- rvm:
5
- - 2.2.5
6
- - 2.3.1
7
-
8
- gemfile:
9
- - Gemfile.rails42
10
- - Gemfile.rails50
11
- - Gemfile.rails51
12
- - Gemfile.rails52
13
-
14
- matrix:
15
- include:
16
- - rvm: 2.1.9
17
- gemfile: Gemfile.rails42
18
-
19
- services:
20
- - mysql
21
-
22
- before_script:
23
- - mysql -e 'create database ar_transaction_changes_test'
data/Gemfile.rails42 DELETED
@@ -1,5 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gem "rails", "~> 4.2.0"
4
-
5
- gemspec
data/Gemfile.rails50 DELETED
@@ -1,5 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gem "rails", "~> 5.0.0"
4
-
5
- gemspec
data/Gemfile.rails51 DELETED
@@ -1,5 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gem "rails", "~> 5.1.0.rc1"
4
-
5
- gemspec