mongery 1.0.3 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3aeb64347aabfea21e8a23c2160e10256404f948
4
- data.tar.gz: 60d53661a827f430c4dfe6bd34466deab7b1168f
3
+ metadata.gz: fe6385d3fabb1f17ebd5637f248fab8b776d7718
4
+ data.tar.gz: 1acfe3b40ce8de1d187fa43b7ad4277cc6cf534e
5
5
  SHA512:
6
- metadata.gz: 6e3a644c5a6c6409c2923f7c1a228fd5f287011f94134b460b4adcff86076fecc4ce990fd0d38e04263b61e6166627f739dbb73c558af6018371677eef40c858
7
- data.tar.gz: 2112b7028f0c874bc3e8024d668ae0b254e34116ca1464b8fe4fecc09c8ac5fd6ae33e61e3ef9f874218391f019fd328b7eae02f2321608b28cfeb24d1fa47c3
6
+ metadata.gz: 21a99f928bd828a80391a10d90a0db8c8bd2401cebc8538df8d5d309fddd5d4bddd96c870bb3c99a1464a59889c786887aad59536f67bbf042c96f6bcf47bde6
7
+ data.tar.gz: bb095b44a1482056496e3a209169f27f3d6c255f621717d065a9be4132cd060281723f8f390dd1368420010d32ca6fb5c049d1f6fd1681fdd53c22a9a8e6ead9
@@ -1,3 +1,6 @@
1
+ ## 1.0.4 (2015/01/19)
2
+ - Support custom operators
3
+
1
4
  ## 1.0.3 (2015/01/09)
2
5
  - Support index method to create expression indexes
3
6
 
@@ -5,12 +5,14 @@ require "arel"
5
5
  module Mongery
6
6
  class Builder
7
7
  attr_reader :model, :table, :schema, :mapped_properties
8
+ attr_accessor :custom_operators
8
9
 
9
10
  def initialize(model, engine = ActiveRecord::Base, schema = nil)
10
11
  @model = model
11
12
  @table = Arel::Table.new(model, engine)
12
13
  @schema = Schema.new(schema) if schema
13
14
  @mapped_properties = {}
15
+ @custom_operators = {}
14
16
  end
15
17
 
16
18
  def mapped_properties=(value)
@@ -23,25 +25,32 @@ module Mongery
23
25
  end
24
26
 
25
27
  def find(*args)
26
- Query.new(table, schema, mapped_properties).where(*args)
28
+ build_query.where(*args)
27
29
  end
28
30
 
29
31
  def insert(*args)
30
- Query.new(table, schema, mapped_properties).insert(*args)
32
+ build_query.insert(*args)
31
33
  end
32
34
 
33
35
  def index(*args)
34
- Query.new(table, schema, mapped_properties).index(*args)
36
+ build_query.index(*args)
37
+ end
38
+
39
+ private
40
+
41
+ def build_query
42
+ Query.new(table, schema, mapped_properties, custom_operators)
35
43
  end
36
44
  end
37
45
 
38
46
  class Query
39
- attr_reader :table, :schema, :mapped_properties
47
+ attr_reader :table, :schema, :mapped_properties, :custom_operators
40
48
 
41
- def initialize(table, schema, mapped_properties)
49
+ def initialize(table, schema, mapped_properties, custom_operators)
42
50
  @table = table
43
51
  @schema = schema
44
52
  @mapped_properties = mapped_properties
53
+ @custom_operators = custom_operators
45
54
  @condition = nil
46
55
  end
47
56
 
@@ -179,7 +188,9 @@ module Mongery
179
188
  when Hash
180
189
  if has_operator?(value)
181
190
  chain(:and, value.map {|op, val|
182
- if OPERATOR_MAP.key?(op)
191
+ if custom_operators[op]
192
+ operator(col, custom_operators[op], val)
193
+ elsif OPERATOR_MAP.key?(op)
183
194
  col.send(OPERATOR_MAP[op], val)
184
195
  else
185
196
  raise UnsupportedQuery, "Unknown operator #{op}"
@@ -193,36 +204,6 @@ module Mongery
193
204
  end
194
205
  end
195
206
 
196
- def translate_value_dynamic(col, value)
197
- case value
198
- when String, TrueClass, FalseClass
199
- compare(col, value.to_s, :eq)
200
- when Numeric, NilClass
201
- compare(col, value, :eq)
202
- when Hash
203
- if has_operator?(value)
204
- chain(:and, value.map {|op, val|
205
- case op
206
- when "$in"
207
- if val.all? {|v| v.is_a? Numeric }
208
- wrap(col, val.first).in(val)
209
- else
210
- col.in(val.map(&:to_s))
211
- end
212
- when "$eq", "$ne", "$gt", "$gte", "$lt", "$lte"
213
- compare(col, val, OPERATOR_MAP[op])
214
- else
215
- raise UnsupportedQuery, "Unknown operator #{op}"
216
- end
217
- })
218
- else
219
- col.eq(value.to_json)
220
- end
221
- else
222
- col.eq(value.to_json)
223
- end
224
- end
225
-
226
207
  def translate_value_schema(column, col, value)
227
208
  type = schema.column_type(column.to_s)
228
209
  case value
@@ -237,8 +218,10 @@ module Mongery
237
218
  else
238
219
  compare_schema(col, val, type, :in)
239
220
  end
221
+ when *(custom_operators.keys)
222
+ compare_schema(col, val, type, custom_operators[op])
240
223
  when "$eq", "$ne", "$gt", "$gte", "$lt", "$lte"
241
- compare_schema(col, val, type, OPERATOR_MAP[op])
224
+ compare_schema(col, val, type, OPERATOR_MAP[op])
242
225
  else
243
226
  raise UnsupportedQuery, "Unknown operator #{op}"
244
227
  end
@@ -269,6 +252,8 @@ module Mongery
269
252
  else
270
253
  col.in(val.map(&:to_s))
271
254
  end
255
+ when *(custom_operators.keys)
256
+ compare(col, val, custom_operators[op])
272
257
  when "$eq", "$ne", "$gt", "$gte", "$lt", "$lte"
273
258
  compare(col, val, OPERATOR_MAP[op])
274
259
  else
@@ -288,7 +273,7 @@ module Mongery
288
273
  end
289
274
 
290
275
  def compare(col, val, op)
291
- wrap(col, val).send(op, val)
276
+ operator(wrap(col, val), op, val)
292
277
  end
293
278
 
294
279
  def wrap(col, val)
@@ -312,19 +297,28 @@ module Mongery
312
297
  def compare_schema(col, val, type, op)
313
298
  case type
314
299
  when "string"
315
- Arel.sql("(#{col})").send(op, val)
300
+ operator(Arel.sql("(#{col})"), op, val)
316
301
  when "number", "integer"
317
- Arel.sql("(#{col})::numeric").send(op, val)
302
+ operator(Arel.sql("(#{col})::numeric"), op, val)
318
303
  else
319
304
  case val
320
305
  when Numeric
321
- Arel.sql("(#{col})").send(op, val.to_s)
306
+ operator(Arel.sql("(#{col})"), op, val.to_s)
322
307
  else
323
- Arel.sql("(#{col})").send(op, val)
308
+ operator(Arel.sql("(#{col})"), op, val)
324
309
  end
325
310
  end
326
311
  end
327
312
 
313
+ def operator(col, op, val)
314
+ case op
315
+ when Symbol
316
+ col.send(op, val)
317
+ else
318
+ op.call(col, val)
319
+ end
320
+ end
321
+
328
322
  def sql_json_path(col)
329
323
  paths = col.to_s.split('.')
330
324
  Arel.sql("data#>>#{json_pathize(paths)}")
@@ -1,3 +1,3 @@
1
1
  module Mongery
2
- VERSION = "1.0.3"
2
+ VERSION = "1.0.4"
3
3
  end
@@ -23,6 +23,10 @@ describe Mongery::Builder do
23
23
  /WHERE \(data#>>'{height}'\) IN \('6\.1', '6\.2'\)$/ ],
24
24
  [ { height: nil },
25
25
  /WHERE \(data#>>'{height}'\) IS NULL$/ ],
26
+ [ { name: { "$as" => "miyagawa" } },
27
+ /WHERE \(data#>>'{name}'\) = 'miyagawa'$/ ],
28
+ [ { name: { "$land" => "foo" } },
29
+ /WHERE \(data#>>'{name}'\) && 'foo'$/ ],
26
30
  ]
27
31
 
28
32
  schema = JsonSchema.parse!(JSON.parse(<<-EOF))
@@ -49,6 +53,12 @@ describe Mongery::Builder do
49
53
  EOF
50
54
 
51
55
  builder = Mongery::Builder.new(:test, ActiveRecord::Base, schema)
56
+ builder.custom_operators = {
57
+ "$as" => :eq,
58
+ "$land" => ->(col, val) {
59
+ Arel::Nodes::InfixOperation.new("&&", col, val)
60
+ }
61
+ }
52
62
 
53
63
  queries.each do |query, sql|
54
64
  context "with query #{query}" do
@@ -70,6 +70,10 @@ describe Mongery::Builder do
70
70
  /WHERE data#>>'{bar}' = '{"foo":"bar","baz":\[1,2,3\]}'$/ ],
71
71
  [ { "foo.bar" => true }, { },
72
72
  /WHERE data#>>'{foo,bar}' = 'true'$/ ],
73
+ [ { bar: {"$as" => 1} }, { },
74
+ /WHERE \(data#>>'{bar}'\)::numeric = 1$/ ],
75
+ [ { bar: {"$land" => 'foo'} }, { },
76
+ /WHERE data#>>'{bar}' && 'foo'$/ ],
73
77
  ]
74
78
 
75
79
  bad_queries = [
@@ -80,6 +84,12 @@ describe Mongery::Builder do
80
84
  ]
81
85
 
82
86
  builder = Mongery::Builder.new(:test)
87
+ builder.custom_operators = {
88
+ "$as" => :eq,
89
+ "$land" => ->(col, val) {
90
+ Arel::Nodes::InfixOperation.new("&&", col, val)
91
+ }
92
+ }
83
93
 
84
94
  queries.each do |query, condition, sql|
85
95
  context "with query #{query}" do
@@ -4,6 +4,12 @@ describe "#mapped_properties" do
4
4
  let(:builder) {
5
5
  Mongery::Builder.new(:test).tap do |builder|
6
6
  builder.mapped_properties = [:user_id, :created_at, :updated_at]
7
+ builder.custom_operators = {
8
+ "$as" => :eq,
9
+ "$land" => ->(col, val) {
10
+ Arel::Nodes::InfixOperation.new("&&", col, val)
11
+ }
12
+ }
7
13
  end
8
14
  }
9
15
 
@@ -31,4 +37,14 @@ describe "#mapped_properties" do
31
37
  expect(builder.find("created_at" => {'$in' => ['2014-01-01', '2015-01-01']}, "foo" => "bar").to_sql)
32
38
  .to match /WHERE "test"\."created_at" IN \('2014-01-01', '2015-01-01'\) AND data#>>'{foo}' = 'bar'/;
33
39
  end
40
+
41
+ it 'does custom operators' do
42
+ expect(builder.find(user_id: { "$as" => 2 }).to_sql)
43
+ .to match /WHERE "test"\."user_id" = 2/;
44
+ end
45
+
46
+ it 'does custom operators with proc' do
47
+ expect(builder.find(user_id: { "$land" => 'foo' }).to_sql)
48
+ .to match /WHERE "test"\."user_id" && 'foo'/;
49
+ end
34
50
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongery
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tatsuhiko Miyagawa
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-09 00:00:00.000000000 Z
11
+ date: 2015-01-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: arel