plucky 0.6.4 → 0.6.5
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.
- data/lib/plucky/criteria_hash.rb +71 -62
- data/lib/plucky/normalizers/hash_key.rb +19 -0
- data/lib/plucky/normalizers/options_hash_value.rb +4 -6
- data/lib/plucky/options_hash.rb +7 -2
- data/lib/plucky/version.rb +1 -1
- data/spec/functional/options_hash_spec.rb +36 -0
- data/spec/helper.rb +1 -1
- data/spec/plucky/criteria_hash_spec.rb +34 -0
- data/spec/plucky/normalizers/hash_key_spec.rb +15 -0
- data/spec/plucky/normalizers/sort_value_spec.rb +5 -1
- metadata +7 -5
- data/lib/plucky/normalizers/options_hash_key.rb +0 -23
- data/spec/plucky/normalizers/options_hash_key_spec.rb +0 -23
data/lib/plucky/criteria_hash.rb
CHANGED
@@ -77,58 +77,9 @@ module Plucky
|
|
77
77
|
@source
|
78
78
|
end
|
79
79
|
|
80
|
-
# Public
|
80
|
+
# Public
|
81
81
|
def merge(other)
|
82
|
-
|
83
|
-
other.source.each_key do |key|
|
84
|
-
value, other_value = target[key], other[key]
|
85
|
-
target[key] =
|
86
|
-
if target.key?(key)
|
87
|
-
value_is_hash = value.is_a?(Hash)
|
88
|
-
other_is_hash = other_value.is_a?(Hash)
|
89
|
-
|
90
|
-
if value_is_hash && other_is_hash
|
91
|
-
value.update(other_value) do |key, old_value, new_value|
|
92
|
-
if old_value.is_a?(Hash) && new_value.is_a?(Hash)
|
93
|
-
self.class.new(old_value).merge(self.class.new(new_value)).to_hash
|
94
|
-
else
|
95
|
-
merge_values_into_array(old_value, new_value)
|
96
|
-
end
|
97
|
-
end
|
98
|
-
elsif value_is_hash && !other_is_hash
|
99
|
-
if modifier_key = value.keys.detect { |k| Plucky.modifier?(k) }
|
100
|
-
current_value = value[modifier_key]
|
101
|
-
value[modifier_key] = current_value.concat(array(other_value)).uniq
|
102
|
-
else
|
103
|
-
# kaboom! Array(value).concat(Array(other_value)).uniq
|
104
|
-
end
|
105
|
-
elsif other_is_hash && !value_is_hash
|
106
|
-
if modifier_key = other_value.keys.detect { |k| Plucky.modifier?(k) }
|
107
|
-
current_value = other_value[modifier_key]
|
108
|
-
other_value[modifier_key] = current_value.concat(array(value)).uniq
|
109
|
-
else
|
110
|
-
# kaboom! Array(value).concat(Array(other_value)).uniq
|
111
|
-
end
|
112
|
-
else
|
113
|
-
merge_values_into_array(value, other_value)
|
114
|
-
end
|
115
|
-
else
|
116
|
-
other_value
|
117
|
-
end
|
118
|
-
end
|
119
|
-
self.class.new(target)
|
120
|
-
end
|
121
|
-
|
122
|
-
# Private
|
123
|
-
def merge_values_into_array(value, other_value)
|
124
|
-
array(value).concat(array(other_value)).uniq
|
125
|
-
end
|
126
|
-
|
127
|
-
# Private: Array(BSON::ObjectId) returns the byte array or what not instead
|
128
|
-
# of the object id. This makes sure it is an array of object ids, not the
|
129
|
-
# guts of the object id.
|
130
|
-
def array(value)
|
131
|
-
value.is_a?(BSON::ObjectId) ? [value] : Array(value)
|
82
|
+
self.class.new hash_merge(@source, other.source)
|
132
83
|
end
|
133
84
|
|
134
85
|
# Public
|
@@ -139,17 +90,6 @@ module Plucky
|
|
139
90
|
self
|
140
91
|
end
|
141
92
|
|
142
|
-
# Private
|
143
|
-
def object_ids
|
144
|
-
@options[:object_ids] ||= []
|
145
|
-
end
|
146
|
-
|
147
|
-
# Private
|
148
|
-
def object_ids=(value)
|
149
|
-
raise ArgumentError unless value.is_a?(Array)
|
150
|
-
@options[:object_ids] = value.flatten
|
151
|
-
end
|
152
|
-
|
153
93
|
# Public: The definition of simple is querying by only _id or _id and _type.
|
154
94
|
# If this is the case, you can use IdentityMap in library to not perform
|
155
95
|
# query and instead just return from map.
|
@@ -165,6 +105,75 @@ module Plucky
|
|
165
105
|
object_ids.include?(key.to_sym)
|
166
106
|
end
|
167
107
|
|
108
|
+
# Private
|
109
|
+
def object_ids
|
110
|
+
@options[:object_ids] ||= []
|
111
|
+
end
|
112
|
+
|
113
|
+
# Private
|
114
|
+
def object_ids=(value)
|
115
|
+
raise ArgumentError unless value.is_a?(Array)
|
116
|
+
@options[:object_ids] = value.flatten
|
117
|
+
end
|
118
|
+
|
119
|
+
private
|
120
|
+
|
121
|
+
# Private
|
122
|
+
def hash_merge(oldhash, newhash)
|
123
|
+
merge_compound_or_clauses!(oldhash, newhash)
|
124
|
+
oldhash.merge(newhash) do |key, oldval, newval|
|
125
|
+
old_is_hash = oldval.instance_of? Hash
|
126
|
+
new_is_hash = newval.instance_of? Hash
|
127
|
+
|
128
|
+
if old_is_hash && new_is_hash
|
129
|
+
hash_merge(oldval, newval)
|
130
|
+
elsif old_is_hash
|
131
|
+
modifier_merge(oldval, newval)
|
132
|
+
elsif new_is_hash
|
133
|
+
modifier_merge(newval, oldval)
|
134
|
+
else
|
135
|
+
merge_values_into_array(oldval, newval)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def merge_compound_or_clauses!(oldhash, newhash)
|
141
|
+
old_or = oldhash[:$or]
|
142
|
+
new_or = newhash[:$or]
|
143
|
+
if old_or && new_or
|
144
|
+
oldhash[:$and] ||= []
|
145
|
+
oldhash[:$and] << {:$or => oldhash.delete(:$or)}
|
146
|
+
oldhash[:$and] << {:$or => newhash.delete(:$or)}
|
147
|
+
elsif new_or && oldhash[:$and]
|
148
|
+
if oldhash[:$and].any? {|v| v.key? :$or }
|
149
|
+
oldhash[:$and] << {:$or => newhash.delete(:$or)}
|
150
|
+
end
|
151
|
+
elsif old_or && newhash[:$and]
|
152
|
+
if newhash[:$and].any? {|v| v.key? :$or }
|
153
|
+
newhash[:$and] << {:$or => oldhash.delete(:$or)}
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Private
|
159
|
+
def modifier_merge(hash, value)
|
160
|
+
if modifier_key = hash.keys.detect { |k| Plucky.modifier?(k) }
|
161
|
+
hash[modifier_key].concat( array(value) ).uniq
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# Private
|
166
|
+
def merge_values_into_array(value, other_value)
|
167
|
+
array(value).concat(array(other_value)).uniq
|
168
|
+
end
|
169
|
+
|
170
|
+
# Private: Array(BSON::ObjectId) returns the byte array or what not instead
|
171
|
+
# of the object id. This makes sure it is an array of object ids, not the
|
172
|
+
# guts of the object id.
|
173
|
+
def array(value)
|
174
|
+
value.is_a?(BSON::ObjectId) ? [value] : Array(value)
|
175
|
+
end
|
176
|
+
|
168
177
|
# Private
|
169
178
|
def normalized_key(key)
|
170
179
|
key_normalizer.call(key)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Plucky
|
2
|
+
module Normalizers
|
3
|
+
class HashKey
|
4
|
+
|
5
|
+
def initialize(keys)
|
6
|
+
@keys = keys
|
7
|
+
end
|
8
|
+
|
9
|
+
# Public: Normalizes an options hash key
|
10
|
+
#
|
11
|
+
# key - The key to normalize
|
12
|
+
#
|
13
|
+
# Returns a Symbol.
|
14
|
+
def call(key)
|
15
|
+
@keys.fetch key.to_sym, key
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -5,9 +5,9 @@ require 'plucky/normalizers/sort_value'
|
|
5
5
|
module Plucky
|
6
6
|
module Normalizers
|
7
7
|
class OptionsHashValue
|
8
|
-
|
9
|
-
# Public: Initialize an OptionsHashValue.
|
10
|
-
#
|
8
|
+
|
9
|
+
# Public: Initialize an OptionsHashValue.
|
10
|
+
#
|
11
11
|
# args - The hash of arguments (default: {})
|
12
12
|
# :key_normalizer - The key normalizer to use, must respond to call
|
13
13
|
# :value_normalizers - Hash where key is name of options hash key
|
@@ -66,9 +66,7 @@ module Plucky
|
|
66
66
|
|
67
67
|
# Private
|
68
68
|
def default_sort_value_normalizer
|
69
|
-
Normalizers::SortValue.new({
|
70
|
-
:key_normalizer => @key_normalizer,
|
71
|
-
})
|
69
|
+
Normalizers::SortValue.new(:key_normalizer => Normalizers::HashKey.new({:_id => :id}))
|
72
70
|
end
|
73
71
|
|
74
72
|
# Private
|
data/lib/plucky/options_hash.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
|
-
require 'plucky/normalizers/
|
3
|
+
require 'plucky/normalizers/hash_key'
|
4
4
|
require 'plucky/normalizers/options_hash_value'
|
5
5
|
|
6
6
|
module Plucky
|
@@ -82,7 +82,12 @@ module Plucky
|
|
82
82
|
# Private
|
83
83
|
def key_normalizer
|
84
84
|
@key_normalizer ||= @options.fetch(:key_normalizer) {
|
85
|
-
Normalizers::
|
85
|
+
Normalizers::HashKey.new({
|
86
|
+
:order => :sort,
|
87
|
+
:select => :fields,
|
88
|
+
:offset => :skip,
|
89
|
+
:id => :_id,
|
90
|
+
})
|
86
91
|
}
|
87
92
|
end
|
88
93
|
|
data/lib/plucky/version.rb
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Plucky::OptionsHash do
|
4
|
+
subject { described_class.new }
|
5
|
+
|
6
|
+
describe "#[]=" do
|
7
|
+
it "changes order to sort" do
|
8
|
+
subject[:order] = "foo asc"
|
9
|
+
subject[:sort].should == [["foo", 1]]
|
10
|
+
subject[:order].should be_nil
|
11
|
+
end
|
12
|
+
|
13
|
+
it "changes select to fields" do
|
14
|
+
subject[:select] = [:foo]
|
15
|
+
subject[:fields].should == [:foo]
|
16
|
+
subject[:select].should be_nil
|
17
|
+
end
|
18
|
+
|
19
|
+
it "changes offset to skip" do
|
20
|
+
subject[:offset] = 10
|
21
|
+
subject[:skip].should == 10
|
22
|
+
subject[:offset].should be_nil
|
23
|
+
end
|
24
|
+
|
25
|
+
it "changes id to _id" do
|
26
|
+
subject[:id] = :foo
|
27
|
+
subject[:_id].should == :foo
|
28
|
+
subject[:id].should be_nil
|
29
|
+
end
|
30
|
+
|
31
|
+
it "does not change the sort field" do
|
32
|
+
subject[:order] = :order.asc
|
33
|
+
subject[:sort].should == [["order", 1]]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/spec/helper.rb
CHANGED
@@ -17,7 +17,7 @@ Log = Logger.new(File.join(log_dir, 'test.log'))
|
|
17
17
|
|
18
18
|
LogBuddy.init :logger => Log
|
19
19
|
|
20
|
-
port = ENV.fetch "
|
20
|
+
port = ENV.fetch "BOXEN_MONGODB_PORT", 27017
|
21
21
|
connection = Mongo::MongoClient.new('127.0.0.1', port.to_i, :logger => Log)
|
22
22
|
DB = connection.db('test')
|
23
23
|
|
@@ -147,6 +147,40 @@ describe Plucky::CriteriaHash do
|
|
147
147
|
c1.merge(c2).should_not equal(c1)
|
148
148
|
c1[:foo].should == 'bar'
|
149
149
|
end
|
150
|
+
|
151
|
+
context "given multiple $or clauses" do
|
152
|
+
before do
|
153
|
+
@c1 = described_class.new(:$or => [{:a => 1}, {:b => 2}])
|
154
|
+
@c2 = described_class.new(:$or => [{:a => 3}, {:b => 4}])
|
155
|
+
@c3 = described_class.new(:$or => [{:a => 4}, {:b => 4}])
|
156
|
+
end
|
157
|
+
|
158
|
+
it "merges two $ors into a compound $and" do
|
159
|
+
merged = @c1.merge(@c2)
|
160
|
+
merged[:$and].should == [
|
161
|
+
{:$or => [{:a => 1}, {:b => 2}]},
|
162
|
+
{:$or => [{:a => 3}, {:b => 4}]}
|
163
|
+
]
|
164
|
+
end
|
165
|
+
|
166
|
+
it "merges an $and and a $or into a compound $and" do
|
167
|
+
merged = @c1.merge(@c2).merge(@c3)
|
168
|
+
merged[:$and].should == [
|
169
|
+
{:$or => [{:a => 1}, {:b => 2}]},
|
170
|
+
{:$or => [{:a => 3}, {:b => 4}]},
|
171
|
+
{:$or => [{:a => 4}, {:b => 4}]}
|
172
|
+
]
|
173
|
+
end
|
174
|
+
|
175
|
+
it "merges an $or and an $and into a compound $and" do
|
176
|
+
merged = @c3.merge @c1.merge(@c2)
|
177
|
+
merged[:$and].should == [
|
178
|
+
{:$or => [{:a => 1}, {:b => 2}]},
|
179
|
+
{:$or => [{:a => 3}, {:b => 4}]},
|
180
|
+
{:$or => [{:a => 4}, {:b => 4}]}
|
181
|
+
]
|
182
|
+
end
|
183
|
+
end
|
150
184
|
end
|
151
185
|
|
152
186
|
context "#merge!" do
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
describe Plucky::Normalizers::HashKey do
|
4
|
+
subject {
|
5
|
+
described_class.new(:bacon => :sizzle)
|
6
|
+
}
|
7
|
+
|
8
|
+
it "changes defined fields" do
|
9
|
+
subject.call(:bacon).should eq(:sizzle)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "does not change undefined fields" do
|
13
|
+
subject.call(:sausage).should eq(:sausage)
|
14
|
+
end
|
15
|
+
end
|
@@ -3,7 +3,7 @@ require 'plucky/normalizers/sort_value'
|
|
3
3
|
|
4
4
|
describe Plucky::Normalizers::SortValue do
|
5
5
|
let(:key_normalizer) {
|
6
|
-
|
6
|
+
Plucky::Normalizers::HashKey.new({:id => :_id})
|
7
7
|
}
|
8
8
|
|
9
9
|
subject {
|
@@ -88,6 +88,10 @@ describe Plucky::Normalizers::SortValue do
|
|
88
88
|
subject.call([:id.asc]).should eq([['_id', 1]])
|
89
89
|
end
|
90
90
|
|
91
|
+
it "doesn't convert keys like :sort to :order via key normalizer" do
|
92
|
+
subject.call(:order.asc).should eq([['order', 1]])
|
93
|
+
end
|
94
|
+
|
91
95
|
it "converts string with $natural correctly" do
|
92
96
|
subject.call('$natural desc').should eq([['$natural', -1]])
|
93
97
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: plucky
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-07-
|
12
|
+
date: 2013-07-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mongo
|
@@ -52,8 +52,8 @@ files:
|
|
52
52
|
- lib/plucky/normalizers/criteria_hash_key.rb
|
53
53
|
- lib/plucky/normalizers/criteria_hash_value.rb
|
54
54
|
- lib/plucky/normalizers/fields_value.rb
|
55
|
+
- lib/plucky/normalizers/hash_key.rb
|
55
56
|
- lib/plucky/normalizers/integer.rb
|
56
|
-
- lib/plucky/normalizers/options_hash_key.rb
|
57
57
|
- lib/plucky/normalizers/options_hash_value.rb
|
58
58
|
- lib/plucky/normalizers/sort_value.rb
|
59
59
|
- lib/plucky/options_hash.rb
|
@@ -67,13 +67,14 @@ files:
|
|
67
67
|
- script/criteria_hash.rb
|
68
68
|
- script/release
|
69
69
|
- script/test
|
70
|
+
- spec/functional/options_hash_spec.rb
|
70
71
|
- spec/helper.rb
|
71
72
|
- spec/plucky/criteria_hash_spec.rb
|
72
73
|
- spec/plucky/normalizers/criteria_hash_key_spec.rb
|
73
74
|
- spec/plucky/normalizers/criteria_hash_value_spec.rb
|
74
75
|
- spec/plucky/normalizers/fields_value_spec.rb
|
76
|
+
- spec/plucky/normalizers/hash_key_spec.rb
|
75
77
|
- spec/plucky/normalizers/integer_spec.rb
|
76
|
-
- spec/plucky/normalizers/options_hash_key_spec.rb
|
77
78
|
- spec/plucky/normalizers/options_hash_value_spec.rb
|
78
79
|
- spec/plucky/normalizers/sort_value_spec.rb
|
79
80
|
- spec/plucky/options_hash_spec.rb
|
@@ -110,13 +111,14 @@ specification_version: 3
|
|
110
111
|
summary: Thin layer over the ruby driver that allows you to quickly grab hold of your
|
111
112
|
data (pluck it!).
|
112
113
|
test_files:
|
114
|
+
- spec/functional/options_hash_spec.rb
|
113
115
|
- spec/helper.rb
|
114
116
|
- spec/plucky/criteria_hash_spec.rb
|
115
117
|
- spec/plucky/normalizers/criteria_hash_key_spec.rb
|
116
118
|
- spec/plucky/normalizers/criteria_hash_value_spec.rb
|
117
119
|
- spec/plucky/normalizers/fields_value_spec.rb
|
120
|
+
- spec/plucky/normalizers/hash_key_spec.rb
|
118
121
|
- spec/plucky/normalizers/integer_spec.rb
|
119
|
-
- spec/plucky/normalizers/options_hash_key_spec.rb
|
120
122
|
- spec/plucky/normalizers/options_hash_value_spec.rb
|
121
123
|
- spec/plucky/normalizers/sort_value_spec.rb
|
122
124
|
- spec/plucky/options_hash_spec.rb
|
@@ -1,23 +0,0 @@
|
|
1
|
-
module Plucky
|
2
|
-
module Normalizers
|
3
|
-
class OptionsHashKey
|
4
|
-
|
5
|
-
# Internal: Keys with values that they should normalize to
|
6
|
-
NormalizedKeys = {
|
7
|
-
:order => :sort,
|
8
|
-
:select => :fields,
|
9
|
-
:offset => :skip,
|
10
|
-
:id => :_id,
|
11
|
-
}
|
12
|
-
|
13
|
-
# Public: Normalizes an options hash key
|
14
|
-
#
|
15
|
-
# key - The key to normalize
|
16
|
-
#
|
17
|
-
# Returns a Symbol.
|
18
|
-
def call(key)
|
19
|
-
NormalizedKeys.fetch key.to_sym, key
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
describe Plucky::Normalizers::OptionsHashKey do
|
4
|
-
subject {
|
5
|
-
described_class.new
|
6
|
-
}
|
7
|
-
|
8
|
-
it "changes order to sort" do
|
9
|
-
subject.call(:order).should eq(:sort)
|
10
|
-
end
|
11
|
-
|
12
|
-
it "changes select to fields" do
|
13
|
-
subject.call(:select).should eq(:fields)
|
14
|
-
end
|
15
|
-
|
16
|
-
it "changes offset to skip" do
|
17
|
-
subject.call(:offset).should eq(:skip)
|
18
|
-
end
|
19
|
-
|
20
|
-
it "changes id to _id" do
|
21
|
-
subject.call(:id).should eq(:_id)
|
22
|
-
end
|
23
|
-
end
|