jonbell-plucky 0.3.8

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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 John Nunemaker
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,19 @@
1
+ = Plucky
2
+
3
+ Thin layer over the ruby driver that allows you to quickly grab hold of your data (pluck it!).
4
+
5
+ == Install
6
+
7
+ $ gem install plucky
8
+
9
+ == Note on Patches/Pull Requests
10
+
11
+ * Fork the project.
12
+ * Make your feature addition or bug fix.
13
+ * Add tests for it. This is important so I don't break it in a future version unintentionally.
14
+ * Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
15
+ * Send me a pull request. Bonus points for topic branches.
16
+
17
+ == Copyright
18
+
19
+ Copyright (c) 2010 John Nunemaker. See LICENSE for details.
data/lib/plucky.rb ADDED
@@ -0,0 +1,30 @@
1
+ # encoding: UTF-8
2
+ require 'set'
3
+ require 'mongo'
4
+ require 'plucky/extensions'
5
+
6
+ module Plucky
7
+ autoload :CriteriaHash, 'plucky/criteria_hash'
8
+ autoload :OptionsHash, 'plucky/options_hash'
9
+ autoload :Query, 'plucky/query'
10
+ autoload :Version, 'plucky/version'
11
+
12
+ module Pagination
13
+ autoload :Decorator, 'plucky/pagination/decorator'
14
+ autoload :Paginator, 'plucky/pagination/paginator'
15
+ end
16
+
17
+ def self.to_object_id(value)
18
+ if value.nil? || (value.respond_to?(:empty?) && value.empty?)
19
+ nil
20
+ elsif value.is_a?(BSON::ObjectId)
21
+ value
22
+ else
23
+ if BSON::ObjectId.legal?(value.to_s)
24
+ BSON::ObjectId.from_string(value.to_s)
25
+ else
26
+ value
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,139 @@
1
+ # encoding: UTF-8
2
+ module Plucky
3
+ class CriteriaHash
4
+ attr_reader :source, :options
5
+
6
+ def initialize(hash={}, options={})
7
+ @source, @options = {}, options
8
+ hash.each { |key, value| self[key] = value }
9
+ end
10
+
11
+ def initialize_copy(source)
12
+ super
13
+ @options = @options.dup
14
+ @source = @source.dup
15
+ each do |key, value|
16
+ self[key] = value.clone if value.duplicable?
17
+ end
18
+ end
19
+
20
+ def []=(key, value)
21
+ normalized_key = normalized_key(key)
22
+ if key.is_a?(SymbolOperator)
23
+ operator = "$#{key.operator}"
24
+ normalized_value = normalized_value(normalized_key, operator, value)
25
+ source[normalized_key] ||= {}
26
+ source[normalized_key][operator] = normalized_value
27
+ else
28
+ if key == :conditions
29
+ value.each { |k, v| self[k] = v }
30
+ else
31
+ normalized_value = normalized_value(normalized_key, normalized_key, value)
32
+ source[normalized_key] = normalized_value
33
+ end
34
+ end
35
+ end
36
+
37
+ def ==(other)
38
+ source == other.source
39
+ end
40
+
41
+ def to_hash
42
+ source
43
+ end
44
+
45
+ def merge(other)
46
+ target = source.dup
47
+ other.source.each_key do |key|
48
+ value, other_value = target[key], other[key]
49
+ target[key] =
50
+ if target.key?(key)
51
+ value_is_hash = value.is_a?(Hash)
52
+ other_is_hash = other_value.is_a?(Hash)
53
+
54
+ if value_is_hash && other_is_hash
55
+ value.update(other_value) do |key, old_value, new_value|
56
+ Array(old_value).concat(Array(new_value)).uniq
57
+ end
58
+ elsif value_is_hash && !other_is_hash
59
+ if modifier_key = value.keys.detect { |k| k.to_s[0, 1] == '$' }
60
+ value[modifier_key].concat(Array(other_value)).uniq!
61
+ else
62
+ # kaboom! Array(value).concat(Array(other_value)).uniq
63
+ end
64
+ elsif other_is_hash && !value_is_hash
65
+ if modifier_key = other_value.keys.detect { |k| k.to_s[0, 1] == '$' }
66
+ other_value[modifier_key].concat(Array(value)).uniq!
67
+ else
68
+ # kaboom! Array(value).concat(Array(other_value)).uniq
69
+ end
70
+ else
71
+ Array(value).concat(Array(other_value)).uniq
72
+ end
73
+ else
74
+ other_value
75
+ end
76
+ end
77
+ self.class.new(target)
78
+ end
79
+
80
+ def merge!(other)
81
+ merge(other).to_hash.each do |key, value|
82
+ self[key] = value
83
+ end
84
+ end
85
+
86
+ def object_ids
87
+ @options[:object_ids] ||= []
88
+ end
89
+
90
+ def object_ids=(value)
91
+ raise ArgumentError unless value.is_a?(Array)
92
+ @options[:object_ids] = value.flatten
93
+ end
94
+
95
+ # The definition of simple is querying by only _id or _id and _type.
96
+ # If this is the case, you can use IdentityMap in library to not perform
97
+ # query and instead just return from map.
98
+ def simple?
99
+ key_set = keys.to_set
100
+ key_set == [:_id].to_set || key_set == [:_id, :_type].to_set
101
+ end
102
+
103
+ private
104
+ def method_missing(method, *args, &block)
105
+ @source.send(method, *args, &block)
106
+ end
107
+
108
+ def object_id?(key)
109
+ object_ids.include?(key.to_sym)
110
+ end
111
+
112
+ def normalized_key(key)
113
+ key = key.to_sym if key.respond_to?(:to_sym)
114
+ return normalized_key(key.field) if key.respond_to?(:field)
115
+ return :_id if key == :id
116
+ key
117
+ end
118
+
119
+ def normalized_value(parent_key, key, value)
120
+ case value
121
+ when Array, Set
122
+ value.map! { |v| Plucky.to_object_id(v) } if object_id?(parent_key)
123
+ parent_key == key && key != :$or ? {'$in' => value.to_a} : value.to_a
124
+ when Time
125
+ value.utc
126
+ when String
127
+ return Plucky.to_object_id(value) if object_id?(key)
128
+ value
129
+ when Hash
130
+ value.each { |k, v| value[k] = normalized_value(key, k, v) }
131
+ value
132
+ when Regexp
133
+ Regexp.new(value)
134
+ else
135
+ value
136
+ end
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,3 @@
1
+ # encoding: UTF-8
2
+ require 'plucky/extensions/duplicable'
3
+ require 'plucky/extensions/symbol'
@@ -0,0 +1,86 @@
1
+ # Copyright (c) 2005-2010 David Heinemeier Hansson
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+ #
22
+ # Most objects are cloneable, but not all. For example you can't dup +nil+:
23
+ #
24
+ # nil.dup # => TypeError: can't dup NilClass
25
+ #
26
+ # Classes may signal their instances are not duplicable removing +dup+/+clone+
27
+ # or raising exceptions from them. So, to dup an arbitrary object you normally
28
+ # use an optimistic approach and are ready to catch an exception, say:
29
+ #
30
+ # arbitrary_object.dup rescue object
31
+ #
32
+ # Rails dups objects in a few critical spots where they are not that arbitrary.
33
+ # That rescue is very expensive (like 40 times slower than a predicate), and it
34
+ # is often triggered.
35
+ #
36
+ # That's why we hardcode the following cases and check duplicable? instead of
37
+ # using that rescue idiom.
38
+ class Object
39
+ # Can you safely .dup this object?
40
+ # False for nil, false, true, symbols, numbers, class and module objects; true otherwise.
41
+ def duplicable?
42
+ true
43
+ end
44
+ end
45
+
46
+ class NilClass #:nodoc:
47
+ def duplicable?
48
+ false
49
+ end
50
+ end
51
+
52
+ class FalseClass #:nodoc:
53
+ def duplicable?
54
+ false
55
+ end
56
+ end
57
+
58
+ class TrueClass #:nodoc:
59
+ def duplicable?
60
+ false
61
+ end
62
+ end
63
+
64
+ class Symbol #:nodoc:
65
+ def duplicable?
66
+ false
67
+ end
68
+ end
69
+
70
+ class Numeric #:nodoc:
71
+ def duplicable?
72
+ false
73
+ end
74
+ end
75
+
76
+ class Class #:nodoc:
77
+ def duplicable?
78
+ false
79
+ end
80
+ end
81
+
82
+ class Module #:nodoc:
83
+ def duplicable?
84
+ false
85
+ end
86
+ end
@@ -0,0 +1,84 @@
1
+ # encoding: UTF-8
2
+ module Plucky
3
+ module Extensions
4
+ module Symbol
5
+ def gt
6
+ SymbolOperator.new(self, 'gt')
7
+ end
8
+
9
+ def lt
10
+ SymbolOperator.new(self, 'lt')
11
+ end
12
+
13
+ def gte
14
+ SymbolOperator.new(self, 'gte')
15
+ end
16
+
17
+ def lte
18
+ SymbolOperator.new(self, 'lte')
19
+ end
20
+
21
+ def ne
22
+ SymbolOperator.new(self, 'ne')
23
+ end
24
+
25
+ def in
26
+ SymbolOperator.new(self, 'in')
27
+ end
28
+
29
+ def nin
30
+ SymbolOperator.new(self, 'nin')
31
+ end
32
+
33
+ def mod
34
+ SymbolOperator.new(self, 'mod')
35
+ end
36
+
37
+ def all
38
+ SymbolOperator.new(self, 'all')
39
+ end
40
+
41
+ def size
42
+ SymbolOperator.new(self, 'size')
43
+ end unless Symbol.instance_methods.include?(:size) # Ruby 1.9 defines symbol size
44
+
45
+ def exists
46
+ SymbolOperator.new(self, 'exists')
47
+ end
48
+
49
+ def asc
50
+ SymbolOperator.new(self, 'asc')
51
+ end
52
+
53
+ def desc
54
+ SymbolOperator.new(self, 'desc')
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ class SymbolOperator
61
+ include Comparable
62
+
63
+ attr_reader :field, :operator
64
+
65
+ def initialize(field, operator, options={})
66
+ @field, @operator = field, operator
67
+ end unless method_defined?(:initialize)
68
+
69
+ def <=>(other)
70
+ if field == other.field
71
+ operator <=> other.operator
72
+ else
73
+ field.to_s <=> other.field.to_s
74
+ end
75
+ end
76
+
77
+ def ==(other)
78
+ field == other.field && operator == other.operator
79
+ end
80
+ end
81
+
82
+ class Symbol
83
+ include Plucky::Extensions::Symbol
84
+ end
@@ -0,0 +1,127 @@
1
+ # encoding: UTF-8
2
+ module Plucky
3
+ class OptionsHash
4
+ attr_reader :source
5
+
6
+ def initialize(hash={})
7
+ @source = {}
8
+ hash.each { |key, value| self[key] = value }
9
+ end
10
+
11
+ def initialize_copy(source)
12
+ super
13
+ @source = @source.dup
14
+ each do |key, value|
15
+ self[key] = value.clone if value.duplicable?
16
+ end
17
+ end
18
+
19
+ def []=(key, value)
20
+ key = normalized_key(key)
21
+ source[key] = normalized_value(key, value)
22
+ end
23
+
24
+ def ==(other)
25
+ source == other.source
26
+ end
27
+
28
+ def to_hash
29
+ source
30
+ end
31
+
32
+ def fields?
33
+ !self[:fields].nil?
34
+ end
35
+
36
+ def merge(other)
37
+ self.class.new(to_hash.merge(other.to_hash))
38
+ end
39
+
40
+ def merge!(other)
41
+ other.to_hash.each { |key, value| self[key] = value }
42
+ self
43
+ end
44
+
45
+ private
46
+ def method_missing(method, *args, &block)
47
+ @source.send(method, *args, &block)
48
+ end
49
+
50
+ NormalizedKeys = {
51
+ :order => :sort,
52
+ :select => :fields,
53
+ :offset => :skip,
54
+ :id => :_id,
55
+ }
56
+
57
+ def normalized_key(key)
58
+ NormalizedKeys.default = key
59
+ NormalizedKeys[key.to_sym]
60
+ end
61
+
62
+ def normalized_value(key, value)
63
+ case key
64
+ when :fields
65
+ normalized_fields(value)
66
+ when :sort
67
+ normalized_sort(value)
68
+ when :limit, :skip
69
+ value.nil? ? nil : value.to_i
70
+ else
71
+ value
72
+ end
73
+ end
74
+
75
+ def normalized_fields(value)
76
+ return nil if value.respond_to?(:empty?) && value.empty?
77
+ case value
78
+ when Array
79
+ if value.size == 1 && value.first.is_a?(Hash)
80
+ value.first
81
+ else
82
+ value.flatten
83
+ end
84
+ when Symbol
85
+ [value]
86
+ when String
87
+ value.split(',').map { |v| v.strip }
88
+ else
89
+ value
90
+ end
91
+ end
92
+
93
+ def normalized_sort(value)
94
+ case value
95
+ when Array
96
+ if value.size == 1 && value[0].is_a?(String)
97
+ normalized_sort_piece(value[0])
98
+ else
99
+ value.compact.map { |v| normalized_sort_piece(v).flatten }
100
+ end
101
+ else
102
+ normalized_sort_piece(value)
103
+ end
104
+ end
105
+
106
+ def normalized_sort_piece(value)
107
+ case value
108
+ when SymbolOperator
109
+ [normalized_direction(value.field, value.operator)]
110
+ when String
111
+ value.split(',').map do |piece|
112
+ normalized_direction(*piece.split(' '))
113
+ end
114
+ when Symbol
115
+ [normalized_direction(value)]
116
+ else
117
+ value
118
+ end
119
+ end
120
+
121
+ def normalized_direction(field, direction=nil)
122
+ direction ||= 'ASC'
123
+ direction = direction.upcase == 'ASC' ? 1 : -1
124
+ [normalized_key(field).to_s, direction]
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,21 @@
1
+ require 'forwardable'
2
+ module Plucky
3
+ module Pagination
4
+ module Decorator
5
+ extend Forwardable
6
+
7
+ def_delegators :@paginator,
8
+ :total_entries, :total_pages,
9
+ :current_page, :per_page,
10
+ :previous_page, :next_page,
11
+ :skip, :limit,
12
+ :offset, :out_of_bounds?
13
+
14
+ def paginator(p=nil)
15
+ return @paginator if p.nil?
16
+ @paginator = p
17
+ self
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,37 @@
1
+ # encoding: UTF-8
2
+ module Plucky
3
+ module Pagination
4
+ class Paginator
5
+ attr_reader :total_entries, :current_page, :per_page
6
+
7
+ def initialize(total, page, per_page=nil)
8
+ @total_entries = total.to_i
9
+ @current_page = [page.to_i, 1].max
10
+ @per_page = (per_page || 25).to_i
11
+ end
12
+
13
+ def total_pages
14
+ (total_entries / per_page.to_f).ceil
15
+ end
16
+
17
+ def out_of_bounds?
18
+ current_page > total_pages
19
+ end
20
+
21
+ def previous_page
22
+ current_page > 1 ? (current_page - 1) : nil
23
+ end
24
+
25
+ def next_page
26
+ current_page < total_pages ? (current_page + 1) : nil
27
+ end
28
+
29
+ def skip
30
+ (current_page - 1) * per_page
31
+ end
32
+
33
+ alias :limit :per_page
34
+ alias :offset :skip
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,209 @@
1
+ # encoding: UTF-8
2
+ require 'forwardable'
3
+ module Plucky
4
+ class Query
5
+ include Enumerable
6
+ extend Forwardable
7
+
8
+ OptionKeys = [
9
+ :select, :offset, :order, # MM
10
+ :fields, :skip, :limit, :sort, :hint, :snapshot, # Ruby Driver
11
+ :batch_size, :timeout, :transformer # Ruby Driver
12
+ ]
13
+
14
+ attr_reader :criteria, :options, :collection
15
+ def_delegator :criteria, :simple?
16
+ def_delegator :options, :fields?
17
+ def_delegators :to_a, :each, :include?
18
+
19
+ def initialize(collection, opts={})
20
+ @collection, @options, @criteria = collection, OptionsHash.new, CriteriaHash.new
21
+ opts.each { |key, value| self[key] = value }
22
+ end
23
+
24
+ def initialize_copy(source)
25
+ super
26
+ @criteria = @criteria.dup
27
+ @options = @options.dup
28
+ end
29
+
30
+ def object_ids(*keys)
31
+ return criteria.object_ids if keys.empty?
32
+ criteria.object_ids = *keys
33
+ self
34
+ end
35
+
36
+ def per_page(limit=nil)
37
+ return @per_page || 25 if limit.nil?
38
+ @per_page = limit
39
+ self
40
+ end
41
+
42
+ def paginate(opts={})
43
+ page = opts.delete(:page)
44
+ limit = opts.delete(:per_page) || per_page
45
+ query = clone.update(opts)
46
+ total = query.count
47
+ paginator = Pagination::Paginator.new(total, page, limit)
48
+ query[:limit] = paginator.limit
49
+ query[:skip] = paginator.skip
50
+ query.all.tap do |docs|
51
+ docs.extend(Pagination::Decorator)
52
+ docs.paginator(paginator)
53
+ end
54
+ end
55
+
56
+ def find_each(opts={})
57
+ query = clone.update(opts)
58
+ query.collection.find(query.criteria.to_hash, query.options.to_hash)
59
+ end
60
+
61
+ def find_one(opts={})
62
+ query = clone.update(opts)
63
+ query.collection.find_one(query.criteria.to_hash, query.options.to_hash)
64
+ end
65
+
66
+ def find(*ids)
67
+ return nil if ids.empty?
68
+ if ids.size == 1 && !ids[0].is_a?(Array)
69
+ first(:_id => ids[0])
70
+ else
71
+ all(:_id => ids.flatten)
72
+ end
73
+ end
74
+
75
+ def all(opts={})
76
+ find_each(opts).to_a
77
+ end
78
+
79
+ def first(opts={})
80
+ find_one(opts)
81
+ end
82
+
83
+ def last(opts={})
84
+ clone.update(opts).reverse.find_one
85
+ end
86
+
87
+ def remove(opts={})
88
+ query = clone.update(opts)
89
+ query.collection.remove(query.criteria.to_hash)
90
+ end
91
+
92
+ def count(opts={})
93
+ find_each(opts).count
94
+ end
95
+
96
+ def size
97
+ count
98
+ end
99
+
100
+ def distinct(key, opts = {})
101
+ query = clone.update(opts)
102
+ query.collection.distinct(key, query.criteria.to_hash)
103
+ end
104
+
105
+ def update(opts={})
106
+ opts.each { |key, value| self[key] = value }
107
+ self
108
+ end
109
+
110
+ def fields(*args)
111
+ clone.tap { |query| query.options[:fields] = *args }
112
+ end
113
+
114
+ def ignore(*args)
115
+ set_fields(args, 0)
116
+ end
117
+
118
+ def only(*args)
119
+ set_fields(args, 1)
120
+ end
121
+
122
+ def limit(count=nil)
123
+ clone.tap { |query| query.options[:limit] = count }
124
+ end
125
+
126
+ def reverse
127
+ clone.tap do |query|
128
+ query[:sort] = query[:sort].map do |s|
129
+ [s[0], -s[1]]
130
+ end unless query.options[:sort].nil?
131
+ end
132
+ end
133
+
134
+ def skip(count=nil)
135
+ clone.tap { |query| query.options[:skip] = count }
136
+ end
137
+ alias offset skip
138
+
139
+ def sort(*args)
140
+ clone.tap { |query| query.options[:sort] = *args }
141
+ end
142
+ alias order sort
143
+
144
+ def where(hash={})
145
+ clone.tap do |query|
146
+ query.criteria.merge!(CriteriaHash.new(hash))
147
+ end
148
+ end
149
+
150
+ def empty?
151
+ count.zero?
152
+ end
153
+
154
+ def exists?(options={})
155
+ !count(options).zero?
156
+ end
157
+ alias :exist? :exists?
158
+
159
+ def to_a
160
+ all
161
+ end
162
+
163
+ def [](key)
164
+ key = key.to_sym if key.respond_to?(:to_sym)
165
+ if OptionKeys.include?(key)
166
+ @options[key]
167
+ else
168
+ @criteria[key]
169
+ end
170
+ end
171
+
172
+ def []=(key, value)
173
+ key = key.to_sym if key.respond_to?(:to_sym)
174
+ if OptionKeys.include?(key)
175
+ @options[key] = value
176
+ else
177
+ @criteria[key] = value
178
+ end
179
+ end
180
+
181
+ def merge(other)
182
+ merged_criteria = criteria.merge(other.criteria).to_hash
183
+ merged_options = options.merge(other.options).to_hash
184
+ clone.update(merged_criteria).update(merged_options)
185
+ end
186
+
187
+ def to_hash
188
+ criteria.to_hash.merge(options.to_hash)
189
+ end
190
+
191
+ def explain
192
+ collection.find(criteria.to_hash, options.to_hash).explain
193
+ end
194
+
195
+ def inspect
196
+ as_nice_string = to_hash.collect do |key, value|
197
+ " #{key}: #{value.inspect}"
198
+ end.sort.join(",")
199
+ "#<#{self.class}#{as_nice_string}>"
200
+ end
201
+
202
+ private
203
+ def set_fields(field_list, value)
204
+ the_fields = {}
205
+ field_list.each {|field| the_fields[field.to_sym] = value}
206
+ clone.tap { |query| query.options[:fields] = the_fields}
207
+ end
208
+ end
209
+ end
@@ -0,0 +1,5 @@
1
+ # encoding: UTF-8
2
+ module Plucky
3
+ Version = '0.3.8'
4
+ MongoVersion = '~> 1.3'
5
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jonbell-plucky
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 3
8
+ - 8
9
+ version: 0.3.8
10
+ platform: ruby
11
+ authors:
12
+ - John Nunemaker
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-06-29 00:00:00 -05:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: jonbell-mongo
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 1
30
+ - 3
31
+ version: "1.3"
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ description:
35
+ email:
36
+ - nunemaker@gmail.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - lib/plucky/criteria_hash.rb
45
+ - lib/plucky/extensions/duplicable.rb
46
+ - lib/plucky/extensions/symbol.rb
47
+ - lib/plucky/extensions.rb
48
+ - lib/plucky/options_hash.rb
49
+ - lib/plucky/pagination/decorator.rb
50
+ - lib/plucky/pagination/paginator.rb
51
+ - lib/plucky/query.rb
52
+ - lib/plucky/version.rb
53
+ - lib/plucky.rb
54
+ - LICENSE
55
+ - README.rdoc
56
+ has_rdoc: true
57
+ homepage: http://github.com/jonbell/plucky
58
+ licenses: []
59
+
60
+ post_install_message:
61
+ rdoc_options: []
62
+
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ segments:
79
+ - 0
80
+ version: "0"
81
+ requirements: []
82
+
83
+ rubyforge_project:
84
+ rubygems_version: 1.3.7
85
+ signing_key:
86
+ specification_version: 3
87
+ summary: Thin layer over the ruby driver that allows you to quickly grab hold of your data (pluck it!).
88
+ test_files: []
89
+