vorpal 1.0.3 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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")