vorpal 1.0.3 → 1.1.0

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.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -10
  3. data/lib/vorpal/aggregate_mapper.rb +11 -0
  4. data/lib/vorpal/driver/postgresql.rb +39 -3
  5. data/lib/vorpal/version.rb +1 -1
  6. data/vorpal.gemspec +4 -3
  7. metadata +9 -59
  8. data/.editorconfig +0 -13
  9. data/.envrc +0 -4
  10. data/.gitignore +0 -16
  11. data/.rspec +0 -1
  12. data/.ruby-version +0 -1
  13. data/.travis.yml +0 -18
  14. data/.yardopts +0 -1
  15. data/Appraisals +0 -18
  16. data/Gemfile +0 -4
  17. data/Rakefile +0 -39
  18. data/bin/appraisal +0 -29
  19. data/bin/rake +0 -29
  20. data/bin/rspec +0 -29
  21. data/docker-compose.yml +0 -19
  22. data/gemfiles/rails_5_1.gemfile +0 -11
  23. data/gemfiles/rails_5_1.gemfile.lock +0 -101
  24. data/gemfiles/rails_5_2.gemfile +0 -11
  25. data/gemfiles/rails_5_2.gemfile.lock +0 -101
  26. data/gemfiles/rails_6_0.gemfile +0 -9
  27. data/gemfiles/rails_6_0.gemfile.lock +0 -101
  28. data/spec/acceptance/vorpal/aggregate_mapper_spec.rb +0 -910
  29. data/spec/helpers/codecov_helper.rb +0 -7
  30. data/spec/helpers/db_helpers.rb +0 -69
  31. data/spec/helpers/profile_helpers.rb +0 -26
  32. data/spec/integration/vorpal/driver/postgresql_spec.rb +0 -42
  33. data/spec/integration_spec_helper.rb +0 -29
  34. data/spec/performance/vorpal/performance_spec.rb +0 -305
  35. data/spec/unit/vorpal/configs_spec.rb +0 -117
  36. data/spec/unit/vorpal/db_loader_spec.rb +0 -103
  37. data/spec/unit/vorpal/dsl/config_builder_spec.rb +0 -18
  38. data/spec/unit/vorpal/dsl/defaults_generator_spec.rb +0 -75
  39. data/spec/unit/vorpal/identity_map_spec.rb +0 -62
  40. data/spec/unit/vorpal/loaded_objects_spec.rb +0 -22
  41. data/spec/unit/vorpal/util/string_utils_spec.rb +0 -25
  42. data/spec/unit_spec_helper.rb +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9833373892cb8a97f3b37ba1ec0fe9d06fe0b39dc6caaf9f7b333b28f20c2a47
4
- data.tar.gz: 47df18148ce8412236a13032055da0ca6d3c1c21c9839e99c329a2df88982a55
3
+ metadata.gz: c866f3e83daac73f28e5c9a53875b73d7f8db95cbf437200f0b0c69cce81d317
4
+ data.tar.gz: e1e91f848552e1f3710849370978d4a1e322e65b12c65bebcd995b76960ba44e
5
5
  SHA512:
6
- metadata.gz: 24c5cd71c9d56d8b882bb6691808c22749317d81ca1b104c90ddcf846c35ee0d8b36809cf1558f5a973f3696a48dc2aa9e80a6c0d6f7ea80dac275ef7b1d8597
7
- data.tar.gz: c1012c585122a6259137e9de766247222b7c1a20606b27aca7fb219d947914a860016c1ec1c7ba8387d223d9bbde53c416065f52b837680b0bcff2fc6d177d40
6
+ metadata.gz: 5bcd5518f56b4c43f4180d3f63c75c6186c1bd89bee939b8410e656f3df411920238eaf51da4a590367f929507c3bdb1ada98cf972d6ebf6785432417018b9a2
7
+ data.tar.gz: 85e53e6946ea0d0f06e14d8913ac3eba45668b3d08bfc0036a789620ea05af587cb5a97991467eadfea1f76d5dd3fccaf71c96aeec2345327d9538e714e0e720
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Vorpal [![Build Status](https://travis-ci.org/nulogy/vorpal.svg?branch=master)](https://travis-ci.org/nulogy/vorpal) [![Code Climate](https://codeclimate.com/github/nulogy/vorpal/badges/gpa.svg)](https://codeclimate.com/github/nulogy/vorpal) [![Code Coverage](https://codecov.io/gh/nulogy/vorpal/branch/master/graph/badge.svg)](https://codecov.io/gh/nulogy/vorpal/branch/master)
1
+ # Vorpal [![Build Status](https://travis-ci.com/nulogy/vorpal.svg?branch=master)](https://travis-ci.com/nulogy/vorpal) [![Code Climate](https://codeclimate.com/github/nulogy/vorpal/badges/gpa.svg)](https://codeclimate.com/github/nulogy/vorpal) [![Code Coverage](https://codecov.io/gh/nulogy/vorpal/branch/master/graph/badge.svg)](https://codecov.io/gh/nulogy/vorpal/branch/master)
2
2
 
3
3
  Separate your domain model from your persistence mechanism. Some problems call for a really sharp tool.
4
4
 
@@ -181,13 +181,11 @@ It also does not do some things that you might expect from other ORMs:
181
181
  1. Only supports PostgreSQL.
182
182
 
183
183
  ## Future Enhancements
184
- * Aggregate updated_at.
185
- * Support for other DBMSs (no MySQL support until ids can be generated without inserting into a table!)
186
- * Support for other ORMs.
187
- * Value objects.
188
- * Remove dependency on ActiveRecord (optimistic locking? updated_at, created_at support? Data type conversions? TimeZone support?)
189
- * More efficient updates (use fewer queries.)
184
+ * Support for UUID primary keys.
190
185
  * Nicer DSL for specifying attributes that have different names in the domain model than in the DB.
186
+ * Show how to implement POROs without using Virtus (it is unsupported and can be crazy slow)
187
+ * Aggregate updated_at.
188
+ * Better support for value objects.
191
189
 
192
190
  ## FAQ
193
191
 
@@ -203,11 +201,12 @@ It also does not do some things that you might expect from other ORMs:
203
201
 
204
202
  **A.** Create a method on a [Repository](http://martinfowler.com/eaaCatalog/repository.html)! They have full access to the DB/ORM so you can use [Arel](https://github.com/rails/arel) and go [crazy](http://asciicasts.com/episodes/239-activerecord-relation-walkthrough) or use direct SQL if you want.
205
203
 
206
- For example:
204
+ For example, use the [#query](https://rubydoc.info/github/nulogy/vorpal/master/Vorpal/AggregateMapper#query-instance_method) method on the [AggregateMapper](https://rubydoc.info/github/nulogy/vorpal/master/Vorpal/AggregateMapper) to access the underyling [ActiveRecordRelation](https://api.rubyonrails.org/classes/ActiveRecord/Relation.html):
207
205
 
208
206
  ```ruby
209
- def find_all
210
- @mapper.query.load_all # use the mapper to load all the aggregates
207
+ def find_special_ones
208
+ # use `load_all` or `load_one` to convert from ActiveRecord objects to domain POROs.
209
+ @mapper.query.where(special: true).load_all
211
210
  end
212
211
  ```
213
212
 
@@ -229,6 +228,10 @@ For example:
229
228
 
230
229
  **A.** You can use [ActiveModel::Serialization](http://api.rubyonrails.org/classes/ActiveModel/Serialization.html) or [ActiveModel::Serializers](https://github.com/rails-api/active_model_serializers) but they are not heartily recommended. The former is too coupled to the model and the latter is too coupled to Rails controllers. Vorpal uses [SimpleSerializer](https://github.com/nulogy/simple_serializer) for this purpose.
231
230
 
231
+ **Q.** Are `updated_at` and `created_at` supported?
232
+
233
+ **A.** Yes. If they exist on your database tables, they will behave exactly as if you were using vanilla ActiveRecord.
234
+
232
235
  ## Contributing
233
236
 
234
237
  1. Fork it ( https://github.com/nulogy/vorpal/fork )
@@ -84,6 +84,17 @@ module Vorpal
84
84
  @engine
85
85
  end
86
86
 
87
+ # Returns a 'Vorpal-aware' [ActiveRecord::Relation](https://api.rubyonrails.org/classes/ActiveRecord/Relation.html)
88
+ # for the ActiveRecord object underlying the domain entity mapped by this mapper.
89
+ #
90
+ # This method allows you to easily access the power of ActiveRecord::Relation to do more complex
91
+ # queries in your repositories.
92
+ #
93
+ # The ActiveRecord::Relation is 'Vorpal-aware' because it has the {#load_one} and {#load_many} methods
94
+ # mixed in so that you can get the POROs from your domain model instead of the ActiveRecord
95
+ # objects normally returned by ActiveRecord::Relation.
96
+ #
97
+ # @return [ActiveRecord::Relation]
87
98
  def query
88
99
  @engine.query(@domain_class)
89
100
  end
@@ -9,7 +9,12 @@ module Vorpal
9
9
  end
10
10
 
11
11
  def insert(db_class, db_objects)
12
- if defined? ActiveRecord::Import
12
+ if ActiveRecord::VERSION::MAJOR >= 6
13
+ return if db_objects.empty?
14
+
15
+ update_timestamps_on_create(db_class, db_objects)
16
+ db_class.insert_all!(db_objects.map(&:attributes))
17
+ elsif defined? ActiveRecord::Import
13
18
  db_class.import(db_objects, validate: false)
14
19
  else
15
20
  db_objects.each do |db_object|
@@ -19,8 +24,15 @@ module Vorpal
19
24
  end
20
25
 
21
26
  def update(db_class, db_objects)
22
- db_objects.each do |db_object|
23
- db_object.save!(validate: false)
27
+ if ActiveRecord::VERSION::MAJOR >= 6
28
+ return if db_objects.empty?
29
+
30
+ update_timestamps_on_update(db_class, db_objects)
31
+ db_class.upsert_all(db_objects.map(&:attributes))
32
+ else
33
+ db_objects.each do |db_object|
34
+ db_object.save!(validate: false)
35
+ end
24
36
  end
25
37
  end
26
38
 
@@ -100,6 +112,30 @@ module Vorpal
100
112
 
101
113
  private
102
114
 
115
+ # Adapted from https://github.com/rails/rails/blob/614580270d7789e5275defc3da020ce27b3b2302/activerecord/lib/active_record/timestamp.rb#L99
116
+ def update_timestamps_on_create(db_class, db_objects)
117
+ return unless db_class.record_timestamps
118
+
119
+ current_time = db_class.current_time_from_proper_timezone
120
+ db_objects.each do |db_object|
121
+ db_class.all_timestamp_attributes_in_model.each do |column|
122
+ db_object.write_attribute(column, current_time) unless db_object.read_attribute(column)
123
+ end
124
+ end
125
+ end
126
+
127
+ #Adapted from https://github.com/rails/rails/blob/614580270d7789e5275defc3da020ce27b3b2302/activerecord/lib/active_record/timestamp.rb#L111
128
+ def update_timestamps_on_update(db_class, db_objects)
129
+ return unless db_class.record_timestamps
130
+
131
+ current_time = db_class.current_time_from_proper_timezone
132
+ db_objects.each do |db_object|
133
+ db_class.timestamp_attributes_for_update_in_model.each do |column|
134
+ db_object.write_attribute(column, current_time)
135
+ end
136
+ end
137
+ end
138
+
103
139
  def sequence_name(db_class)
104
140
  @sequence_names[db_class] ||= execute(
105
141
  "SELECT substring(column_default from '''(.*)''') FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = $1 AND column_name = 'id' LIMIT 1",
@@ -1,3 +1,3 @@
1
1
  module Vorpal
2
- VERSION = "1.0.3"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -13,15 +13,16 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = "https://github.com/nulogy/vorpal"
14
14
  spec.license = "MIT"
15
15
 
16
- spec.files = `git ls-files -z`.split("\x0")
17
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
16
+ spec.files = Dir["CHANGELOG.md", "LICENSE.txt", "README.md", "vorpal.gemspec", "lib/**/*"]
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
19
  spec.require_paths = ["lib"]
19
20
 
20
21
  spec.add_runtime_dependency "simple_serializer", "~> 1.0"
21
22
  spec.add_runtime_dependency "equalizer"
22
23
  spec.add_runtime_dependency "activesupport"
23
24
 
24
- spec.add_development_dependency "rake", "~> 10"
25
+ spec.add_development_dependency "rake", "~> 13"
25
26
  spec.add_development_dependency "rspec", "~> 3.0"
26
27
  spec.add_development_dependency "virtus", "~> 1.0"
27
28
  spec.add_development_dependency "appraisal", "~> 2.2"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vorpal
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Kirby
8
- autorequire:
9
- bindir: bin
8
+ autorequire:
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2020-01-31 00:00:00.000000000 Z
11
+ date: 2020-10-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: simple_serializer
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '10'
61
+ version: '13'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '10'
68
+ version: '13'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -172,29 +172,9 @@ executables: []
172
172
  extensions: []
173
173
  extra_rdoc_files: []
174
174
  files:
175
- - ".editorconfig"
176
- - ".envrc"
177
- - ".gitignore"
178
- - ".rspec"
179
- - ".ruby-version"
180
- - ".travis.yml"
181
- - ".yardopts"
182
- - Appraisals
183
175
  - CHANGELOG.md
184
- - Gemfile
185
176
  - LICENSE.txt
186
177
  - README.md
187
- - Rakefile
188
- - bin/appraisal
189
- - bin/rake
190
- - bin/rspec
191
- - docker-compose.yml
192
- - gemfiles/rails_5_1.gemfile
193
- - gemfiles/rails_5_1.gemfile.lock
194
- - gemfiles/rails_5_2.gemfile
195
- - gemfiles/rails_5_2.gemfile.lock
196
- - gemfiles/rails_6_0.gemfile
197
- - gemfiles/rails_6_0.gemfile.lock
198
178
  - lib/vorpal.rb
199
179
  - lib/vorpal/aggregate_mapper.rb
200
180
  - lib/vorpal/aggregate_traversal.rb
@@ -213,27 +193,12 @@ files:
213
193
  - lib/vorpal/util/hash_initialization.rb
214
194
  - lib/vorpal/util/string_utils.rb
215
195
  - lib/vorpal/version.rb
216
- - spec/acceptance/vorpal/aggregate_mapper_spec.rb
217
- - spec/helpers/codecov_helper.rb
218
- - spec/helpers/db_helpers.rb
219
- - spec/helpers/profile_helpers.rb
220
- - spec/integration/vorpal/driver/postgresql_spec.rb
221
- - spec/integration_spec_helper.rb
222
- - spec/performance/vorpal/performance_spec.rb
223
- - spec/unit/vorpal/configs_spec.rb
224
- - spec/unit/vorpal/db_loader_spec.rb
225
- - spec/unit/vorpal/dsl/config_builder_spec.rb
226
- - spec/unit/vorpal/dsl/defaults_generator_spec.rb
227
- - spec/unit/vorpal/identity_map_spec.rb
228
- - spec/unit/vorpal/loaded_objects_spec.rb
229
- - spec/unit/vorpal/util/string_utils_spec.rb
230
- - spec/unit_spec_helper.rb
231
196
  - vorpal.gemspec
232
197
  homepage: https://github.com/nulogy/vorpal
233
198
  licenses:
234
199
  - MIT
235
200
  metadata: {}
236
- post_install_message:
201
+ post_install_message:
237
202
  rdoc_options: []
238
203
  require_paths:
239
204
  - lib
@@ -249,22 +214,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
249
214
  version: '0'
250
215
  requirements: []
251
216
  rubygems_version: 3.1.2
252
- signing_key:
217
+ signing_key:
253
218
  specification_version: 4
254
219
  summary: Separate your domain model from your persistence mechanism.
255
- test_files:
256
- - spec/acceptance/vorpal/aggregate_mapper_spec.rb
257
- - spec/helpers/codecov_helper.rb
258
- - spec/helpers/db_helpers.rb
259
- - spec/helpers/profile_helpers.rb
260
- - spec/integration/vorpal/driver/postgresql_spec.rb
261
- - spec/integration_spec_helper.rb
262
- - spec/performance/vorpal/performance_spec.rb
263
- - spec/unit/vorpal/configs_spec.rb
264
- - spec/unit/vorpal/db_loader_spec.rb
265
- - spec/unit/vorpal/dsl/config_builder_spec.rb
266
- - spec/unit/vorpal/dsl/defaults_generator_spec.rb
267
- - spec/unit/vorpal/identity_map_spec.rb
268
- - spec/unit/vorpal/loaded_objects_spec.rb
269
- - spec/unit/vorpal/util/string_utils_spec.rb
270
- - spec/unit_spec_helper.rb
220
+ test_files: []
@@ -1,13 +0,0 @@
1
- root = true
2
-
3
- [*]
4
-
5
- indent_style = space
6
- indent_size = 2
7
- end_of_line = lf
8
- charset = utf-8
9
- trim_trailing_whitespace = true
10
- insert_final_newline = true
11
-
12
- [*.md]
13
- trim_trailing_whitespace = false
data/.envrc DELETED
@@ -1,4 +0,0 @@
1
- #@IgnoreInspection BashAddShebang
2
- # Configuration for direnv (see https://github.com/direnv/direnv)
3
-
4
- PATH_add bin
data/.gitignore DELETED
@@ -1,16 +0,0 @@
1
- /.bundle/
2
- /.idea/
3
- /.yardoc
4
- /Gemfile.lock
5
- /_yardoc/
6
- /coverage/
7
- /doc/
8
- /pkg/
9
- /spec/reports/
10
- /tmp/
11
- *.bundle
12
- *.so
13
- *.o
14
- *.a
15
- mkmf.log
16
- /projectFilesBackup
data/.rspec DELETED
@@ -1 +0,0 @@
1
- --colour
@@ -1 +0,0 @@
1
- 2.7.0
@@ -1,18 +0,0 @@
1
- language: ruby
2
- services:
3
- - postgresql
4
- matrix:
5
- include:
6
- - rvm: 2.5.7
7
- gemfile: gemfiles/rails_5_1.gemfile
8
- - rvm: 2.6
9
- gemfile: gemfiles/rails_5_1.gemfile
10
- - rvm: 2.6
11
- gemfile: gemfiles/rails_5_2.gemfile
12
- - rvm: 2.7
13
- gemfile: gemfiles/rails_6_0.gemfile
14
- cache:
15
- - bundler
16
- script: "bundle exec rake"
17
- env:
18
- - CODECOV_TOKEN="fab4ddb8-ba2c-47cb-a407-941209ad54a4"
data/.yardopts DELETED
@@ -1 +0,0 @@
1
- --no-private -m markdown lib/**/*.*
data/Appraisals DELETED
@@ -1,18 +0,0 @@
1
- appraise "rails-6-0" do
2
- ruby ">= 2.7.0"
3
- gem "activerecord", "~> 6.0.0"
4
- end
5
-
6
- appraise "rails-5-2" do
7
- ruby ">= 2.5.7"
8
- gem "activerecord", "~> 5.2.0"
9
- gem "pg", "~> 0.18.0"
10
- gem "activerecord-import", "= 0.13.0"
11
- end
12
-
13
- appraise "rails-5-1" do
14
- ruby ">= 2.5.7"
15
- gem "activerecord", "~> 5.1.0"
16
- gem "pg", "~> 0.18.0"
17
- gem "activerecord-import", "= 0.13.0"
18
- end
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in vorpal.gemspec
4
- gemspec
data/Rakefile DELETED
@@ -1,39 +0,0 @@
1
- #!/usr/bin/env rake
2
- begin
3
- require "bundler/gem_tasks"
4
- rescue LoadError
5
- puts 'You must `gem install bundler` and `bundle install` to run rake tasks associated with creating new versions of the gem.'
6
- end
7
-
8
- begin
9
- require 'rspec/core/rake_task'
10
-
11
- namespace :spec do
12
- RSpec::Core::RakeTask.new(:acceptance) do |t|
13
- t.pattern = "spec/acceptance/**/*_spec.rb"
14
- end
15
-
16
- RSpec::Core::RakeTask.new(:integration) do |t|
17
- t.pattern = "spec/integration/**/*_spec.rb"
18
- end
19
-
20
- RSpec::Core::RakeTask.new(:performance) do |t|
21
- t.pattern = "spec/performance/**/*_spec.rb"
22
- end
23
-
24
- RSpec::Core::RakeTask.new(:unit) do |t|
25
- t.pattern = "spec/unit/**/*_spec.rb"
26
- end
27
-
28
- desc "Run all non-performance related specs"
29
- task non_perf: [:unit, :integration, :acceptance]
30
-
31
- desc "Run all specs"
32
- task all: [:acceptance, :integration, :unit, :performance]
33
- end
34
-
35
- task default: :'spec:all'
36
- rescue LoadError
37
- # Allow the Rakefile to be used in environments where the RSpec gem is unavailable
38
- # (e.g. Production)
39
- end
@@ -1,29 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- #
5
- # This file was generated by Bundler.
6
- #
7
- # The application 'appraisal' is installed as part of a gem, and
8
- # this file is here to facilitate running it.
9
- #
10
-
11
- require "pathname"
12
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
- Pathname.new(__FILE__).realpath)
14
-
15
- bundle_binstub = File.expand_path("../bundle", __FILE__)
16
-
17
- if File.file?(bundle_binstub)
18
- if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
- load(bundle_binstub)
20
- else
21
- abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
- Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
- end
24
- end
25
-
26
- require "rubygems"
27
- require "bundler/setup"
28
-
29
- load Gem.bin_path("appraisal", "appraisal")