aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Kemper <jeremy@bitsweat.net>2006-12-29 01:18:09 +0000
committerJeremy Kemper <jeremy@bitsweat.net>2006-12-29 01:18:09 +0000
commit4e57ac35443759778bd6c1fcfd29e8bd85e9d15d (patch)
treed1414e69479fcc0807d4e57f3c86b624f1981ebe
parentf9f84d9f6dea72cae4fc8e31448df408caccbd59 (diff)
downloadrails-4e57ac35443759778bd6c1fcfd29e8bd85e9d15d.tar.gz
rails-4e57ac35443759778bd6c1fcfd29e8bd85e9d15d.tar.bz2
rails-4e57ac35443759778bd6c1fcfd29e8bd85e9d15d.zip
Query string support. Closes #6855.
git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@5804 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
-rw-r--r--activeresource/CHANGELOG4
-rw-r--r--activeresource/lib/active_resource/base.rb44
-rw-r--r--activeresource/test/base_test.rb22
3 files changed, 64 insertions, 6 deletions
diff --git a/activeresource/CHANGELOG b/activeresource/CHANGELOG
index a9bb625781..3a2d70c387 100644
--- a/activeresource/CHANGELOG
+++ b/activeresource/CHANGELOG
@@ -1,5 +1,9 @@
*SVN*
+* Query string support. [untext, Jeremy Kemper]
+ # GET /forums/1/topics.xml?sort=created_at
+ Topic.find(:all, :forum_id => 1, :sort => 'created_at')
+
* Base#==, eql?, and hash methods. == returns true if its argument is identical to self or if it's an instance of the same class, is not new?, and has the same id. eql? is an alias for ==. hash delegates to id. [Jeremy Kemper]
* Allow subclassed resources to share the site info [Rick, Jeremy Kemper]
diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb
index a8918b1eee..8c4d82c421 100644
--- a/activeresource/lib/active_resource/base.rb
+++ b/activeresource/lib/active_resource/base.rb
@@ -1,4 +1,6 @@
require 'active_resource/connection'
+require 'cgi'
+require 'set'
module ActiveResource
class Base
@@ -29,7 +31,7 @@ module ActiveResource
attr_accessor_with_default(:element_name) { to_s.underscore }
attr_accessor_with_default(:collection_name) { element_name.pluralize }
attr_accessor_with_default(:primary_key, 'id')
-
+
def prefix(options={})
default = site.path
default << '/' unless default[-1..-1] == '/'
@@ -38,21 +40,29 @@ module ActiveResource
end
def prefix=(value = '/')
- prefix_call = value.gsub(/:\w+/) { |s| "\#{options[#{s}]}" }
- method_decl = %(def self.prefix(options={}) "#{prefix_call}" end)
- eval method_decl
+ @prefix_parameters = Set.new
+ prefix_call = value.gsub(/:\w+/) do |key|
+ @prefix_parameters << key[1..-1].to_sym
+ "\#{options[#{key}]}"
+ end
+ method_decl = %(def prefix(options={}) "#{prefix_call}" end)
+ instance_eval method_decl, __FILE__, __LINE__
+ rescue
+ logger.error "Couldn't set prefix: #{$!}\n #{method_decl}"
+ raise
end
+
alias_method :set_prefix, :prefix=
alias_method :set_element_name, :element_name=
alias_method :set_collection_name, :collection_name=
def element_path(id, options = {})
- "#{prefix(options)}#{collection_name}/#{id}.xml"
+ "#{prefix(options)}#{collection_name}/#{id}.xml#{query_string(options)}"
end
def collection_path(options = {})
- "#{prefix(options)}#{collection_name}.xml"
+ "#{prefix(options)}#{collection_name}.xml#{query_string(options)}"
end
alias_method :set_primary_key, :primary_key=
@@ -88,6 +98,28 @@ module ActiveResource
def create_site_uri_from(site)
site.is_a?(URI) ? site.dup : URI.parse(site)
end
+
+ def query_string(options)
+ # Omit parameters which appear in the URI path.
+ query_params = options.reject { |key, value| @prefix_parameters.include?(key) }
+
+ # Accumulate a list of escaped key=value pairs for the given parameters.
+ pairs = []
+ query_params.each do |key, value|
+ key = CGI.escape(key.to_s)
+
+ # a => b becomes a=b
+ # a => [b, c] becomes a[]=b&a[]=c
+ case value
+ when Array
+ value.each { |val| pairs << "#{key}[]=#{CGI.escape(val.to_s)}" }
+ else
+ pairs << "#{key}=#{CGI.escape(value.to_s)}"
+ end
+ end
+
+ "?#{pairs * '&'}" unless pairs.empty?
+ end
end
attr_accessor :attributes
diff --git a/activeresource/test/base_test.rb b/activeresource/test/base_test.rb
index b036e1d346..bfc8a9fb68 100644
--- a/activeresource/test/base_test.rb
+++ b/activeresource/test/base_test.rb
@@ -82,14 +82,34 @@ class BaseTest < Test::Unit::TestCase
assert_equal '/people.xml', Person.collection_path
end
+ def test_collection_path_with_parameters
+ assert_equal '/people.xml?gender=male', Person.collection_path(:gender => 'male')
+ assert_equal '/people.xml?gender=false', Person.collection_path(:gender => false)
+ assert_equal '/people.xml?gender=', Person.collection_path(:gender => nil)
+
+ assert_equal '/people.xml?gender=male', Person.collection_path('gender' => 'male')
+ assert_equal '/people.xml?student=true&gender=male', Person.collection_path(:gender => 'male', :student => true)
+
+ assert_equal '/people.xml?name[]=bob&name[]=your+uncle%2Bme&name[]=&name[]=false', Person.collection_path(:name => ['bob', 'your uncle+me', nil, false])
+ end
+
def test_custom_element_path
assert_equal '/people/1/addresses/1.xml', StreetAddress.element_path(1, :person_id => 1)
end
+ def test_custom_element_path_with_parameters
+ assert_equal '/people/1/addresses/1.xml?type=work', StreetAddress.element_path(1, :person_id => 1, :type => 'work')
+ assert_equal '/people/1/addresses/1.xml?type[]=work&type[]=play+time', StreetAddress.element_path(1, :person_id => 1, :type => ['work', 'play time'])
+ end
+
def test_custom_collection_path
assert_equal '/people/1/addresses.xml', StreetAddress.collection_path(:person_id => 1)
end
+ def test_custom_collection_path_with_parameters
+ assert_equal '/people/1/addresses.xml?type=work', StreetAddress.collection_path(:person_id => 1, :type => 'work')
+ end
+
def test_custom_element_name
assert_equal 'address', StreetAddress.element_name
end
@@ -108,11 +128,13 @@ class BaseTest < Test::Unit::TestCase
def test_prefix
assert_equal "/", Person.prefix
+ assert_equal Set.new, Person.instance_variable_get('@prefix_parameters')
end
def test_custom_prefix
assert_equal '/people//', StreetAddress.prefix
assert_equal '/people/1/', StreetAddress.prefix(:person_id => 1)
+ assert_equal [:person_id].to_set, StreetAddress.instance_variable_get('@prefix_parameters')
end
def test_find_by_id