mongoid-denormalize 0.2.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 89273ea3cdebd9a638a98696f6ab82c479eee5c3
4
- data.tar.gz: fde78762ab929df91264df24ed978c656e3deb23
2
+ SHA256:
3
+ metadata.gz: 601856686a5f670b81ae5704ecdfb107c251010190a2c0c4a1df87797a7480df
4
+ data.tar.gz: e2258b9b466e37ee420e05f6f16c5eda0b1fd18a63d0fceca8961866a174f6f1
5
5
  SHA512:
6
- metadata.gz: a3a815fc670066d01bad8a47ee1e37353d07c74d1c193d46c6439e53dc5fb2771706c421ff0d8752ebe8376d3fe39aa1ad1057c981ff937c79121b400f3e43c5
7
- data.tar.gz: ef2a98a526e9f07d57e934906a224ec13761b016f26280e1acf10220974da66d01bf59285e15d7aced196227c753b7c9d7af4f36298a0079da92fca4c839a770
6
+ metadata.gz: 6ebddf92b6193919dc47464a2ab2ae9868b5c8a8b49ff2855d954fa226383d13ea5548e2848b845a4b0a04136d789588fda11798f2775a30b2306cae8fdaa059
7
+ data.tar.gz: 84d082b7e3f53e312d42668791593287e88ecb8c135449109b14755113e0fa7e5d362d45962a4f8f8c8984776b53adb9d2c7b3eac7d2bd868a4a57c752dbb641
data/README.md CHANGED
@@ -84,6 +84,45 @@ end
84
84
  "User2"
85
85
  ```
86
86
 
87
+ ## Options of denormalize
88
+
89
+ ### as
90
+
91
+ Enables to customize the final field name
92
+
93
+ ```ruby
94
+ denormalize :name, from: :top, as: :custom_name
95
+ ```
96
+
97
+ It will create the field `custom_name` with the content of `top.name`. Also support an array:
98
+
99
+ ```ruby
100
+ denormalize :name, :age, from: :top, as: [:custom_name, :custom_age]
101
+ ```
102
+
103
+ ### prefix
104
+
105
+ In somes cases it could be interesting to customize the prefix of the final name, instead of using the basic `from_field`
106
+
107
+ ```ruby
108
+ denormalize :color, :name, from: :top, prefix: :ancestor
109
+ ```
110
+
111
+ It will create the fields `ancestor_name` and `ancestor_color` with the content of `top.name` and `top.color`.
112
+
113
+ ### child_callback
114
+
115
+ By default when a child is created the denormalization is executed into `before_save` hook.
116
+ This option let you change this callback by other, for example:
117
+
118
+ ```ruby
119
+ denormalize :name, from: :top, child_callback: :before_validation
120
+
121
+ validate :top_name, presence: true
122
+ ```
123
+
124
+ It will denormalize field `name` into `before_validation` callback so that we can validate it.
125
+
87
126
  ## Development
88
127
 
89
128
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -1,5 +1,5 @@
1
1
  module Mongoid
2
2
  module Denormalize
3
- VERSION = "0.2.0"
3
+ VERSION = "0.3.0"
4
4
  end
5
5
  end
@@ -8,50 +8,84 @@ module Mongoid
8
8
 
9
9
  module ClassMethods
10
10
  def denormalize(*args)
11
- options = args.pop
11
+ *fields, options = args
12
12
 
13
- unless options.is_a?(Hash) && (from = options[:from]&.to_s)
14
- raise ArgumentError, 'Option :from is needed (e.g. delegate :name, from: :user).'
13
+ unless options.is_a?(Hash) && options[:from]
14
+ raise ArgumentError, 'Option :from is needed (e.g. denormalize :name, from: :user).'
15
15
  end
16
16
 
17
+ fields = Mongoid::Denormalize.get_fields_with_names(fields, options)
18
+
17
19
  # Add fields to model
18
- args.each { |field| field "#{from}_#{field}" }
19
-
20
- # Denormalize fields when model is saved and 'from' has changed
21
- before_save do
22
- if send(from) && send("#{from}_id_changed?")
23
- args.each do |field|
24
- send("#{from}_#{field}=", send(from).send(field))
25
- end
26
- end
20
+ fields.each { |field| field field[:as] }
21
+
22
+ # Add hooks
23
+ Mongoid::Denormalize.add_hook_to_child(self, fields, options)
24
+ Mongoid::Denormalize.add_hook_to_parent(self, fields, options)
25
+ end
26
+ end
27
+
28
+ # Check options and return name for each field
29
+ def self.get_fields_with_names(fields, options)
30
+ if options.include?(:as)
31
+ options[:as] = [options[:as]] unless options[:as].is_a?(Array)
32
+
33
+ unless fields.size == options[:as].size
34
+ raise ArgumentError, 'When option :as is used you must pass a name for each field.'
27
35
  end
28
36
 
29
- from_class = (relations[from].class_name || relations[from].name.capitalize).constantize
30
- child_model_name = model_name
31
- child_inverse_of = relations[from].inverse_of
37
+ return fields.map.with_index { |field, index| {name: field, as: options[:as][index]} }
38
+ elsif options.include?(:prefix)
39
+ return fields.map { |field| {name: field, as: "#{options[:prefix]}_#{field}"} }
40
+ end
32
41
 
33
- # When 'from' is updated, update child/childs
34
- from_class.send(:after_update) do
35
- attributes = {}
36
- args.each { |field| attributes["#{from}_#{field}"] = send(field) }
42
+ fields.map { |field| {name: field, as: "#{options[:from]}_#{field}"} }
43
+ end
37
44
 
38
- relation = relations[child_inverse_of.to_s] ||
39
- relations[child_model_name.plural] ||
40
- relations[child_model_name.singular]
45
+ # Add hook to child class to denormalize fields when parent relation is changed
46
+ def self.add_hook_to_child(child_class, fields, options)
47
+ from = options[:from].to_s
41
48
 
42
- unless relation
43
- raise "Option :inverse_of is needed for 'belongs_to :#{from}' into #{child_model_name.name}."
49
+ child_class.send(options[:child_callback] || 'before_save') do
50
+ if send(from) && send("#{from}_id_changed?")
51
+ fields.each do |field|
52
+ send("#{field[:as]}=", send(from).send(field[:name]))
44
53
  end
54
+ end
55
+ end
56
+ end
57
+
58
+ # Add hook to parent class to denormalize fields when parent object is updated
59
+ def self.add_hook_to_parent(child_class, fields, options)
60
+ from = options[:from].to_s
61
+
62
+ parent = (child_class.relations[from].class_name ||
63
+ child_class.relations[from].name.capitalize).constantize
64
+
65
+ relation = parent.relations[child_class.relations[from].inverse_of.to_s] ||
66
+ parent.relations[child_class.model_name.plural] ||
67
+ parent.relations[child_class.model_name.singular]
68
+
69
+ unless relation
70
+ raise "Option :inverse_of is needed for 'belongs_to :#{from}' into #{child_class}."
71
+ end
72
+
73
+ parent.after_update do
74
+ attributes = {}
75
+ fields.each do |field|
76
+ attributes[field[:as]] = send(field[:name]) if send("#{field[:name]}_changed?")
77
+ end
78
+ next if attributes.blank?
45
79
 
46
- case relation.relation.to_s
47
- when 'Mongoid::Relations::Referenced::One'
48
- document = send(relation.name)
49
- document.collection.update_one({_id: document._id}, {'$set' => attributes}) if document
50
- when 'Mongoid::Relations::Referenced::Many'
51
- send(relation.name).update_all('$set' => attributes)
52
- else
53
- raise "Relation type unsupported: #{relation.relation}"
80
+ case relation.relation.to_s
81
+ when 'Mongoid::Relations::Referenced::One'
82
+ if (document = send(relation.name))
83
+ document.collection.update_one({_id: document._id}, {'$set' => attributes})
54
84
  end
85
+ when 'Mongoid::Relations::Referenced::Many'
86
+ send(relation.name).update_all('$set' => attributes)
87
+ else
88
+ raise "Relation type unsupported: #{relation.relation}"
55
89
  end
56
90
  end
57
91
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid-denormalize
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - rjurado01
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-12-29 00:00:00.000000000 Z
11
+ date: 2018-02-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -105,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
105
105
  version: '0'
106
106
  requirements: []
107
107
  rubyforge_project:
108
- rubygems_version: 2.5.2
108
+ rubygems_version: 2.7.3
109
109
  signing_key:
110
110
  specification_version: 4
111
111
  summary: Denormalize fields from relations