muster 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 99866bb235ad97109e1b1a3d2cf79d83c24c8f80
4
- data.tar.gz: 21cd93ae1d09692932c1acb43ffd7800bbc9e3a6
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ Yzc3OThjMTE2N2JhMjI1YWNhMDQ3NDVhNGY1MDZjNDlkZDQwNjc4YQ==
5
+ data.tar.gz: !binary |-
6
+ YzUyMGVkODhjOTdjOTZiZWJhMzMwMjhmZTU5YmZhNDljMTU3MTkxNQ==
5
7
  SHA512:
6
- metadata.gz: 0e2332f2f2b14034b6298c8803277565c0820ce1f878c7526567d018cacf53d17183c44203ca622bf4565087d56c45ef3888bcf2aabeb0c607c0dcad28612d7c
7
- data.tar.gz: 63d92c6acdb5e31848d4a0d3292eb26b2507da6f8d0123f73a776f81ef4065befee3c0175c14050c792c1a140a008c3468b7c650f41dabc5c0e0adb4ddad33b1
8
+ metadata.gz: !binary |-
9
+ ZjQ4YzNjNjYzMjE4ZjlkNzg1NTNlMzFhNjAyMzA1YWJhNTMwODk2NzhmNGVj
10
+ MDQzYzA2MjU3MzgwZTIzNDVkODQyM2E3OGY0ZmYxMjhiOTZhYjY1OTNlZThh
11
+ OWU1ZjUzZjczMDQ2YWQzNGNlOGQ5NGFjNWU3ODZhMzJjYmI3YjM=
12
+ data.tar.gz: !binary |-
13
+ NjljOGJjNGEzZTFmMDI5ODAzMDMxNTU5MWI2MGJjODE5NzE3MjllZDViM2Q3
14
+ Y2ZmNGY0Y2Y0YWQwZTQ0MWU4MjgyZGY2N2UyMDc1ZmE5YjZmYzk1NjI2ZTQ5
15
+ YzAxNmJkODFhMzQyZjNjZTcyNDJhNzhkZmU2NGNjYWVkNDgxOGU=
@@ -0,0 +1,14 @@
1
+ Metrics/LineLength:
2
+ Max: 150
3
+
4
+ Style/HashSyntax:
5
+ Enabled: False
6
+
7
+ Style/IfUnlessModifier:
8
+ Enabled: False
9
+
10
+ Style/Lambda:
11
+ Enabled: False
12
+
13
+ Style/WordArray:
14
+ MinSize: 3
data/Changes CHANGED
@@ -1,3 +1,7 @@
1
+ = 0.0.11
2
+
3
+ * Massive rubocop cleanup
4
+
1
5
  = 0.0.10
2
6
 
3
7
  * Added support for 'IS NULL' queries in ActiveRecord Strategy (drydevelopment)
data/Rakefile CHANGED
@@ -1,11 +1,16 @@
1
1
  #!/usr/bin/env rake
2
- require "bundler/gem_tasks"
2
+ require 'bundler/gem_tasks'
3
3
  require 'rspec/core/rake_task'
4
4
  require 'yard'
5
5
  require 'yard/rake/yardoc_task'
6
+ require 'rubocop/rake_task'
6
7
 
7
8
  RSpec::Core::RakeTask.new(:spec) do |t|
8
9
  t.verbose = false
9
10
  end
10
11
 
12
+ RuboCop::RakeTask.new
13
+
11
14
  YARD::Rake::YardocTask.new(:yard)
15
+
16
+ task :default => [:rubocop, :spec, :yard]
@@ -2,7 +2,6 @@ require 'active_support/hash_with_indifferent_access'
2
2
  require 'rack'
3
3
 
4
4
  module Muster
5
-
6
5
  # Rack middleware plugin for Muster query string parsing
7
6
  #
8
7
  # @example
@@ -10,23 +9,22 @@ module Muster
10
9
  # app = Rack::Builder.new do
11
10
  # use Muster::Rack, Muster::Strategies::Hash, :fields => [:name, :choices]
12
11
  # end
13
- #
12
+ #
14
13
  # # GET /?name=bob&choices=1&choices=2
15
14
  # match '/' do
16
15
  # env['muster.query'] #=> {'name' => 'bob', 'choices' => ['1', '2']}
17
16
  # end
18
17
  class Rack
19
-
20
18
  # @attribute [r] app
21
19
  # @return [Object] Rack application middleware is running under
22
20
  attr_reader :app
23
-
21
+
24
22
  # @attribute [r] strategy
25
23
  # @return [Muster::Strategies::Rack] Muster Strategy to run
26
24
  attr_reader :strategy
27
-
25
+
28
26
  # @attribute [r] options
29
- # @return [Hash] options to pass to strategy
27
+ # @return [Hash] options to pass to strategy
30
28
  attr_reader :options
31
29
 
32
30
  # Key in ENV where processed query string are stored
@@ -44,10 +42,10 @@ module Muster
44
42
  # @example
45
43
  #
46
44
  # middleware = Muster::Rack.new(app, Muster::Strategies::Hash, :fields => [:name, :choices])
47
- #
45
+ #
48
46
  # strategy = Muster::Strategies::Hash.new(:fields => [:name, :choices])
49
47
  # middleware = Muster::Rack.new(app, strategy)
50
- def initialize( app, strategy, options={} )
48
+ def initialize(app, strategy, options = {})
51
49
  @app = app
52
50
  @strategy = strategy
53
51
  @options = options
@@ -58,9 +56,9 @@ module Muster
58
56
  # @param env [Hash] Rack environment
59
57
  #
60
58
  # @return [Array]
61
- def call( env )
59
+ def call(env) # rubocop:disable Metrics/AbcSize
62
60
  request = ::Rack::Request.new(env)
63
- parser = self.strategy.kind_of?(Class) ? self.strategy.new(options) : self.strategy
61
+ parser = strategy.is_a?(Class) ? strategy.new(options) : strategy
64
62
 
65
63
  env[QUERY] ||= Muster::Results.new({})
66
64
  env[QUERY].merge! parser.parse(request.query_string)
@@ -68,6 +66,5 @@ module Muster
68
66
 
69
67
  @app.call(env)
70
68
  end
71
-
72
69
  end
73
70
  end
@@ -3,7 +3,6 @@ require 'active_support/core_ext/object/blank'
3
3
  require 'active_support/hash_with_indifferent_access'
4
4
 
5
5
  module Muster
6
-
7
6
  # Query parsed results helper class
8
7
  #
9
8
  # As with most Muster classes, all hashes returned and options specified support with indifferent access.
@@ -32,7 +31,6 @@ module Muster
32
31
  # results.filtered[:select] #=> [:id, :name]
33
32
  # results.filtered.select #=> [:id, :name]
34
33
  class Results < ActiveSupport::HashWithIndifferentAccess
35
-
36
34
  # @attribute [r] data
37
35
  # @return [Hash] raw data specified during initialization
38
36
  attr_reader :data
@@ -51,7 +49,7 @@ module Muster
51
49
  #
52
50
  # data = { :select => [:id, :name, :created_at] }
53
51
  # results = Muster::Results.new(data)
54
- def initialize( data, options={} )
52
+ def initialize(data, options = {}) # rubocop:disable Lint/UnusedMethodArgument
55
53
  super(data)
56
54
 
57
55
  @data = data
@@ -83,8 +81,8 @@ module Muster
83
81
  # results.add_filter(:select, :only => [:id, :name])
84
82
  # results.add_filter(:select, :except => [:id])
85
83
  # results.add_filter(:page, 1)
86
- def add_filter( key, *options )
87
- self.filters[key] = options
84
+ def add_filter(key, *options)
85
+ filters[key] = options
88
86
  end
89
87
 
90
88
  # Returns the raw data with all of the filters applied
@@ -99,15 +97,13 @@ module Muster
99
97
  # results.add_dilter(:page, 1)
100
98
  # results.filtered #=> { 'select' => [:id, :name], 'page' => 1 }
101
99
  def filtered
102
- return self if self.filters.empty?
100
+ return self if filters.empty?
103
101
 
104
- filtered_results = self.filters.inject( {} ) do |results, (key, options)|
105
- results[key] = self.filter( key, *options )
106
-
107
- results
102
+ filtered_results = filters.each_with_object({}) do |(key, options), results|
103
+ results[key] = filter(key, *options)
108
104
  end
109
105
 
110
- return self.class.new(filtered_results)
106
+ self.class.new(filtered_results)
111
107
  end
112
108
 
113
109
  # Filters and returns the raw data values for the specifid key and options
@@ -139,31 +135,32 @@ module Muster
139
135
  # results.filter(:select, :only => [:other, :name]) #=> [:name]
140
136
  # results.filter(:other, :default) #=> :default
141
137
  # results.filter(:other) #=> KeyError
142
- def filter( key, *options )
138
+ def filter(key, *options)
143
139
  if options.present? && options.first.instance_of?(Hash)
144
140
  options = options.first.with_indifferent_access
145
141
 
146
- if options.has_key?(:only)
147
- return filter_only_values( key, options[:only] )
148
- elsif options.has_key?(:except)
149
- return filter_excluded_values( key, options[:except] )
142
+ if options.key?(:only)
143
+ return filter_only_values(key, options[:only])
144
+ elsif options.key?(:except)
145
+ return filter_excluded_values(key, options[:except])
150
146
  end
151
147
  else
152
- return self.fetch(key, *options)
148
+ return fetch(key, *options)
153
149
  end
154
150
  end
155
151
 
156
152
  private
157
153
 
154
+ # rubocop:disable Lint/NestedMethodDefinition, Metrics/MethodLength
158
155
  def method_missing(meth, *args, &block)
159
- if self.has_key?(meth)
156
+ if key?(meth)
160
157
  value = self[meth]
161
158
 
162
- if value.kind_of?(Hash)
159
+ if value.is_a?(Hash)
163
160
  value.instance_eval do
164
161
  def method_missing(meth, *args, &block)
165
- if self.has_key?(meth)
166
- return self.fetch(meth)
162
+ if key?(meth)
163
+ return fetch(meth)
167
164
  end
168
165
 
169
166
  super
@@ -173,11 +170,12 @@ module Muster
173
170
 
174
171
  return value
175
172
  end
173
+ # rubocop:enable
176
174
 
177
175
  super
178
176
  end
179
177
 
180
- def filter_excluded_values( key, excluded )
178
+ def filter_excluded_values(key, excluded)
181
179
  value = self[key]
182
180
  excluded = Array.wrap(excluded)
183
181
 
@@ -190,8 +188,8 @@ module Muster
190
188
  end
191
189
  end
192
190
 
193
- def filter_only_values( key, allowed )
194
- values = Array.wrap( self[key] )
191
+ def filter_only_values(key, allowed)
192
+ values = Array.wrap(self[key])
195
193
 
196
194
  if allowed.instance_of?(Array)
197
195
  return values & allowed
@@ -199,6 +197,5 @@ module Muster
199
197
  return allowed
200
198
  end
201
199
  end
202
-
203
200
  end
204
201
  end
@@ -9,7 +9,6 @@ require 'muster/strategies/joins_expression'
9
9
 
10
10
  module Muster
11
11
  module Strategies
12
-
13
12
  # Query string parsing strategy that outputs ActiveRecord Query compatible options
14
13
  #
15
14
  # @example
@@ -21,7 +20,6 @@ module Muster
21
20
  # #
22
21
  # # Person.select( results[:select] ).where( results[:where] ).order( results[:order] )
23
22
  class ActiveRecord < Muster::Strategies::Rack
24
-
25
23
  # Processes a query string and returns a hash of its fields/values
26
24
  #
27
25
  # @param query_string [String] the query string to parse
@@ -33,22 +31,22 @@ module Muster
33
31
  # results = strategy.parse('select=id,name&where=status:new&order=name:desc')
34
32
  #
35
33
  # # { 'select' => ['id', 'name'], :where => {'status' => 'new}, :order => 'name desc' }
36
- def parse( query_string )
37
- pagination = self.parse_pagination( query_string )
34
+ def parse(query_string) # rubocop:disable Metrics/MethodLength
35
+ pagination = parse_pagination(query_string)
38
36
 
39
37
  parameters = Muster::Results.new(
40
- :select => self.parse_select(query_string),
41
- :order => self.parse_order(query_string),
38
+ :select => parse_select(query_string),
39
+ :order => parse_order(query_string),
42
40
  :limit => pagination[:limit],
43
41
  :offset => pagination[:offset],
44
- :where => self.parse_where(query_string),
45
- :joins => self.parse_joins(query_string),
46
- :includes => self.parse_includes(query_string)
42
+ :where => parse_where(query_string),
43
+ :joins => parse_joins(query_string),
44
+ :includes => parse_includes(query_string)
47
45
  )
48
46
 
49
47
  parameters.regular_writer('pagination', pagination[:pagination].symbolize_keys)
50
48
 
51
- return parameters
49
+ parameters
52
50
  end
53
51
 
54
52
  protected
@@ -61,12 +59,12 @@ module Muster
61
59
  #
62
60
  # @example
63
61
  #
64
- # value = self.parse_select('select=id,name') #=> ['id', 'name']
65
- def parse_select( query_string )
62
+ # value = parse_select('select=id,name') #=> ['id', 'name']
63
+ def parse_select(query_string)
66
64
  strategy = Muster::Strategies::Hash.new(:field => :select)
67
65
  results = strategy.parse(query_string)
68
66
 
69
- return Array.wrap( results[:select] )
67
+ Array.wrap(results[:select])
70
68
  end
71
69
 
72
70
  # Returns order by clauses for AR queries
@@ -77,12 +75,12 @@ module Muster
77
75
  #
78
76
  # @example
79
77
  #
80
- # value = self.parse_order('order=name:desc') #=> ['name asc']
81
- def parse_order( query_string )
78
+ # value = parse_order('order=name:desc') #=> ['name asc']
79
+ def parse_order(query_string)
82
80
  strategy = Muster::Strategies::SortExpression.new(:field => :order)
83
81
  results = strategy.parse(query_string)
84
82
 
85
- return Array.wrap( results[:order] )
83
+ Array.wrap(results[:order])
86
84
  end
87
85
 
88
86
  # Returns pagination information for AR queries
@@ -93,12 +91,10 @@ module Muster
93
91
  #
94
92
  # @example
95
93
  #
96
- # value = self.parse_pagination('page=2&page_size=10') #=> { 'pagination' => {:page => 2, :per_page => 10}, 'limit' => 10, 'offset' => 10 }
97
- def parse_pagination( query_string )
94
+ # value = parse_pagination('page=2&page_size=10') #=> { 'pagination' => {:page => 2, :per_page => 10}, 'limit' => 10, 'offset' => 10 }
95
+ def parse_pagination(query_string)
98
96
  strategy = Muster::Strategies::Pagination.new(:fields => [:pagination, :limit, :offset])
99
- results = strategy.parse(query_string)
100
-
101
- return results
97
+ strategy.parse(query_string)
102
98
  end
103
99
 
104
100
  # Returns where clauses for AR queries
@@ -111,10 +107,10 @@ module Muster
111
107
  #
112
108
  # @example
113
109
  #
114
- # value = self.parse_where('where=id:1') #=> {'id' => '1'}
115
- # value = self.parse_where('where=id:null') #=> {'id' => nil}
116
- # value = self.parse_where('where=id:nil') #=> {'id' => nil}
117
- def parse_where( query_string )
110
+ # value = parse_where('where=id:1') #=> {'id' => '1'}
111
+ # value = parse_where('where=id:null') #=> {'id' => nil}
112
+ # value = parse_where('where=id:nil') #=> {'id' => nil}
113
+ def parse_where(query_string)
118
114
  strategy = Muster::Strategies::FilterExpression.new(:field => :where)
119
115
  results = strategy.parse(query_string)
120
116
 
@@ -126,7 +122,7 @@ module Muster
126
122
  end
127
123
  end
128
124
 
129
- return results[:where] || {}
125
+ results[:where] || {}
130
126
  end
131
127
 
132
128
  # Returns joins clauses for AR queries
@@ -137,12 +133,12 @@ module Muster
137
133
  #
138
134
  # @example
139
135
  #
140
- # value = self.parse_joins('joins=authors') #=> {'joins' => 'authors'}
141
- def parse_joins( query_string )
136
+ # value = parse_joins('joins=authors') #=> {'joins' => 'authors'}
137
+ def parse_joins(query_string)
142
138
  strategy = Muster::Strategies::JoinsExpression.new(:field => :joins)
143
139
  results = strategy.parse(query_string)
144
140
 
145
- return results[:joins] || {}
141
+ results[:joins] || {}
146
142
  end
147
143
 
148
144
  # Returns includes clauses for AR queries
@@ -153,14 +149,13 @@ module Muster
153
149
  #
154
150
  # @example
155
151
  #
156
- # value = self.parse_joins('includes=authors') #=> {'includes' => 'authors'}
157
- def parse_includes( query_string )
152
+ # value = parse_joins('includes=authors') #=> {'includes' => 'authors'}
153
+ def parse_includes(query_string)
158
154
  strategy = Muster::Strategies::JoinsExpression.new(:field => :includes)
159
155
  results = strategy.parse(query_string)
160
156
 
161
- return results[:includes] || {}
157
+ results[:includes] || {}
162
158
  end
163
-
164
159
  end
165
160
  end
166
161
  end
@@ -4,7 +4,6 @@ require 'muster/strategies/hash'
4
4
 
5
5
  module Muster
6
6
  module Strategies
7
-
8
7
  # Query string parsing strategy with additional value handling options for separating filtering expressions
9
8
  #
10
9
  # @example
@@ -12,11 +11,10 @@ module Muster
12
11
  # strategy = Muster::Strategies::FilterExpression.new
13
12
  # results = strategy.parse('where=id:1&name:Bob') #=> { 'where' => {'id' => '1', 'name' => 'Bob'} }
14
13
  class FilterExpression < Muster::Strategies::Hash
15
-
16
14
  # @attribute [r] expression_separator
17
15
  # @return [String,RegEx] when specified, each field value will be split into multiple expressions using the specified separator
18
16
  attr_reader :expression_separator
19
-
17
+
20
18
  # @attribute [r] field_separator
21
19
  # @return [String,RegEx] when specified, each expression will be split into multiple field/values using the specified separator
22
20
  attr_reader :field_separator
@@ -38,7 +36,7 @@ module Muster
38
36
  #
39
37
  # strategy = Muster::Strategies::FilterExpression.new
40
38
  # strategy = Muster::Strategies::FilterExpression.new(:unique_values => false)
41
- def initialize( options={} )
39
+ def initialize(options = {})
42
40
  super
43
41
 
44
42
  @expression_separator = self.options.fetch(:expression_separator, /,\s*/)
@@ -53,93 +51,106 @@ module Muster
53
51
  # @return [Muster::Results]
54
52
  #
55
53
  # @example
56
- #
54
+ #
57
55
  # results = strategy.parse('where=id:1&name:Bob') #=> { 'where' => {'id' => '1', 'name' => 'Bob'} }
58
- def parse( query_string )
59
- parameters = Muster::Results.new( self.fields_to_parse(query_string) )
56
+ def parse(query_string)
57
+ parameters = Muster::Results.new(fields_to_parse(query_string))
60
58
 
61
59
  parameters.each do |key, value|
62
- parameters[key] = self.separate_expressions(value)
63
- parameters[key] = self.separate_fields(parameters[key])
60
+ parameters[key] = separate_expressions(value)
61
+ parameters[key] = separate_fields(parameters[key])
64
62
  end
65
63
 
66
- return parameters
64
+ parameters
67
65
  end
68
66
 
69
67
  protected
70
68
 
71
69
  # Separates values into an Array of expressions using :expression_separator
72
70
  #
73
- # @param value [String,Array] the original query string field value to separate
71
+ # @param expression [String,Array] the original query string field value to separate
74
72
  #
75
73
  # @return [String,Array] String if a single value exists, Array otherwise
76
74
  #
77
75
  # @example
78
76
  #
79
- # value = self.separate_values('where=id:1') #=> {'where' => 'id:1'}
80
- # value = self.separate_values('where=id:1,id:2') #=> {'where' => ['id:1', 'id:2']}
81
- def separate_expressions( value )
82
- values = Array.wrap(value)
77
+ # value = separate_values('where=id:1') #=> {'where' => 'id:1'}
78
+ # value = separate_values('where=id:1,id:2') #=> {'where' => ['id:1', 'id:2']}
79
+ def separate_expressions(expression)
80
+ values = Array.wrap(expression)
83
81
 
84
82
  values = values.map do |value|
85
- value.split(self.expression_separator)
83
+ value.split(expression_separator)
86
84
  end.flatten
87
85
 
88
- return (values.size > 1) ? values : values.first
86
+ (values.size > 1) ? values : values.first
89
87
  end
90
88
 
91
89
  # Separates expression field values into an Hash of expression filters using :field_separator
92
90
  #
93
- # @param value [String,Array] the expressions field value to separate
91
+ # @param values_string [String,Array] the expressions field value to separate
94
92
  #
95
93
  # @return [Hash]
96
94
  #
97
95
  # @example
98
96
  #
99
- # value = self.separate_fields('id:1') #=> {'id' => '1'}
100
- # value = self.separate_values('id:1|2') #=> {'id' => '1|2'}
101
- def separate_fields( value )
102
- values = Array.wrap(value)
103
-
97
+ # value = separate_fields('id:1') #=> {'id' => '1'}
98
+ # value = separate_values('id:1|2') #=> {'id' => '1|2'}
99
+ def separate_fields(values_string)
100
+ values = Array.wrap(values_string)
101
+
104
102
  filters = {}
105
103
 
106
104
  values.each do |value|
107
- name, value = value.split(self.field_separator, 2)
108
-
109
- if self.value_separator.present?
110
- value = self.separate_values(value)
111
- end
105
+ name, value = value.split(field_separator, 2)
106
+ value = separate_values(value)
112
107
 
113
- filters[name] = filters.has_key?(name) ? [filters[name], value].flatten : value
108
+ filters[name] = filters.key?(name) ? [filters[name], value].flatten : value
114
109
 
115
- if self.unique_values == true && filters[name].instance_of?(Array)
116
- filters[name].uniq!
117
- end
110
+ filters[name] = ensure_unique_values(filters[name])
118
111
  end
119
112
 
120
- return filters
113
+ filters
121
114
  end
122
115
 
123
116
  # Separates expression filter values into an Array of expression filter values using :value_separator
124
117
  #
125
- # @param value [String,Array] the expressions filter value to separate
118
+ # @param values_string [String,Array] the expressions filter value to separate
126
119
  #
127
120
  # @return [String,Array] String if a single value exists, Array otherwise
128
121
  #
129
122
  # @example
130
123
  #
131
- # value = self.separate_values('1') #=> '1'
132
- # value = self.separate_values('1|2') #=> ['1', '2']
133
- def separate_values( value )
134
- values = Array.wrap(value)
124
+ # value = separate_values('1') #=> '1'
125
+ # value = separate_values('1|2') #=> ['1', '2']
126
+ def separate_values(values_string)
127
+ values = Array.wrap(values_string)
135
128
 
136
129
  values = values.map do |value|
137
- value.split(self.value_separator)
130
+ value.split(value_separator)
138
131
  end.flatten
139
132
 
140
- return (values.size > 1) ? values : value
133
+ (values.size > 1) ? values : values_string
141
134
  end
142
135
 
136
+ # Ensures that if an Array is given, the values are unique if unique_values is set.
137
+ #
138
+ # @param values [String,Array] the expressions filter values to ensure are unique
139
+ #
140
+ # @return [String,Array] String if a single value exists, Array otherwise
141
+ #
142
+ # @example
143
+ #
144
+ # value = ensure_unique_values('1') #=> '1'
145
+ # value = ensure_unique_values(['1', '2']) #=> ['1', '2']
146
+ # value = ensure_unique_values(['1', '1']) #=> ['1']
147
+ def ensure_unique_values(values)
148
+ if unique_values && values.instance_of?(Array)
149
+ values.uniq
150
+ else
151
+ values
152
+ end
153
+ end
143
154
  end
144
155
  end
145
156
  end