Class: ActiveAggregate::Relation
- Inherits:
-
Object
- Object
- ActiveAggregate::Relation
show all
- Includes:
- ActiveSupport::Concern
- Defined in:
- lib/active_aggregate/relation.rb
Instance Attribute Summary collapse
Instance Method Summary
collapse
Constructor Details
#initialize(scope_class, body = nil, options = {}) ⇒ Relation
Returns a new instance of Relation.
7
8
9
10
11
12
13
14
15
16
|
# File 'lib/active_aggregate/relation.rb', line 7
def initialize(scope_class, body = nil, options = {})
@scope_class = scope_class
@cacheable = true
if body.respond_to?(:call)
init_default_value(options)
@body = body
else
init_default_value(body.nil? ? options : body)
end
end
|
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(scope_name, *args, &block) ⇒ Object
131
132
133
134
135
136
137
138
|
# File 'lib/active_aggregate/relation.rb', line 131
def method_missing(scope_name, *args, &block)
name = scope_name.to_sym
if scope?(scope_name)
merge(scope_class.public_send(name, *args, &block))
else
super
end
end
|
Instance Attribute Details
#body ⇒ Object
Returns the value of attribute body.
4
5
6
|
# File 'lib/active_aggregate/relation.rb', line 4
def body
@body
end
|
#cacheable ⇒ Object
Returns the value of attribute cacheable.
5
6
7
|
# File 'lib/active_aggregate/relation.rb', line 5
def cacheable
@cacheable
end
|
#scope_class ⇒ Object
Returns the value of attribute scope_class.
4
5
6
|
# File 'lib/active_aggregate/relation.rb', line 4
def scope_class
@scope_class
end
|
Instance Method Details
#add_pipeline(*stages) ⇒ Object
119
120
121
|
# File 'lib/active_aggregate/relation.rb', line 119
def add_pipeline(*stages)
@pipeline.push(*stages.flatten)
end
|
#aggregate(options = {}, *args) ⇒ Object
108
109
110
|
# File 'lib/active_aggregate/relation.rb', line 108
def aggregate(options = {}, *args)
model.collection.aggregate(generate_execute_pipeline(options), *args)
end
|
#all_of(*args) ⇒ Object
166
167
168
|
# File 'lib/active_aggregate/relation.rb', line 166
def all_of(*args)
query_criteria(model.all_of(*args))
end
|
#any_of(*args) ⇒ Object
162
163
164
|
# File 'lib/active_aggregate/relation.rb', line 162
def any_of(*args)
query_criteria(model.any_of(*args))
end
|
#expose ⇒ Object
62
63
64
65
66
67
68
69
70
71
|
# File 'lib/active_aggregate/relation.rb', line 62
def expose
{
pipeline: @pipeline,
criteria: @criteria,
group: @group,
project: @project,
sort: @sort,
limit: @limit
}
end
|
#generate(*args) ⇒ Object
94
95
96
97
98
99
100
101
102
103
104
105
106
|
# File 'lib/active_aggregate/relation.rb', line 94
def generate(*args)
return self if body.nil?
result = scope_class.instance_exec(*args, &body)
case result
when Hash
init_default_value(merge_exposed(result))
self
when self.class
merge(result)
else
self
end
end
|
#generate_execute_pipeline(select_all: false, aggregate: {}) ⇒ Object
82
83
84
85
86
87
88
89
90
91
92
|
# File 'lib/active_aggregate/relation.rb', line 82
def generate_execute_pipeline(select_all: false, aggregate: {})
merge(aggregate) if aggregate.present?
[].tap do |execute_pipeline|
execute_pipeline << { '$match': selector } if selector.present?
execute_pipeline << { '$group': @group } if @group.present?
execute_pipeline << { '$sort': @sort } if @sort.present?
execute_pipeline << { '$project': generate_project } if select_all || @project.present?
execute_pipeline << { '$limit': @limit } if @limit.present?
execute_pipeline.push(*@pipeline)
end
end
|
#generate_project ⇒ Object
73
74
75
76
|
# File 'lib/active_aggregate/relation.rb', line 73
def generate_project
return @project if @project.present?
selector.keys.each_with_object({}) { |con, hashes| hashes[con] = "$#{con}" }
end
|
#group(options) ⇒ Object
40
41
42
|
# File 'lib/active_aggregate/relation.rb', line 40
def group(options)
query(group: options)
end
|
#in(*args) ⇒ Object
Also known as:
where_in
144
145
146
|
# File 'lib/active_aggregate/relation.rb', line 144
def in(*args)
query_criteria(model.in(*args))
end
|
#limit(options) ⇒ Object
57
58
59
60
|
# File 'lib/active_aggregate/relation.rb', line 57
def limit(options)
@limit = options
self
end
|
#merge(relation) ⇒ Object
170
171
172
173
174
175
|
# File 'lib/active_aggregate/relation.rb', line 170
def merge(relation)
if !relation.is_a?(ActiveAggregate::Relation) || relation.scope_class != scope_class
raise TypeError, "#relation much be an ActiveAggregate::Relation of #{scope_class}"
end
self.class.new(scope_class, merge_exposed(relation.expose))
end
|
#merge_exposed(exposed) ⇒ Object
177
178
179
180
181
182
183
184
185
186
|
# File 'lib/active_aggregate/relation.rb', line 177
def merge_exposed(exposed)
{
pipeline: @pipeline + (exposed[:pipeline] || []),
criteria: [@criteria, format_criteria(exposed[:criteria])].compact.reduce(&:merge),
group: [@group, exposed[:group]].compact.reduce(&:deep_merge),
project: [@project, exposed[:project]].compact.reduce(&:deep_merge),
sort: exposed[:sort] || nil,
limit: exposed[:limit] || nil
}
end
|
#override(*stages) ⇒ Object
123
124
125
|
# File 'lib/active_aggregate/relation.rb', line 123
def override(*stages)
@pipeline = stages.flatten
end
|
#pipeline(options) ⇒ Object
44
45
46
|
# File 'lib/active_aggregate/relation.rb', line 44
def pipeline(options)
query(pipeline: options)
end
|
#pluck(*fields) ⇒ Object
148
149
150
151
152
153
154
155
156
157
158
|
# File 'lib/active_aggregate/relation.rb', line 148
def pluck(*fields)
fields = Array.wrap(fields).map(&:to_s)
to_a.each_with_object([]) do |doc, result|
record = if fields.size == 1
doc[fields.first]
else
doc.slice(*fields).values
end
result << record unless record.nil?
end
end
|
#project(options) ⇒ Object
48
49
50
|
# File 'lib/active_aggregate/relation.rb', line 48
def project(options)
query(project: options)
end
|
#query(options) ⇒ Object
25
26
27
28
29
30
31
32
33
34
|
# File 'lib/active_aggregate/relation.rb', line 25
def query(options)
case options
when Hash
merge(self.class.new(scope_class, options))
when self.class
merge(options)
else
self
end
end
|
#query_criteria(options) ⇒ Object
36
37
38
|
# File 'lib/active_aggregate/relation.rb', line 36
def query_criteria(options)
query(criteria: options)
end
|
#respond_to_missing?(method_name, include_private = false) ⇒ Boolean
127
128
129
|
# File 'lib/active_aggregate/relation.rb', line 127
def respond_to_missing?(method_name, include_private = false)
scope?(scope_name) || super
end
|
#selector ⇒ Object
78
79
80
|
# File 'lib/active_aggregate/relation.rb', line 78
def selector
@criteria ? @criteria.selector : {}
end
|
#sort(options) ⇒ Object
52
53
54
55
|
# File 'lib/active_aggregate/relation.rb', line 52
def sort(options)
@sort = options
self
end
|
#to_a ⇒ Object
Also known as:
load
112
113
114
115
|
# File 'lib/active_aggregate/relation.rb', line 112
def to_a
return @as_array if cacheable && @as_array
aggregate.to_a.tap { |array| @as_array ||= array if cacheable }
end
|
#where(*args) ⇒ Object
140
141
142
|
# File 'lib/active_aggregate/relation.rb', line 140
def where(*args)
query_criteria(model.where(*args))
end
|