Class: Groovy::Query
Constant Summary collapse
- AND =
'+'.freeze
- NOT =
'-'.freeze
- PER_PAGE =
50.freeze
- VALID_QUERY_CHARS =
'a-zA-Z0-9_\.,&-'.freeze
- REMOVE_INVALID_CHARS_REGEX =
Regexp.new('[^\s' + VALID_QUERY_CHARS + ']').freeze
Instance Attribute Summary collapse
-
#parameters ⇒ Object
readonly
Returns the value of attribute parameters.
-
#sorting ⇒ Object
readonly
Returns the value of attribute sorting.
Class Method Summary collapse
Instance Method Summary collapse
- #[](index) ⇒ Object
- #all ⇒ Object
-
#as_json(options = {}) ⇒ Object
def inspect “<#selfself.classself.class.name ##parameters>” end.
- #each(&block) ⇒ Object
- #find(id) ⇒ Object
- #find_by(conditions) ⇒ Object
- #find_each(opts = {}, &block) ⇒ Object
- #group_by(column) ⇒ Object
- #in_batches(of: 1000, from: nil, &block) ⇒ Object
-
#initialize(model, table, options = {}) ⇒ Query
constructor
A new instance of Query.
- #last(count = 1) ⇒ Object
- #limit(num) ⇒ Object
- #not(conditions = {}) ⇒ Object
- #offset(num) ⇒ Object
- #paginate(page = 1, per_page: PER_PAGE) ⇒ Object
- #query ⇒ Object
- #records ⇒ Object
- #search(obj) ⇒ Object
- #select(&block) ⇒ Object
- #size ⇒ Object (also: #count)
-
#sort_by(hash) ⇒ Object
sort_by(title: :asc).
- #to_a ⇒ Object
- #total_entries ⇒ Object
- #update_all(attrs) ⇒ Object
-
#where(conditions = nil) ⇒ Object
groonga.org/docs/reference/grn_expr/query_syntax.html TODO: support match_columns (search value in two or more columns).
Constructor Details
#initialize(model, table, options = {}) ⇒ Query
Returns a new instance of Query.
21 22 23 24 25 26 |
# File 'lib/groovy/query.rb', line 21 def initialize(model, table, = {}) @model, @table, @options = model, table, @parameters = .delete(:parameters) || [] @sorting = { limit: -1, offset: 0 } @default_sort_key = table.is_a?(Groonga::Hash) ? '_key' : '_id' end |
Instance Attribute Details
#parameters ⇒ Object (readonly)
Returns the value of attribute parameters.
12 13 14 |
# File 'lib/groovy/query.rb', line 12 def parameters @parameters end |
#sorting ⇒ Object (readonly)
Returns the value of attribute sorting.
12 13 14 |
# File 'lib/groovy/query.rb', line 12 def sorting @sorting end |
Class Method Details
.add_scope(name, obj) ⇒ Object
14 15 16 17 18 19 |
# File 'lib/groovy/query.rb', line 14 def self.add_scope(name, obj) define_method(name) do |*args| res = obj.respond_to?(:call) ? instance_exec(*args, &obj) : obj self end end |
Instance Method Details
#[](index) ⇒ Object
192 193 194 |
# File 'lib/groovy/query.rb', line 192 def [](index) records[index] end |
#all ⇒ Object
178 179 180 |
# File 'lib/groovy/query.rb', line 178 def all @records || query end |
#as_json(options = {}) ⇒ Object
def inspect
"<#{self.class.name} #{parameters}>"
end
32 33 34 35 36 |
# File 'lib/groovy/query.rb', line 32 def as_json( = {}) Array.new.tap do |arr| each { |record| arr.push(record.as_json()) } end end |
#each(&block) ⇒ Object
196 197 198 |
# File 'lib/groovy/query.rb', line 196 def each(&block) records.each { |r| block.call(r) } end |
#find(id) ⇒ Object
55 56 57 |
# File 'lib/groovy/query.rb', line 55 def find(id) find_by(_id: id) end |
#find_by(conditions) ⇒ Object
59 60 61 |
# File 'lib/groovy/query.rb', line 59 def find_by(conditions) where(conditions).limit(1).first end |
#find_each(opts = {}, &block) ⇒ Object
63 64 65 66 67 68 69 |
# File 'lib/groovy/query.rb', line 63 def find_each(opts = {}, &block) count = 0 in_batches({ of: 10 }.merge(opts)) do |group| group.each { |item| count += 1; yield(item) } end count end |
#group_by(column) ⇒ Object
169 170 171 172 |
# File 'lib/groovy/query.rb', line 169 def group_by(column) sorting[:group_by] = column self end |
#in_batches(of: 1000, from: nil, &block) ⇒ Object
217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/groovy/query.rb', line 217 def in_batches(of: 1000, from: nil, &block) @sorting[:limit] = of @sorting[:offset] = from || 0 while results.any? yield to_a break if results.size < of @sorting[:offset] += of @records = @results = nil # reset end end |
#last(count = 1) ⇒ Object
209 210 211 212 213 214 215 |
# File 'lib/groovy/query.rb', line 209 def last(count = 1) if count > 1 records[(size-count)..-1] else records[size-1] end end |
#limit(num) ⇒ Object
139 140 141 142 |
# File 'lib/groovy/query.rb', line 139 def limit(num) @sorting[:limit] = num self end |
#not(conditions = {}) ⇒ Object
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
# File 'lib/groovy/query.rb', line 107 def not(conditions = {}) case conditions when String # "foo:bar" parameters.push(NOT + "(#{map_operator(conditions)})") when Hash # { foo: 'bar' } conditions.each do |key, val| if val.is_a?(Range) add_param(AND + [key, val.min].join(':<=')) if val.min > 0 # gte add_param(AND + [key, val.max].join(':>=')) if val.max # lte, nil if range.max is -1 elsif val.is_a?(Regexp) str = val.source.gsub(REMOVE_INVALID_CHARS_REGEX, '') param = val.source[0] == '^' ? ':^' : val.source[-1] == '$' ? ':$' : ':~' # starts with or regexp add_param(NOT + [key, str.downcase].join(param)) # regex must be downcase elsif val.is_a?(Array) # { foo: [1,2,3] } str = "#{key}:!#{val.join(" #{AND}#{key}:!")}" add_param(AND + str) else str = val.nil? || val === false || val.to_s.strip == '' ? "\"\"" : escape_val(val) add_param(AND + [key, str].join(':!')) # not end end # when Array # ["foo:?", val] # parameters.push(conditions.first.sub('?', conditions.last)) else raise 'not supported' end self end |
#offset(num) ⇒ Object
144 145 146 147 |
# File 'lib/groovy/query.rb', line 144 def offset(num) @sorting[:offset] = num self end |
#paginate(page = 1, per_page: PER_PAGE) ⇒ Object
149 150 151 152 153 |
# File 'lib/groovy/query.rb', line 149 def paginate(page = 1, per_page: PER_PAGE) page = 1 if page.to_i < 1 offset = ((page.to_i)-1) * per_page offset(offset).limit(per_page) # returns self end |
#query ⇒ Object
174 175 176 |
# File 'lib/groovy/query.rb', line 174 def query self end |
#records ⇒ Object
230 231 232 233 234 |
# File 'lib/groovy/query.rb', line 230 def records @records ||= results.map do |r| model.new_from_record(r) end end |
#search(obj) ⇒ Object
38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/groovy/query.rb', line 38 def search(obj) obj.each do |col, q| # unless model.schema.index_columns.include?(col) # raise "Not an index column, so cannot do fulltext search: #{col}" # end q.split(' ').each do |word| parameters.push(AND + "(#{col}:@#{word})") end if q.is_a?(String) && q.strip != '' end self end |
#select(&block) ⇒ Object
50 51 52 53 |
# File 'lib/groovy/query.rb', line 50 def select(&block) @select_block = block self end |
#size ⇒ Object Also known as: count
182 183 184 |
# File 'lib/groovy/query.rb', line 182 def size results.size end |
#sort_by(hash) ⇒ Object
sort_by(title: :asc)
156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/groovy/query.rb', line 156 def sort_by(hash) if hash.is_a?(String) || hash.is_a?(Symbol) # e.g. 'title.desc' or :title (asc by default) param, dir = hash.to_s.split('.') hash = {} hash[param] = dir || 'asc' end sorting[:by] = hash.keys.map do |key| { key: key.to_s, order: hash[key] } end self end |
#to_a ⇒ Object
188 189 190 |
# File 'lib/groovy/query.rb', line 188 def to_a records end |
#total_entries ⇒ Object
204 205 206 207 |
# File 'lib/groovy/query.rb', line 204 def total_entries results # ensure query has been run @total_entries end |
#update_all(attrs) ⇒ Object
200 201 202 |
# File 'lib/groovy/query.rb', line 200 def update_all(attrs) each { |r| r.update_attributes(attrs) } end |
#where(conditions = nil) ⇒ Object
groonga.org/docs/reference/grn_expr/query_syntax.html TODO: support match_columns (search value in two or more columns)
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/groovy/query.rb', line 73 def where(conditions = nil) case conditions when String # "foo:bar" add_param(AND + "(#{map_operator(conditions)})") when Hash # { foo: 'bar' } or { views: 1..100 } conditions.each do |key, val| if val.is_a?(Range) add_param(AND + [key, val.min].join(':>=')) if val.min # lte add_param(AND + [key, val.max].join(':<=')) if val.max # gte elsif val.is_a?(Regexp) str = val.source.gsub(REMOVE_INVALID_CHARS_REGEX, '') param = val.source[0] == '^' ? ':^' : val.source[-1] == '$' ? ':$' : ':~' # starts with or regexp add_param(AND + [key, str.downcase].join(param)) # regex must be downcase elsif val.is_a?(Array) # { foo: [1,2,3] } str = "#{key}:#{val.join(" OR #{key}:")}" add_param(AND + str) else str = val.nil? || val === false || val.to_s.strip == '' ? "\"\"" : escape_val(val) add_param(AND + [key, str].join(':')) end end # when Array # ["foo:?", val] # parameters.push(conditions.first.sub('?', conditions.last)) when NilClass # doing where.not probably else raise 'not supported' end self end |