plucky 0.6.3 → 0.8.0

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.
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)