mongoid_query_string_interface 0.7.1 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
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.