Permalink
Browse files

Query string support. Closes #6855.

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@5804 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
jeremy committed Dec 29, 2006
1 parent f9f84d9 commit 4e57ac35443759778bd6c1fcfd29e8bd85e9d15d
Showing with 64 additions and 6 deletions.
  1. +4 −0 activeresource/CHANGELOG
  2. +38 −6 activeresource/lib/active_resource/base.rb
  3. +22 −0 activeresource/test/base_test.rb
View
@@ -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]
@@ -1,4 +1,6 @@
require 'active_resource/connection'
+require 'cgi'
+require 'set'
module ActiveResource
class Base
@@ -29,7 +31,7 @@ def connection(refresh = false)
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 @@ def prefix(options={})
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 @@ def find_single(scope, options)
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
@@ -82,14 +82,34 @@ def test_collection_path
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 @@ def test_nested_element_name
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

0 comments on commit 4e57ac3

Please sign in to comment.