jet_set 0.3.2 → 0.5.3
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 +5 -5
- data/Gemfile +0 -1
- data/README.md +153 -5
- data/jet_set.gemspec +7 -8
- data/lib/jet_set.rb +3 -0
- data/lib/jet_set/entity_builder.rb +2 -0
- data/lib/jet_set/mapper.rb +13 -5
- data/lib/jet_set/mixin/entity.rb +5 -1
- data/lib/jet_set/row.rb +6 -1
- data/lib/jet_set/session.rb +21 -6
- data/lib/jet_set/validation_definition_error.rb +4 -0
- data/lib/jet_set/validation_error.rb +10 -0
- data/lib/jet_set/validations.rb +97 -0
- data/lib/jet_set/version.rb +1 -1
- metadata +27 -26
- data/test.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: bb3d54a41c9a91c8761053dd1ba08314f3f5416f9b9762cace0758bdb32e2c5f
|
4
|
+
data.tar.gz: 94c834a0a75d2cf2bae2a25d8e57b24ac68b7870e6e61ed6fc1fafb62c9e5a8c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e08aeb9e15d4918b310dcf33b03e9df48fa555ade341901518b21fa51b67eb4c22b98d184922ef7291baeb3edf08171e2737e90580b61e563e61f9452159645
|
7
|
+
data.tar.gz: 024b1e91903efb225aac4142932ce67abed52eb16681214ccf2a6803d72c929c77e183fb1352e58124bec1a70b2786320eabf426bd212a99ae0fcdf6a1d6cc3d
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
# JetSet 
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
TODO: Delete this and the text above, and describe your gem
|
3
|
+
JetSet is a data mapping framework for domain-driven developers who think that SQL is the best tool for data querying.
|
4
|
+
JetSet is built on top of [Sequel](https://github.com/jeremyevans/sequel) ORM and it's just an abstraction for making
|
5
|
+
the persistence of mapped objects invisible.
|
7
6
|
|
8
7
|
## Installation
|
9
8
|
|
@@ -23,7 +22,156 @@ Or install it yourself as:
|
|
23
22
|
|
24
23
|
## Usage
|
25
24
|
|
26
|
-
|
25
|
+
### Initialization
|
26
|
+
Open DB connection, see [Sequel docs](https://sequel.jeremyevans.net/rdoc/files/doc/opening_databases_rdoc.html):
|
27
|
+
```ruby
|
28
|
+
@connection = Sequel.connect('sqlite:/') # you can connect to any DB supported by Sequel
|
29
|
+
```
|
30
|
+
|
31
|
+
Create a mapping of your model, details described [here]:
|
32
|
+
```ruby
|
33
|
+
class Mapping
|
34
|
+
def self.load_mapping
|
35
|
+
JetSet::map do
|
36
|
+
entity User do
|
37
|
+
field :first_name # reqular field
|
38
|
+
collection :invoices, type: Invoice # "has many" association
|
39
|
+
reference :plan, type: Plan, weak: true # "belongs to" association
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
Init JetSet environment on start of your application:
|
47
|
+
```ruby
|
48
|
+
JetSet::init(Mapping.load_mapping, @container)
|
49
|
+
```
|
50
|
+
|
51
|
+
Open JetSet session:
|
52
|
+
```ruby
|
53
|
+
@jet_set = JetSet::open_session(@connection)
|
54
|
+
```
|
55
|
+
For web-applications it's reasonable to bind JetSet session to request lifetime -
|
56
|
+
all modification operations in an MVC action can represent a ["Unit of Work"](https://martinfowler.com/eaaCatalog/unitOfWork.html).
|
57
|
+
|
58
|
+
### Object model
|
59
|
+
Using JetSet you can wrap an application domain model and purely implement "Persistence Ignorance" approach.
|
60
|
+
The model objects are pure Ruby objects without any noisy stuff like annotations, inline mapping, etc:
|
61
|
+
```ruby
|
62
|
+
class User
|
63
|
+
attr_reader :invoices
|
64
|
+
|
65
|
+
def initialize(attrs = {})
|
66
|
+
@first_name = attrs[:first_name]
|
67
|
+
@last_name = attrs[:last_name]
|
68
|
+
@invoices = []
|
69
|
+
end
|
70
|
+
|
71
|
+
def add_invoice(invoice)
|
72
|
+
@invoices << invoice
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
class Invoice
|
77
|
+
attr_reader :created_at, :amount
|
78
|
+
|
79
|
+
def initialize(attrs = {})
|
80
|
+
@created_at = DateTime.now
|
81
|
+
@amount = attrs[:amount] || 0
|
82
|
+
end
|
83
|
+
end
|
84
|
+
```
|
85
|
+
|
86
|
+
### Object model tracking and saving
|
87
|
+
Create an objects which is described in the mapping:
|
88
|
+
```ruby
|
89
|
+
user = User.new(first_name: 'Ivan', last_name: 'Ivanov')
|
90
|
+
invoice = Invoice.new(created_at: DateTime.now, user: user, amount: 100.0)
|
91
|
+
```
|
92
|
+
|
93
|
+
Attach them to the session:
|
94
|
+
```ruby
|
95
|
+
@session.attach(invoice, user)
|
96
|
+
```
|
97
|
+
It makes the objects tracked by JetSet.
|
98
|
+
|
99
|
+
Finalize the session:
|
100
|
+
```ruby
|
101
|
+
@session.finalize
|
102
|
+
```
|
103
|
+
It saves all added/changed objects to the database.
|
104
|
+
|
105
|
+
### Object model loading
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
user_query = <<~SQL
|
109
|
+
SELECT
|
110
|
+
u.* AS ENTITY user
|
111
|
+
FROM users u
|
112
|
+
LIMIT 1
|
113
|
+
SQL
|
114
|
+
|
115
|
+
invoices_sql = <<~SQL
|
116
|
+
SELECT
|
117
|
+
i.* AS ENTITY invoice
|
118
|
+
WHERE i.user_id = :user_id
|
119
|
+
SQL
|
120
|
+
|
121
|
+
customer = @session.fetch(User, user_query) do |user|
|
122
|
+
preload(user, :invoices, invoices_sql, user_id: user.id)
|
123
|
+
end
|
124
|
+
```
|
125
|
+
All loaded objects are already attached to the session and you can perform a changes which will be saved after the session finalization:
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
customer.invoices[0].apply # changes invoice state
|
129
|
+
@session.finalize
|
130
|
+
```
|
131
|
+
|
132
|
+
Do not load your object model just for drawing a views. For showing a results just use Sequel without any object mappings:
|
133
|
+
```ruby
|
134
|
+
result = @connection[:user].where(role: 'admin').to_a
|
135
|
+
json = JSON.generate(data: result)
|
136
|
+
```
|
137
|
+
In other words, following [CQS](https://en.wikipedia.org/wiki/Command%E2%80%93query_separation) approach you can
|
138
|
+
load your model for a command but not for a query.
|
139
|
+
|
140
|
+
### Validation
|
141
|
+
Simple validation is optional feature provided by JetSet out of the box. To add this to your domain object you just need
|
142
|
+
to include module `JetSet::Validations` and use `validate` statements:
|
143
|
+
|
144
|
+
```ruby
|
145
|
+
require 'jet_set/validations'
|
146
|
+
|
147
|
+
class User
|
148
|
+
include JetSet::Validations
|
149
|
+
validate :name, 'cannot be empty', -> (value) {!value.nil? && !value.empty?}
|
150
|
+
validate :email, type: :string, presence: true
|
151
|
+
validate :email, 'should be valid email address', -> (value) {value.match(...)}
|
152
|
+
|
153
|
+
def initialize(attrs = {})
|
154
|
+
@name = attrs[:name]
|
155
|
+
end
|
156
|
+
end
|
157
|
+
```
|
158
|
+
JetSet uses such validations automatically on saving objects in the database. Also you can invoke validation manually,
|
159
|
+
i.e. in unit tests, using `validate!` method:
|
160
|
+
|
161
|
+
```ruby
|
162
|
+
user = User.new(name: nil)
|
163
|
+
user.validate! # raises JetSet::ValidationError
|
164
|
+
```
|
165
|
+
|
166
|
+
`JetSet::ValidationError` contains details regarding invalid items like:
|
167
|
+
|
168
|
+
```ruby
|
169
|
+
error.invalid_items # => {name: 'cannot be empty'}
|
170
|
+
```
|
171
|
+
|
172
|
+
|
173
|
+
|
174
|
+
You can find more interesting examples in [JetSet integration tests](https://github.com/cylon-v/jet_set/tree/master/spec/integration).
|
27
175
|
|
28
176
|
## Development
|
29
177
|
|
data/jet_set.gemspec
CHANGED
@@ -30,12 +30,11 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
31
31
|
spec.require_paths = ['lib']
|
32
32
|
|
33
|
-
spec.add_dependency 'sequel', '
|
34
|
-
spec.add_dependency 'hypo', '
|
35
|
-
|
36
|
-
spec.add_development_dependency '
|
37
|
-
spec.add_development_dependency '
|
38
|
-
spec.add_development_dependency '
|
39
|
-
spec.add_development_dependency '
|
40
|
-
spec.add_development_dependency 'simplecov', '~> 0.16'
|
33
|
+
spec.add_dependency 'sequel', '>= 5.4.0'
|
34
|
+
spec.add_dependency 'hypo', '>= 1.0.0'
|
35
|
+
spec.add_development_dependency 'bundler', '>= 2.1'
|
36
|
+
spec.add_development_dependency 'rake', '>= 10.0'
|
37
|
+
spec.add_development_dependency 'rspec', '>= 3.0'
|
38
|
+
spec.add_development_dependency 'sqlite3', '>= 1.3'
|
39
|
+
spec.add_development_dependency 'simplecov', '>= 0.16'
|
41
40
|
end
|
data/lib/jet_set.rb
CHANGED
@@ -3,6 +3,9 @@ require 'sequel'
|
|
3
3
|
require 'sequel/extensions/inflector'
|
4
4
|
require 'jet_set/environment'
|
5
5
|
require 'jet_set/mapping'
|
6
|
+
require 'jet_set/validations'
|
7
|
+
require 'jet_set/validation_error'
|
8
|
+
require 'jet_set/validation_definition_error'
|
6
9
|
require 'jet_set/version'
|
7
10
|
|
8
11
|
module JetSet
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'jet_set/mixin/identity'
|
2
2
|
require 'jet_set/mixin/entity'
|
3
|
+
require 'jet_set/validations'
|
3
4
|
|
4
5
|
module JetSet
|
5
6
|
# A converter of a pure Ruby object to JetSet trackable object.
|
@@ -22,6 +23,7 @@ module JetSet
|
|
22
23
|
|
23
24
|
object.extend(Identity)
|
24
25
|
object.extend(Entity)
|
26
|
+
object.extend(Validations)
|
25
27
|
end
|
26
28
|
end
|
27
29
|
end
|
data/lib/jet_set/mapper.rb
CHANGED
@@ -15,7 +15,8 @@ module JetSet
|
|
15
15
|
@container = container
|
16
16
|
|
17
17
|
@mapping.entity_mappings.values.each do |entity_mapping|
|
18
|
-
|
18
|
+
entity_name = "jet_set__#{entity_mapping.type.name.underscore}".to_sym
|
19
|
+
container.register(entity_mapping.type, entity_name)
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
@@ -29,22 +30,29 @@ module JetSet
|
|
29
30
|
# "SELECT u.name AS customer__name from users u"
|
30
31
|
def map(type, row_hash, session, prefix = type.name.underscore)
|
31
32
|
entity_name = type.name.underscore.to_sym
|
33
|
+
resolve_name = "jet_set__#{type.name.underscore}".to_sym
|
32
34
|
entity_mapping = @mapping.get(entity_name)
|
33
35
|
row = Row.new(row_hash, entity_mapping.fields, prefix)
|
34
|
-
object = @container.resolve(entity_name)
|
35
|
-
entity = @entity_builder.create(object)
|
36
|
-
entity.load_attributes!(row.attributes)
|
37
36
|
|
37
|
+
reference_hash = {}
|
38
38
|
row.reference_names.each do |reference_name|
|
39
39
|
if entity_mapping.references.key? reference_name.to_sym
|
40
40
|
reference_id_name = reference_name + '__id'
|
41
41
|
unless row_hash[reference_id_name.to_sym].nil?
|
42
42
|
type = entity_mapping.references[reference_name.to_sym].type
|
43
|
-
|
43
|
+
reference_hash[reference_name.to_sym] = map(type, row_hash, session, reference_name)
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
object = @container.resolve(resolve_name, row.attributes_hash.merge(reference_hash))
|
49
|
+
entity = @entity_builder.create(object)
|
50
|
+
entity.load_attributes!(row.attributes)
|
51
|
+
|
52
|
+
reference_hash.each do |key, value|
|
53
|
+
entity.set_reference! key.to_s, value
|
54
|
+
end
|
55
|
+
|
48
56
|
session.attach(entity)
|
49
57
|
entity
|
50
58
|
end
|
data/lib/jet_set/mixin/entity.rb
CHANGED
@@ -6,7 +6,7 @@ module JetSet
|
|
6
6
|
module Entity
|
7
7
|
# Loads the entity attributes.
|
8
8
|
# Parameters:
|
9
|
-
# +attributes+::
|
9
|
+
# +attributes+:: an array of key-pairs in format :field => :value
|
10
10
|
def load_attributes!(attributes)
|
11
11
|
attributes.each do |attribute|
|
12
12
|
name = "@#{attribute[:field]}"
|
@@ -77,6 +77,8 @@ module JetSet
|
|
77
77
|
# Parameters:
|
78
78
|
# +sequel+:: Sequel sequel
|
79
79
|
def flush(sequel)
|
80
|
+
validate! if respond_to? :validate!
|
81
|
+
|
80
82
|
table_name = self.class.name.underscore.pluralize.to_sym
|
81
83
|
table = sequel[table_name]
|
82
84
|
entity_name = self.class.name.underscore.to_sym
|
@@ -113,12 +115,14 @@ module JetSet
|
|
113
115
|
values << value.instance_variable_get('@id')
|
114
116
|
end
|
115
117
|
end
|
118
|
+
|
116
119
|
new_id = table.insert(fields, values)
|
117
120
|
@__attributes['@id'] = Attribute.new('@id', new_id)
|
118
121
|
@id = new_id
|
119
122
|
elsif dirty?
|
120
123
|
attributes = {}
|
121
124
|
dirty_attributes.each {|attribute| attributes[attribute.name.sub('@', '')] = instance_variable_get(attribute.name)}
|
125
|
+
|
122
126
|
if attributes.keys.length > 0
|
123
127
|
table.where(id: @id).update(attributes)
|
124
128
|
end
|
data/lib/jet_set/row.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module JetSet
|
2
2
|
# A container for fields/references extraction logic
|
3
3
|
class Row
|
4
|
-
attr_reader :attributes, :reference_names
|
4
|
+
attr_reader :attributes, :attributes_hash, :reference_names
|
5
5
|
|
6
6
|
def initialize(row_hash, entity_fields, prefix)
|
7
7
|
keys = row_hash.keys.map {|key| key.to_s}
|
@@ -10,6 +10,11 @@ module JetSet
|
|
10
10
|
.select {|key| entity_fields.include? key.sub(prefix + '__', '')}
|
11
11
|
.map {|key| {field: key.sub(prefix + '__', ''), value: row_hash[key.to_sym]}}
|
12
12
|
|
13
|
+
@attributes_hash = {}
|
14
|
+
@attributes.each do |attr|
|
15
|
+
@attributes_hash[attr[:field].to_sym] = attr[:value]
|
16
|
+
end
|
17
|
+
|
13
18
|
@reference_names = keys.select {|key| !key.start_with?(prefix) && key.include?('__')}
|
14
19
|
.map {|key| key.split('__')[0]}
|
15
20
|
.uniq
|
data/lib/jet_set/session.rb
CHANGED
@@ -14,6 +14,7 @@ module JetSet
|
|
14
14
|
@query_parser = query_parser
|
15
15
|
@entity_builder = entity_builder
|
16
16
|
@dependency_graph = dependency_graph
|
17
|
+
@mutex = Mutex.new
|
17
18
|
end
|
18
19
|
|
19
20
|
# Fetches root entity using a result of +execute+ method.
|
@@ -87,9 +88,17 @@ module JetSet
|
|
87
88
|
end
|
88
89
|
end
|
89
90
|
|
90
|
-
|
91
|
-
|
92
|
-
|
91
|
+
@mutex.synchronize do
|
92
|
+
to_attach.each do |object|
|
93
|
+
if object.kind_of?(Entity)
|
94
|
+
obj = object
|
95
|
+
else
|
96
|
+
obj = @entity_builder.create(object)
|
97
|
+
obj.validate! if obj.respond_to? :validate!
|
98
|
+
end
|
99
|
+
|
100
|
+
@objects << obj
|
101
|
+
end
|
93
102
|
end
|
94
103
|
end
|
95
104
|
|
@@ -100,9 +109,15 @@ module JetSet
|
|
100
109
|
dirty_objects = @objects.select {|object| object.dirty?}
|
101
110
|
ordered_objects = @dependency_graph.order(dirty_objects)
|
102
111
|
|
103
|
-
|
104
|
-
|
105
|
-
|
112
|
+
begin
|
113
|
+
if ordered_objects.length > 0
|
114
|
+
@sequel.transaction do
|
115
|
+
ordered_objects.each{|obj| obj.flush(@sequel)}
|
116
|
+
end
|
117
|
+
end
|
118
|
+
ensure
|
119
|
+
@mutex.synchronize do
|
120
|
+
@objects = []
|
106
121
|
end
|
107
122
|
end
|
108
123
|
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'jet_set/validation_error'
|
2
|
+
|
3
|
+
module JetSet
|
4
|
+
# Optional validation decorator. Adds validation logic to pure Ruby objects.
|
5
|
+
module Validations
|
6
|
+
# The method runs all validations declared in the model
|
7
|
+
def validate!
|
8
|
+
@to_skip ||= []
|
9
|
+
|
10
|
+
validations = self.class.class_variable_defined?(:@@validations) ? self.class.class_variable_get(:@@validations) : {}
|
11
|
+
attributes = validations.keys - @to_skip
|
12
|
+
invalid_items = []
|
13
|
+
|
14
|
+
attributes.each do |attribute|
|
15
|
+
attribute_validations = validations[attribute] || []
|
16
|
+
|
17
|
+
error = nil
|
18
|
+
attribute_validations.each do |validation|
|
19
|
+
value = instance_variable_get("@#{attribute}")
|
20
|
+
if validation[:func].call(value) == false
|
21
|
+
error = validation[:message]
|
22
|
+
break
|
23
|
+
end
|
24
|
+
end
|
25
|
+
invalid_items << {"#{attribute}": error} if error
|
26
|
+
end
|
27
|
+
|
28
|
+
raise ValidationError.new("#{self.class.name} is invalid", invalid_items) if invalid_items.length > 0
|
29
|
+
end
|
30
|
+
|
31
|
+
# Disables attribute validation for edge cases
|
32
|
+
def do_not_validate(*attributes)
|
33
|
+
@to_skip ||= []
|
34
|
+
attributes.each { |a| @to_skip << a}
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.included(base)
|
38
|
+
base.extend(ClassMethods)
|
39
|
+
end
|
40
|
+
|
41
|
+
module ClassMethods
|
42
|
+
# Adds a validation to an attribute of the entity
|
43
|
+
# Parameters:
|
44
|
+
# +attribute_name+:: +Symbol+ attribute name
|
45
|
+
# +options+ || +message+:: validation options {type, presence, message, custom} or just a message
|
46
|
+
# +func+:: boolean proc with a check for validity
|
47
|
+
def validate(attribute_name, options, func = nil)
|
48
|
+
validations = self.class_variable_defined?(:@@validations) ? self.class_variable_get(:@@validations) : {}
|
49
|
+
validations[attribute_name] ||= []
|
50
|
+
|
51
|
+
if options.is_a?(Hash)
|
52
|
+
if options.has_key?(:type)
|
53
|
+
validations[attribute_name] << validate_type(options[:type])
|
54
|
+
end
|
55
|
+
|
56
|
+
if options[:presence] == true
|
57
|
+
validations[attribute_name] << validate_presence
|
58
|
+
end
|
59
|
+
|
60
|
+
message = options[:message]
|
61
|
+
elsif options.is_a?(String)
|
62
|
+
message = options
|
63
|
+
else
|
64
|
+
raise ValidationDefinitionError, "Validation definition of attribute #{attribute_name} is incorrect."
|
65
|
+
end
|
66
|
+
|
67
|
+
func ||= options[:custom]
|
68
|
+
|
69
|
+
unless func.nil?
|
70
|
+
validations[attribute_name] << {func: func, message: message}
|
71
|
+
end
|
72
|
+
|
73
|
+
self.class_variable_set(:@@validations, validations)
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def validate_presence
|
79
|
+
{message: 'cannot be blank', func: -> (value) {!value.nil? && value != ''}}
|
80
|
+
end
|
81
|
+
|
82
|
+
def validate_type(type)
|
83
|
+
unless [:numeric, :string, :boolean].include?(type)
|
84
|
+
raise ValidationDefinitionError, "the type should be :numeric, :string or :boolean"
|
85
|
+
end
|
86
|
+
|
87
|
+
checks = {
|
88
|
+
numeric: -> (value) {value.is_a?(Numeric)},
|
89
|
+
string: -> (value) {value.is_a?(String)},
|
90
|
+
boolean: -> (value) {!!value == value}
|
91
|
+
}
|
92
|
+
|
93
|
+
{message: "should be #{type}", func: -> (value) {value.nil? || checks[type].call(value)}}
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
data/lib/jet_set/version.rb
CHANGED
metadata
CHANGED
@@ -1,111 +1,111 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jet_set
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3
|
4
|
+
version: 0.5.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vladimir Kalinkin
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-06-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 5.4.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 5.4.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: hypo
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.
|
33
|
+
version: 1.0.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.
|
40
|
+
version: 1.0.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: bundler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '1
|
47
|
+
version: '2.1'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '1
|
54
|
+
version: '2.1'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '10.0'
|
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
68
|
version: '10.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rspec
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '3.0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '3.0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: sqlite3
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '1.3'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - "
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '1.3'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: simplecov
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- - "
|
101
|
+
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '0.16'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- - "
|
108
|
+
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0.16'
|
111
111
|
description: ''
|
@@ -143,14 +143,16 @@ files:
|
|
143
143
|
- lib/jet_set/reference.rb
|
144
144
|
- lib/jet_set/row.rb
|
145
145
|
- lib/jet_set/session.rb
|
146
|
+
- lib/jet_set/validation_definition_error.rb
|
147
|
+
- lib/jet_set/validation_error.rb
|
148
|
+
- lib/jet_set/validations.rb
|
146
149
|
- lib/jet_set/version.rb
|
147
|
-
- test.rb
|
148
150
|
homepage: https://github.com/cylon-v/jet_set
|
149
151
|
licenses:
|
150
152
|
- MIT
|
151
153
|
metadata:
|
152
154
|
allowed_push_host: https://rubygems.org
|
153
|
-
post_install_message:
|
155
|
+
post_install_message:
|
154
156
|
rdoc_options: []
|
155
157
|
require_paths:
|
156
158
|
- lib
|
@@ -165,9 +167,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
165
167
|
- !ruby/object:Gem::Version
|
166
168
|
version: '0'
|
167
169
|
requirements: []
|
168
|
-
|
169
|
-
|
170
|
-
signing_key:
|
170
|
+
rubygems_version: 3.2.15
|
171
|
+
signing_key:
|
171
172
|
specification_version: 4
|
172
173
|
summary: JetSet is a microscopic ORM for DDD projects.
|
173
174
|
test_files: []
|