mongoid-denormalize 0.2.0 → 0.3.0

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
- 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