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: 475dd9ec0d2b0bf95696301523c3e1dc4868c709
4
- data.tar.gz: f28660a5b552fcf7b2175f4bb02a8cd31d2a88c7
3
+ metadata.gz: 7c633cfd0dd50f6ceea4998f90c90927767fadae
4
+ data.tar.gz: 15af4ae0a658e49c2943315c1713b553c280622e
5
5
  SHA512:
6
- metadata.gz: f0f0fbc2d9341bff4abc9c729ce0194e6ee83aa79238950050cf47909243236002e2932c0df9a52591bac42270b5b852c82ec030af1900974ea9a2b3cb7773b7
7
- data.tar.gz: 0a9ae7ce32452b26d617faf4e06d276165980d2db39097124a6443adae37302c5b692fc37aa4003527ecc281ce3fbe27ac642dfd3012de733e061685bac64415
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
- if fields[field_name].respond_to? :type
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
- if related_object.respond_to? :type
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}
@@ -1,3 +1,3 @@
1
1
  module UniverseCompiler
2
- VERSION = '0.5.5'.freeze
2
+ VERSION = '0.5.6'.freeze
3
3
  end
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.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-05 00:00:00.000000000 Z
11
+ date: 2019-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler