universe_compiler 0.5.5 → 0.5.6
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
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7c633cfd0dd50f6ceea4998f90c90927767fadae
|
4
|
+
data.tar.gz: 15af4ae0a658e49c2943315c1713b553c280622e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6da30e7fe34302bad36cc3a1a79d28840ed25a7fbe7d8c11339ccc8c86b893feaba659c344a88c59e31a62cb46a9a7b25feb97d0929c7bcc60ad932a903371c8
|
7
|
+
data.tar.gz: d6422c866a2b525fc37d2f435c0c57ae4603f6481db994da66d85191e0335511e87329d283988aa798fc1cc570615b2567c690560d50e37f6c9387c3295f39a1
|
data/README.md
CHANGED
@@ -15,6 +15,8 @@ UniverseCompiler
|
|
15
15
|
- [Relational directives](#relational-directives)
|
16
16
|
- [Basic relations](#basic-relations)
|
17
17
|
- [Advanced relations](#advanced-relations)
|
18
|
+
- [Reverse methods](#reverse-methods)
|
19
|
+
- [Strict vs permissive](#strict-vs-permissive)
|
18
20
|
- [Validations](#validations)
|
19
21
|
- [Compilation](#compilation)
|
20
22
|
- [Inheritance](#inheritance)
|
@@ -274,6 +276,8 @@ e.bars == e[:bars]
|
|
274
276
|
|
275
277
|
#### Advanced relations
|
276
278
|
|
279
|
+
##### Reverse methods
|
280
|
+
|
277
281
|
Sometimes you may want entities _targeted_ by `has_one` or `has_many` relations to _be aware_ of this fact. **You can then implement complex relations without duplicating information**.
|
278
282
|
|
279
283
|
This is called **reverse methods**.
|
@@ -342,6 +346,52 @@ t.leaves.last.trunk
|
|
342
346
|
An exception is returned. the `unique` option actually specifies that only one entity should reference it !
|
343
347
|
If you don't specify this option, an array is returned instead and this check is not performed.
|
344
348
|
|
349
|
+
##### Strict vs permissive
|
350
|
+
|
351
|
+
By default, when a relation is declared between entities using `has_one` or `has_many`, the relation is said to be _permissive_, ie subclasses are allowed to be used for the relation. For example, let's consider the following classes:
|
352
|
+
|
353
|
+
```ruby
|
354
|
+
class Level1 < UniverseCompiler::Entity::Base
|
355
|
+
entity_type :level1
|
356
|
+
|
357
|
+
has_one :level1, name: :permissive_link
|
358
|
+
|
359
|
+
end
|
360
|
+
|
361
|
+
class Level2 < RootLevel
|
362
|
+
entity_type :level2
|
363
|
+
end
|
364
|
+
|
365
|
+
class Level3 < Level2
|
366
|
+
entity_type :level3
|
367
|
+
end
|
368
|
+
```
|
369
|
+
|
370
|
+
It means that any instance of `Level2` or `Level3` can be used in the `has_one` relation declared in `Level1`. This is the default behavior.
|
371
|
+
|
372
|
+
But if you consider the following classes:
|
373
|
+
|
374
|
+
```ruby
|
375
|
+
class Level1 < UniverseCompiler::Entity::Base
|
376
|
+
entity_type :level1
|
377
|
+
|
378
|
+
has_one :level1, name: :strict_link, strict_type: true
|
379
|
+
|
380
|
+
end
|
381
|
+
|
382
|
+
class Level2 < RootLevel
|
383
|
+
entity_type :level2
|
384
|
+
end
|
385
|
+
|
386
|
+
class Level3 < Level2
|
387
|
+
entity_type :level3
|
388
|
+
end
|
389
|
+
```
|
390
|
+
|
391
|
+
Then only `Level1` instances will be valid for the `has_one` relation declared. The keyword as you guessed is `strict_type: true`.
|
392
|
+
|
393
|
+
:information_source: It works the same way for `has_many` relations, applied to **all** instances added to the array...
|
394
|
+
|
345
395
|
### Validations
|
346
396
|
|
347
397
|
Every constraint defined on a field or a relation is enforced when an entity is validated (which is as well true when saving it). Continuing on previous example:
|
@@ -5,10 +5,11 @@ module UniverseCompiler
|
|
5
5
|
|
6
6
|
module RelationsManagement
|
7
7
|
|
8
|
-
def has_one(target_entity_type_or_class, name: nil, with_reverse_method: nil, unique: false)
|
8
|
+
def has_one(target_entity_type_or_class, name: nil, strict_type: false, with_reverse_method: nil, unique: false)
|
9
9
|
target_entity_type = normalize_entity_type target_entity_type_or_class
|
10
10
|
field_name = relation_field_name name, target_entity_type
|
11
11
|
define_constraint field_name, :has_one, target_entity_type
|
12
|
+
define_constraint field_name, :strict_type, target_entity_type if strict_type
|
12
13
|
return unless with_reverse_method
|
13
14
|
|
14
15
|
define_constraint_for_reverse_method :has_one,
|
@@ -18,11 +19,12 @@ module UniverseCompiler
|
|
18
19
|
unique
|
19
20
|
end
|
20
21
|
|
21
|
-
def has_many(target_entity_type_or_class, name: nil, with_reverse_method: nil, unique: false)
|
22
|
+
def has_many(target_entity_type_or_class, name: nil, strict_type: false, with_reverse_method: nil, unique: false)
|
22
23
|
target_entity_type = normalize_entity_type target_entity_type_or_class
|
23
24
|
field_name = relation_field_name name, target_entity_type
|
24
25
|
field_name = field_name.to_s.pluralize.to_sym if name.nil?
|
25
26
|
define_constraint field_name, :has_many, target_entity_type
|
27
|
+
define_constraint field_name, :strict_type, target_entity_type if strict_type
|
26
28
|
return unless with_reverse_method
|
27
29
|
|
28
30
|
define_constraint_for_reverse_method :has_many,
|
@@ -35,9 +35,7 @@ module UniverseCompiler
|
|
35
35
|
end
|
36
36
|
when :has_one
|
37
37
|
unless fields[field_name].nil?
|
38
|
-
|
39
|
-
invalid_for_constraint invalid, field_name, constraint_name, value unless fields[field_name].type == value
|
40
|
-
else
|
38
|
+
unless provided_entity_compatible_with_type? fields[field_name], value, constraints[:strict_type]
|
41
39
|
invalid_for_constraint invalid, field_name, constraint_name, value
|
42
40
|
end
|
43
41
|
end
|
@@ -46,9 +44,7 @@ module UniverseCompiler
|
|
46
44
|
invalid_for_constraint invalid, field_name, constraint_name, value
|
47
45
|
else
|
48
46
|
fields[field_name].each do |related_object|
|
49
|
-
|
50
|
-
invalid_for_constraint invalid, field_name, constraint_name, value unless related_object.type == value
|
51
|
-
else
|
47
|
+
unless provided_entity_compatible_with_type? related_object, value, constraints[:strict_type]
|
52
48
|
invalid_for_constraint invalid, field_name, constraint_name, value
|
53
49
|
end
|
54
50
|
end
|
@@ -87,6 +83,15 @@ module UniverseCompiler
|
|
87
83
|
|
88
84
|
private
|
89
85
|
|
86
|
+
def provided_entity_compatible_with_type?(linked_object, declared_type, strict_type)
|
87
|
+
declared_class = UniverseCompiler::Entity::TypeManagement.type_class_mapping(declared_type)
|
88
|
+
if strict_type
|
89
|
+
linked_object.class == declared_class
|
90
|
+
else
|
91
|
+
linked_object.is_a? declared_class
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
90
95
|
def invalid_for_constraint(invalid_fields_definition, field_name, constraint_name, value)
|
91
96
|
invalid_fields_definition[field_name] ||= []
|
92
97
|
invalid_fields_definition[field_name] << { constraint_name => value}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: universe_compiler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Laurent B.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-11-
|
11
|
+
date: 2019-11-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|