gin 1.2.0 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,12 @@
1
+ === 1.2.1 / 2014-03-12
2
+
3
+ * Minor Enhancements
4
+ * Controller.autocast_params to determine if/which params should be typecast
5
+ * Warn when sprockets isn't found and asset pipeline is enabled
6
+
7
+ * Bugfixes
8
+ * Fix for numeric and boolean param parsing
9
+
1
10
  === 1.2.0 / 2013-11-18
2
11
 
3
12
  * Major Enhancements
data/lib/gin.rb CHANGED
@@ -3,7 +3,7 @@ require 'rack'
3
3
  require 'tilt'
4
4
 
5
5
  class Gin
6
- VERSION = '1.2.0'
6
+ VERSION = '1.2.1'
7
7
 
8
8
  LIB_DIR = File.expand_path("..", __FILE__) #:nodoc:
9
9
  PUBLIC_DIR = File.expand_path("../../public/", __FILE__) #:nodoc:
@@ -1134,6 +1134,13 @@ class Gin::App
1134
1134
  w.run
1135
1135
  w.wait
1136
1136
  end
1137
+
1138
+ rescue LoadError => e
1139
+ raise e unless e =~ /sprockets/
1140
+ logger << "\nWARNING: #{self.class} asset pipelining is enabled but the \
1141
+ sprockets gem wasn't found.\nIf you want asset pipelining turned off, add the \
1142
+ following to your #{self.class} definition:
1143
+ asset_pipeline false\n\n"
1137
1144
  end
1138
1145
 
1139
1146
 
@@ -69,12 +69,14 @@ class Gin::Controller
69
69
 
70
70
  def self.inherited subclass
71
71
  subclass.setup
72
+ subclass.autocast_params self.autocast_params
72
73
  super
73
74
  end
74
75
 
75
76
 
76
77
  def self.setup # :nodoc:
77
78
  @layout = nil
79
+ @autocast_params = true
78
80
  @ctrl_name = Gin.underscore(self.to_s).gsub(/_?controller_?/,'')
79
81
  end
80
82
 
@@ -178,6 +180,47 @@ class Gin::Controller
178
180
  end
179
181
 
180
182
 
183
+ ##
184
+ # Define if params should be cast to autodetected types.
185
+ # This is an inherited attribute.
186
+ # * Passing a boolean turns auto-casting on or off for all params.
187
+ # * Passing a hash with :only or :except limits auto-casting to the
188
+ # given param names
189
+ # By default all params are cast to their autodetected types.
190
+ #
191
+ # autocast_params true # enabled for all params
192
+ # autocast_params false # disabled for all params
193
+ # autocast_params except: [:zip, :phone, :fax]
194
+ # autocast_params only: [:timestamp, :age]
195
+ #
196
+ # Params get cast as follows:
197
+ # * TrueClass true
198
+ # * FalseClass: false
199
+ # * Fixnum: 1234, -1234
200
+ # * Float: 1.123, -1.123
201
+ # * String: Everything else, including numbers that start with a 0
202
+
203
+ def self.autocast_params arg=nil
204
+ if Hash === arg && Hash === @autocast_params
205
+ arg.each do |k, v|
206
+ if @autocast_params[k]
207
+ @autocast_params[k] |= [*v]
208
+ else
209
+ @autocast_params[k] = [*v]
210
+ end
211
+ end
212
+
213
+ elsif arg == true || arg == false
214
+ @autocast_params = arg
215
+
216
+ elsif Hash === arg
217
+ @autocast_params = arg.dup
218
+ end
219
+
220
+ return @autocast_params
221
+ end
222
+
223
+
181
224
  class_rproxy :controller_name, :actions
182
225
 
183
226
  # The Gin::App instance used by the controller. The App instance is meant for
@@ -203,6 +246,7 @@ class Gin::Controller
203
246
  @env = env
204
247
  @request = Gin::Request.new env
205
248
  @response = Gin::Response.new
249
+ @request.autocast_params = self.class.autocast_params
206
250
  end
207
251
 
208
252
 
@@ -1,9 +1,13 @@
1
1
  class Gin::Request < Rack::Request
2
2
  include Gin::Constants
3
3
 
4
+ attr_accessor :autocast_params # :nodoc:
5
+
4
6
  def initialize env
7
+ @params = nil
8
+ @params_processed = false
9
+ @autocast_params = true
5
10
  super
6
- self.params.update env[GIN_PATH_PARAMS] if env[GIN_PATH_PARAMS]
7
11
  end
8
12
 
9
13
 
@@ -28,7 +32,12 @@ class Gin::Request < Rack::Request
28
32
 
29
33
 
30
34
  def params
31
- @params ||= process_params(super) || {}
35
+ return @params if @params_processed
36
+ @params = super
37
+ @params.update @env[GIN_PATH_PARAMS] if @env[GIN_PATH_PARAMS]
38
+ @params = process_params(@params)
39
+ @params_processed = true
40
+ @params
32
41
  end
33
42
 
34
43
 
@@ -45,19 +54,23 @@ class Gin::Request < Rack::Request
45
54
 
46
55
  private
47
56
 
48
- M_BOOLEAN = /^true|false$/ #:nodoc:
49
- M_FLOAT = /^-?([^0]\d+|\d)\.\d+$/ #:nodoc:
50
- M_INTEGER = /^-?([^0]\d+|\d)$/ #:nodoc:
57
+ M_BOOLEAN = /^(true|false)$/ #:nodoc:
58
+ M_FLOAT = /^-?([1-9]\d+|\d)\.\d+$/ #:nodoc:
59
+ M_INTEGER = /^-?([1-9]\d+|\d)$/ #:nodoc:
51
60
 
52
61
  ##
53
62
  # Enable string or symbol key access to the nested params hash.
54
63
  # Make String numbers into Numerics.
55
64
 
56
65
  def process_params object
66
+ return object unless @autocast_params
67
+
57
68
  case object
58
69
  when Hash
59
70
  new_hash = Gin::StrictHash.new
60
- object.each { |key, value| new_hash[key] = process_params(value) }
71
+ object.each do |key, value|
72
+ new_hash[key] = process_param?(key) ? process_params(value) : value
73
+ end
61
74
  new_hash
62
75
  when Array
63
76
  object.map { |item| process_params(item) }
@@ -71,4 +84,17 @@ class Gin::Request < Rack::Request
71
84
  object
72
85
  end
73
86
  end
87
+
88
+
89
+ def process_param? name
90
+ if Hash === @autocast_params
91
+ return false if @autocast_params[:except] &&
92
+ @autocast_params[:except].include?(name.to_sym)
93
+
94
+ return @autocast_params[:only].include?(name.to_sym) if
95
+ @autocast_params[:only]
96
+ end
97
+
98
+ !!@autocast_params
99
+ end
74
100
  end
@@ -132,6 +132,109 @@ class ControllerTest < Test::Unit::TestCase
132
132
  end
133
133
 
134
134
 
135
+ def test_autocast_params
136
+ rack_env['QUERY_STRING'] =
137
+ 'id=456&foo=bar&bar=5&bool=true&nbool=truefalse&zip=01234&nint=m3&nflt=01.123&neg=-12&negf=-2.1'
138
+
139
+ klass = Class.new(AppController)
140
+ params = klass.new(@app, rack_env).params
141
+
142
+ assert_equal true, params['bool']
143
+ assert_equal 'truefalse', params['nbool']
144
+ assert_equal 'bar', params['foo']
145
+ assert_equal 5, params['bar']
146
+ assert_equal '01234', params['zip']
147
+ assert_equal 'm3', params['nint']
148
+ assert_equal '01.123', params['nflt']
149
+ assert_equal -12, params['neg']
150
+ assert_equal -2.1, params['negf']
151
+ end
152
+
153
+
154
+ def test_autocast_params_off
155
+ rack_env['QUERY_STRING'] =
156
+ 'id=456&foo=bar&bar=5&bool=true&nbool=truefalse&zip=01234&nint=m3&nflt=01.123&neg=-12&negf=-2.1'
157
+
158
+ klass = Class.new(AppController)
159
+ klass.autocast_params false
160
+ params = klass.new(@app, rack_env).params
161
+
162
+ assert_equal 'true', params['bool']
163
+ assert_equal 'truefalse', params['nbool']
164
+ assert_equal 'bar', params['foo']
165
+ assert_equal '5', params['bar']
166
+ assert_equal '01234', params['zip']
167
+ assert_equal 'm3', params['nint']
168
+ assert_equal '01.123', params['nflt']
169
+ assert_equal '-12', params['neg']
170
+ assert_equal '-2.1', params['negf']
171
+ end
172
+
173
+
174
+ def test_autocast_params_only
175
+ rack_env['QUERY_STRING'] =
176
+ 'foo=bar&bar=5&bool=true&nbool=truefalse&zip=01234&nint=m3&nflt=01.123&neg=-12&negf=-2.1'
177
+
178
+ klass = Class.new(AppController)
179
+ klass.autocast_params :only => [:bool, :bar, :zip]
180
+ params = klass.new(@app, rack_env).params
181
+
182
+ assert_equal true, params['bool']
183
+ assert_equal 'truefalse', params['nbool']
184
+ assert_equal 'bar', params['foo']
185
+ assert_equal 5, params['bar']
186
+ assert_equal '01234', params['zip']
187
+ assert_equal 'm3', params['nint']
188
+ assert_equal '01.123', params['nflt']
189
+ assert_equal '-12', params['neg']
190
+ assert_equal '-2.1', params['negf']
191
+ end
192
+
193
+
194
+ def test_autocast_params_except
195
+ rack_env['QUERY_STRING'] =
196
+ 'id=456&foo=bar&bar=5&bool=true&nbool=truefalse&zip=01234&nint=m3&nflt=01.123&neg=-12&negf=-2.1'
197
+
198
+ klass = Class.new(AppController)
199
+ klass.autocast_params :except => [:bool, :bar, :zip]
200
+ params = klass.new(@app, rack_env).params
201
+
202
+ assert_equal 'true', params['bool']
203
+ assert_equal 'truefalse', params['nbool']
204
+ assert_equal 'bar', params['foo']
205
+ assert_equal '5', params['bar']
206
+ assert_equal '01234', params['zip']
207
+ assert_equal 'm3', params['nint']
208
+ assert_equal '01.123', params['nflt']
209
+ assert_equal -12, params['neg']
210
+ assert_equal -2.1, params['negf']
211
+ end
212
+
213
+
214
+ def test_autocast_params_inherit
215
+ rack_env['QUERY_STRING'] =
216
+ 'foo=bar&bar=5&bool=true&nbool=truefalse&zip=01234&nint=m3&nflt=01.123&neg=-12&negf=-2.1'
217
+
218
+ klass = Class.new(AppController)
219
+ klass.autocast_params :only => [:bool, :bar, :zip]
220
+
221
+ subklass = Class.new(klass)
222
+ subklass.autocast_params :only => :neg
223
+
224
+ params = klass.new(@app, rack_env).params
225
+
226
+ assert_equal true, params['bool']
227
+ assert_equal 5, params['bar']
228
+ assert_equal '-12', params['neg']
229
+
230
+ params = subklass.new(@app, rack_env).params
231
+
232
+ assert_equal true, params['bool']
233
+ assert_equal 5, params['bar']
234
+ assert_equal -12, params['neg']
235
+ end
236
+
237
+
135
238
  def test_class_layout
136
239
  assert_equal :foo, BarController.layout
137
240
  assert_equal :foo, AppController.layout
@@ -7,8 +7,8 @@ class RequestTest < Test::Unit::TestCase
7
7
  'HTTP_HOST' => 'example.com',
8
8
  'rack.input' => '',
9
9
  'QUERY_STRING' =>
10
- 'id=456&foo=bar&bar=5&bool=true&zip=01234&nflt=01.123&neg=-12&negf=-2.1',
11
- 'gin.path_query_hash' => {'id' => 123},
10
+ 'id=456&foo=bar&bar=5&bool=true&nbool=truefalse&zip=01234&nint=m3&nflt=01.123&neg=-12&negf=-2.1',
11
+ 'gin.path_query_hash' => {'id' => 123, 'age' => '22'},
12
12
  }
13
13
  @req = Gin::Request.new @env
14
14
  end
@@ -16,9 +16,55 @@ class RequestTest < Test::Unit::TestCase
16
16
 
17
17
  def test_query_hash_as_param
18
18
  assert_equal 123, @req.params['id']
19
+ assert_equal 22, @req.params['age']
20
+ assert_equal true, @req.params['bool']
21
+ assert_equal 'truefalse', @req.params['nbool']
19
22
  assert_equal 'bar', @req.params['foo']
20
23
  assert_equal 5, @req.params['bar']
21
24
  assert_equal '01234', @req.params['zip']
25
+ assert_equal 'm3', @req.params['nint']
26
+ assert_equal '01.123', @req.params['nflt']
27
+ assert_equal -12, @req.params['neg']
28
+ assert_equal -2.1, @req.params['negf']
29
+ end
30
+
31
+
32
+ def test_query_hash_as_param_w_autocast_off
33
+ @req.autocast_params = false
34
+ assert_equal '22', @req.params['age']
35
+ assert_equal 'true', @req.params['bool']
36
+ assert_equal 'bar', @req.params['foo']
37
+ assert_equal '5', @req.params['bar']
38
+ assert_equal '01234', @req.params['zip']
39
+ assert_equal 'm3', @req.params['nint']
40
+ assert_equal '01.123', @req.params['nflt']
41
+ assert_equal '-12', @req.params['neg']
42
+ assert_equal '-2.1', @req.params['negf']
43
+ end
44
+
45
+
46
+ def test_query_hash_as_param_w_autocast_only
47
+ @req.autocast_params = {:only => [:age, :bool, :zip]}
48
+ assert_equal 22, @req.params['age']
49
+ assert_equal true, @req.params['bool']
50
+ assert_equal 'bar', @req.params['foo']
51
+ assert_equal '5', @req.params['bar']
52
+ assert_equal '01234', @req.params['zip']
53
+ assert_equal 'm3', @req.params['nint']
54
+ assert_equal '01.123', @req.params['nflt']
55
+ assert_equal '-12', @req.params['neg']
56
+ assert_equal '-2.1', @req.params['negf']
57
+ end
58
+
59
+
60
+ def test_query_hash_as_param_w_autocast_except
61
+ @req.autocast_params = {:except => [:age, :bool, :zip]}
62
+ assert_equal '22', @req.params['age']
63
+ assert_equal 'true', @req.params['bool']
64
+ assert_equal 'bar', @req.params['foo']
65
+ assert_equal 5, @req.params['bar']
66
+ assert_equal '01234', @req.params['zip']
67
+ assert_equal 'm3', @req.params['nint']
22
68
  assert_equal '01.123', @req.params['nflt']
23
69
  assert_equal -12, @req.params['neg']
24
70
  assert_equal -2.1, @req.params['negf']
@@ -74,6 +120,7 @@ class RequestTest < Test::Unit::TestCase
74
120
  assert_equal false, @req.send(:process_params, "false")
75
121
  assert_equal 1, @req.send(:process_params, "1")
76
122
  assert_equal 1.1, @req.send(:process_params, "1.1")
123
+ assert_equal "w1", @req.send(:process_params, "w1")
77
124
  assert_equal "not_true", @req.send(:process_params, "not_true")
78
125
 
79
126
  ary = @req.send(:process_params, ["true", "1", "foo"])
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gin
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-11-19 00:00:00.000000000 Z
12
+ date: 2014-03-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
@@ -232,7 +232,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
232
232
  version: '0'
233
233
  segments:
234
234
  - 0
235
- hash: -366786020832610929
235
+ hash: -1291900085741485412
236
236
  required_rubygems_version: !ruby/object:Gem::Requirement
237
237
  none: false
238
238
  requirements: