mongoid_query_string_interface 0.1.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.
data/MIT_LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Vicente Mundim
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,83 @@
1
+ = Overview
2
+
3
+ == About Mongoid::QueryStringInterace
4
+
5
+ Gives a method that can parse query string parameters into a set of criterias
6
+ that Mongoid can use to perform actual queries in MongoDB databases for a given
7
+ model.
8
+
9
+ == Repository
10
+
11
+ http://github.com/vicentemundim/mongoid-query-string-interface
12
+
13
+ = Installing
14
+
15
+ This is a gem, so you can install it by:
16
+
17
+ sudo gem install mongoid_query_string_interface
18
+
19
+ Or, if you are using rails, put this in your Gemfile:
20
+
21
+ gem 'mongoid_query_string_interface'
22
+
23
+ = Usage
24
+
25
+ To use it, just extend Mongoid::QueryStringInterface in your document model:
26
+
27
+ class Document
28
+ include Mongoid::Document
29
+ extend Mongoid::QueryInterfaceString
30
+
31
+ # ... add fields here
32
+ end
33
+
34
+ Then, in your controllers put:
35
+
36
+ def index
37
+ @documents = Document.filter_by(params)
38
+ # ... do something like render a HTML template or a XML/JSON view of documents
39
+ end
40
+
41
+ That's it! Now you can do something like this:
42
+
43
+ http://myhost.com/documents?tags.all=ruby|rails|mongodb&tags.nin=sql|java&updated_at.gt=2010-01-01&created_at.desc&per_page=10&page=3
44
+
45
+ This would get all documents which have the tags 'ruby', 'rails' and 'mongo',
46
+ and that don't have both 'sql' and 'java' tags, and that were updated after
47
+ 2010-01-01, ordered by descending created_at. It will return 10 elements per
48
+ page, and the 3rd page of results.
49
+
50
+ You could even query for embedded documents, and use any of the Mongodb
51
+ conditional operators:
52
+
53
+ http://myhost.com/documents?comments.author=Shrek
54
+
55
+ Which would get all documents that have been commented by 'Shrek'. Basically,
56
+ any valid path that you can use in a Mongoid::Criteria can be used here, and
57
+ you can also append any of the Mongodb conditional operators.
58
+
59
+ You can sort results like this:
60
+
61
+ http://myhost.com/documents?order_by=created_at.desc
62
+
63
+ or
64
+
65
+ http://myhost.com/documents?order_by=created_at
66
+
67
+ Which is the same as:
68
+
69
+ http://myhost.com/documents?order_by=created_at.asc
70
+
71
+ To order by more than one field:
72
+
73
+ http://myhost.com/documents?created_at.desc&updated_at.desc
74
+
75
+ Or even:
76
+
77
+ http://myhost.com/documents?created_at=desc&updated_at=desc
78
+
79
+ Check the specs for more use cases.
80
+
81
+ = Credits
82
+
83
+ Vicente Mundim: vicente.mundim at gmail dot com
@@ -0,0 +1,175 @@
1
+ module Mongoid
2
+ module QueryStringInterface
3
+ CONDITIONAL_OPERATORS = [:all, :exists, :gte, :gt, :in, :lte, :lt, :ne, :nin, :size, :near, :within]
4
+ ARRAY_CONDITIONAL_OPERATORS = [:all, :in, :nin]
5
+ SORTING_OPERATORS = [:asc, :desc]
6
+
7
+ def filter_by(params={})
8
+ params = hash_with_indifferent_access(params)
9
+ where(filtering_options(params)).order_by(*sorting_options(params)).paginate(pagination_options(params))
10
+ end
11
+
12
+ def paginated_collection_with_filter_by(params={})
13
+ params = hash_with_indifferent_access(params)
14
+
15
+ pagination = pagination_options(params)
16
+ pager = WillPaginate::Collection.new pagination[:page], pagination[:per_page], where(filtering_options(params)).count
17
+
18
+ [:total_entries, :total_pages, :per_page, :offset, :previous_page, :current_page, :next_page].inject({}) do |result, attr|
19
+ result[attr] = pager.send(attr)
20
+ result
21
+ end
22
+ end
23
+
24
+ def default_filtering_options
25
+ {}
26
+ end
27
+
28
+ def default_sorting_options
29
+ []
30
+ end
31
+
32
+ private
33
+ def pagination_options(options)
34
+ options.reverse_merge :per_page => 12, :page => 1
35
+ end
36
+
37
+ def filtering_options(options)
38
+ default_filtering_options.merge(parse_operators(only_filtering(options)))
39
+ end
40
+
41
+ def sorting_options(options)
42
+ options = only_sorting(options)
43
+
44
+ sorting_options = []
45
+ sorting_options.concat(parse_order_by(options))
46
+ sorting_options.concat(parse_sorting(options))
47
+
48
+ sorting_options.empty? ? default_sorting_options : sorting_options
49
+ end
50
+
51
+ def parse_operators(options)
52
+ options.inject({}) do |result, item|
53
+ key, value = item
54
+
55
+ attribute = attribute_from(key)
56
+ operator = operator_from(key)
57
+ value = parse_value(value, operator)
58
+
59
+ if operator
60
+ filter = { operator => value }
61
+
62
+ if result.has_key?(attribute)
63
+ result[attribute].merge!(filter)
64
+ else
65
+ result[attribute] = filter
66
+ end
67
+ else
68
+ result[attribute] = value
69
+ end
70
+
71
+ result
72
+ end
73
+ end
74
+
75
+ def attribute_from(key)
76
+ if match = key.match(/(.*)\.(#{(CONDITIONAL_OPERATORS + SORTING_OPERATORS).join('|')})/)
77
+ match[1].to_sym
78
+ else
79
+ key.to_sym
80
+ end
81
+ end
82
+
83
+ def operator_from(key)
84
+ if match = key.match(/.*\.(#{CONDITIONAL_OPERATORS.join('|')})/)
85
+ "$#{match[1]}".to_sym
86
+ end
87
+ end
88
+
89
+ def parse_value(value, operator)
90
+ parse_date(value) or parse_integer(value) or parse_array(value, operator) or value
91
+ end
92
+
93
+ def parse_date(date)
94
+ date.to_time and Time.parse(date)
95
+ rescue Exception
96
+ nil
97
+ end
98
+
99
+ def parse_integer(integer)
100
+ if match = integer.match(/\d+/)
101
+ match[0].to_i
102
+ end
103
+ end
104
+
105
+ def parse_float(float)
106
+ if match = float.match(/^(\d+)(\.?\d*)$/)
107
+ match[0].to_f
108
+ end
109
+ end
110
+
111
+ def parse_array(value, operator)
112
+ split_and_strip(value) if array_operator?(operator)
113
+ end
114
+
115
+ def array_operator?(operator)
116
+ ARRAY_CONDITIONAL_OPERATORS.map { |op| "$#{op}" }.include?(operator.to_s)
117
+ end
118
+
119
+ def split_and_strip(values)
120
+ values.split('|').map(&:strip)
121
+ end
122
+
123
+ def hash_with_indifferent_access(params)
124
+ params.is_a?(HashWithIndifferentAccess) ? params : HashWithIndifferentAccess.new(params)
125
+ end
126
+
127
+ def only_filtering(options)
128
+ options.except(*only_sorting(options).keys).except(:per_page, :page, :action, :controller, :format, :order_by)
129
+ end
130
+
131
+ def only_sorting(options)
132
+ options.inject({}) do |result, item|
133
+ key, value = item
134
+ result[key] = value if sorting_parameter?(key, value)
135
+ result
136
+ end
137
+ end
138
+
139
+ def sorting_parameter?(key, value)
140
+ key.to_s == 'order_by' or key.match(/(.*)\.(#{SORTING_OPERATORS.join('|')})/) or SORTING_OPERATORS.include?(value.to_sym)
141
+ end
142
+
143
+ def parse_order_by(options)
144
+ sorting_options = []
145
+
146
+ if order_by = options.delete('order_by')
147
+ if match = order_by.match(/(.*)\.(#{SORTING_OPERATORS.join('|')})/)
148
+ sorting_options << match[1].to_sym.send(match[2])
149
+ else
150
+ sorting_options << order_by.to_sym.asc
151
+ end
152
+ end
153
+
154
+ sorting_options
155
+ end
156
+
157
+ def parse_sorting(options)
158
+ options.inject([]) do |result, item|
159
+ key, value = item
160
+
161
+ attribute = attribute_from(key)
162
+ sorting_operator = sorting_operator_from(key)
163
+
164
+ result << attribute.send(sorting_operator || value)
165
+ result
166
+ end
167
+ end
168
+
169
+ def sorting_operator_from(key)
170
+ if match = key.match(/.*\.(#{SORTING_OPERATORS.join('|')})/)
171
+ match[1].to_sym
172
+ end
173
+ end
174
+ end
175
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc
3
+ module QueryStringInterface #:nodoc
4
+ VERSION = "0.1.0"
5
+ end
6
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mongoid_query_string_interface
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Vicente Mundim
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-07-22 00:00:00 -03:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: mongoid
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 31098209
30
+ segments:
31
+ - 2
32
+ - 0
33
+ - 0
34
+ - beta
35
+ version: 2.0.0.beta
36
+ type: :runtime
37
+ version_requirements: *id001
38
+ - !ruby/object:Gem::Dependency
39
+ name: rspec
40
+ prerelease: false
41
+ requirement: &id002 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ hash: 31098209
47
+ segments:
48
+ - 2
49
+ - 0
50
+ - 0
51
+ - beta
52
+ version: 2.0.0.beta
53
+ type: :development
54
+ version_requirements: *id002
55
+ description: Gives a method that can parse query string parameters into a set of criterias that Mongoid can use to perform actual queries in MongoDB databases for a given model.
56
+ email:
57
+ - vicente.mundim@gmail.com
58
+ executables: []
59
+
60
+ extensions: []
61
+
62
+ extra_rdoc_files: []
63
+
64
+ files:
65
+ - lib/mongoid_query_string_interface.rb
66
+ - lib/version.rb
67
+ - MIT_LICENSE
68
+ - README.rdoc
69
+ has_rdoc: true
70
+ homepage: http://github.com/vicentemundim/mongoid_query_string_interface
71
+ licenses: []
72
+
73
+ post_install_message:
74
+ rdoc_options: []
75
+
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ hash: 3
84
+ segments:
85
+ - 0
86
+ version: "0"
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ hash: 23
93
+ segments:
94
+ - 1
95
+ - 3
96
+ - 6
97
+ version: 1.3.6
98
+ requirements: []
99
+
100
+ rubyforge_project: mongoid_query_string_interface
101
+ rubygems_version: 1.3.7
102
+ signing_key:
103
+ specification_version: 3
104
+ summary: An interface for performing queries in MongoDB using query string parameters.
105
+ test_files: []
106
+