Permalink
Browse files

provide Rack::Request#update_param and Rack::Request#delete_param

  • Loading branch information...
seamusabshere committed May 1, 2012
1 parent 6496241 commit 02c4ecd2d45e9d4686579035a92e5bfd30cab013
Showing with 101 additions and 1 deletion.
  1. +24 −1 lib/rack/request.rb
  2. +77 −0 test/spec_request.rb
View
@@ -217,10 +217,31 @@ def POST
end
# The union of GET and POST data.
+ #
+ # Note that modifications will not be persisted in the env. Use update_param or delete_param if you want to destructively modify params.
def params
@params ||= self.GET.merge(self.POST)
rescue EOFError
- self.GET
+ self.GET.dup
+ end
+
+ # Destructively update a parameter, whether it's in GET and/or POST. Returns nil.
+ #
+ # The parameter is added to both GET and POST to reduce confusion.
+ def update_param(k, v)
+ self.GET[k] = v
+ self.POST[k] = v
+ @params = nil
+ nil
+ end
+
+ # Destructively delete a parameter, whether it's in GET or POST. Returns the value of the deleted parameter.
+ #
+ # If the parameter is in both GET and POST, the POST value takes precedence since that's how #params works.
+ def delete_param(k)
+ v = [ self.POST.delete(k), self.GET.delete(k) ].compact.first
+ @params = nil
+ v
end
# shortcut for request.params[key]
@@ -229,6 +250,8 @@ def [](key)
end
# shortcut for request.params[key] = value
+ #
+ # Note that modifications will not be persisted in the env. Use update_param or delete_param if you want to destructively modify params.
def []=(key, value)
params[key.to_s] = value
end
View
@@ -411,6 +411,83 @@
req.cookies.should.equal 'foo' => 'bar'
end
+ should "not modify the params hash in place" do
+ e = Rack::MockRequest.env_for("")
+ req1 = Rack::Request.new(e)
+ req1.params.should.equal({})
+ req1.params['foo'] = 'bar'
+ req1.params.should.equal 'foo' => 'bar'
+ req2 = Rack::Request.new(e)
+ req2.params.should.equal({})
+ end
+
+ should "modify params hash if param is in GET" do
+ e = Rack::MockRequest.env_for("?foo=duh")
+ req1 = Rack::Request.new(e)
+ req1.params.should.equal 'foo' => 'duh'
+ req1.update_param 'foo', 'bar'
+ req1.params.should.equal 'foo' => 'bar'
+ req2 = Rack::Request.new(e)
+ req2.params.should.equal 'foo' => 'bar'
+ end
+
+ should "modify params hash if param is in POST" do
+ e = Rack::MockRequest.env_for("", "REQUEST_METHOD" => 'POST', :input => 'foo=duh')
+ req1 = Rack::Request.new(e)
+ req1.params.should.equal 'foo' => 'duh'
+ req1.update_param 'foo', 'bar'
+ req1.params.should.equal 'foo' => 'bar'
+ req2 = Rack::Request.new(e)
+ req2.params.should.equal 'foo' => 'bar'
+ end
+
+ should "modify params hash, even if param didn't exist before" do
+ e = Rack::MockRequest.env_for("")
+ req1 = Rack::Request.new(e)
+ req1.params.should.equal({})
+ req1.update_param 'foo', 'bar'
+ req1.params.should.equal 'foo' => 'bar'
+ req2 = Rack::Request.new(e)
+ req2.params.should.equal 'foo' => 'bar'
+ end
+
+ should "modify params hash, even if param is defined in both POST and GET" do
+ e = Rack::MockRequest.env_for("?foo=duhget", "REQUEST_METHOD" => 'POST', :input => "foo=duhpost")
+ req1 = Rack::Request.new(e)
+ req1.GET.should.equal 'foo' => 'duhget'
+ req1.POST.should.equal 'foo' => 'duhpost'
+ req1.params.should.equal 'foo' => 'duhpost'
+ req1.update_param 'foo', 'bar'
+ req1.GET.should.equal 'foo' => 'bar'
+ req1.POST.should.equal 'foo' => 'bar'
+ req1.params.should.equal 'foo' => 'bar'
+ req2 = Rack::Request.new(e)
+ req2.GET.should.equal 'foo' => 'bar'
+ req2.POST.should.equal 'foo' => 'bar'
+ req2.params.should.equal 'foo' => 'bar'
+ req2.params.should.equal 'foo' => 'bar'
+ end
+
+ should "allow deleting from params hash if param is in GET" do
+ e = Rack::MockRequest.env_for("?foo=bar")
+ req1 = Rack::Request.new(e)
+ req1.params.should.equal 'foo' => 'bar'
+ req1.delete_param('foo').should.equal 'bar'
+ req1.params.should.equal({})
+ req2 = Rack::Request.new(e)
+ req2.params.should.equal({})
+ end
+
+ should "allow deleting from params hash if param is in POST" do
+ e = Rack::MockRequest.env_for("", "REQUEST_METHOD" => 'POST', :input => 'foo=bar')
+ req1 = Rack::Request.new(e)
+ req1.params.should.equal 'foo' => 'bar'
+ req1.delete_param('foo').should.equal 'bar'
+ req1.params.should.equal({})
+ req2 = Rack::Request.new(e)
+ req2.params.should.equal({})
+ end
+
should "raise any errors on every request" do
req = Rack::Request.new Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=%")
2.times { proc { req.cookies }.should.raise(ArgumentError) }

0 comments on commit 02c4ecd

Please sign in to comment.