gin 1.2.0 → 1.2.1

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