Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Addition of ActiveRecord-like convenience methods

  • Loading branch information...
commit 6bdd72ccadccee1ec18e4b7200532006bd6036eb 1 parent b2fb5da
@DenzelMorris DenzelMorris authored
View
18 lib/active_resource/base.rb
@@ -891,6 +891,11 @@ def all(*args)
find(:all, *args)
end
+ def where(clauses = {})
+ raise ArgumentError, "expected a clauses Hash, got #{clauses.inspect}" unless clauses.is_a? Hash
+ find(:all, :params => clauses)
+ end
+
# Deletes the resources with the ID in the +id+ parameter.
#
@@ -943,14 +948,14 @@ def find_every(options)
begin
case from = options[:from]
when Symbol
- instantiate_collection(get(from, options[:params]))
+ instantiate_collection(get(from, options[:params]), options[:params])
when String
path = "#{from}#{query_string(options[:params])}"
- instantiate_collection(format.decode(connection.get(path, headers).body) || [])
+ instantiate_collection(format.decode(connection.get(path, headers).body) || [], options[:params])
else
prefix_options, query_options = split_options(options[:params])
path = collection_path(prefix_options, query_options)
- instantiate_collection( (format.decode(connection.get(path, headers).body) || []), prefix_options )
+ instantiate_collection( (format.decode(connection.get(path, headers).body) || []), query_options, prefix_options )
end
rescue ActiveResource::ResourceNotFound
# Swallowing ResourceNotFound exceptions and return nil - as per
@@ -977,8 +982,11 @@ def find_single(scope, options)
instantiate_record(format.decode(connection.get(path, headers).body), prefix_options)
end
- def instantiate_collection(collection, prefix_options = {})
- collection_parser.new(collection).collect! { |record| instantiate_record(record, prefix_options) }
+ def instantiate_collection(collection, original_params = {}, prefix_options = {})
+ parser = collection_parser.new(collection)
+ parser.resource_class = self
+ parser.original_params = original_params
+ parser.collect! { |record| instantiate_record(record, prefix_options) }
end
def instantiate_record(record, prefix_options = {})
View
14 lib/active_resource/collection.rb
@@ -1,4 +1,5 @@
require 'active_support/core_ext/module/delegation'
+require 'active_support/inflector'
module ActiveResource # :nodoc:
class Collection # :nodoc:
@@ -6,7 +7,7 @@ class Collection # :nodoc:
delegate :to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?, :to_ary, :size, :last, :first, :[], :to => :to_a
# The array of actual elements returned by index actions
- attr_accessor :elements
+ attr_accessor :elements, :resource_class, :original_params
# ActiveResource::Collection is a wrapper to handle parsing index responses that
# do not directly map to Rails conventions.
@@ -69,5 +70,16 @@ def collect!
end
alias map! collect!
+ def first_or_create(attributes = {})
+ first || resource_class.create(original_params.update(attributes))
+ rescue NoMethodError
+ raise "Cannot create resource from resource type: #{resource_class.inspect}"
+ end
+
+ def first_or_initialize(attributes = {})
+ first || resource_class.build(original_params.update(attributes))
+ rescue NoMethodError
+ raise "Cannot build resource from resource type: #{resource_class.inspect}"
+ end
end
end
View
40 test/cases/collection_test.rb
@@ -8,9 +8,26 @@ class BasicCollectionTest < CollectionTest
def test_collection_respond_to_collect!
assert @collection.respond_to?(:collect!)
end
+
def test_collection_respond_to_map!
assert @collection.respond_to?(:map!)
end
+
+ def test_collection_respond_to_first_or_create
+ assert @collection.respond_to?(:first_or_create)
+ end
+
+ def test_collection_respond_to_first_or_initialize
+ assert @collection.respond_to?(:first_or_initialize)
+ end
+
+ def test_first_or_create_without_resource_class_raises_error
+ assert_raise(RuntimeError) { @collection.first_or_create }
+ end
+
+ def test_first_or_initialize_without_resource_class_raises_error
+ assert_raise(RuntimeError) { @collection.first_or_initialize }
+ end
def test_collect_bang_modifies_elements
elements = %w(a b c)
@@ -51,18 +68,41 @@ def setup
@posts_hash = {"results" => [@post], :next_page => '/paginated_posts.json?page=2'}
@posts = @posts_hash.to_json
@posts2 = {"results" => [@post.merge({:id => 2})], :next_page => nil}.to_json
+
+ @empty_posts = { "results" => [], :next_page => nil }.to_json
+ @new_post = { :id => nil, :title => nil }.to_json
ActiveResource::HttpMock.respond_to do |mock|
mock.get '/paginated_posts.json', {}, @posts
+ mock.get '/paginated_posts/new.json', {}, @new_post
mock.get '/paginated_posts.json?page=2', {}, @posts
+ mock.get '/paginated_posts.json?title=test', {}, @empty_posts
+ mock.post '/paginated_posts.json', {}, nil
end
end
def test_setting_collection_parser
assert_kind_of PaginatedCollection, PaginatedPost.find(:all)
end
+
+ def test_setting_collection_parser_resource_class
+ assert_equal PaginatedPost, PaginatedPost.where(:page => 2).resource_class
+ end
+
+ def test_setting_collection_parser_original_params
+ assert_equal({:page => 2}, PaginatedPost.where(:page => 2).original_params)
+ end
def test_custom_accessor
assert_equal PaginatedPost.find(:all).next_page, @posts_hash[:next_page]
end
+ def test_first_or_create
+ post = PaginatedPost.where(:title => 'test').first_or_create
+ assert post.valid?
+ end
+
+ def test_first_or_initialize
+ post = PaginatedPost.where(:title => 'test').first_or_initialize
+ assert post.valid?
+ end
end
Please sign in to comment.
Something went wrong with that request. Please try again.