mongoid-history 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +19 -1
- data/Gemfile +1 -2
- data/README.md +123 -1
- data/VERSION +1 -1
- data/lib/mongoid/history.rb +14 -0
- data/lib/mongoid/history/trackable.rb +142 -59
- data/lib/mongoid/history/tracker.rb +77 -27
- data/mongoid-history.gemspec +2 -4
- data/spec/integration/integration_spec.rb +382 -238
- data/spec/integration/multi_relation_spec.rb +9 -2
- data/spec/integration/nested_embedded_documents_spec.rb +7 -5
- data/spec/spec_helper.rb +1 -3
- data/spec/support/mongoid.rb +8 -10
- data/spec/trackable_spec.rb +168 -41
- metadata +3 -5
- data/config/mongoid.yml +0 -8
- data/spec/support/database_cleaner.rb +0 -9
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,22 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0 (6/12/2013)
|
2
|
+
-----------------
|
3
|
+
|
4
|
+
* Add Mongoid::History.disable and Mongoid::History.enabled? methods for global tracking disablement - [@johnnyshields](https://github.com/johnnyshields)
|
5
|
+
* Add `:changes_method` that optionally overrides which method to call to collect changes - [@joelnordel](https://github.com/joelnordell).
|
6
|
+
* [API Change] The `:destroy` action now stores trackers in the format `original=value, modified=nil` (previously it was the reverse) - [@johnnyshields](https://github.com/johnnyshields)
|
7
|
+
* Support for polymorphic embedded classes - [@tstepp](https://github.com/tstepp)
|
8
|
+
* Support for Mongoid field aliases, e.g. `field :n, as: :name` - [@johnnyshields](https://github.com/johnnyshields)
|
9
|
+
* Support for Mongoid embedded aliases, e.g. `embeds_many :comments, store_as: :coms` - [@johnnyshields](https://github.com/johnnyshields)
|
10
|
+
* Add `#tracked_changes` and `#tracked_edits` methods to `Tracker` class for nicer change summaries - [@johnnyshields](https://github.com/johnnyshields) and [@tstepp](https://github.com/tstepp)
|
11
|
+
* Refactored and exposed `#trackable_parent_class` in `Tracker`, which returns the class of the trackable regardless of whether the trackable itself has been destroyed - [@johnnyshields](https://github.com/johnnyshields)
|
12
|
+
* Add class-level `#tracked_field?` and `#tracked_fields` methods; refactor logic to determine whether a field is tracked - [@johnnyshields](https://github.com/johnnyshields)
|
13
|
+
* Fix bug in Trackable#track_update where `return` condition at beginning of method caused a short-circuit where memoization would not be cleared properly. - [@johnnyshields](https://github.com/johnnyshields)
|
14
|
+
* Tests: Added spec for nested embedded documents - [@matekb](https://github.com/matekb)
|
15
|
+
* Tests: Test run time cut in half (~2.5s versus ~5s) by using `#let` helper and removing class initialization before each test - [@johnnyshields](https://github.com/johnnyshields)
|
16
|
+
* Tests: Remove `database_cleaner` gem in favor of `Mongoid.purge!` - [@johnnyshields](https://github.com/johnnyshields)
|
17
|
+
* Tests: Remove dependency on non-committed file `mongoid.yml` and hardcode collection to `mongoid_history_test` - [@johnnyshields](https://github.com/johnnyshields)
|
18
|
+
|
19
|
+
0.3.3 (4/1/2013)
|
2
20
|
----------------
|
3
21
|
|
4
22
|
* [#42](https://github.com/aq1018/mongoid-history/issues/42) Fix: corrected creation of association chain when using nested embedded documents - [@matekb](https://github.com/matekb).
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -2,6 +2,7 @@ mongoid-history
|
|
2
2
|
===============
|
3
3
|
|
4
4
|
[![Build Status](https://secure.travis-ci.org/aq1018/mongoid-history.png?branch=master)](http://travis-ci.org/aq1018/mongoid-history)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/aq1018/mongoid-history.png)](https://codeclimate.com/github/aq1018/mongoid-history)
|
5
6
|
|
6
7
|
Mongoid-history tracks historical changes for any document, including embedded ones. It achieves this by storing all history tracks in a single collection that you define. Embedded documents are referenced by storing an association path, which is an array of `document_name` and `document_id` fields starting from the top most parent document and down to the embedded document that should track history.
|
7
8
|
|
@@ -10,7 +11,7 @@ This gem also implements multi-user undo, which allows users to undo any history
|
|
10
11
|
Stable Release
|
11
12
|
--------------
|
12
13
|
|
13
|
-
You're reading the documentation the 0.
|
14
|
+
You're reading the documentation the 0.4.x release that supports Mongoid 3.x. For 2.x compatible mongoid-history, please use a 0.2.x version from the [2.x-stable branch](https://github.com/aq1018/mongoid-history/tree/2.4-stable).
|
14
15
|
|
15
16
|
Install
|
16
17
|
-------
|
@@ -160,7 +161,128 @@ post.undo! user
|
|
160
161
|
Comment.disable_tracking do
|
161
162
|
comment.update_attributes(:title => "Test 3")
|
162
163
|
end
|
164
|
+
|
165
|
+
# globally disable all history tracking
|
166
|
+
Mongoid::History.disable do
|
167
|
+
comment.update_attributes(:title => "Test 3")
|
168
|
+
user.update_attributes(:name => "Eddie Van Halen")
|
169
|
+
end
|
170
|
+
```
|
171
|
+
|
172
|
+
**Retrieving the list of tracked fields**
|
173
|
+
|
174
|
+
```ruby
|
175
|
+
class Book
|
176
|
+
...
|
177
|
+
field :title
|
178
|
+
field :author
|
179
|
+
field :price
|
180
|
+
track_history :on => [:title, :price]
|
181
|
+
end
|
182
|
+
|
183
|
+
Book.tracked_fields #=> ["title", "price"]
|
184
|
+
Book.tracked_field?(:title) #=> true
|
185
|
+
Book.tracked_field?(:author) #=> false
|
163
186
|
```
|
187
|
+
|
188
|
+
**Displaying history trackers as an audit trail**
|
189
|
+
|
190
|
+
In your Controller:
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
# Fetch history trackers
|
194
|
+
@trackers = HistoryTracker.limit(25)
|
195
|
+
|
196
|
+
# get change set for the first tracker
|
197
|
+
@changes = @trackers.first.tracked_changes
|
198
|
+
#=> {field: {to: val1, from: val2}}
|
199
|
+
|
200
|
+
# get edit set for the first tracker
|
201
|
+
@edits = @trackers.first.tracked_changes
|
202
|
+
#=> { add: {field: val},
|
203
|
+
# remove: {field: val},
|
204
|
+
# modify: { to: val1, from: val2 },
|
205
|
+
# array: { add: [val2], remove: [val1] } }
|
206
|
+
```
|
207
|
+
|
208
|
+
In your View, you might do something like (example in HAML format):
|
209
|
+
|
210
|
+
```haml
|
211
|
+
%ul.changes
|
212
|
+
- (@edits[:add]||[]).each do |k,v|
|
213
|
+
%li.remove Added field #{k} value #{v}
|
214
|
+
|
215
|
+
- (@edits[:modify]||[]).each do |k,v|
|
216
|
+
%li.modify Changed field #{k} from #{v[:from]} to #{v[:to]}
|
217
|
+
|
218
|
+
- (@edits[:array]||[]).each do |k,v|
|
219
|
+
%li.modify
|
220
|
+
- if v[:remove].nil?
|
221
|
+
Changed field #{k} by adding #{v[:add]}
|
222
|
+
- elsif v[:add].nil?
|
223
|
+
Changed field #{k} by removing #{v[:remove]}
|
224
|
+
- else
|
225
|
+
Changed field #{k} by adding #{v[:add]} and removing #{v[:remove]}
|
226
|
+
|
227
|
+
- (@edits[:remove]||[]).each do |k,v|
|
228
|
+
%li.remove Removed field #{k} (was previously #{v})
|
229
|
+
```
|
230
|
+
|
231
|
+
**Using an alternate changes method**
|
232
|
+
|
233
|
+
Sometimes you may wish to provide an alternate method for determining which changes should be tracked. For example, if you are using embedded documents
|
234
|
+
and nested attributes, you may wish to write your own changes method that includes changes from the embedded documents.
|
235
|
+
|
236
|
+
Mongoid::History provides an option named `:changes_method` which allows you to do this. It defaults to `:changes`, which is the standard changes method.
|
237
|
+
|
238
|
+
Example:
|
239
|
+
|
240
|
+
```ruby
|
241
|
+
class Foo
|
242
|
+
include Mongoid::Document
|
243
|
+
include Mongoid::Timestamps
|
244
|
+
include Mongoid::History::Trackable
|
245
|
+
|
246
|
+
field :bar
|
247
|
+
embeds_one :baz
|
248
|
+
accepts_nested_attributes_for :baz
|
249
|
+
|
250
|
+
# use changes_with_baz to include baz's changes in this document's
|
251
|
+
# history.
|
252
|
+
track_history :changes_method => :changes_with_baz
|
253
|
+
|
254
|
+
def changes_with_baz
|
255
|
+
if baz.changed?
|
256
|
+
changes.merge( :baz => summarized_changes(baz) )
|
257
|
+
else
|
258
|
+
changes
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
private
|
263
|
+
# This method takes the changes from an embedded doc and formats them
|
264
|
+
# in a summarized way, similar to how the embedded doc appears in the
|
265
|
+
# parent document's attributes
|
266
|
+
def summarized_changes obj
|
267
|
+
obj.changes.keys.map do |field|
|
268
|
+
next unless obj.respond_to?("#{field}_change")
|
269
|
+
[ { field => obj.send("#{field}_change")[0] },
|
270
|
+
{ field => obj.send("#{field}_change")[1] } ]
|
271
|
+
end.compact.transpose.map do |fields|
|
272
|
+
fields.inject({}) {|map,f| map.merge(f)}
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
class Baz
|
278
|
+
include Mongoid::Document
|
279
|
+
include Mongoid::Timestamps
|
280
|
+
|
281
|
+
embedded_in :foo
|
282
|
+
field :value
|
283
|
+
end
|
284
|
+
```
|
285
|
+
|
164
286
|
For more examples, check out [spec/integration/integration_spec.rb](https://github.com/aq1018/mongoid-history/blob/master/spec/integration/integration_spec.rb).
|
165
287
|
|
166
288
|
Contributing to mongoid-history
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/lib/mongoid/history.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module Mongoid
|
2
2
|
module History
|
3
|
+
GLOBAL_TRACK_HISTORY_FLAG = "mongoid_history_trackable_enabled"
|
4
|
+
|
3
5
|
mattr_accessor :tracker_class_name
|
4
6
|
mattr_accessor :trackable_class_options
|
5
7
|
mattr_accessor :modifier_class_name
|
@@ -9,5 +11,17 @@ module Mongoid
|
|
9
11
|
@tracker_class ||= tracker_class_name.to_s.classify.constantize
|
10
12
|
end
|
11
13
|
|
14
|
+
def self.disable(&block)
|
15
|
+
begin
|
16
|
+
Thread.current[GLOBAL_TRACK_HISTORY_FLAG] = false
|
17
|
+
yield
|
18
|
+
ensure
|
19
|
+
Thread.current[GLOBAL_TRACK_HISTORY_FLAG] = true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.enabled?
|
24
|
+
Thread.current[GLOBAL_TRACK_HISTORY_FLAG] != false
|
25
|
+
end
|
12
26
|
end
|
13
27
|
end
|
@@ -10,6 +10,7 @@ module Mongoid::History
|
|
10
10
|
:except => [:created_at, :updated_at],
|
11
11
|
:modifier_field => :modifier,
|
12
12
|
:version_field => :version,
|
13
|
+
:changes_method => :changes,
|
13
14
|
:scope => scope_name,
|
14
15
|
:track_create => false,
|
15
16
|
:track_update => true,
|
@@ -18,19 +19,14 @@ module Mongoid::History
|
|
18
19
|
|
19
20
|
options = default_options.merge(options)
|
20
21
|
|
21
|
-
# normalize except fields
|
22
|
-
# manually ensure _id, id, version will not be tracked in history
|
22
|
+
# normalize :except fields to an array of database field strings
|
23
23
|
options[:except] = [options[:except]] unless options[:except].is_a? Array
|
24
|
-
options[:except]
|
25
|
-
options[:except] << "#{options[:modifier_field]}_id".to_sym
|
26
|
-
options[:except] += [:_id, :id]
|
27
|
-
options[:except] = options[:except].map(&:to_s).flatten.compact.uniq
|
28
|
-
options[:except].map(&:to_s)
|
24
|
+
options[:except] = options[:except].map{|field| database_field_name(field)}.compact.uniq
|
29
25
|
|
30
|
-
# normalize fields to
|
26
|
+
# normalize :on fields to either :all or an array of database field strings
|
31
27
|
if options[:on] != :all
|
32
28
|
options[:on] = [options[:on]] unless options[:on].is_a? Array
|
33
|
-
options[:on] = options[:on].map(
|
29
|
+
options[:on] = options[:on].map{|field| database_field_name(field)}.compact.uniq
|
34
30
|
end
|
35
31
|
|
36
32
|
field options[:version_field].to_sym, :type => Integer
|
@@ -54,8 +50,7 @@ module Mongoid::History
|
|
54
50
|
end
|
55
51
|
|
56
52
|
def track_history?
|
57
|
-
enabled
|
58
|
-
enabled.nil? ? true : enabled
|
53
|
+
Mongoid::History.enabled? && Thread.current[track_history_flag] != false
|
59
54
|
end
|
60
55
|
|
61
56
|
def disable_tracking(&block)
|
@@ -101,6 +96,14 @@ module Mongoid::History
|
|
101
96
|
save!
|
102
97
|
end
|
103
98
|
|
99
|
+
def get_embedded(name)
|
100
|
+
self.send(self.class.embedded_alias(name))
|
101
|
+
end
|
102
|
+
|
103
|
+
def create_embedded(name, value)
|
104
|
+
self.send("create_#{self.class.embedded_alias(name)}!", value)
|
105
|
+
end
|
106
|
+
|
104
107
|
private
|
105
108
|
def get_versions_criteria(options_or_version)
|
106
109
|
if options_or_version.is_a? Hash
|
@@ -124,10 +127,6 @@ module Mongoid::History
|
|
124
127
|
versions.desc(:version)
|
125
128
|
end
|
126
129
|
|
127
|
-
def should_track_update?
|
128
|
-
track_history? && !modified_attributes_for_update.blank?
|
129
|
-
end
|
130
|
-
|
131
130
|
def traverse_association_chain(node=self)
|
132
131
|
list = node._parent ? traverse_association_chain(node._parent) : []
|
133
132
|
list << association_hash(node)
|
@@ -141,7 +140,7 @@ module Mongoid::History
|
|
141
140
|
# the child to parent (embedded_in, belongs_to) relation will be defined
|
142
141
|
if node._parent
|
143
142
|
meta = node._parent.relations.values.select do |relation|
|
144
|
-
relation.class_name == node.
|
143
|
+
relation.class_name == node.metadata.class_name.to_s
|
145
144
|
end.first
|
146
145
|
end
|
147
146
|
|
@@ -151,81 +150,68 @@ module Mongoid::History
|
|
151
150
|
ActiveSupport::OrderedHash['name', name, 'id', node.id]
|
152
151
|
end
|
153
152
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
153
|
+
# Returns a Hash of field name to pairs of original and modified values
|
154
|
+
# for each tracked field for a given action.
|
155
|
+
#
|
156
|
+
# @param [ String | Symbol ] action The modification action (:create, :update, :destroy)
|
157
|
+
#
|
158
|
+
# @return [ Hash<String, Array<Object>> ] the pairs of original and modified
|
159
|
+
# values for each field
|
160
|
+
def modified_attributes_for_action(action)
|
161
|
+
case action.to_sym
|
162
|
+
when :destroy then modified_attributes_for_destroy
|
163
|
+
when :create then modified_attributes_for_create
|
164
|
+
else modified_attributes_for_update
|
164
165
|
end
|
165
166
|
end
|
166
167
|
|
168
|
+
def modified_attributes_for_update
|
169
|
+
@modified_attributes_for_update ||= self.send(history_trackable_options[:changes_method]).select{|k, v| self.class.tracked_field?(k, :update)}
|
170
|
+
end
|
171
|
+
|
167
172
|
def modified_attributes_for_create
|
168
|
-
@modified_attributes_for_create ||= attributes.inject({}) do |h,
|
169
|
-
k,v = pair
|
173
|
+
@modified_attributes_for_create ||= attributes.inject({}) do |h,(k,v)|
|
170
174
|
h[k] = [nil, v]
|
171
175
|
h
|
172
|
-
end.
|
173
|
-
history_trackable_options[:except].include?(k)
|
174
|
-
end
|
176
|
+
end.select{|k, v| self.class.tracked_field?(k, :create)}
|
175
177
|
end
|
176
178
|
|
177
179
|
def modified_attributes_for_destroy
|
178
|
-
@modified_attributes_for_destroy ||= attributes.inject({}) do |h,
|
179
|
-
k,
|
180
|
-
h[k] = [nil, v]
|
180
|
+
@modified_attributes_for_destroy ||= attributes.inject({}) do |h,(k,v)|
|
181
|
+
h[k] = [v, nil]
|
181
182
|
h
|
182
|
-
end
|
183
|
+
end.select{|k, v| self.class.tracked_field?(k, :destroy)}
|
183
184
|
end
|
184
185
|
|
185
|
-
def history_tracker_attributes(
|
186
|
+
def history_tracker_attributes(action)
|
186
187
|
return @history_tracker_attributes if @history_tracker_attributes
|
187
188
|
|
188
189
|
@history_tracker_attributes = {
|
189
190
|
:association_chain => traverse_association_chain,
|
190
191
|
:scope => history_trackable_options[:scope],
|
191
|
-
:modifier
|
192
|
+
:modifier => send(history_trackable_options[:modifier_field])
|
192
193
|
}
|
193
194
|
|
194
|
-
original, modified = transform_changes(
|
195
|
-
when :destroy then modified_attributes_for_destroy
|
196
|
-
when :create then modified_attributes_for_create
|
197
|
-
else modified_attributes_for_update
|
198
|
-
end)
|
195
|
+
original, modified = transform_changes(modified_attributes_for_action(action))
|
199
196
|
|
200
197
|
@history_tracker_attributes[:original] = original
|
201
198
|
@history_tracker_attributes[:modified] = modified
|
202
199
|
@history_tracker_attributes
|
203
200
|
end
|
204
201
|
|
205
|
-
def
|
206
|
-
|
207
|
-
current_version = (self.send(history_trackable_options[:version_field]) || 0 ) + 1
|
208
|
-
self.send("#{history_trackable_options[:version_field]}=", current_version)
|
209
|
-
Mongoid::History.tracker_class.create!(history_tracker_attributes(:update).merge(:version => current_version, :action => "update", :trackable => self))
|
210
|
-
clear_memoization
|
202
|
+
def track_create
|
203
|
+
track_history_for_action(:create)
|
211
204
|
end
|
212
205
|
|
213
|
-
def
|
214
|
-
|
215
|
-
current_version = (self.send(history_trackable_options[:version_field]) || 0 ) + 1
|
216
|
-
self.send("#{history_trackable_options[:version_field]}=", current_version)
|
217
|
-
Mongoid::History.tracker_class.create!(history_tracker_attributes(:create).merge(:version => current_version, :action => "create", :trackable => self))
|
218
|
-
clear_memoization
|
206
|
+
def track_update
|
207
|
+
track_history_for_action(:update)
|
219
208
|
end
|
220
209
|
|
221
210
|
def track_destroy
|
222
|
-
|
223
|
-
current_version = (self.send(history_trackable_options[:version_field]) || 0 ) + 1
|
224
|
-
Mongoid::History.tracker_class.create!(history_tracker_attributes(:destroy).merge(:version => current_version, :action => "destroy", :trackable => self))
|
225
|
-
clear_memoization
|
211
|
+
track_history_for_action(:destroy)
|
226
212
|
end
|
227
213
|
|
228
|
-
def
|
214
|
+
def clear_trackable_memoization
|
229
215
|
@history_tracker_attributes = nil
|
230
216
|
@modified_attributes_for_create = nil
|
231
217
|
@modified_attributes_for_update = nil
|
@@ -244,12 +230,109 @@ module Mongoid::History
|
|
244
230
|
[ original, modified ]
|
245
231
|
end
|
246
232
|
|
233
|
+
protected
|
234
|
+
|
235
|
+
def track_history_for_action?(action)
|
236
|
+
track_history? && !(action.to_sym == :update && modified_attributes_for_update.blank?)
|
237
|
+
end
|
238
|
+
|
239
|
+
def track_history_for_action(action)
|
240
|
+
if track_history_for_action?(action)
|
241
|
+
current_version = (self.send(history_trackable_options[:version_field]) || 0 ) + 1
|
242
|
+
self.send("#{history_trackable_options[:version_field]}=", current_version)
|
243
|
+
Mongoid::History.tracker_class.create!(history_tracker_attributes(action.to_sym).merge(version: current_version, action: action.to_s, trackable: self))
|
244
|
+
end
|
245
|
+
clear_trackable_memoization
|
246
|
+
end
|
247
247
|
end
|
248
248
|
|
249
249
|
module SingletonMethods
|
250
|
+
|
251
|
+
# Whether or not the field should be tracked.
|
252
|
+
#
|
253
|
+
# @param [ String | Symbol ] field The name or alias of the field
|
254
|
+
# @param [ String | Symbol ] action The optional action name (:create, :update, or :destroy)
|
255
|
+
#
|
256
|
+
# @return [ Boolean ] whether or not the field is tracked for the given action
|
257
|
+
def tracked_field?(field, action = :update)
|
258
|
+
tracked_fields_for_action(action).include? database_field_name(field)
|
259
|
+
end
|
260
|
+
|
261
|
+
# Retrieves the list of tracked fields for a given action.
|
262
|
+
#
|
263
|
+
# @param [ String | Symbol ] action The action name (:create, :update, or :destroy)
|
264
|
+
#
|
265
|
+
# @return [ Array < String > ] the list of tracked fields for the given action
|
266
|
+
def tracked_fields_for_action(action)
|
267
|
+
case action.to_sym
|
268
|
+
when :destroy then tracked_fields + reserved_tracked_fields
|
269
|
+
else tracked_fields
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
# Retrieves the memoized base list of tracked fields, excluding reserved fields.
|
274
|
+
#
|
275
|
+
# @return [ Array < String > ] the base list of tracked database field names
|
276
|
+
def tracked_fields
|
277
|
+
@tracked_fields ||= self.fields.keys.select do |field|
|
278
|
+
h = history_trackable_options
|
279
|
+
(h[:on]==:all || h[:on].include?(field)) && !h[:except].include?(field)
|
280
|
+
end - reserved_tracked_fields
|
281
|
+
end
|
282
|
+
|
283
|
+
# Retrieves the memoized list of reserved tracked fields, which are only included for certain actions.
|
284
|
+
#
|
285
|
+
# @return [ Array < String > ] the list of reserved database field names
|
286
|
+
def reserved_tracked_fields
|
287
|
+
@reserved_tracked_fields ||= ["_id", history_trackable_options[:version_field].to_s, "#{history_trackable_options[:modifier_field]}_id"]
|
288
|
+
end
|
289
|
+
|
250
290
|
def history_trackable_options
|
251
291
|
@history_trackable_options ||= Mongoid::History.trackable_class_options[self.collection_name.to_s.singularize.to_sym]
|
252
292
|
end
|
293
|
+
|
294
|
+
# Indicates whether there is an Embedded::One relation for the given embedded field.
|
295
|
+
#
|
296
|
+
# @param [ String | Symbol ] embed The name of the embedded field
|
297
|
+
#
|
298
|
+
# @return [ Boolean ] true if there is an Embedded::One relation for the given embedded field
|
299
|
+
def embeds_one?(embed)
|
300
|
+
relation_of(embed) == Mongoid::Relations::Embedded::One
|
301
|
+
end
|
302
|
+
|
303
|
+
# Indicates whether there is an Embedded::Many relation for the given embedded field.
|
304
|
+
#
|
305
|
+
# @param [ String | Symbol ] embed The name of the embedded field
|
306
|
+
#
|
307
|
+
# @return [ Boolean ] true if there is an Embedded::Many relation for the given embedded field
|
308
|
+
def embeds_many?(embed)
|
309
|
+
relation_of(embed) == Mongoid::Relations::Embedded::Many
|
310
|
+
end
|
311
|
+
|
312
|
+
# Retrieves the database representation of an embedded field name, in case the :store_as option is used.
|
313
|
+
#
|
314
|
+
# @param [ String | Symbol ] embed The name or alias of the embedded field
|
315
|
+
#
|
316
|
+
# @return [ String ] the database name of the embedded field
|
317
|
+
def embedded_alias(embed)
|
318
|
+
embedded_aliases[embed]
|
319
|
+
end
|
320
|
+
|
321
|
+
protected
|
322
|
+
|
323
|
+
# Retrieves the memoized hash of embedded aliases and their associated database representations.
|
324
|
+
#
|
325
|
+
# @return [ Hash < String, String > ] hash of embedded aliases (keys) to database representations (values)
|
326
|
+
def embedded_aliases
|
327
|
+
@embedded_aliases ||= relations.inject(HashWithIndifferentAccess.new) do |h,(k,v)|
|
328
|
+
h[v[:store_as]||k]=k; h
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
def relation_of(embed)
|
333
|
+
meta = reflect_on_association(embedded_alias(embed))
|
334
|
+
meta ? meta.relation : nil
|
335
|
+
end
|
253
336
|
end
|
254
337
|
end
|
255
338
|
end
|