muster 0.0.10 → 0.0.11

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.
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