Class: ToughGuy::Query

Inherits:
Plucky::Query
  • Object
show all
Defined in:
lib/toughguy/query.rb

Direct Known Subclasses

MappedQuery

Defined Under Namespace

Modules: PaginationMethods

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(klass, opts = {}) ⇒ Query

Returns a new instance of Query.



5
6
7
8
# File 'lib/toughguy/query.rb', line 5

def initialize(klass, opts = {})
  super(klass.collection, opts)
  @klass = klass
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(m, *args) ⇒ Object

Allow self-changing methods: where!, sort! etc.



11
12
13
14
15
16
17
18
# File 'lib/toughguy/query.rb', line 11

def method_missing(m, *args)
  if m.to_s =~ /^(.+)!$/
    send($1.to_sym, *args).tap {|q| @criteria, @options = q.criteria, q.options}
    self
  else
    super(m, *args)
  end
end

Instance Attribute Details

#klassObject

Returns the value of attribute klass.



3
4
5
# File 'lib/toughguy/query.rb', line 3

def klass
  @klass
end

Instance Method Details

#all(opts = {}) ⇒ Object Also known as: to_a



28
29
30
31
32
33
34
# File 'lib/toughguy/query.rb', line 28

def all(opts={})
  if @klass
    orig_all(opts).map {|d| @klass.load(d)}
  else
    orig_all(opts)
  end
end

#avg(key) ⇒ Object



96
97
98
99
# File 'lib/toughguy/query.rb', line 96

def avg(key)
  values = raw.select(key).map(key.to_s)
  values.inject(0) {|m, i| m += i} / values.size.to_f
end

#each(opts = {}, &block) ⇒ Object



38
39
40
41
42
43
44
45
# File 'lib/toughguy/query.rb', line 38

def each(opts={}, &block)
  if @klass
    find_each(opts).each {|d| block[@klass.load(d)]}
  else
    find_each(opts).each(&block)
  end
  self
end

#explain(opts = {}) ⇒ Object



20
21
22
# File 'lib/toughguy/query.rb', line 20

def explain(opts={})
  find_each(opts).explain
end

#find_one(opts = {}) ⇒ Object Also known as: first



49
50
51
# File 'lib/toughguy/query.rb', line 49

def find_one(opts={})
  (doc = orig_find_one(opts)) ? (@klass ? @klass.load(doc) : doc) : nil
end

#group(key, initial, reduce, finalize = nil) ⇒ Object



69
70
71
72
73
# File 'lib/toughguy/query.rb', line 69

def group(key, initial, reduce, finalize = nil)
  key = [key] unless key.is_a?(Array)
  collection.group(key.map {|k| k.to_s}, criteria.to_hash,
    initial, reduce, finalize)
end

#group_and_avg(group, key) ⇒ Object



79
80
81
82
83
84
# File 'lib/toughguy/query.rb', line 79

def group_and_avg(group, key)
  group(group, {'count' => 0, 'sum' => 0},
    "function(doc, out) {out.count++; out.sum += doc.#{key}}",
    "function(out){ if (out.count > 0) out.avg = out.sum / out.count }"
  ).map {|g| g.symbolize_keys}.sort_by {|g| -g[:avg]}
end

#group_and_count(key) ⇒ Object



75
76
77
# File 'lib/toughguy/query.rb', line 75

def group_and_count(key)
  group(key, {'sum' => 0}, "function(doc, prev) { prev.sum += 1}")
end

#insert_rate(opts = {}) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/toughguy/query.rb', line 101

def insert_rate(opts={})
  opts[:limit] ||= 100
  opts[:key] ||= :_id
  docs = raw.limit(opts[:limit]).sort(:_id.desc).select(opts[:key]).all
  if docs.empty?
    nil
  else
    t1, t2 = docs.first[opts[:key].to_s], docs.last[opts[:key].to_s]
    if opts[:key] == :_id
      t1, t2 = t1.generation_time, t2.generation_time
    end
    docs.size.to_f / (t1 - t2)
  end
end

#map(key = nil, &block) ⇒ Object

Extend map to accept key argument, allowing stuff like:

map(:path) # equivalent to map {|d| d[:path]}


58
59
60
61
62
# File 'lib/toughguy/query.rb', line 58

def map(key = nil, &block)
  m = []
  key ? each {|d| m << d[key]} : each {|d| m << block[d]}
  m
end

#map_idObject

Return an array of object ids.



65
66
67
# File 'lib/toughguy/query.rb', line 65

def map_id
  map(:_id)
end

#max(key) ⇒ Object



91
92
93
94
# File 'lib/toughguy/query.rb', line 91

def max(key)
  d = sort(key.desc).first
  d ? d[key] : nil
end

#min(key) ⇒ Object



86
87
88
89
# File 'lib/toughguy/query.rb', line 86

def min(key)
  d = sort(key).first
  d ? d[key] : nil
end

#orig_allObject



26
# File 'lib/toughguy/query.rb', line 26

alias_method :orig_all, :all

#orig_find_oneObject



47
# File 'lib/toughguy/query.rb', line 47

alias_method :orig_find_one, :find_one

#orig_sortObject



116
# File 'lib/toughguy/query.rb', line 116

alias_method :orig_sort, :sort

#paginate(opts) ⇒ Object



146
147
148
149
150
151
152
153
# File 'lib/toughguy/query.rb', line 146

def paginate(opts)
  per_page = opts[:per_page] || 50
  page = opts[:page] || 1

  paginated = limit(per_page).skip((page - 1) * per_page)
  paginated.set_pagination_info(page, per_page, count)
  paginated
end

#rawObject

Returns a query that does not converted docs to model instances



138
139
140
# File 'lib/toughguy/query.rb', line 138

def raw
  @klass ? clone.tap {|q| q.klass = nil} : self
end

#select(fields) ⇒ Object

Add select method to select the fields to return



130
131
132
133
134
135
# File 'lib/toughguy/query.rb', line 130

def select(fields)
  if (fields == []) || (fields.nil?)
    fields = [:_id]
  end
  clone.tap {|q| q.options[:fields] = fields}
end

#set_pagination_info(page_no, page_size, record_count) ⇒ Object

Sets the pagination info



156
157
158
159
160
161
162
163
164
165
# File 'lib/toughguy/query.rb', line 156

def set_pagination_info(page_no, page_size, record_count)
  @current_page = page_no
  @per_page = page_size
  @total_count = record_count
  @total_pages = (record_count / page_size.to_f).ceil

  extend PaginationMethods

  self
end

#sort(*args) ⇒ Object

Extend the sort API to allow stuff like:

sort(:kind, :stamp)
sort(:kind, :stamp.desc) # see Symbol#desc below


121
122
123
124
125
126
127
# File 'lib/toughguy/query.rb', line 121

def sort(*args)
  if args.all? {|a| a.is_a?(Symbol) || a.is_a?(Array)}
    orig_sort(args.map {|a| a.is_a?(Symbol) ? [a, 1] : a})
  else
    orig_sort(*args)
  end
end

#update_values(doc, opts = {}) ⇒ Object



142
143
144
# File 'lib/toughguy/query.rb', line 142

def update_values(doc, opts={})
  collection.update(criteria.to_hash, doc, opts)
end