universe_compiler 0.5.5 → 0.5.6

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