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 +5 -5
- data/README.md +39 -0
- data/lib/mongoid-denormalize/version.rb +1 -1
- data/lib/mongoid-denormalize.rb +66 -32
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 601856686a5f670b81ae5704ecdfb107c251010190a2c0c4a1df87797a7480df
|
4
|
+
data.tar.gz: e2258b9b466e37ee420e05f6f16c5eda0b1fd18a63d0fceca8961866a174f6f1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
data/lib/mongoid-denormalize.rb
CHANGED
@@ -8,50 +8,84 @@ module Mongoid
|
|
8
8
|
|
9
9
|
module ClassMethods
|
10
10
|
def denormalize(*args)
|
11
|
-
options = args
|
11
|
+
*fields, options = args
|
12
12
|
|
13
|
-
unless options.is_a?(Hash) &&
|
14
|
-
raise ArgumentError, 'Option :from is needed (e.g.
|
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
|
-
|
19
|
-
|
20
|
-
#
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
-
|
30
|
-
|
31
|
-
|
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
|
-
|
34
|
-
|
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
|
-
|
39
|
-
|
40
|
-
|
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
|
-
|
43
|
-
|
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
|
-
|
47
|
-
|
48
|
-
|
49
|
-
document.collection.update_one({_id: document._id}, {'$set' => attributes})
|
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.
|
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:
|
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.
|
108
|
+
rubygems_version: 2.7.3
|
109
109
|
signing_key:
|
110
110
|
specification_version: 4
|
111
111
|
summary: Denormalize fields from relations
|