vorpal 1.0.0 → 1.2.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.
- checksums.yaml +4 -4
- data/README.md +85 -47
- data/lib/vorpal/aggregate_mapper.rb +11 -0
- data/lib/vorpal/config/class_config.rb +71 -0
- data/lib/vorpal/configs.rb +9 -66
- data/lib/vorpal/driver/postgresql.rb +40 -4
- data/lib/vorpal/dsl/config_builder.rb +12 -50
- data/lib/vorpal/dsl/configuration.rb +131 -42
- data/lib/vorpal/dsl/defaults_generator.rb +14 -4
- data/lib/vorpal/engine.rb +16 -3
- data/lib/vorpal/identity_map.rb +15 -14
- data/lib/vorpal/version.rb +1 -1
- data/vorpal.gemspec +11 -10
- metadata +43 -63
- data/.editorconfig +0 -13
- data/.gitignore +0 -16
- data/.rspec +0 -1
- data/.yardopts +0 -1
- data/Gemfile +0 -4
- data/Rakefile +0 -10
- data/spec/helpers/db_helpers.rb +0 -51
- data/spec/helpers/profile_helpers.rb +0 -26
- data/spec/integration_spec_helper.rb +0 -36
- data/spec/unit_spec_helper.rb +0 -0
- data/spec/vorpal/acceptance/aggregate_mapper_spec.rb +0 -911
- data/spec/vorpal/integration/driver/postgresql_spec.rb +0 -42
- data/spec/vorpal/performance/performance_spec.rb +0 -195
- data/spec/vorpal/unit/configs_spec.rb +0 -117
- data/spec/vorpal/unit/db_loader_spec.rb +0 -103
- data/spec/vorpal/unit/dsl/config_builder_spec.rb +0 -18
- data/spec/vorpal/unit/dsl/defaults_generator_spec.rb +0 -75
- data/spec/vorpal/unit/identity_map_spec.rb +0 -62
- data/spec/vorpal/unit/loaded_objects_spec.rb +0 -22
- data/spec/vorpal/unit/util/string_utils_spec.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf920ae279d48b7b9db84a79c77eeb521602a885c8fe88e8f2121e47a5a46e41
|
4
|
+
data.tar.gz: 9e97596434cf65e598279005a0bb325cadde5d7a6d3f2180ea5a828432f89760
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d7c07c613b24c7d342be0361e33bda6db6cff0270222db1b7ca8018cf141fb623b2583e49a0d39db51d53389225e527d6a5fd74f133edc6f7653309e86644be4
|
7
|
+
data.tar.gz: 492d62d23506de0e26ffdc8e525169dcb78d6c1060dc9309c9828e9865f2341e8f01cc84fe95a059d01d89462c62292a67ebcfc4148ce4ace770884a56e5e04c
|
data/README.md
CHANGED
@@ -1,16 +1,13 @@
|
|
1
|
-
# Vorpal [](https://travis-ci.com/nulogy/vorpal) [](https://codeclimate.com/github/nulogy/vorpal) [](https://codecov.io/gh/nulogy/vorpal/branch/main)
|
2
2
|
|
3
3
|
Separate your domain model from your persistence mechanism. Some problems call for a really sharp tool.
|
4
4
|
|
5
|
-
|
6
|
-
>
|
7
|
-
|
8
|
-
> The vorpal blade went snicker-snack!
|
9
|
-
|
10
|
-
> He left it dead, and with its head
|
11
|
-
|
5
|
+
> One, two! One, two! and through and through<br/>
|
6
|
+
> The vorpal blade went snicker-snack!<br/>
|
7
|
+
> He left it dead, and with its head<br/>
|
12
8
|
> He went galumphing back.
|
13
9
|
|
10
|
+
\- [Jabberwocky](https://www.poetryfoundation.org/poems/42916/jabberwocky) by Lewis Carroll
|
14
11
|
|
15
12
|
## Overview
|
16
13
|
Vorpal is a [Data Mapper](http://martinfowler.com/eaaCatalog/dataMapper.html)-style ORM (object relational mapper) framelet that persists POROs (plain old Ruby objects) to a relational DB. It has been heavily influenced by concepts from [Domain Driven Design](http://www.infoq.com/minibooks/domain-driven-design-quickly).
|
@@ -48,27 +45,21 @@ Or install it yourself as:
|
|
48
45
|
Start with a domain model of POROs and AR::Base objects that form an aggregate:
|
49
46
|
|
50
47
|
```ruby
|
51
|
-
class Tree; end
|
52
|
-
|
53
48
|
class Branch
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
attribute :diameter, Decimal
|
59
|
-
attribute :tree, Tree
|
49
|
+
attr_accessor :id
|
50
|
+
attr_accessor :length
|
51
|
+
attr_accessor :diameter
|
52
|
+
attr_accessor :tree
|
60
53
|
end
|
61
54
|
|
62
|
-
class Gardener
|
55
|
+
class Gardener
|
63
56
|
end
|
64
57
|
|
65
58
|
class Tree
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
attribute :gardener, Gardener
|
71
|
-
attribute :branches, Array[Branch]
|
59
|
+
attr_accessor :id
|
60
|
+
attr_accessor :name
|
61
|
+
attr_accessor :gardener
|
62
|
+
attr_accessor :branches
|
72
63
|
end
|
73
64
|
```
|
74
65
|
|
@@ -143,7 +134,8 @@ module TreeRepository
|
|
143
134
|
end
|
144
135
|
```
|
145
136
|
|
146
|
-
Here we've used the `owned` flag on the `belongs_to` from the Tree to the Gardener to show
|
137
|
+
Here we've used the `owned: false` flag on the `belongs_to` from the Tree to the Gardener to show
|
138
|
+
that the Gardener is on the aggregate boundary.
|
147
139
|
|
148
140
|
And use it:
|
149
141
|
|
@@ -164,9 +156,35 @@ TreeRepository.destroy(dead_tree)
|
|
164
156
|
TreeRepository.destroy_by_id(dead_tree_id)
|
165
157
|
```
|
166
158
|
|
159
|
+
### Ids
|
160
|
+
|
161
|
+
Vorpal by default will use auto-incrementing Integers from a DB sequence for ids. However, UUID v4 ids are also
|
162
|
+
supported:
|
163
|
+
|
164
|
+
```ruby
|
165
|
+
Vorpal.define do
|
166
|
+
# UUID v4 id!
|
167
|
+
map Tree, primary_key_type: :uuid do
|
168
|
+
# ..
|
169
|
+
end
|
170
|
+
|
171
|
+
# Also a UUID v4 id, the Rails Way!
|
172
|
+
map Trunk, id: :uuid do
|
173
|
+
# ..
|
174
|
+
end
|
175
|
+
|
176
|
+
# If you feel the need to specify an auto-incrementing integer id.
|
177
|
+
map Branch, primary_key_type: :serial do
|
178
|
+
# ..
|
179
|
+
end
|
180
|
+
end
|
181
|
+
```
|
182
|
+
|
183
|
+
CAVEAT: Vorpal currently does NOT SUPPORT anyone but Vorpal setting the id of an entity!
|
184
|
+
|
167
185
|
## API Documentation
|
168
186
|
|
169
|
-
http://rubydoc.info/github/nulogy/vorpal/
|
187
|
+
http://rubydoc.info/github/nulogy/vorpal/main/frames
|
170
188
|
|
171
189
|
## Caveats
|
172
190
|
It also does not do some things that you might expect from other ORMs:
|
@@ -174,7 +192,7 @@ It also does not do some things that you might expect from other ORMs:
|
|
174
192
|
1. No lazy loading of associations. This might sound like a big deal, but with [correctly designed aggregates](http://dddcommunity.org/library/vernon_2011/) it turns out not to be.
|
175
193
|
1. No managing of transactions. It is the strong opinion of the authors that managing transactions is an application-level concern.
|
176
194
|
1. No support for validations. Validations are not a persistence concern.
|
177
|
-
1. No AR-style callbacks. Use Infrastructure, Application, or Domain
|
195
|
+
1. No AR-style callbacks. Use [Infrastructure, Application, or Domain services](http://martinfowler.com/bliki/EvansClassification.html) instead.
|
178
196
|
1. No has-many-through associations. Use two has-many associations to a join entity instead.
|
179
197
|
1. The `id` attribute is reserved for database primary keys. If you have a natural key/id on your domain model, name it something that makes sense for your domain. It is the strong opinion of the authors that using natural keys as foreign keys is a bad idea. This mixes domain and persistence concerns.
|
180
198
|
|
@@ -183,13 +201,10 @@ It also does not do some things that you might expect from other ORMs:
|
|
183
201
|
1. Only supports PostgreSQL.
|
184
202
|
|
185
203
|
## Future Enhancements
|
186
|
-
*
|
187
|
-
* Support for other DBMSs (no MySQL support until ids can be generated without inserting into a table!)
|
188
|
-
* Support for other ORMs.
|
189
|
-
* Value objects.
|
190
|
-
* Remove dependency on ActiveRecord (optimistic locking? updated_at, created_at support? Data type conversions? TimeZone support?)
|
191
|
-
* More efficient updates (use fewer queries.)
|
204
|
+
* Support for clients to set UUID-based ids.
|
192
205
|
* Nicer DSL for specifying attributes that have different names in the domain model than in the DB.
|
206
|
+
* Aggregate updated_at.
|
207
|
+
* Better support for value objects.
|
193
208
|
|
194
209
|
## FAQ
|
195
210
|
|
@@ -205,11 +220,12 @@ It also does not do some things that you might expect from other ORMs:
|
|
205
220
|
|
206
221
|
**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.
|
207
222
|
|
208
|
-
For example:
|
223
|
+
For example, use the [#query](https://rubydoc.info/github/nulogy/vorpal/main/Vorpal/AggregateMapper#query-instance_method) method on the [AggregateMapper](https://rubydoc.info/github/nulogy/vorpal/main/Vorpal/AggregateMapper) to access the underyling [ActiveRecordRelation](https://api.rubyonrails.org/classes/ActiveRecord/Relation.html):
|
209
224
|
|
210
225
|
```ruby
|
211
|
-
def
|
212
|
-
|
226
|
+
def find_special_ones
|
227
|
+
# use `load_all` or `load_one` to convert from ActiveRecord objects to domain POROs.
|
228
|
+
@mapper.query.where(special: true).load_all
|
213
229
|
end
|
214
230
|
```
|
215
231
|
|
@@ -231,19 +247,9 @@ For example:
|
|
231
247
|
|
232
248
|
**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.
|
233
249
|
|
234
|
-
|
250
|
+
**Q.** Are `updated_at` and `created_at` supported?
|
235
251
|
|
236
|
-
|
237
|
-
2. Either:
|
238
|
-
* Create a DB user called `vorpal` with password `pass`. OR:
|
239
|
-
* Modify `spec/helpers/db_helpers.rb`.
|
240
|
-
3. Run `rake` from the terminal.
|
241
|
-
|
242
|
-
## Contributors
|
243
|
-
|
244
|
-
* [Sean Kirby](https://github.com/sskirby)
|
245
|
-
* [Paul Sobocinski](https://github.com/psobocinski)
|
246
|
-
* [Jason Cheong-Kee-You](https://github.com/jchunky)
|
252
|
+
**A.** Yes. If they exist on your database tables, they will behave exactly as if you were using vanilla ActiveRecord.
|
247
253
|
|
248
254
|
## Contributing
|
249
255
|
|
@@ -252,3 +258,35 @@ For example:
|
|
252
258
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
253
259
|
4. Push to the branch (`git push origin my-new-feature`)
|
254
260
|
5. Create a new Pull Request
|
261
|
+
|
262
|
+
## OSX Environment setup
|
263
|
+
|
264
|
+
1. Install [Homebrew](https://brew.sh/)
|
265
|
+
2. Install [rbenv](https://github.com/rbenv/rbenv#installation) ([RVM](https://rvm.io/) can work too)
|
266
|
+
3. Install [DirEnv](https://direnv.net/docs/installation.html) (`brew install direnv`)
|
267
|
+
4. Install Docker Desktop Community Edition (`brew cask install docker`)
|
268
|
+
5. Start Docker Desktop Community Edition (`CMD+space docker ENTER`)
|
269
|
+
6. Install Ruby (`rbenv install 2.7.0`)
|
270
|
+
7. Install PostgreSQL (`brew install postgresql`)
|
271
|
+
8. Clone the repo (`git clone git@github.com:nulogy/vorpal.git`) and `cd` to the project root.
|
272
|
+
8. Copy the contents of `gemfiles/rails_<version>.gemfile.lock` into a `Gemfile.lock` file
|
273
|
+
at the root of the project. (`cp gemfiles/rails_6_0.gemfile.lock gemfile.lock`)
|
274
|
+
9. `bundle`
|
275
|
+
|
276
|
+
### Running Tests
|
277
|
+
|
278
|
+
1. Start a PostgreSQL server using `docker-compose up`
|
279
|
+
3. Run `rake` from the terminal to run all specs or `rspec <path to spec file>` to
|
280
|
+
run a single spec.
|
281
|
+
|
282
|
+
### Running Tests for a specific version of Rails
|
283
|
+
|
284
|
+
1. Start a PostgreSQL server using `docker-compose up`
|
285
|
+
2. Run `appraisal rails-5-2 rake` from the terminal to run all specs or
|
286
|
+
`appraisal rails-5-2 rspec <path to spec file>` to run a single spec.
|
287
|
+
|
288
|
+
Please see the [Appraisal gem docs](https://github.com/thoughtbot/appraisal) for more information.
|
289
|
+
|
290
|
+
## Contributors
|
291
|
+
|
292
|
+
See who's [contributed](https://github.com/nulogy/vorpal/graphs/contributors)!
|
@@ -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
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'equalizer'
|
2
|
+
|
3
|
+
module Vorpal
|
4
|
+
module Config
|
5
|
+
# @private
|
6
|
+
class ClassConfig
|
7
|
+
include Equalizer.new(:domain_class, :db_class)
|
8
|
+
attr_reader :serializer, :deserializer, :domain_class, :db_class, :primary_key_type, :local_association_configs
|
9
|
+
attr_accessor :has_manys, :belongs_tos, :has_ones
|
10
|
+
|
11
|
+
ALLOWED_PRIMARY_KEY_TYPE_OPTIONS = [:serial, :uuid]
|
12
|
+
|
13
|
+
def initialize(attrs)
|
14
|
+
@has_manys = []
|
15
|
+
@belongs_tos = []
|
16
|
+
@has_ones = []
|
17
|
+
@local_association_configs = []
|
18
|
+
|
19
|
+
@serializer = attrs[:serializer]
|
20
|
+
@deserializer = attrs[:deserializer]
|
21
|
+
@domain_class = attrs[:domain_class]
|
22
|
+
@db_class = attrs[:db_class]
|
23
|
+
@primary_key_type = attrs[:primary_key_type]
|
24
|
+
raise "Invalid primary_key_type: '#{@primary_key_type}'" unless ALLOWED_PRIMARY_KEY_TYPE_OPTIONS.include?(@primary_key_type)
|
25
|
+
end
|
26
|
+
|
27
|
+
def build_db_object(attributes)
|
28
|
+
db_class.new(attributes)
|
29
|
+
end
|
30
|
+
|
31
|
+
def set_db_object_attributes(db_object, attributes)
|
32
|
+
db_object.attributes = attributes
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_db_object_attributes(db_object)
|
36
|
+
symbolize_keys(db_object.attributes)
|
37
|
+
end
|
38
|
+
|
39
|
+
def serialization_required?
|
40
|
+
domain_class.superclass.name != 'ActiveRecord::Base'
|
41
|
+
end
|
42
|
+
|
43
|
+
def serialize(object)
|
44
|
+
serializer.serialize(object)
|
45
|
+
end
|
46
|
+
|
47
|
+
def deserialize(db_object)
|
48
|
+
attributes = get_db_object_attributes(db_object)
|
49
|
+
serialization_required? ? deserializer.deserialize(domain_class.new, attributes) : db_object
|
50
|
+
end
|
51
|
+
|
52
|
+
def set_attribute(db_object, attribute, value)
|
53
|
+
db_object.send("#{attribute}=", value)
|
54
|
+
end
|
55
|
+
|
56
|
+
def get_attribute(db_object, attribute)
|
57
|
+
db_object.send(attribute)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def symbolize_keys(hash)
|
63
|
+
result = {}
|
64
|
+
hash.each_key do |key|
|
65
|
+
result[key.to_sym] = hash[key]
|
66
|
+
end
|
67
|
+
result
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/vorpal/configs.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'vorpal/util/hash_initialization'
|
2
2
|
require 'vorpal/exceptions'
|
3
|
+
require 'vorpal/config/class_config'
|
3
4
|
require 'equalizer'
|
4
5
|
|
5
6
|
module Vorpal
|
6
7
|
# @private
|
7
|
-
class
|
8
|
-
def initialize
|
9
|
-
@class_configs =
|
10
|
-
initialize_association_configs
|
8
|
+
class MainConfig
|
9
|
+
def initialize
|
10
|
+
@class_configs = []
|
11
11
|
end
|
12
12
|
|
13
13
|
def config_for(clazz)
|
@@ -20,7 +20,9 @@ module Vorpal
|
|
20
20
|
@class_configs.detect { |conf| conf.db_class == db_object.class }
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
def add_class_config(class_config)
|
24
|
+
@class_configs << class_config
|
25
|
+
end
|
24
26
|
|
25
27
|
def initialize_association_configs
|
26
28
|
association_configs = {}
|
@@ -50,6 +52,8 @@ module Vorpal
|
|
50
52
|
end
|
51
53
|
end
|
52
54
|
|
55
|
+
private
|
56
|
+
|
53
57
|
def build_association_config(association_configs, local_config, fk, fk_type)
|
54
58
|
association_config = AssociationConfig.new(local_config, fk, fk_type)
|
55
59
|
if association_configs[association_config]
|
@@ -126,67 +130,6 @@ module Vorpal
|
|
126
130
|
end
|
127
131
|
end
|
128
132
|
|
129
|
-
# @private
|
130
|
-
class ClassConfig
|
131
|
-
include Equalizer.new(:domain_class, :db_class)
|
132
|
-
attr_reader :serializer, :deserializer, :domain_class, :db_class, :local_association_configs
|
133
|
-
attr_accessor :has_manys, :belongs_tos, :has_ones
|
134
|
-
|
135
|
-
def initialize(attrs)
|
136
|
-
@has_manys = []
|
137
|
-
@belongs_tos = []
|
138
|
-
@has_ones = []
|
139
|
-
@local_association_configs = []
|
140
|
-
|
141
|
-
attrs.each do |k,v|
|
142
|
-
instance_variable_set("@#{k}", v)
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
def build_db_object(attributes)
|
147
|
-
db_class.new(attributes)
|
148
|
-
end
|
149
|
-
|
150
|
-
def set_db_object_attributes(db_object, attributes)
|
151
|
-
db_object.attributes = attributes
|
152
|
-
end
|
153
|
-
|
154
|
-
def get_db_object_attributes(db_object)
|
155
|
-
symbolize_keys(db_object.attributes)
|
156
|
-
end
|
157
|
-
|
158
|
-
def serialization_required?
|
159
|
-
domain_class.superclass.name != 'ActiveRecord::Base'
|
160
|
-
end
|
161
|
-
|
162
|
-
def serialize(object)
|
163
|
-
serializer.serialize(object)
|
164
|
-
end
|
165
|
-
|
166
|
-
def deserialize(db_object)
|
167
|
-
attributes = get_db_object_attributes(db_object)
|
168
|
-
serialization_required? ? deserializer.deserialize(domain_class.new, attributes) : db_object
|
169
|
-
end
|
170
|
-
|
171
|
-
def set_attribute(db_object, attribute, value)
|
172
|
-
db_object.send("#{attribute}=", value)
|
173
|
-
end
|
174
|
-
|
175
|
-
def get_attribute(db_object, attribute)
|
176
|
-
db_object.send(attribute)
|
177
|
-
end
|
178
|
-
|
179
|
-
private
|
180
|
-
|
181
|
-
def symbolize_keys(hash)
|
182
|
-
result = {}
|
183
|
-
hash.each_key do |key|
|
184
|
-
result[key.to_sym] = hash[key]
|
185
|
-
end
|
186
|
-
result
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
133
|
# @private
|
191
134
|
class ForeignKeyInfo
|
192
135
|
include Equalizer.new(:fk_column, :fk_type_column, :fk_type)
|
@@ -9,7 +9,12 @@ module Vorpal
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def insert(db_class, db_objects)
|
12
|
-
if
|
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,13 +24,20 @@ module Vorpal
|
|
19
24
|
end
|
20
25
|
|
21
26
|
def update(db_class, db_objects)
|
22
|
-
|
23
|
-
|
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
|
|
27
39
|
def destroy(db_class, ids)
|
28
|
-
db_class.
|
40
|
+
db_class.where(id: ids).delete_all
|
29
41
|
end
|
30
42
|
|
31
43
|
# Loads instances of the given class by primary key.
|
@@ -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",
|