mongoid_query_string_interface 0.7.1 → 0.7.2

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/Gemfile CHANGED
@@ -11,6 +11,6 @@ platforms :mri_18 do
11
11
  end
12
12
 
13
13
  platforms :mri_19 do
14
- gem "ruby-debug19", :require => 'ruby-debug' if RUBY_VERSION < "1.9.3"
14
+ gem "debugger"
15
15
  gem 'simplecov', :require => false
16
16
  end
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mongoid_query_string_interface (0.7.1)
4
+ mongoid_query_string_interface (0.7.2)
5
5
  mongoid (>= 2.0.2)
6
6
  query_string_interface (>= 0.5.0)
7
7
  will_paginate (~> 3.0.pre2)
@@ -9,31 +9,35 @@ PATH
9
9
  GEM
10
10
  remote: http://rubygems.org/
11
11
  specs:
12
- activemodel (3.2.6)
13
- activesupport (= 3.2.6)
12
+ activemodel (3.2.12)
13
+ activesupport (= 3.2.12)
14
14
  builder (~> 3.0.0)
15
- activesupport (3.2.6)
15
+ activesupport (3.2.12)
16
16
  i18n (~> 0.6)
17
17
  multi_json (~> 1.0)
18
- archive-tar-minitar (0.5.2)
19
18
  bson (1.3.1)
20
19
  bson_ext (1.3.1)
21
- builder (3.0.0)
20
+ builder (3.0.4)
22
21
  columnize (0.3.4)
23
22
  database_cleaner (0.6.7)
23
+ debugger (1.5.0)
24
+ columnize (>= 0.3.1)
25
+ debugger-linecache (~> 1.2.0)
26
+ debugger-ruby_core_source (~> 1.2.0)
27
+ debugger-linecache (1.2.0)
28
+ debugger-ruby_core_source (1.2.0)
24
29
  diff-lcs (1.1.2)
25
- i18n (0.6.0)
30
+ i18n (0.6.4)
26
31
  linecache (0.46)
27
32
  rbx-require-relative (> 0.0.4)
28
- linecache19 (0.5.12)
29
- ruby_core_source (>= 0.1.4)
30
- mongo (1.3.1)
31
- bson (>= 1.3.1)
32
- mongoid (2.4.11)
33
- activemodel (~> 3.1)
34
- mongo (<= 1.6.2)
33
+ mongoid (3.1.2)
34
+ activemodel (~> 3.2)
35
+ moped (~> 1.4.2)
36
+ origin (~> 1.0)
35
37
  tzinfo (~> 0.3.22)
36
- multi_json (1.3.6)
38
+ moped (1.4.3)
39
+ multi_json (1.7.0)
40
+ origin (1.0.11)
37
41
  query_string_interface (0.5.0)
38
42
  activesupport (>= 3.0.0)
39
43
  rake (0.8.7)
@@ -51,21 +55,11 @@ GEM
51
55
  ruby-debug-base (~> 0.10.4.0)
52
56
  ruby-debug-base (0.10.4)
53
57
  linecache (>= 0.3)
54
- ruby-debug-base19 (0.11.25)
55
- columnize (>= 0.3.1)
56
- linecache19 (>= 0.5.11)
57
- ruby_core_source (>= 0.1.4)
58
- ruby-debug19 (0.11.6)
59
- columnize (>= 0.3.1)
60
- linecache19 (>= 0.5.11)
61
- ruby-debug-base19 (>= 0.11.19)
62
- ruby_core_source (0.1.5)
63
- archive-tar-minitar (>= 0.5.2)
64
58
  simplecov (0.4.2)
65
59
  simplecov-html (~> 0.4.4)
66
60
  simplecov-html (0.4.5)
67
- tzinfo (0.3.33)
68
- will_paginate (3.0.3)
61
+ tzinfo (0.3.37)
62
+ will_paginate (3.0.4)
69
63
 
70
64
  PLATFORMS
71
65
  ruby
@@ -74,9 +68,9 @@ DEPENDENCIES
74
68
  bson
75
69
  bson_ext
76
70
  database_cleaner (>= 0.5.0)
71
+ debugger
77
72
  mongoid_query_string_interface!
78
73
  rake (= 0.8.7)
79
74
  rspec (>= 2.3.0)
80
75
  ruby-debug
81
- ruby-debug19
82
76
  simplecov
@@ -0,0 +1,24 @@
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
@@ -0,0 +1,28 @@
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
+ regex_parser.parse(item) or item
14
+ end
15
+ end
16
+
17
+ private
18
+ def regex_parser
19
+ @regex_parser ||= RegexParser.new
20
+ end
21
+
22
+ def conditional_operators
23
+ @conditional_operators ||= Mongoid::QueryStringInterface::ARRAY_CONDITIONAL_OPERATORS.map { |o| "$#{o}" }
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,30 @@
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
@@ -0,0 +1,17 @@
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
@@ -0,0 +1,158 @@
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::DateTimeParser.new,
19
+ Mongoid::QueryStringInterface::Parsers::NumberParser.new,
20
+ Mongoid::QueryStringInterface::Parsers::ArrayParser.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
@@ -0,0 +1,77 @@
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
@@ -0,0 +1,28 @@
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
@@ -0,0 +1,17 @@
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
@@ -91,7 +91,7 @@ module Mongoid
91
91
  end
92
92
 
93
93
  def collection_name_in_pagination_result
94
- model_name.human.underscore.pluralize.to_sym
94
+ model_name.human.underscore.pluralize.gsub(/\s/, "_").to_sym
95
95
  end
96
96
  end
97
97
  end
@@ -1,6 +1,6 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc
3
3
  module QueryStringInterface #:nodoc
4
- VERSION = "0.7.1"
4
+ VERSION = "0.7.2"
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid_query_string_interface
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.7.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-20 00:00:00.000000000Z
12
+ date: 2013-03-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: query_string_interface
16
- requirement: &2164829240 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,15 @@ dependencies:
21
21
  version: 0.5.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *2164829240
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.5.0
25
30
  - !ruby/object:Gem::Dependency
26
31
  name: will_paginate
27
- requirement: &2164828760 !ruby/object:Gem::Requirement
32
+ requirement: !ruby/object:Gem::Requirement
28
33
  none: false
29
34
  requirements:
30
35
  - - ~>
@@ -32,10 +37,15 @@ dependencies:
32
37
  version: 3.0.pre2
33
38
  type: :runtime
34
39
  prerelease: false
35
- version_requirements: *2164828760
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 3.0.pre2
36
46
  - !ruby/object:Gem::Dependency
37
47
  name: mongoid
38
- requirement: &2164828280 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
39
49
  none: false
40
50
  requirements:
41
51
  - - ! '>='
@@ -43,10 +53,15 @@ dependencies:
43
53
  version: 2.0.2
44
54
  type: :runtime
45
55
  prerelease: false
46
- version_requirements: *2164828280
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 2.0.2
47
62
  - !ruby/object:Gem::Dependency
48
63
  name: rspec
49
- requirement: &2164827800 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
50
65
  none: false
51
66
  requirements:
52
67
  - - ! '>='
@@ -54,10 +69,15 @@ dependencies:
54
69
  version: 2.3.0
55
70
  type: :development
56
71
  prerelease: false
57
- version_requirements: *2164827800
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: 2.3.0
58
78
  - !ruby/object:Gem::Dependency
59
79
  name: database_cleaner
60
- requirement: &2164827320 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
61
81
  none: false
62
82
  requirements:
63
83
  - - ! '>='
@@ -65,7 +85,12 @@ dependencies:
65
85
  version: 0.5.0
66
86
  type: :development
67
87
  prerelease: false
68
- version_requirements: *2164827320
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: 0.5.0
69
94
  description: Gives a method that can parse query string parameters into a set of criterias
70
95
  that Mongoid can use to perform actual queries in MongoDB databases for a given
71
96
  model.
@@ -77,8 +102,16 @@ extra_rdoc_files: []
77
102
  files:
78
103
  - lib/mongoid/paginate.rb
79
104
  - lib/mongoid/query_string_interface.rb
80
- - lib/mongoid_query_string_interface.rb
105
+ - lib/mongoid/helpers.rb
106
+ - lib/mongoid/parsers/date_time_parser.rb
107
+ - lib/mongoid/parsers/filters_parser.rb
108
+ - lib/mongoid/parsers/regex_parser.rb
109
+ - lib/mongoid/parsers/boolean_and_nil_parser.rb
110
+ - lib/mongoid/parsers/array_parser.rb
111
+ - lib/mongoid/parsers/filter_parser.rb
112
+ - lib/mongoid/parsers/number_parser.rb
81
113
  - lib/version.rb
114
+ - lib/mongoid_query_string_interface.rb
82
115
  - MIT_LICENSE
83
116
  - README.md
84
117
  - Gemfile
@@ -103,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
136
  version: 1.3.6
104
137
  requirements: []
105
138
  rubyforge_project: mongoid_query_string_interface
106
- rubygems_version: 1.8.15
139
+ rubygems_version: 1.8.25
107
140
  signing_key:
108
141
  specification_version: 3
109
142
  summary: An interface for performing queries in MongoDB using query string parameters.