plucky 0.6.3 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -3
  3. data/.rspec +1 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +7 -4
  6. data/Gemfile +6 -5
  7. data/Gemfile.lock +84 -0
  8. data/LICENSE +1 -1
  9. data/README.md +17 -75
  10. data/Rakefile +0 -3
  11. data/examples/query.rb +8 -7
  12. data/lib/plucky.rb +1 -0
  13. data/lib/plucky/criteria_hash.rb +78 -62
  14. data/lib/plucky/extensions/symbol.rb +8 -0
  15. data/lib/plucky/normalizers/criteria_hash_value.rb +3 -1
  16. data/lib/plucky/normalizers/fields_value.rb +3 -3
  17. data/lib/plucky/normalizers/hash_key.rb +19 -0
  18. data/lib/plucky/normalizers/options_hash_value.rb +5 -7
  19. data/lib/plucky/normalizers/sort_value.rb +8 -6
  20. data/lib/plucky/options_hash.rb +9 -3
  21. data/lib/plucky/pagination.rb +1 -1
  22. data/lib/plucky/pagination/{decorator.rb → collection.rb} +10 -1
  23. data/lib/plucky/query.rb +56 -21
  24. data/lib/plucky/transformer.rb +14 -0
  25. data/lib/plucky/version.rb +1 -1
  26. data/plucky.gemspec +4 -5
  27. data/script/bootstrap +21 -0
  28. data/script/release +42 -0
  29. data/script/test +20 -0
  30. data/spec/functional/options_hash_spec.rb +41 -0
  31. data/spec/helper.rb +12 -4
  32. data/spec/plucky/criteria_hash_spec.rb +68 -4
  33. data/spec/plucky/normalizers/criteria_hash_value_spec.rb +1 -1
  34. data/spec/plucky/normalizers/fields_value_spec.rb +5 -5
  35. data/spec/plucky/normalizers/hash_key_spec.rb +15 -0
  36. data/spec/plucky/normalizers/options_hash_value_spec.rb +2 -2
  37. data/spec/plucky/normalizers/sort_value_spec.rb +24 -20
  38. data/spec/plucky/options_hash_spec.rb +2 -2
  39. data/spec/plucky/pagination/{decorator_spec.rb → collection_spec.rb} +8 -5
  40. data/spec/plucky/query_spec.rb +92 -35
  41. data/spec/plucky_spec.rb +5 -5
  42. data/spec/symbol_operator_spec.rb +18 -1
  43. metadata +37 -36
  44. data/lib/plucky/normalizers/options_hash_key.rb +0 -23
  45. data/script/criteria_hash.rb +0 -21
  46. data/spec/plucky/normalizers/options_hash_key_spec.rb +0 -23
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: e6482980490f769425d02c3e26483021ce5d22839f733c9d46fcfb30eb762928
4
+ data.tar.gz: 0564b1238d7cb08823fedaadc7d3090349580967942750f5021dfd7b24f28cc8
5
+ SHA512:
6
+ metadata.gz: 033bfdd0c0bee0b7b25ece80fa54d4bf8f229deec703b63bdcff772a7a0d82cd8b1f3d6e83c6f773f9100bccf655cf5d5da165a58dc276ae78ac5dcb5fe7883d
7
+ data.tar.gz: b83627ae90f345dac4587654d8b74434a384473caddf3512f0c2de978a08997e2778b489b3217905ac5c2e5c2ef4ab05b29b1b5b18834719d01d952a0da77d7f
data/.gitignore CHANGED
@@ -1,6 +1,4 @@
1
1
  *.project
2
2
  log
3
3
  *.gem
4
- Gemfile.lock
5
- bin
6
- vendor
4
+ .byebug_history
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1 @@
1
+ ruby-2.7.1
@@ -1,9 +1,12 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 1.8.7
4
- - ree
5
- - 1.9.3
3
+ - jruby-19mode
4
+ - 2.4.10
5
+ - 2.5.8
6
+ - 2.6.6
7
+ - 2.7.1
6
8
  notifications:
7
- email: false
9
+ email:
10
+ - scott@railsnewbie.com
8
11
  bundler_args: --without debug guard performance
9
12
  services: mongodb
data/Gemfile CHANGED
@@ -1,16 +1,17 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec
3
3
 
4
- gem 'bson_ext', '~> 1.5'
5
4
  gem 'rake'
6
5
 
7
- group :performance do
8
- gem 'perftools.rb', :require => 'perftools'
9
- end
10
-
11
6
  group(:test) do
12
7
  gem 'rspec'
13
8
  gem 'log_buddy'
9
+
10
+ if RUBY_ENGINE == "ruby" && RUBY_VERSION >= '2.3'
11
+ platforms :mri do
12
+ gem 'byebug'
13
+ end
14
+ end
14
15
  end
15
16
 
16
17
  group(:guard) do
@@ -0,0 +1,84 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ plucky (0.8.0)
5
+ mongo (~> 2.0)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ bson (4.10.0)
11
+ byebug (11.1.3)
12
+ coderay (1.1.3)
13
+ diff-lcs (1.4.4)
14
+ ffi (1.13.1)
15
+ formatador (0.2.5)
16
+ guard (2.16.2)
17
+ formatador (>= 0.2.4)
18
+ listen (>= 2.7, < 4.0)
19
+ lumberjack (>= 1.0.12, < 2.0)
20
+ nenv (~> 0.1)
21
+ notiffany (~> 0.0)
22
+ pry (>= 0.9.12)
23
+ shellany (~> 0.0)
24
+ thor (>= 0.18.1)
25
+ guard-bundler (3.0.0)
26
+ bundler (>= 2.1, < 3)
27
+ guard (~> 2.2)
28
+ guard-compat (~> 1.1)
29
+ guard-compat (1.2.1)
30
+ guard-rspec (4.7.3)
31
+ guard (~> 2.1)
32
+ guard-compat (~> 1.1)
33
+ rspec (>= 2.99.0, < 4.0)
34
+ listen (3.2.1)
35
+ rb-fsevent (~> 0.10, >= 0.10.3)
36
+ rb-inotify (~> 0.9, >= 0.9.10)
37
+ log_buddy (0.7.0)
38
+ lumberjack (1.2.8)
39
+ method_source (1.0.0)
40
+ mongo (2.13.0)
41
+ bson (>= 4.8.2, < 5.0.0)
42
+ nenv (0.3.0)
43
+ notiffany (0.1.3)
44
+ nenv (~> 0.1)
45
+ shellany (~> 0.0)
46
+ pry (0.13.1)
47
+ coderay (~> 1.1)
48
+ method_source (~> 1.0)
49
+ rake (13.0.1)
50
+ rb-fsevent (0.10.4)
51
+ rb-inotify (0.10.1)
52
+ ffi (~> 1.0)
53
+ rspec (3.9.0)
54
+ rspec-core (~> 3.9.0)
55
+ rspec-expectations (~> 3.9.0)
56
+ rspec-mocks (~> 3.9.0)
57
+ rspec-core (3.9.2)
58
+ rspec-support (~> 3.9.3)
59
+ rspec-expectations (3.9.2)
60
+ diff-lcs (>= 1.2.0, < 2.0)
61
+ rspec-support (~> 3.9.0)
62
+ rspec-mocks (3.9.1)
63
+ diff-lcs (>= 1.2.0, < 2.0)
64
+ rspec-support (~> 3.9.0)
65
+ rspec-support (3.9.3)
66
+ shellany (0.0.1)
67
+ thor (1.0.1)
68
+
69
+ PLATFORMS
70
+ ruby
71
+
72
+ DEPENDENCIES
73
+ byebug
74
+ guard
75
+ guard-bundler
76
+ guard-rspec
77
+ log_buddy
78
+ plucky!
79
+ rake
80
+ rb-fsevent
81
+ rspec
82
+
83
+ BUNDLED WITH
84
+ 2.1.4
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010 John Nunemaker
1
+ Copyright (c) 2010-2020 MongoMapper: John Nunemaker, Chris Heald, Scott Taylor
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Plucky
2
2
 
3
- Thin layer over the ruby driver that allows you to quickly grab hold of your data (pluck it!).
3
+ A thin layer over the ruby driver that allows you to quickly grab hold of your data (pluck it!).
4
+
5
+ Used as a query selector inside of MongoMapper.
4
6
 
5
7
  ## Install
6
8
 
@@ -10,79 +12,7 @@ gem install plucky
10
12
 
11
13
  ## Examples
12
14
 
13
- ```ruby
14
- connection = Mongo::MongoClient.new
15
- db = connection.db('test')
16
- collection = db['users']
17
- collection.remove # clear out the collection
18
-
19
- collection.insert({'_id' => 'chris', 'age' => 26, 'name' => 'Chris'})
20
- collection.insert({'_id' => 'steve', 'age' => 29, 'name' => 'Steve'})
21
- collection.insert({'_id' => 'john', 'age' => 28, 'name' => 'John'})
22
-
23
- # initialize query with collection
24
- query = Plucky::Query.new(collection)
25
-
26
- puts 'Querying'
27
- pp query.where(:name => 'John').first
28
- pp query.first(:name => 'John')
29
- pp query.where(:name => 'John').all
30
- pp query.all(:name => 'John')
31
-
32
- puts 'Find by _id'
33
- pp query.find('chris')
34
- pp query.find('chris', 'steve')
35
- pp query.find(['chris', 'steve'])
36
-
37
- puts 'Sort'
38
- pp query.sort(:age).all
39
- pp query.sort(:age.asc).all # same as above
40
- pp query.sort(:age.desc).all
41
- pp query.sort(:age).last # steve
42
-
43
- puts 'Counting'
44
- pp query.count # 3
45
- pp query.size # 3
46
- pp query.count(:name => 'John') # 1
47
- pp query.where(:name => 'John').count # 1
48
- pp query.where(:name => 'John').size # 1
49
-
50
- puts 'Distinct'
51
- pp query.distinct(:age) # [26, 29, 28]
52
-
53
- puts 'Select only certain fields'
54
- pp query.fields(:age).find('chris') # {"_id"=>"chris", "age"=>26}
55
- pp query.only(:age).find('chris') # {"_id"=>"chris", "age"=>26}
56
- pp query.ignore(:name).find('chris') # {"_id"=>"chris", "age"=>26}
57
-
58
- puts 'Pagination, yeah we got that'
59
- pp query.sort(:age).paginate(:per_page => 1, :page => 2)
60
- pp query.sort(:age).per_page(1).paginate(:page => 2)
61
-
62
- pp query.sort(:age).limit(2).to_a # [chris, john]
63
- pp query.sort(:age).skip(1).limit(2).to_a # [john, steve]
64
- pp query.sort(:age).offset(1).limit(2).to_a # [john, steve]
65
-
66
- puts 'Using a cursor'
67
- cursor = query.find_each(:sort => :age) do |doc|
68
- pp doc
69
- end
70
- pp cursor
71
-
72
- puts 'Symbol Operators'
73
- pp query.where(:age.gt => 28).count # 1 (steve)
74
- pp query.where(:age.lt => 28).count # 1 (chris)
75
- pp query.where(:age.in => [26, 28]).to_a # [chris, john]
76
- pp query.where(:age.nin => [26, 28]).to_a # [steve]
77
-
78
- puts 'Removing'
79
- query.remove(:name => 'John')
80
- pp query.count # 2
81
- query.where(:name => 'Chris').remove
82
- pp query.count # 1
83
- query.remove
84
- pp query.count # 0
85
- ```
15
+ See `examples/query.rb`.
86
16
 
87
17
  ## Help
88
18
 
@@ -98,4 +28,16 @@ https://groups.google.com/forum/#!forum/mongomapper
98
28
 
99
29
  ## Copyright
100
30
 
101
- Copyright (c) 2010 John Nunemaker. See LICENSE for details.
31
+ Copyright (c) 2010-2020 MongoMapper. See LICENSE for details.
32
+
33
+ ## Contributors
34
+
35
+ MongoMapper/Plucky is:
36
+
37
+ * John Nunemaker
38
+ * Chris Heald
39
+ * Scott Taylor
40
+
41
+ With contributions from:
42
+
43
+ * Frederick Cheung
data/Rakefile CHANGED
@@ -1,6 +1,3 @@
1
- require 'bundler'
2
- Bundler::GemHelper.install_tasks
3
-
4
1
  require 'rspec/core/rake_task'
5
2
  RSpec::Core::RakeTask.new
6
3
 
@@ -7,18 +7,19 @@ lib_path = root_path.join('lib')
7
7
  $:.unshift(lib_path)
8
8
  require 'plucky'
9
9
 
10
- connection = Mongo::MongoClient.new
11
- db = connection.db('test')
10
+ connection = Mongo::Client.new(["127.0.0.1"], :logger => Logger.new('/dev/null'))
11
+ db = connection.use('test').database
12
12
  collection = db['users']
13
- collection.remove # clear out the collection
14
-
15
- collection.insert({'_id' => 'chris', 'age' => 26, 'name' => 'Chris'})
16
- collection.insert({'_id' => 'steve', 'age' => 29, 'name' => 'Steve'})
17
- collection.insert({'_id' => 'john', 'age' => 28, 'name' => 'John'})
18
13
 
19
14
  # initialize query with collection
20
15
  query = Plucky::Query.new(collection)
21
16
 
17
+ query.remove # clear out the collection
18
+
19
+ query.insert({'_id' => 'chris', 'age' => 26, 'name' => 'Chris'})
20
+ query.insert({'_id' => 'steve', 'age' => 29, 'name' => 'Steve'})
21
+ query.insert({'_id' => 'john', 'age' => 28, 'name' => 'John'})
22
+
22
23
  puts 'Querying'
23
24
  pp query.where(:name => 'John').first
24
25
  pp query.first(:name => 'John')
@@ -5,6 +5,7 @@ require 'plucky/extensions'
5
5
  require 'plucky/criteria_hash'
6
6
  require 'plucky/options_hash'
7
7
  require 'plucky/query'
8
+ require 'plucky/transformer'
8
9
  require 'plucky/pagination'
9
10
 
10
11
  module Plucky
@@ -77,58 +77,9 @@ module Plucky
77
77
  @source
78
78
  end
79
79
 
80
- # Public and completely disgusting
80
+ # Public
81
81
  def merge(other)
82
- target = @source.dup
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,82 @@ 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 oldval == newval
129
+ oldval
130
+ elsif old_is_hash && new_is_hash
131
+ hash_merge(oldval, newval)
132
+ elsif old_is_hash
133
+ modifier_merge(oldval, newval)
134
+ elsif new_is_hash
135
+ modifier_merge(newval, oldval)
136
+ else
137
+ merge_values_into_array(oldval, newval)
138
+ end
139
+ end
140
+ end
141
+
142
+ def merge_compound_or_clauses!(oldhash, newhash)
143
+ old_or = oldhash[:$or]
144
+ new_or = newhash[:$or]
145
+ if old_or && new_or
146
+ oldhash[:$and] ||= []
147
+ oldhash[:$and] << {:$or => oldhash.delete(:$or)}
148
+ oldhash[:$and] << {:$or => newhash.delete(:$or)}
149
+ elsif new_or && oldhash[:$and]
150
+ if oldhash[:$and].any? {|v| v.key? :$or }
151
+ oldhash[:$and] << {:$or => newhash.delete(:$or)}
152
+ end
153
+ elsif old_or && newhash[:$and]
154
+ if newhash[:$and].any? {|v| v.key? :$or }
155
+ newhash[:$and] << {:$or => oldhash.delete(:$or)}
156
+ end
157
+ end
158
+ end
159
+
160
+ # Private
161
+ def modifier_merge(hash, value)
162
+ if modifier_key = hash.keys.detect { |k| Plucky.modifier?(k) }
163
+ hash[modifier_key].concat( array(value) ).uniq
164
+ end
165
+ end
166
+
167
+ # Private
168
+ def merge_values_into_array(value, other_value)
169
+ array(value).concat(array(other_value)).uniq
170
+ end
171
+
172
+ # Private: Array(BSON::ObjectId) returns the byte array or what not instead
173
+ # of the object id. This makes sure it is an array of object ids, not the
174
+ # guts of the object id.
175
+ def array(value)
176
+ case value
177
+ when nil, BSON::ObjectId
178
+ [value]
179
+ else
180
+ Array(value)
181
+ end
182
+ end
183
+
168
184
  # Private
169
185
  def normalized_key(key)
170
186
  key_normalizer.call(key)