Permalink
Browse files

Start integration with iO Me. Added some missing parts, for example b…

…eing able to wrap inside a domain model.
  • Loading branch information...
1 parent 5bf9c72 commit c5b5ab4adf899dd094f9dda9c79289675dadf4fd @mlangenberg committed Apr 4, 2012
Showing with 106 additions and 10 deletions.
  1. +22 −4 lib/ahora/representation.rb
  2. +12 −3 lib/ahora/resource.rb
  3. +68 −3 test/ahora_test.rb
  4. +4 −0 test/fixtures/user_posts.xml
@@ -9,8 +9,18 @@ module Ahora
class Representation < Nibbler
INTEGER_PARSER = lambda { |node| Integer(node.content) if node.content.present? }
DATE_PARSER = lambda { |node| Date.parse(node.content) if node.content.present? }
+ TIME_PARSER = lambda { |node| Time.parse(node.content) if node.content.present? } # TEST
+ BOOL_PARSER = lambda { |node| node.content.to_s.downcase == 'true' if node.content.present? } # TEST
module Definition
+ def element(*)
+ name = super
+ define_method name.to_s+'?' do
+ !!name
+ end
+ name
+ end
+
def attribute(*names)
names = names.flatten
parser = names.pop if names.last.is_a?(Proc)
@@ -48,6 +58,14 @@ def integer(*names)
def date(*names)
attribute(names, DATE_PARSER)
end
+
+ # FIXME test
+ def time(*names)
+ attribute(names, TIME_PARSER)
+ end
+ def boolean(*names)
+ attribute(names, BOOL_PARSER)
+ end
end
extend Definition
@@ -66,8 +84,8 @@ def initialize(doc_or_atts = {})
class Collection < DelegateClass(Array)
attr_reader :cache_key
- def initialize(klass, document_parser, response)
- @klass = klass
+ def initialize(instantiator, document_parser, response)
+ @instantiator = instantiator
@document_parser = document_parser
@response = response
@cache_key = response.env[:url].to_s
@@ -102,8 +120,8 @@ def [](*)
private
def kicker
__setobj__ doc.search("/*[@type='array']/*").map { |element|
- @klass.parse element
- }.to_a
+ @instantiator.call element
+ }.to_a.compact
end
def doc
View
@@ -22,10 +22,19 @@ def connection
end
# @abstract override to use custom Faraday middleware
- def extend_middleware; end;
+ def extend_middleware(builder); end;
- def collection(klass, response)
- Collection.new klass, document_parser, response
+ def collection(*args, &block)
+ if args.size == 2
+ klass, response = args
+ instantiator = lambda do |doc|
+ klass.parse(doc)
+ end
+ else
+ response = args.first
+ instantiator = block
+ end
+ Collection.new instantiator, document_parser, response
end
private
View
@@ -61,9 +61,40 @@ class Post < Ahora::Representation
element 'user', :with => Ahora::Representation do
string :first_name, :last_name
end
+ boolean :hidden
elements 'replies/userPost' => :replies, :with => Post
end
+class PostDomainRepository < PostRepository
+ def find_by_user_id(id)
+ collection PostDomain, get("/users/#{id}/posts.xml")
+ end
+end
+
+class PostDomain < DelegateClass(Post)
+ def self.parse(doc)
+ post = Post.parse(doc)
+ post.hidden ? nil : new(post)
+ end
+
+ def initialize(post)
+ super(post)
+ end
+
+ def published?
+ created_at < Date.today
+ end
+end
+
+class BlogPostRepository < PostRepository
+ include Ahora::Resource
+
+ def all
+ collection get("/users/1/posts.xml") do |doc|
+ Post.parse(doc)
+ end
+ end
+end
describe "requesting a collection" do
before do
@@ -72,7 +103,7 @@ class Post < Ahora::Representation
end
it "has the right size" do
- @posts.size.must_equal 1
+ @posts.size.must_equal 2
end
it "has a cache key" do
@@ -86,6 +117,10 @@ class Post < Ahora::Representation
subject.body.must_equal "How is everybody today?"
end
+ it "generates a questionmark method" do
+ subject.body?.must_equal true
+ end
+
it "renames foreign element names and converts integers" do
subject.id.must_equal 1
subject.user_id.must_equal 1
@@ -126,8 +161,8 @@ class Post < Ahora::Representation
end
it "caches when response header includes Last-Modified" do
- @repository.find_by_user_id(1).size.must_equal(1)
- @posts = @repository.find_by_user_id(1).size.must_equal(1)
+ @repository.find_by_user_id(1).size.must_equal(2)
+ @posts = @repository.find_by_user_id(1).size.must_equal(2)
end
end
@@ -141,11 +176,41 @@ class Post < Ahora::Representation
fake_http '/users/1/posts.xml', fixture('user_posts')
@posts = PostRepository.new.find_by_user_id(1)
end
+
+ it "should work the same for domain layer type models" do
+ fake_http '/users/1/posts.xml', fixture('user_posts')
+ PostDomainRepository.new.find_by_user_id(1)
+ end
end
describe "creating a new instance" do
it "allows to create a new instance with an attribute hash" do
p = Post.new :body => 'hi'
p.body.must_equal 'hi'
end
+end
+
+describe "being wrapped by a domain layer" do
+ before do
+ fake_http '/users/1/posts.xml', fixture('user_posts')
+ @posts = PostDomainRepository.new.find_by_user_id(1)
+ @post = @posts.first
+ end
+
+ it "handles a collection" do
+ @post.published?.must_equal true
+ @post.user.first_name.must_equal 'John'
+ end
+
+ it "allows filtering by letting the instantiator return nil" do
+ @posts.size.must_equal 1
+ end
+end
+
+describe "passing a block instead of a class to collection" do
+ it "returns the parsed document" do
+ fake_http '/users/1/posts.xml', fixture('user_posts')
+ repository = BlogPostRepository.new
+ repository.all.first.id.must_equal 1
+ end
end
@@ -1,6 +1,7 @@
<?xml version="1.0"?>
<userPosts type="array">
<userPost>
+ <hidden>false</hidden>
<objectId>1</objectId>
<userObjectId>1</userObjectId>
<user>
@@ -35,4 +36,7 @@
</userPost>
</replies>
</userPost>
+ <userPost>
+ <hidden>true</hidden>
+ </userPost>
</userPosts>

0 comments on commit c5b5ab4

Please sign in to comment.