deli 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +77 -0
- data/lib/deli.rb +18 -0
- data/lib/deli/adapters.rb +9 -0
- data/lib/deli/adapters/active_record.rb +251 -0
- data/lib/deli/adapters/cassandra.rb +52 -0
- data/lib/deli/adapters/mongoid.rb +180 -0
- data/lib/deli/adapters/neo4j.rb +54 -0
- data/lib/deli/adapters/simple.rb +39 -0
- data/lib/deli/configuration.rb +47 -0
- data/lib/deli/controller.rb +75 -0
- data/lib/deli/helper.rb +61 -0
- data/lib/deli/model.rb +13 -0
- data/lib/deli/pagination.rb +117 -0
- data/lib/deli/param.rb +189 -0
- data/lib/deli/query.rb +133 -0
- data/lib/deli/railtie.rb +14 -0
- data/spec/active_record_spec.rb +358 -0
- data/spec/cassandra_spec.rb +40 -0
- data/spec/mongoid_spec.rb +40 -0
- data/spec/neo4j_spec.rb +40 -0
- data/spec/param_spec.rb +318 -0
- data/spec/spec_helper.rb +33 -0
- data/spec/support/database.rb +69 -0
- data/spec/support/models.rb +27 -0
- metadata +77 -0
data/Rakefile
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require "rake/rdoctask"
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
|
5
|
+
spec = Gem::Specification.new do |s|
|
6
|
+
s.name = "deli"
|
7
|
+
s.authors = ["Lance Pollard"]
|
8
|
+
s.version = "0.5.0"
|
9
|
+
s.summary = "Tasty URL Parameters for Rails"
|
10
|
+
s.homepage = "http://github.com/viatropos/deli"
|
11
|
+
s.email = "lancejpollard@gmail.com"
|
12
|
+
s.description = "Tasty URL Parameters for Rails"
|
13
|
+
s.has_rdoc = false
|
14
|
+
s.rubyforge_project = "deli"
|
15
|
+
s.platform = Gem::Platform::RUBY
|
16
|
+
s.files = %w(Rakefile) + Dir["{lib,rails,spec,app}/**/*"] - Dir["spec/tmp"]
|
17
|
+
s.require_path = "lib"
|
18
|
+
end
|
19
|
+
|
20
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
21
|
+
pkg.gem_spec = spec
|
22
|
+
end
|
23
|
+
|
24
|
+
desc 'run unit tests'
|
25
|
+
task :test do
|
26
|
+
Dir["test/**/*"].each do |file|
|
27
|
+
next unless File.basename(file) =~ /test_/
|
28
|
+
next unless File.extname(file) == ".rb"
|
29
|
+
system "ruby #{file}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "Create .gemspec file (useful for github)"
|
34
|
+
task :gemspec do
|
35
|
+
File.open("#{spec.name}.gemspec", "w") do |f|
|
36
|
+
f.puts spec.to_ruby
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
desc "Build the gem into the current directory"
|
41
|
+
task :gem => :gemspec do
|
42
|
+
`gem build #{spec.name}.gemspec`
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "Publish gem to rubygems"
|
46
|
+
task :publish => [:package] do
|
47
|
+
%x[gem push #{spec.name}-#{spec.version}.gem]
|
48
|
+
end
|
49
|
+
|
50
|
+
desc "Print a list of the files to be put into the gem"
|
51
|
+
task :manifest do
|
52
|
+
File.open("Manifest", "w") do |f|
|
53
|
+
spec.files.each do |file|
|
54
|
+
f.puts file
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
desc "Install the gem locally"
|
60
|
+
task :install => [:package] do
|
61
|
+
File.mkdir("pkg") unless File.exists?("pkg")
|
62
|
+
command = "gem install pkg/#{spec.name}-#{spec.version} --no-ri --no-rdoc"
|
63
|
+
command = "sudo #{command}" if ENV["SUDO"] == true
|
64
|
+
sh %{#{command}}
|
65
|
+
end
|
66
|
+
|
67
|
+
desc "Generate the rdoc"
|
68
|
+
Rake::RDocTask.new do |rdoc|
|
69
|
+
files = ["README.markdown", "lib/**/*.rb"]
|
70
|
+
rdoc.rdoc_files.add(files)
|
71
|
+
rdoc.main = "README.markdown"
|
72
|
+
rdoc.title = spec.summary
|
73
|
+
end
|
74
|
+
|
75
|
+
task :yank do
|
76
|
+
`gem yank #{spec.name} -v #{spec.version}`
|
77
|
+
end
|
data/lib/deli.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'time'
|
3
|
+
require 'date'
|
4
|
+
require 'active_support'
|
5
|
+
require 'active_support/core_ext'
|
6
|
+
require 'uri'
|
7
|
+
|
8
|
+
$:.unshift File.dirname(__FILE__)
|
9
|
+
|
10
|
+
require "deli/configuration"
|
11
|
+
require "deli/railtie" if defined?(::Rails)
|
12
|
+
require "deli/query"
|
13
|
+
require "deli/model"
|
14
|
+
require "deli/controller"
|
15
|
+
require "deli/helper"
|
16
|
+
require "deli/pagination"
|
17
|
+
require "deli/param"
|
18
|
+
require "deli/adapters"
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Deli
|
2
|
+
module Adapters
|
3
|
+
autoload :ActiveRecord, "deli/adapters/active_record"
|
4
|
+
autoload :Cassandra, "deli/adapters/cassandra"
|
5
|
+
autoload :Mongoid, "deli/adapters/mongoid"
|
6
|
+
autoload :Neo4j, "deli/adapters/neo4j"
|
7
|
+
autoload :Simple, "deli/adapters/simple"
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,251 @@
|
|
1
|
+
module Deli
|
2
|
+
module Adapters
|
3
|
+
module ActiveRecord
|
4
|
+
class Model < Deli::Model
|
5
|
+
def model_type(key, options = {})
|
6
|
+
default = options[:type]
|
7
|
+
|
8
|
+
if default.present?
|
9
|
+
value = default.to_sym
|
10
|
+
else
|
11
|
+
value = model_class.columns.detect { |i| i.name == key }
|
12
|
+
value = value.present? ? value.type : nil
|
13
|
+
end
|
14
|
+
|
15
|
+
raise ::ArgumentError.new("Must specify type, such as: `match :#{key}, :type => :string`") if value.blank?
|
16
|
+
|
17
|
+
case value
|
18
|
+
when :datetime, :time
|
19
|
+
:time
|
20
|
+
when :date
|
21
|
+
:date
|
22
|
+
when :integer, :float, :decimal, :count
|
23
|
+
:number
|
24
|
+
when :sort, :order
|
25
|
+
:order
|
26
|
+
when :string, :text
|
27
|
+
:string
|
28
|
+
else
|
29
|
+
value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Query < ::Deli::Query
|
35
|
+
# Converts request parameters into an options Hash for ActiveRecord finder methods.# Outputs a query hash for Mongoid.
|
36
|
+
#
|
37
|
+
# @example Declare the queries you want to make in your controller.
|
38
|
+
#
|
39
|
+
# queries :order => "created_at desc" do
|
40
|
+
# match :full_name
|
41
|
+
# match :created, :field => :created_at, :strict => true
|
42
|
+
# match :status, :operators => [:in] # should ultimately have full-on validations
|
43
|
+
# match :product, :type => :string, :scope => :with_bookmarked_products
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# @example Request with all possible parameters
|
47
|
+
#
|
48
|
+
# "/users?full_name=^lance&created=2011-08-01..t&status=active&product=laptop"
|
49
|
+
#
|
50
|
+
# @param [Hash] params ({}) The query params hash from the controller.
|
51
|
+
#
|
52
|
+
# @option params [::Symbol] :type Defaults to the database field type. If you use named scopes
|
53
|
+
# to reference assiated models, as of now you must specify the type manually. Haven't looked
|
54
|
+
# through the Rails 3 scoping code to figure out how use reflection to get join keys.
|
55
|
+
# @option params [::String, ::Symbol] :field If a ::Symbol, the table/collection attribute
|
56
|
+
# to query, if a ::String, the fully qualified table/collection + attribute string.
|
57
|
+
# @option params [::Array] :operators Optional, refines the allowable query value formats.
|
58
|
+
# @option params [::Boolean] :strict (+false) If true, it will raise an error if the
|
59
|
+
# URL parameter is not properly formatted (e.g. "2011.." vs. "2011..t")
|
60
|
+
# @option params [::Symbol] :scope Optional, a class method on the model for the controller,
|
61
|
+
# used as a named scope. In here place your +joins(:x).where(:y)+ code.
|
62
|
+
#
|
63
|
+
# @return [Hash]
|
64
|
+
def render(params)
|
65
|
+
hash = super
|
66
|
+
|
67
|
+
hash["sort"] = default_sort if hash["sort"].blank? && default_sort.present?
|
68
|
+
|
69
|
+
sort = hash.delete("sort")
|
70
|
+
limit = hash.delete("limit") || 20
|
71
|
+
page = hash.delete("page") || 1
|
72
|
+
|
73
|
+
offset = limit.present? && page.present? ? ((page - 1) * limit).to_i : 0
|
74
|
+
|
75
|
+
keys = []
|
76
|
+
values = []
|
77
|
+
|
78
|
+
hash.values.collect do |array|
|
79
|
+
keys << array[0]
|
80
|
+
values << array[1..-1]
|
81
|
+
end
|
82
|
+
|
83
|
+
keys.map! {|i| "(#{i})"} if keys.length > 1
|
84
|
+
keys = keys.join(" AND ")
|
85
|
+
values.flatten!
|
86
|
+
conditions = [keys, *values]
|
87
|
+
|
88
|
+
result = {}
|
89
|
+
result[:conditions] = conditions if conditions.present?
|
90
|
+
result[:limit] = limit if limit.present? && limit > 0
|
91
|
+
result[:offset] = offset if offset.present? && offset > 0
|
92
|
+
result[:order] = sort if sort.present?
|
93
|
+
|
94
|
+
result
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
class Param < ::Deli::Param
|
99
|
+
attr_accessor :table_key
|
100
|
+
|
101
|
+
def initialize(key, options = {})
|
102
|
+
super(key, options)
|
103
|
+
configure_clauses(options)
|
104
|
+
end
|
105
|
+
|
106
|
+
def parse(value)
|
107
|
+
[value]
|
108
|
+
end
|
109
|
+
|
110
|
+
def configure_clauses(options)
|
111
|
+
case options[:to]
|
112
|
+
when ::String
|
113
|
+
self.table_key = options[:to]
|
114
|
+
when ::Hash
|
115
|
+
join_key = options[:as] || options[:to].keys.first
|
116
|
+
join_class = join_key.to_s.singularize.camelize.constantize
|
117
|
+
attribute = options[:to].values.first.to_sym
|
118
|
+
self.table_key = "#{join_class.table_name}.#{attribute}"
|
119
|
+
else
|
120
|
+
if model_class.respond_to?(:table_name)
|
121
|
+
if association = find_association
|
122
|
+
self.table_key = "#{model_class.table_name}.#{key}_id"
|
123
|
+
else
|
124
|
+
self.table_key = "#{model_class.table_name}.#{key}"
|
125
|
+
end
|
126
|
+
else
|
127
|
+
self.table_key = key
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# what this responds to
|
133
|
+
def operators
|
134
|
+
[:equals, :contains, :start, :end]
|
135
|
+
end
|
136
|
+
|
137
|
+
def find_association
|
138
|
+
key = self.key.to_sym
|
139
|
+
model_class.reflect_on_all_associations.detect do |association|
|
140
|
+
association.name == key
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def render(value)
|
145
|
+
keys, values = [], []
|
146
|
+
|
147
|
+
parse(value).each do |and_collection|
|
148
|
+
and_keys = []
|
149
|
+
|
150
|
+
and_collection.each do |item|
|
151
|
+
and_keys << "#{table_key} #{render_operator(item[:operators][0])} ?"
|
152
|
+
values << render_value(item[:value], item[:operators][1] || item[:operators][0])
|
153
|
+
end
|
154
|
+
|
155
|
+
keys << and_keys
|
156
|
+
end
|
157
|
+
|
158
|
+
keys.map! { |and_keys| and_keys.join(" AND ") }
|
159
|
+
|
160
|
+
if keys.length > 1
|
161
|
+
[parenthesize!(keys).join(" OR "), *values]
|
162
|
+
else
|
163
|
+
[keys.join(" OR "), *values]
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def render_name(*names)
|
168
|
+
names.flatten.compact.join(".")
|
169
|
+
end
|
170
|
+
|
171
|
+
def render_value(value, operator = nil)
|
172
|
+
value
|
173
|
+
end
|
174
|
+
|
175
|
+
def render_operator(value)
|
176
|
+
case value
|
177
|
+
when "=~"
|
178
|
+
match_operator
|
179
|
+
when "!~"
|
180
|
+
"NOT #{match_operator}"
|
181
|
+
else
|
182
|
+
value
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def match_operator
|
187
|
+
postgres? ? "ILIKE" : "LIKE"
|
188
|
+
end
|
189
|
+
|
190
|
+
def parenthesize!(items)
|
191
|
+
items.map! { |i| "(#{i})" } if items.length > 1
|
192
|
+
items
|
193
|
+
end
|
194
|
+
|
195
|
+
def postgres?
|
196
|
+
if @postgres.nil?
|
197
|
+
@postgres = defined?(::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) && ::ActiveRecord::Base.connection.is_a?(::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
|
198
|
+
end
|
199
|
+
@postgres
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
class Time < Param
|
204
|
+
include Deli::Param::Time
|
205
|
+
end
|
206
|
+
|
207
|
+
class Date < Time
|
208
|
+
include Deli::Param::Date
|
209
|
+
end
|
210
|
+
|
211
|
+
class String < Param
|
212
|
+
include Deli::Param::String
|
213
|
+
|
214
|
+
def render_value(value, operator = nil)
|
215
|
+
case operator
|
216
|
+
when "=", "!="
|
217
|
+
value
|
218
|
+
when "^"
|
219
|
+
"%#{value}"
|
220
|
+
when "$"
|
221
|
+
"#{value}%"
|
222
|
+
else
|
223
|
+
"%#{value}%"
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
class Number < Param
|
229
|
+
include Deli::Param::Number
|
230
|
+
end
|
231
|
+
|
232
|
+
class Limit < Param
|
233
|
+
include Deli::Param::Limit
|
234
|
+
end
|
235
|
+
|
236
|
+
class Order < Param
|
237
|
+
include Deli::Param::Order
|
238
|
+
|
239
|
+
def render(value)
|
240
|
+
parse(value).map do |item|
|
241
|
+
"#{render_name(item[:namespace], item[:key])} #{item[:operators][0] == "+" ? "ASC" : "DESC"}"
|
242
|
+
end.join(", ")
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
class Offset < Param
|
247
|
+
include Deli::Param::Offset
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Deli
|
2
|
+
module Adapters
|
3
|
+
# @todo
|
4
|
+
module Cassandra
|
5
|
+
class Query < ::Deli::Query
|
6
|
+
def render(params)
|
7
|
+
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Param < ::Deli::Param
|
12
|
+
def render(value)
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
def render_value(value, operator = nil)
|
17
|
+
value
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Time < Param
|
22
|
+
include Deli::Param::Time
|
23
|
+
end
|
24
|
+
|
25
|
+
class Date < Time
|
26
|
+
include Deli::Param::Date
|
27
|
+
end
|
28
|
+
|
29
|
+
class String < Param
|
30
|
+
include Deli::Param::String
|
31
|
+
end
|
32
|
+
|
33
|
+
class Number < Param
|
34
|
+
include Deli::Param::Number
|
35
|
+
end
|
36
|
+
|
37
|
+
class Limit < Param
|
38
|
+
include Deli::Param::Limit
|
39
|
+
end
|
40
|
+
|
41
|
+
class Order < Param
|
42
|
+
include Deli::Param::Order
|
43
|
+
|
44
|
+
def render(value)
|
45
|
+
parse(value).map do |item|
|
46
|
+
[render_name(item[:namespace], item[:key]), item[:operators][0] == "+" ? :asc : :desc]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
module Deli
|
2
|
+
module Adapters
|
3
|
+
# http://mongoid.org/docs/querying/criteria.html
|
4
|
+
module Mongoid
|
5
|
+
class Model < Deli::Model
|
6
|
+
def model_type(key, options = {})
|
7
|
+
default = options[:type]
|
8
|
+
|
9
|
+
if default.present?
|
10
|
+
value = default.to_sym
|
11
|
+
else
|
12
|
+
value = model_class.fields[key.to_s]
|
13
|
+
value = value.present? ? value.type.to_s.underscore.to_sym : nil
|
14
|
+
end
|
15
|
+
|
16
|
+
raise ::ArgumentError.new("Must specify type, such as: `match :#{key}, :type => :string`") if value.blank?
|
17
|
+
|
18
|
+
case value
|
19
|
+
when :datetime, :time
|
20
|
+
:time
|
21
|
+
when :date
|
22
|
+
:date
|
23
|
+
when :integer, :float, :decimal, :count
|
24
|
+
:number
|
25
|
+
when :sort, :order
|
26
|
+
:order
|
27
|
+
when :string, :text
|
28
|
+
:string
|
29
|
+
else
|
30
|
+
value
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Outputs a query hash for Mongoid.
|
36
|
+
#
|
37
|
+
# @example Declare the queries you want to make in your controller.
|
38
|
+
#
|
39
|
+
# queries :order => "created_at desc" do
|
40
|
+
# match :full_name
|
41
|
+
# match :created, :field => :created_at
|
42
|
+
# match :status, :type => :array
|
43
|
+
# match :product, :type => :string, :field => "products.title"
|
44
|
+
# match :favorites, :type => :string, :scope => :favorite_products # does the joins / default conditions work
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# @example Query for +"title=Hello+World"+
|
48
|
+
#
|
49
|
+
# {:full_name => {"$in" => "John"}}
|
50
|
+
class Query < ::Deli::Query
|
51
|
+
def render(params)
|
52
|
+
params = super
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class Param < ::Deli::Param
|
57
|
+
def render_value(value, operator = nil)
|
58
|
+
value
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class Time < Param
|
63
|
+
include ::Mongoid::Fields::Serializable::Timekeeping
|
64
|
+
include Deli::Param::Time
|
65
|
+
|
66
|
+
def render(value)
|
67
|
+
result = {}
|
68
|
+
|
69
|
+
parse(value).flatten.each do |item|
|
70
|
+
case item[:operators][0]
|
71
|
+
when ">="
|
72
|
+
result["$gte"] = serialize(item[:value]) #time.to_mongo
|
73
|
+
when ">"
|
74
|
+
result["$gt"] = serialize(item[:value])
|
75
|
+
when "<="
|
76
|
+
result["$lte"] = serialize(item[:value]) #time.to_mongo
|
77
|
+
when "<"
|
78
|
+
result["$lt"] = serialize(item[:value])
|
79
|
+
when
|
80
|
+
result = serialize(item[:value])
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
result
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
class Date < Time
|
89
|
+
include Deli::Param::Date
|
90
|
+
end
|
91
|
+
|
92
|
+
class String < Param
|
93
|
+
include Deli::Param::String
|
94
|
+
|
95
|
+
def render(value)
|
96
|
+
result = parse(value).map do |children|
|
97
|
+
regex = []
|
98
|
+
includes = []
|
99
|
+
excludes = []
|
100
|
+
hash = {}
|
101
|
+
|
102
|
+
children.each do |item|
|
103
|
+
start_operator = item[:operators][1] == "^" ? "^" : ""
|
104
|
+
end_operator = item[:operators][1] == "$" ? "$" : ""
|
105
|
+
|
106
|
+
case item[:operators][0]
|
107
|
+
#when "="
|
108
|
+
# includes << item[:value]
|
109
|
+
#when "!="
|
110
|
+
# excludes << item[:value]
|
111
|
+
when "!~", "!="
|
112
|
+
regex << Regexp.new("(?!#{start_operator}#{item[:value]}#{end_operator})", "i")
|
113
|
+
when "=~", "="
|
114
|
+
regex << Regexp.new("#{start_operator}#{item[:value]}#{end_operator}", "i")
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
#hash["$in"] = includes if includes.present?
|
119
|
+
#hash["$nin"] = excludes if excludes.present?
|
120
|
+
hash["$regex"] = Regexp.union(*regex) if regex.present?
|
121
|
+
hash
|
122
|
+
end
|
123
|
+
|
124
|
+
result.length > 1 ? {"$or" => result} : result[0]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
class Number < Param
|
129
|
+
include Deli::Param::Number
|
130
|
+
end
|
131
|
+
|
132
|
+
class Limit < Param
|
133
|
+
include Deli::Param::Limit
|
134
|
+
end
|
135
|
+
|
136
|
+
class Order < Param
|
137
|
+
include Deli::Param::Order
|
138
|
+
|
139
|
+
def render(value)
|
140
|
+
parse(value).map do |item|
|
141
|
+
[item[:key].to_sym, item[:operators][0] == "+" ? :asc : :desc]
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
class Offset < Param
|
147
|
+
include Deli::Param::Offset
|
148
|
+
end
|
149
|
+
|
150
|
+
# # Match all people with first name Emmanuel using Javascript.
|
151
|
+
# { "$where" : "this.first_name == 'Emmanuel'" }
|
152
|
+
#
|
153
|
+
# # Match all people who live in Berlin, where address is embedded.
|
154
|
+
# { "addresses.city" : "Berlin" }
|
155
|
+
#
|
156
|
+
# # Example queries using symbol h4s to perform more complex criteria.
|
157
|
+
# { "title" : { "$all" : [ "Sir" ] } }
|
158
|
+
# { "age" : { "$exists" : true } }
|
159
|
+
# { "age" : { "$gt" : 18 } }
|
160
|
+
# { "age" : { "$gte" : 18 } }
|
161
|
+
# { "title" : { "$in" : [ "Sir", "Madam" ] } }
|
162
|
+
# { "age" : { "$lt" : 55 } }
|
163
|
+
# { "age" : { "$lte" : 55 } }
|
164
|
+
# { "title" : { "$ne" : "Mr" } }
|
165
|
+
# { "title" : { "$nin" : [ "Esquire" ] } }
|
166
|
+
# { "aliases" : { "$size" : 2 } }
|
167
|
+
# { "location" : { "$near" : [ 22.50, -21.33 ] } }
|
168
|
+
# { "location" : { "$within" : { "$center" => [ [ 50, -40 ], 1 ] } } }
|
169
|
+
# 3rd number can be a radius: "22.50,-21.33,7"
|
170
|
+
# - if not null, if null
|
171
|
+
class Geo < Param
|
172
|
+
include Deli::Param::Geo
|
173
|
+
|
174
|
+
def render(value)
|
175
|
+
{"$near" => parse(value).reverse}
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|