junk_drawer 1.3.0 → 1.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: fa1bc248af13f000203f8c72364c382c44de203a
4
- data.tar.gz: 05ad7bf2b95cb6630eab0129811dcb68cd8e1e6b
2
+ SHA256:
3
+ metadata.gz: 4f24671eaa9add85408c8966382db1f81bd41c401bf08bc9fa367507d48a5024
4
+ data.tar.gz: 586334b2252f4e4b19d6338686b4c4b53435a6144f12cc5b642e85509bca8e2a
5
5
  SHA512:
6
- metadata.gz: 99d8ee5d88bc1bcd7d3253fc4dbac3be7be6418ede9a772bc4963233b0785344429ee40a2f8b2078e8d51e678aead1701eeba99ed4227ade2206b79e7af1912b
7
- data.tar.gz: 108ff56c6ed5bbe24e81edcfa099e0ae7a55cada04469a0e9900d76b4b3623b64f334f39eaa52ed048b18811bf7fd8e907b83e95f7169d9f745de2ee93f4673b
6
+ metadata.gz: 68798dd630e0f3508d5fcd30480c9f7eb04e3d12a1035bf4bdd39003d976e1a3eed76bd717fd8671985b4f33924dde6eeabaa37ab2d154d2b4aa42df13b8f7a0
7
+ data.tar.gz: 67bd7ba05df3c718c79c37dffffb3936894a541253b17d382809af1805c36cc330b465016f7ca7f1886a4496128817d8cd3621a4bf2c7a724c6fdad8aadc7a9d
data/.gitignore CHANGED
@@ -1,6 +1,7 @@
1
1
  /.bundle/
2
2
  /.yardoc
3
3
  /Gemfile.lock
4
+ *gems.lock
4
5
  /_yardoc/
5
6
  /coverage/
6
7
  /doc/
@@ -20,7 +20,7 @@ Metrics/MethodLength:
20
20
  Metrics/BlockLength:
21
21
  Exclude:
22
22
  - junk_drawer.gemspec
23
- - spec/**/*_spec.rb
23
+ - spec/**/*
24
24
 
25
25
  RSpec/ExampleLength:
26
26
  Enabled: false
@@ -1,13 +1,21 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.3.1
4
+ - 2.3
5
+ - 2.4
6
+ - 2.5
7
+ - 2.6
8
+ - 2.7
5
9
  addons:
6
10
  postgresql: '9.4'
7
- before_install: gem install bundler -v 1.13.6
11
+ before_install: gem install bundler -v 2.0.2
8
12
  before_script:
9
13
  - createdb junk_drawer_test -U postgres
10
14
  script:
11
15
  - bundle exec rubocop
12
16
  - bundle exec rake
13
17
  - bundle exec rake build
18
+ gemfile:
19
+ - Gemfile
20
+ - gemfiles/rails_5.0.gems
21
+ - gemfiles/rails_4.2.gems
data/Gemfile CHANGED
@@ -3,3 +3,8 @@
3
3
  source 'https://rubygems.org'
4
4
 
5
5
  gemspec
6
+
7
+ gem 'activerecord', '~> 5.1.0'
8
+ gem 'activesupport', '~> 5.1.0'
9
+ gem 'hstore_accessor', '~> 1.1.1'
10
+ gem 'jsonb_accessor', '~> 1.0.0'
data/README.md CHANGED
@@ -211,7 +211,8 @@ database.
211
211
  ## Development
212
212
 
213
213
  After checking out the repo, run `bin/setup` to install dependencies. Then, run
214
- `rake spec` to run the tests. You can also run `bin/console` for an interactive
214
+ `rake spec` to run the tests, or `bin/test` to run tests for all supported
215
+ ActiveRecord versions. You can also run `bin/console` for an interactive
215
216
  prompt that will allow you to experiment.
216
217
 
217
218
  To install this gem onto your local machine, run `bundle exec rake install`. To
@@ -219,10 +220,17 @@ release a new version, update the version number in `version.rb`, and then run
219
220
  `bundle exec rake release`, which will create a git tag for the version, push
220
221
  git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
221
222
 
223
+ In order to run tests against different Rails versions, you can use
224
+ `BUNDLE_GEMFILE`:
225
+
226
+ ```sh
227
+ $ BUNDLE_GEMFILE=gemfiles/rails_4.2.gems rake spec
228
+ ```
229
+
222
230
  ## Contributing
223
231
 
224
232
  Bug reports and pull requests are welcome on GitHub at
225
- https://github.com/mockdeep/junk_drawer. This project is intended to be a
233
+ https://github.com/thread-pond/junk_drawer. This project is intended to be a
226
234
  safe, welcoming space for collaboration, and contributors are expected to
227
235
  adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
228
236
 
data/bin/setup CHANGED
@@ -3,6 +3,9 @@ set -euo pipefail
3
3
  IFS=$'\n\t'
4
4
  set -vx
5
5
 
6
+ createuser -s -r postgres
7
+ createdb junk_drawer_test -U postgres
8
+
6
9
  bundle install
7
10
 
8
11
  # Do any other automated setup that you need to do here
@@ -0,0 +1,3 @@
1
+ (export BUNDLE_GEMFILE=Gemfile; bundle && bundle exec rake)
2
+ (export BUNDLE_GEMFILE=gemfiles/rails_5.0.gems; bundle && bundle exec rake spec)
3
+ (export BUNDLE_GEMFILE=gemfiles/rails_4.2.gems; bundle && bundle exec rake spec)
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec path: '../'
6
+
7
+ gem 'activerecord', '~> 4.2.0'
8
+ gem 'activesupport', '~> 4.2.0'
9
+ gem 'hstore_accessor', '~> 1.1.1'
10
+ gem 'jsonb_accessor', '~> 0.3.3'
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec path: '../'
6
+
7
+ gem 'activerecord', '~> 5.0.0'
8
+ gem 'activesupport', '~> 5.0.0'
9
+ gem 'hstore_accessor', '~> 1.1.1'
10
+ gem 'jsonb_accessor', '~> 1.0.0'
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.email = ['lobatifricha@gmail.com']
10
10
 
11
11
  spec.summary = 'random useful Ruby utilities'
12
- spec.homepage = 'https://github.com/mockdeep/junk_drawer'
12
+ spec.homepage = 'https://github.com/thread-pond/junk_drawer'
13
13
  spec.license = 'MIT'
14
14
 
15
15
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
@@ -21,14 +21,12 @@ Gem::Specification.new do |spec|
21
21
 
22
22
  spec.required_ruby_version = '>= 2.1'
23
23
 
24
- spec.add_development_dependency 'activerecord', '~> 4.2'
25
- spec.add_development_dependency 'activesupport', '~> 4.2'
26
- spec.add_development_dependency 'bundler', '~> 1.13'
27
24
  spec.add_development_dependency 'guard', '~> 2.14'
28
25
  spec.add_development_dependency 'guard-rspec', '~> 4.7'
29
26
  spec.add_development_dependency 'guard-rubocop', '~> 1.2'
30
27
  spec.add_development_dependency 'pg', '~> 0.20'
31
28
  spec.add_development_dependency 'pry', '~> 0.10'
29
+ spec.add_development_dependency 'pry-byebug', '~> 3.6.0'
32
30
  spec.add_development_dependency 'rake', '~> 12.0'
33
31
  spec.add_development_dependency 'rspec', '~> 3.0'
34
32
  spec.add_development_dependency 'rubocop', '~> 0.48.1'
@@ -19,8 +19,8 @@ module JunkDrawer
19
19
  # an instance. It also causes an error to be raised if a public instance
20
20
  # method is defined with a name other than `call`
21
21
  module ClassMethods
22
- def call(*args)
23
- new.(*args)
22
+ def call(*args, **kwargs, &block)
23
+ new.(*args, **kwargs, &block)
24
24
  end
25
25
 
26
26
  def to_proc
@@ -7,34 +7,45 @@ require 'active_record/connection_adapters/postgresql_adapter'
7
7
  module JunkDrawer
8
8
  # module to allow bulk updates for `ActiveRecord` models
9
9
  module BulkUpdatable
10
- ATTRIBUTE_TYPE_TO_POSTGRES_CAST = {
11
- datetime: '::timestamp',
12
- hstore: '::hstore',
13
- boolean: '::boolean',
14
- jsonb: '::jsonb',
15
- }.freeze
16
-
17
- POSTGRES_VALUE_CASTERS = {
18
- hstore: ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Hstore.new,
19
- jsonb: ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Jsonb.new,
20
- }.freeze
21
-
22
10
  def bulk_update(objects)
23
11
  objects = objects.select(&:changed?)
24
12
  return unless objects.any?
25
13
 
26
- changed_attributes = extract_changed_attributes(objects)
27
- query = build_query_for(objects, changed_attributes)
14
+ unique_objects = uniquify_and_merge(objects)
15
+ changed_attributes = extract_changed_attributes(unique_objects)
16
+ query = build_query_for(unique_objects, changed_attributes)
28
17
  connection.execute(query)
18
+ objects.each(&:clear_changes_information)
29
19
  end
30
20
 
31
21
  private
32
22
 
23
+ def uniquify_and_merge(objects)
24
+ grouped_objects = objects.group_by(&:id).values
25
+ grouped_objects.each do |group|
26
+ next if group.length == 1
27
+
28
+ attrs = group.each_with_object({}) do |object, changes|
29
+ object.changed.each do |changed_attribute|
30
+ changes[changed_attribute] = object[changed_attribute]
31
+ end
32
+ end
33
+ group.each { |object| object.attributes = attrs }
34
+ end
35
+ grouped_objects.map(&:first)
36
+ end
37
+
33
38
  def extract_changed_attributes(objects)
34
39
  now = Time.zone.now
35
40
  objects.each { |object| object.updated_at = now }
36
41
 
37
- objects.flat_map(&:changed).uniq
42
+ changed_attributes = objects.flat_map(&:changed).uniq
43
+ if ::ActiveRecord::VERSION::MAJOR >= 5
44
+ column_names & changed_attributes
45
+ else
46
+ # to remove virtual columns from jsonb_accessor 0.3.3
47
+ columns.select(&:sql_type).map(&:name) & changed_attributes
48
+ end
38
49
  end
39
50
 
40
51
  def build_query_for(objects, attributes)
@@ -47,31 +58,37 @@ module JunkDrawer
47
58
  "#{quoted_column_name} = tmp_table.#{quoted_column_name}"
48
59
  end.join(', ')
49
60
 
50
- <<-SQL
51
- UPDATE #{table_name}
52
- SET #{assignment_query}
53
- FROM (VALUES #{object_values}) AS tmp_table(id, #{attributes.join(', ')})
54
- WHERE #{table_name}.id = tmp_table.id
55
- SQL
61
+ "UPDATE #{table_name} " \
62
+ "SET #{assignment_query} " \
63
+ "FROM (VALUES #{object_values}) " \
64
+ "AS tmp_table(id, #{attributes.join(', ')}) " \
65
+ "WHERE #{table_name}.id = tmp_table.id"
56
66
  end
57
67
 
58
68
  def sanitized_values(object, attributes)
59
- postgres_types = attributes.map do |attribute|
60
- attribute_type = columns_hash[attribute.to_s].type
61
- "?#{ATTRIBUTE_TYPE_TO_POSTGRES_CAST[attribute_type]}"
62
- end
63
-
64
69
  postgres_values = attributes.map do |attribute|
65
70
  value = object[attribute]
66
- attribute_type = columns_hash[attribute.to_s].type
67
- caster = POSTGRES_VALUE_CASTERS[attribute_type]
68
71
 
69
- caster ? caster.type_cast_for_database(value) : value
72
+ # AR internal `columns_hash`
73
+ column = columns_hash[attribute.to_s]
74
+
75
+ # AR internal `type_for_attribute`
76
+ type = type_for_attribute(column.name)
77
+ type_cast = "::#{column.sql_type}"
78
+ type_cast = "#{type_cast}[]" if column.array
79
+
80
+ "#{connection.quote(serialized_value(type, value))}#{type_cast}"
70
81
  end
71
82
 
72
- sanitize_sql_array(
73
- ["(?, #{postgres_types.join(', ')})", object.id, *postgres_values],
74
- )
83
+ "(#{[object.id, *postgres_values].join(', ')})"
84
+ end
85
+
86
+ def serialized_value(type, value)
87
+ if ::ActiveRecord::VERSION::MAJOR >= 5
88
+ type.serialize(value)
89
+ else
90
+ type.type_cast_for_database(value)
91
+ end
75
92
  end
76
93
  end
77
94
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JunkDrawer
4
- VERSION = '1.3.0'
4
+ VERSION = '1.6.2'
5
5
  end
metadata CHANGED
@@ -1,57 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: junk_drawer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Fletcher
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-07-21 00:00:00.000000000 Z
11
+ date: 2020-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: activerecord
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '4.2'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '4.2'
27
- - !ruby/object:Gem::Dependency
28
- name: activesupport
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '4.2'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '4.2'
41
- - !ruby/object:Gem::Dependency
42
- name: bundler
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '1.13'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '1.13'
55
13
  - !ruby/object:Gem::Dependency
56
14
  name: guard
57
15
  requirement: !ruby/object:Gem::Requirement
@@ -122,6 +80,20 @@ dependencies:
122
80
  - - "~>"
123
81
  - !ruby/object:Gem::Version
124
82
  version: '0.10'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry-byebug
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 3.6.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 3.6.0
125
97
  - !ruby/object:Gem::Dependency
126
98
  name: rake
127
99
  requirement: !ruby/object:Gem::Requirement
@@ -225,6 +197,9 @@ files:
225
197
  - Rakefile
226
198
  - bin/console
227
199
  - bin/setup
200
+ - bin/test
201
+ - gemfiles/rails_4.2.gems
202
+ - gemfiles/rails_5.0.gems
228
203
  - junk_drawer.gemspec
229
204
  - lib/junk_drawer.rb
230
205
  - lib/junk_drawer/callable.rb
@@ -235,7 +210,7 @@ files:
235
210
  - lib/junk_drawer/rails.rb
236
211
  - lib/junk_drawer/rails/bulk_updatable.rb
237
212
  - lib/junk_drawer/version.rb
238
- homepage: https://github.com/mockdeep/junk_drawer
213
+ homepage: https://github.com/thread-pond/junk_drawer
239
214
  licenses:
240
215
  - MIT
241
216
  metadata: {}
@@ -254,8 +229,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
254
229
  - !ruby/object:Gem::Version
255
230
  version: '0'
256
231
  requirements: []
257
- rubyforge_project:
258
- rubygems_version: 2.6.11
232
+ rubygems_version: 3.1.4
259
233
  signing_key:
260
234
  specification_version: 4
261
235
  summary: random useful Ruby utilities