mongoid_query_string_interface 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,9 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mongoid_query_string_interface (0.5.1)
5
- json (>= 1.4.6)
4
+ mongoid_query_string_interface (0.6.0)
6
5
  mongoid (~> 2.0.2)
6
+ query_string_interface (>= 0.1.0)
7
7
  will_paginate (~> 3.0.pre2)
8
8
 
9
9
  GEM
@@ -22,7 +22,6 @@ GEM
22
22
  database_cleaner (0.6.7)
23
23
  diff-lcs (1.1.2)
24
24
  i18n (0.5.0)
25
- json (1.5.3)
26
25
  linecache (0.46)
27
26
  rbx-require-relative (> 0.0.4)
28
27
  linecache19 (0.5.12)
@@ -33,6 +32,8 @@ GEM
33
32
  activemodel (~> 3.0)
34
33
  mongo (~> 1.3)
35
34
  tzinfo (~> 0.3.22)
35
+ query_string_interface (0.1.0)
36
+ activesupport (>= 3.0.0)
36
37
  rake (0.8.7)
37
38
  rbx-require-relative (0.0.5)
38
39
  rspec (2.6.0)
data/README.rdoc CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  == About Mongoid::QueryStringInterace
4
4
 
5
- Gives a method that can parse query string parameters into a set of criterias
5
+ Gives some methods that can parse query string parameters into a set of criterias
6
6
  that Mongoid can use to perform actual queries in MongoDB databases for a given
7
7
  model.
8
8
 
@@ -27,10 +27,10 @@ To use it, just extend Mongoid::QueryStringInterface in your document model:
27
27
  class Document
28
28
  include Mongoid::Document
29
29
  extend Mongoid::QueryInterfaceString
30
-
30
+
31
31
  # ... add fields here
32
32
  end
33
-
33
+
34
34
  Then, in your controllers put:
35
35
 
36
36
  def index
@@ -41,7 +41,7 @@ Then, in your controllers put:
41
41
  That's it! Now you can do something like this:
42
42
 
43
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
-
44
+
45
45
  This would get all documents which have the tags 'ruby', 'rails' and 'mongo',
46
46
  and that don't have both 'sql' and 'java' tags, and that were updated after
47
47
  2010-01-01, ordered by descending created_at. It will return 10 elements per
@@ -51,12 +51,12 @@ You could even query for embedded documents, and use any of the Mongodb
51
51
  conditional operators:
52
52
 
53
53
  http://myhost.com/documents?comments.author=Shrek
54
-
54
+
55
55
  Which would get all documents that have been commented by 'Shrek'. Basically,
56
56
  any valid path that you can use in a Mongoid::Criteria can be used here, and
57
57
  you can also append any of the Mongodb conditional operators.
58
58
 
59
- You can sort results like this:
59
+ You can sort results by passing a order_by parameter this:
60
60
 
61
61
  http://myhost.com/documents?order_by=created_at.desc
62
62
 
@@ -70,11 +70,7 @@ Which is the same as:
70
70
 
71
71
  To order by more than one field:
72
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
73
+ http://myhost.com/documents?order_by=created_at.desc|updated_at.desc
78
74
 
79
75
  Check the specs for more use cases.
80
76
 
@@ -1,30 +1,17 @@
1
- require File.expand_path(File.join('helpers'), File.dirname(__FILE__))
2
- require File.expand_path(File.join('paginate'), File.dirname(__FILE__))
3
- require File.expand_path(File.join('parsers', 'filter_parser'), File.dirname(__FILE__))
4
- require File.expand_path(File.join('parsers', 'filters_parser'), File.dirname(__FILE__))
1
+ require "query_string_interface"
2
+ require "mongoid/paginate"
5
3
 
6
4
  module Mongoid
7
5
  module QueryStringInterface
8
- include Mongoid::QueryStringInterface::Helpers
9
- include Mongoid::Paginate unless instance_methods(:false).include?(:paginate)
6
+ include ::QueryStringInterface
7
+ include ::QueryStringInterface::Helpers
10
8
 
11
- NORMAL_CONDITIONAL_OPERATORS = [:exists, :gte, :gt, :lte, :lt, :ne, :size, :near, :within]
12
- ARRAY_CONDITIONAL_OPERATORS = [:all, :in, :nin]
13
- CONDITIONAL_OPERATORS = ARRAY_CONDITIONAL_OPERATORS + NORMAL_CONDITIONAL_OPERATORS
14
- SORTING_OPERATORS = [:asc, :desc]
15
- OR_OPERATOR = :or
16
-
17
- ATTRIBUTE_REGEX = /^(.*)\.(#{(CONDITIONAL_OPERATORS + SORTING_OPERATORS + [OR_OPERATOR]).join('|')})$/
18
- OPERATOR_REGEX = /^.*\.(#{Mongoid::QueryStringInterface::CONDITIONAL_OPERATORS.join('|')})$/
9
+ def self.extended(base)
10
+ base.extend Mongoid::Paginate unless base.methods.include?(:paginate)
11
+ end
19
12
 
20
13
  PAGER_ATTRIBUTES = [:total_entries, :total_pages, :per_page, :offset, :previous_page, :current_page, :next_page]
21
14
 
22
- ORDER_BY_PARAMETER = :order_by
23
- PAGINATION_PARAMTERS = [:per_page, :page]
24
- FRAMEWORK_PARAMETERS = [:controller, :action, :format]
25
- CONTROL_PARAMETERS = [:disable_default_filters]
26
- RESERVED_PARAMETERS = FRAMEWORK_PARAMETERS + PAGINATION_PARAMTERS + [ORDER_BY_PARAMETER] + CONTROL_PARAMETERS
27
-
28
15
  def filter_by(params={})
29
16
  params = hash_with_indifferent_access(params)
30
17
  filter_only_and_order_by(params).paginate(pagination_options(params))
@@ -38,7 +25,7 @@ module Mongoid
38
25
  pager
39
26
  end
40
27
 
41
- return { :pager => pager, model_name.human.underscore.pluralize.to_sym => result }
28
+ return { :pager => pager, collection_name_in_pagination_result => result }
42
29
  end
43
30
 
44
31
  def filter_with_optimized_pagination_by(params={})
@@ -71,49 +58,16 @@ module Mongoid
71
58
  end
72
59
  end
73
60
 
74
- def default_filtering_options; {}; end
75
- def default_sorting_options; []; end
76
- def default_pagination_options; { :per_page => 12, :page => 1 }; end
77
- def sorting_attributes_to_replace; {} end
78
- def filtering_attributes_to_replace; {} end
79
-
80
61
  protected
81
- def pagination_options(options)
82
- hash_with_indifferent_access(default_pagination_options).merge(options)
83
- end
84
-
85
- def filtering_options(options)
86
- Mongoid::QueryStringInterface::Parsers::FiltersParser.new(
87
- only_filtering(options),
88
- options.has_key?(:disable_default_filters) ? {} : default_filtering_options,
89
- filtering_attributes_to_replace
90
- ).parse
91
- end
92
-
93
62
  def sorting_options(options)
94
- parse_order_by(options) || default_sorting_options.map { |field| sorting_operator_for(field) }
95
- end
96
-
97
- def only_filtering(options)
98
- options.except(*RESERVED_PARAMETERS)
99
- end
100
-
101
- def parse_order_by(options)
102
- if options.has_key?('order_by')
103
- options['order_by'].split('|').map do |field|
104
- sorting_operator_for(field)
105
- end
63
+ super(options).map do |sort_option|
64
+ attribute = sort_option.keys.first
65
+ attribute.send(sort_option[attribute])
106
66
  end
107
67
  end
108
68
 
109
- def sorting_operator_for(field)
110
- if field.is_a?(Mongoid::Criterion::Complex)
111
- replace_attribute(field.key, sorting_attributes_to_replace).to_sym.send(field.operator)
112
- elsif match = field.match(/(.*)\.(#{SORTING_OPERATORS.join('|')})/)
113
- replace_attribute(match[1], sorting_attributes_to_replace).to_sym.send(match[2])
114
- else
115
- replace_attribute(field, sorting_attributes_to_replace).to_sym.asc
116
- end
69
+ def collection_name_in_pagination_result
70
+ model_name.human.underscore.pluralize.to_sym
117
71
  end
118
72
  end
119
73
  end
data/lib/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc
3
3
  module QueryStringInterface #:nodoc
4
- VERSION = "0.5.1"
4
+ VERSION = "0.6.0"
5
5
  end
6
6
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: mongoid_query_string_interface
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.5.1
5
+ version: 0.6.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Vicente Mundim
@@ -10,17 +10,18 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-07-21 00:00:00 Z
13
+ date: 2011-09-26 00:00:00 -03:00
14
+ default_executable:
14
15
  dependencies:
15
16
  - !ruby/object:Gem::Dependency
16
- name: json
17
+ name: query_string_interface
17
18
  prerelease: false
18
19
  requirement: &id001 !ruby/object:Gem::Requirement
19
20
  none: false
20
21
  requirements:
21
22
  - - ">="
22
23
  - !ruby/object:Gem::Version
23
- version: 1.4.6
24
+ version: 0.1.0
24
25
  type: :runtime
25
26
  version_requirements: *id001
26
27
  - !ruby/object:Gem::Dependency
@@ -77,15 +78,7 @@ extensions: []
77
78
  extra_rdoc_files: []
78
79
 
79
80
  files:
80
- - lib/mongoid/helpers.rb
81
81
  - lib/mongoid/paginate.rb
82
- - lib/mongoid/parsers/array_parser.rb
83
- - lib/mongoid/parsers/boolean_and_nil_parser.rb
84
- - lib/mongoid/parsers/date_time_parser.rb
85
- - lib/mongoid/parsers/filter_parser.rb
86
- - lib/mongoid/parsers/filters_parser.rb
87
- - lib/mongoid/parsers/number_parser.rb
88
- - lib/mongoid/parsers/regex_parser.rb
89
82
  - lib/mongoid/query_string_interface.rb
90
83
  - lib/mongoid_query_string_interface.rb
91
84
  - lib/version.rb
@@ -93,6 +86,7 @@ files:
93
86
  - README.rdoc
94
87
  - Gemfile
95
88
  - Gemfile.lock
89
+ has_rdoc: true
96
90
  homepage: http://github.com/vicentemundim/mongoid_query_string_interface
97
91
  licenses: []
98
92
 
@@ -116,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
110
  requirements: []
117
111
 
118
112
  rubyforge_project: mongoid_query_string_interface
119
- rubygems_version: 1.8.5
113
+ rubygems_version: 1.6.2
120
114
  signing_key:
121
115
  specification_version: 3
122
116
  summary: An interface for performing queries in MongoDB using query string parameters.
@@ -1,24 +0,0 @@
1
- module Mongoid
2
- module QueryStringInterface
3
- module Helpers
4
- def hash_with_indifferent_access(params)
5
- params.is_a?(HashWithIndifferentAccess) ? params : params.with_indifferent_access
6
- end
7
-
8
- def replace_attribute(attribute, hash_with_attributes_to_replace)
9
- hash = hash_with_indifferent_access(hash_with_attributes_to_replace)
10
- hash.has_key?(attribute) ? hash[attribute] : attribute
11
- end
12
-
13
- def replaced_attribute_name(attribute, hash_with_attributes_to_replace)
14
- attribute = replace_attribute(attribute, hash_with_attributes_to_replace)
15
- attribute.is_a?(Hash) ? attribute[:to] : attribute
16
- end
17
-
18
- def replaced_attribute_value(attribute, value, hash_with_attributes_to_replace, raw_params)
19
- attribute = replace_attribute(attribute, hash_with_attributes_to_replace)
20
- attribute.is_a?(Hash) ? attribute[:convert_value_to].call(value, raw_params) : value
21
- end
22
- end
23
- end
24
- end
@@ -1,36 +0,0 @@
1
- module Mongoid
2
- module QueryStringInterface
3
- module Parsers
4
- class ArrayParser
5
- ARRAY_SEPARATOR = '|'
6
-
7
- def parseable?(value, operator)
8
- operator && conditional_operators.include?(operator)
9
- end
10
-
11
- def parse(value)
12
- value.split(ARRAY_SEPARATOR).map(&:strip).map do |item|
13
- parse_item(item)
14
- end
15
- end
16
-
17
- private
18
- def parse_item(item)
19
- other_parsers.each do |parser|
20
- return parser.parse(item) if parser.parseable?(item, '')
21
- end
22
- end
23
-
24
- def other_parsers
25
- @other_parsers ||= Mongoid::QueryStringInterface::Parsers::FilterParser::PARSERS.reject do |parser|
26
- parser.is_a?(ArrayParser)
27
- end
28
- end
29
-
30
- def conditional_operators
31
- @conditional_operators ||= Mongoid::QueryStringInterface::ARRAY_CONDITIONAL_OPERATORS.map { |o| "$#{o}" }
32
- end
33
- end
34
- end
35
- end
36
- end
@@ -1,30 +0,0 @@
1
- module Mongoid
2
- module QueryStringInterface
3
- module Parsers
4
- class BooleanAndNilParser
5
- def parseable?(value, operator)
6
- !value.nil? && !value.empty?
7
- end
8
-
9
- def parse(value)
10
- if boolean?(value)
11
- value.strip == 'true'
12
- elsif value.nil? or value.empty? or nil_value?(value)
13
- nil
14
- else
15
- value
16
- end
17
- end
18
-
19
- private
20
- def boolean?(value)
21
- value && ['true', 'false'].include?(value.strip)
22
- end
23
-
24
- def nil_value?(value)
25
- value && ['nil', 'null'].include?(value.strip)
26
- end
27
- end
28
- end
29
- end
30
- end
@@ -1,17 +0,0 @@
1
- module Mongoid
2
- module QueryStringInterface
3
- module Parsers
4
- class DateTimeParser
5
- DATE_REGEX = /^(?:\d{4}-\d{2}-\d{2}|\d{4}-\d{1,2}-\d{1,2}[T \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?([ \t]*)(Z?|[-+]\d{2}?(:?\d{2})?))$/
6
-
7
- def parseable?(value, operator)
8
- DATE_REGEX.match(value)
9
- end
10
-
11
- def parse(value)
12
- Time.parse(value)
13
- end
14
- end
15
- end
16
- end
17
- end
@@ -1,158 +0,0 @@
1
- require 'cgi'
2
-
3
- require File.expand_path(File.join('date_time_parser'), File.dirname(__FILE__))
4
- require File.expand_path(File.join('number_parser'), File.dirname(__FILE__))
5
- require File.expand_path(File.join('array_parser'), File.dirname(__FILE__))
6
- require File.expand_path(File.join('regex_parser'), File.dirname(__FILE__))
7
- require File.expand_path(File.join('boolean_and_nil_parser'), File.dirname(__FILE__))
8
-
9
- module Mongoid
10
- module QueryStringInterface
11
- module Parsers
12
- class FilterParser
13
- include Mongoid::QueryStringInterface::Helpers
14
-
15
- attr_reader :raw_attribute, :raw_value
16
-
17
- PARSERS = [
18
- Mongoid::QueryStringInterface::Parsers::ArrayParser.new,
19
- Mongoid::QueryStringInterface::Parsers::DateTimeParser.new,
20
- Mongoid::QueryStringInterface::Parsers::NumberParser.new,
21
- Mongoid::QueryStringInterface::Parsers::RegexParser.new,
22
- Mongoid::QueryStringInterface::Parsers::BooleanAndNilParser.new
23
- ]
24
-
25
- def initialize(raw_attribute, raw_value, attributes_to_replace={}, raw_params={})
26
- @raw_attribute = raw_attribute
27
- @raw_value = raw_value
28
- @attributes_to_replace = attributes_to_replace
29
- @raw_params = raw_params
30
- end
31
-
32
- def attribute
33
- @attribute ||= replaced_attribute_name(parsed_attribute, @attributes_to_replace).to_s
34
- end
35
-
36
- def value
37
- @value ||= expanded_value
38
- end
39
-
40
- def operator
41
- @operator ||= operator_from(raw_attribute)
42
- end
43
-
44
- def or_attribute?
45
- raw_attribute == 'or'
46
- end
47
-
48
- def include?(other_filter)
49
- if or_attribute?
50
- json_value.any? do |filters|
51
- filters.filter_parsers.any? do |filter_parser|
52
- filter_parser.attribute == other_filter.attribute &&
53
- conditional_array_operators.include?(filter_parser.operator) &&
54
- filter_parser.operator == other_filter.operator
55
- end
56
- end
57
- end
58
- end
59
-
60
- def merge(other_filter)
61
- if or_attribute?
62
- @value = json_value.map do |filters|
63
- filters.filter_parsers << other_filter
64
- filters.parse
65
- end
66
- elsif conditional_array_operators.include?(other_filter.operator) && operator == other_filter.operator
67
- @value = value.inject({}) do |result, filter|
68
- filter_operation, filter_value = filter
69
- filter_value = filter_value.concat(other_filter.value[filter_operation]) if other_filter.value[filter_operation]
70
- result[filter_operation] = filter_value
71
- result
72
- end
73
- else
74
- @value = value.merge(other_filter.value)
75
- end
76
- end
77
-
78
- private
79
- def parsed_attribute
80
- if raw_attribute.is_a?(Mongoid::Criterion::Complex)
81
- raw_attribute.key.to_s
82
- elsif or_attribute?
83
- '$or'
84
- elsif raw_attribute =~ Mongoid::QueryStringInterface::ATTRIBUTE_REGEX
85
- $1
86
- else
87
- raw_attribute
88
- end
89
- end
90
-
91
- def expanded_value
92
- if operator
93
- if or_attribute?
94
- parsed_json_value
95
- else
96
- { operator => replaced_attribute_value(parsed_attribute, parsed_value, @attributes_to_replace, @raw_params) }
97
- end
98
- else
99
- replaced_attribute_value(parsed_attribute, parsed_value, @attributes_to_replace, @raw_params)
100
- end
101
- end
102
-
103
- def parsed_value
104
- if raw_value.is_a?(String)
105
- PARSERS.each do |parser|
106
- return parser.parse(unescaped_raw_value) if parser.parseable?(unescaped_raw_value, operator)
107
- end
108
-
109
- return nil
110
- else
111
- raw_value
112
- end
113
- end
114
-
115
- def parsed_json_value
116
- if unescaped_raw_value.is_a?(String)
117
- json_value.map(&:parse)
118
- else
119
- unescaped_raw_value
120
- end
121
- end
122
-
123
- def json_value
124
- raw_or_data = ::JSON.parse(unescaped_raw_value)
125
-
126
- raise "$or query filters must be given as an array of hashes" unless valid_or_filters?(raw_or_data)
127
-
128
- raw_or_data.map do |filters|
129
- FiltersParser.new(filters, {}, @attributes_to_replace, @raw_params)
130
- end
131
- end
132
-
133
- def valid_or_filters?(raw_or_data)
134
- raw_or_data.is_a?(Array) and raw_or_data.all? { |item| item.is_a?(Hash) }
135
- end
136
-
137
- def unescaped_raw_value
138
- @unescaped_raw_value ||= raw_value.is_a?(String) ? CGI.unescape(raw_value) : raw_value
139
- end
140
-
141
- def conditional_array_operators
142
- Mongoid::QueryStringInterface::ARRAY_CONDITIONAL_OPERATORS.map { |o| "$#{o}" }
143
- end
144
-
145
- def operator_from(attribute)
146
- if attribute.is_a?(Mongoid::Criterion::Complex)
147
- "$#{attribute.operator}"
148
- elsif or_attribute?
149
- '$or'
150
- elsif attribute =~ Mongoid::QueryStringInterface::OPERATOR_REGEX
151
- "$#{$1}"
152
- end
153
- end
154
-
155
- end
156
- end
157
- end
158
- end
@@ -1,77 +0,0 @@
1
- module Mongoid
2
- module QueryStringInterface
3
- module Parsers
4
- class FiltersParser
5
- include Mongoid::QueryStringInterface::Helpers
6
-
7
- attr_reader :filters, :default_filters
8
-
9
- def initialize(filters, default_filters={}, attributes_to_replace={}, raw_filters=nil)
10
- @filters = filters.with_indifferent_access
11
- @default_filters = default_filters.with_indifferent_access
12
- @attributes_to_replace = attributes_to_replace.with_indifferent_access
13
- @raw_filters = raw_filters.nil? ? @filters : raw_filters.with_indifferent_access
14
- end
15
-
16
- def parse
17
- result = default_filters.inject({}) do |result, item|
18
- raw_attribute, raw_value = item
19
- result[replaced_attribute_name(raw_attribute, @attributes_to_replace).to_s] = replaced_attribute_value(raw_attribute, raw_value, @attributes_to_replace, @raw_filters)
20
- result
21
- end
22
- result.merge(parsed_filters)
23
- end
24
-
25
- def filter_parsers
26
- @filter_parsers ||= filters.map do |raw_attribute, raw_value|
27
- FilterParser.new(raw_attribute, raw_value, @attributes_to_replace, @raw_filters)
28
- end
29
- end
30
-
31
- private
32
-
33
- def parsed_filters
34
- filter_parsers_hash.inject({}) do |result, item|
35
- attribute, filter_parser = item
36
-
37
- result[attribute] = filter_parser.value
38
-
39
- result
40
- end
41
- end
42
-
43
- def filter_parsers_hash
44
- optimized_filter_parsers.inject({}) do |result, filter_parser|
45
- if result.has_key?(filter_parser.attribute)
46
- result[filter_parser.attribute].merge(filter_parser)
47
- else
48
- result[filter_parser.attribute] = filter_parser
49
- end
50
-
51
- result
52
- end
53
- end
54
-
55
- def optimized_filter_parsers
56
- if or_filter_parser
57
- filter_parsers.inject([]) do |result, filter_parser|
58
- if filter_parser != or_filter_parser && or_filter_parser.include?(filter_parser)
59
- or_filter_parser.merge(filter_parser)
60
- else
61
- result << filter_parser
62
- end
63
-
64
- result
65
- end
66
- else
67
- filter_parsers
68
- end
69
- end
70
-
71
- def or_filter_parser
72
- @or_filter_parser ||= filter_parsers.select { |filter_parser| filter_parser.or_attribute? }.first
73
- end
74
- end
75
- end
76
- end
77
- end
@@ -1,28 +0,0 @@
1
- module Mongoid
2
- module QueryStringInterface
3
- module Parsers
4
- class NumberParser
5
- def parseable?(value, operator)
6
- integer?(value) or float?(value)
7
- end
8
-
9
- def parse(value)
10
- if integer?(value)
11
- value.to_i
12
- elsif float?(value)
13
- value.to_f
14
- end
15
- end
16
-
17
- private
18
- def integer?(value)
19
- value =~ /^\d+$/
20
- end
21
-
22
- def float?(value)
23
- value =~ /^(\d+)(\.?\d*)$/
24
- end
25
- end
26
- end
27
- end
28
- end
@@ -1,17 +0,0 @@
1
- module Mongoid
2
- module QueryStringInterface
3
- module Parsers
4
- class RegexParser
5
- def parseable?(value, operator)
6
- value =~ /^\/(.*)\/(i|m|x)?$/
7
- end
8
-
9
- def parse(value)
10
- if value =~ /^\/(.*)\/(i|m|x)?$/
11
- eval($&)
12
- end
13
- end
14
- end
15
- end
16
- end
17
- end