ahora 0.0.4 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f0985b57a670034c7945f5e36a9cc90101bf8f83
4
- data.tar.gz: d0092b586366a543d87a11cec7b739c325fb7f50
3
+ metadata.gz: 1cb06d2658dbbeb7b3ef608c0a075f6bf231a841
4
+ data.tar.gz: 70f9af7383998d3f989e2403d4576a1a087cb92d
5
5
  SHA512:
6
- metadata.gz: 51b4dfac648230d1fd5e0e1623045e38ead1401db50509e6b982b1cd4a6b59b93e240c0dd9ce95329a139104745267db76307b0569258bfb64313cc21033b3e6
7
- data.tar.gz: 1e388b5863a1f2a9808c3b1a59040464a1b35386296ad0d81afb53f578320da1b9b4745cf21b604430c695bf7b194551737e965d608d189f2a552ac98010af80
6
+ metadata.gz: 790ee4e933c2fa58e003f4ab6cf982680da6df0f6ba8861fa9749158cda98a7d10b0b1c51b07748601969c9f2efda1b85baaef154ca7685c9093033a8b388bbd
7
+ data.tar.gz: 3348a8dc3dc622b57521061cfbb219c8a2559b27f9456dd477297390df787a9c51ad59339cad49b732fd3386b8b5e1fe0531169115779d1f204ab684b5f4c6d3
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Matthijs Langenberg and other contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/ahora.gemspec CHANGED
@@ -11,6 +11,7 @@ Gem::Specification.new do |s|
11
11
  s.homepage = ""
12
12
  s.summary = %q{Consume Java-ish XML HTTP Resources easily}
13
13
  s.description = %q{Consume Java-ish XML HTTP Resources easily}
14
+ s.license = 'MIT'
14
15
 
15
16
  s.files = `git ls-files`.split("\n")
16
17
  s.test_files = `git ls-files -- {test}/*`.split("\n")
@@ -20,7 +21,6 @@ Gem::Specification.new do |s|
20
21
  s.add_dependency "nibbler", '>= 1.3.0'
21
22
  s.add_dependency "faraday", '>= 0.7'
22
23
  s.add_dependency "nokogiri", "~> 1.5"
23
- s.add_dependency "activesupport"
24
24
 
25
25
  s.add_development_dependency "fakeweb"
26
26
  s.add_development_dependency "minitest"
@@ -1,3 +1,5 @@
1
+ require 'time'
2
+
1
3
  module Ahora
2
4
  module Middleware
3
5
  class LastModifiedCaching < Faraday::Middleware
@@ -1,17 +1,19 @@
1
1
  require 'nibbler'
2
2
  require 'nokogiri'
3
+ require 'time'
3
4
  require 'date'
4
- require 'active_support/core_ext/string'
5
5
  require 'delegate'
6
+ require 'digest/sha1'
6
7
 
7
8
  module Ahora
8
9
  class Representation < Nibbler
9
- INTEGER_PARSER = lambda { |node| Integer(node.content) if node.content.present? }
10
- FLOAT_PARSER = lambda { |node| Float(node.content) if node.content.present? }
11
- DATE_PARSER = lambda { |node| Date.parse(node.content) if node.content.present? }
12
- TIME_PARSER = lambda { |node| Time.parse(node.content) if node.content.present? }
13
- BOOL_PARSER =
14
- lambda { |node| node.content.to_s.downcase == 'true' if node.content.present? }
10
+ present = lambda { |obj| obj && !obj.empty? }
11
+
12
+ INTEGER_PARSER = lambda { |node| Integer(node.content) if present.call(node.content) }
13
+ FLOAT_PARSER = lambda { |node| Float(node.content) if present.call(node.content) }
14
+ DATE_PARSER = lambda { |node| Date.parse(node.content) if present.call(node.content) }
15
+ TIME_PARSER = lambda { |node| Time.parse(node.content) if present.call(node.content) }
16
+ BOOL_PARSER = lambda { |node| node.content.to_s.downcase == 'true' }
15
17
 
16
18
  module Definition
17
19
  def element(*)
@@ -26,13 +28,20 @@ module Ahora
26
28
  names = names.flatten
27
29
  parser = names.pop if names.last.is_a?(Proc)
28
30
  names.each do |name|
29
- selector = name
30
- selector, name = name.first if name.is_a? Hash
31
- selector = "./#{selector.to_s.camelcase(:lower)}"
31
+ if Hash === name
32
+ selector, name = name.first
33
+ else
34
+ selector = attribute_selector(name)
35
+ end
32
36
  element selector => name.to_s, :with => parser
33
37
  end
34
38
  end
35
39
 
40
+ # override in subclasses for e.g. camelCase support
41
+ def attribute_selector(name)
42
+ name.to_s
43
+ end
44
+
36
45
  def string(*names)
37
46
  attribute(names)
38
47
  end
@@ -87,28 +96,30 @@ module Ahora
87
96
  end
88
97
  end
89
98
 
90
- class Collection < DelegateClass(Array)
91
- NoCacheKeyAvailable = Class.new(StandardError)
99
+ class Response < DelegateClass(Ahora::Representation)
92
100
  def initialize(instantiator, document_parser, response)
93
101
  @instantiator = instantiator
94
102
  @document_parser = document_parser
95
103
  @response = response
96
- super([])
104
+ super(target)
97
105
  end
98
106
 
99
- %w( to_s to_a size each first last [] inspect pretty_print find detect map collect inject select select! delete_if ).each do |method_name|
100
- eval "def #{method_name}(*); kicker; super; end"
107
+ def target
108
+ @instantiator.call @document_parser.call(@response.body)
101
109
  end
102
110
 
103
- private
104
- def kicker
105
- @_collection ||= __setobj__ doc.search("/*[@type='array']/*").map { |element|
106
- @instantiator.call element
107
- }.to_a.compact
111
+ def cache_key
112
+ uri = @response.env[:url].dup
113
+ uri.host = @response.env['HTTP_HOST'] if @response.env['HTTP_HOST']
114
+ "#{Digest::SHA1.hexdigest(uri.normalize.to_s)}/#{Digest::SHA1.hexdigest(@response.body)}"
108
115
  end
116
+ end
109
117
 
110
- def doc
111
- @document_parser.call(@response.body)
118
+ class Collection < Response
119
+ def target
120
+ @document_parser.call(@response.body).search("/*[@type='array']/*").map { |element|
121
+ @instantiator.call element
122
+ }.to_a.compact
112
123
  end
113
124
  end
114
125
 
@@ -63,6 +63,18 @@ module Ahora
63
63
  end
64
64
 
65
65
  def collection(*args, &block)
66
+ instantiator, response = extract_parser_from_args(*args, &block)
67
+ Collection.new instantiator, document_parser, response
68
+ end
69
+
70
+ def single(*args, &block)
71
+ instantiator, response = extract_parser_from_args(*args, &block)
72
+ Response.new instantiator, document_parser, response
73
+ end
74
+
75
+ private
76
+
77
+ def extract_parser_from_args(*args, &block)
66
78
  if args.size == 2
67
79
  klass, response = args
68
80
  instantiator = lambda do |doc|
@@ -72,11 +84,9 @@ module Ahora
72
84
  response = args.first
73
85
  instantiator = block
74
86
  end
75
- Collection.new instantiator, document_parser, response
87
+ [instantiator, response]
76
88
  end
77
89
 
78
- private
79
-
80
90
  def document_parser
81
91
  @document_parser ||= XmlParser.method(:parse)
82
92
  end
data/lib/ahora/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Ahora
2
- VERSION = "0.0.4"
3
- end
2
+ VERSION = "0.1.0"
3
+ end
data/test/ahora_test.rb CHANGED
@@ -31,6 +31,10 @@ class PostRepository
31
31
  collection Post, get("/users/#{id}/posts.xml")
32
32
  end
33
33
 
34
+ def find_by_user_id_and_post_id(user_id, id)
35
+ single PostDomain, get("/users/#{user_id}/posts/#{id}.xml")
36
+ end
37
+
34
38
  def extend_middleware(builder)
35
39
  builder.use Faraday::Request::BasicAuthentication, USERNAME, PASSWORD
36
40
  builder.use Ahora::Middleware::LastModifiedCaching, MemCache.instance
@@ -42,6 +46,14 @@ class PostRepository
42
46
  end
43
47
 
44
48
  class Post < Ahora::Representation
49
+ def self.attribute_selector(name)
50
+ "./#{name.to_s.gsub(/_([a-z])/){ $1.upcase }}"
51
+ end
52
+
53
+ def self.base_parser_class
54
+ Post
55
+ end
56
+
45
57
  element './objectId' => :id, :with => lambda {|n| n.content.to_i }
46
58
  element './userObjectId' => :user_id, :with => lambda {|n| n.content.to_i }
47
59
  element './parentObjectId' => :parent_id, :with => lambda {|n| n.content.to_i }
@@ -95,6 +107,10 @@ describe "requesting a collection" do
95
107
  @posts.size.must_equal 2
96
108
  end
97
109
 
110
+ it "has a cache key" do
111
+ @posts.cache_key.must_equal 'd630281e7b240892745b975d6b3ff9abe4fb3064/c7244914c7109201527c1b59930b64d242eca842'
112
+ end
113
+
98
114
  describe "a single post from the collection" do
99
115
  subject { @posts.first }
100
116
 
@@ -140,6 +156,24 @@ describe "requesting a collection" do
140
156
  end
141
157
  end
142
158
 
159
+ describe 'requesting a single resource' do
160
+ before do
161
+ fake_http '/users/1/posts/2.xml', fixture('user_post')
162
+ @post = PostRepository.new.find_by_user_id_and_post_id(1, 2)
163
+ end
164
+
165
+ subject { @post }
166
+
167
+ it "has the right body" do
168
+ subject.body.must_equal "When will world see Baby Cambridge?"
169
+ end
170
+
171
+ it "has a cache key" do
172
+ subject.cache_key.must_equal 'd2c6c472195a1f74b8271c5e7ced007cf9b2821e/c9e3c5a555a38cc7f99c3cdada0e5ec02341c674'
173
+ end
174
+
175
+ end
176
+
143
177
  describe 'requesting a collection with if-modified-since support' do
144
178
  before do
145
179
  FakeWeb.register_uri :get, uri('/users/1/posts.xml'), [
@@ -207,3 +241,5 @@ describe "passing a block instead of a class to collection" do
207
241
  repository.all.first.id.must_equal 1
208
242
  end
209
243
  end
244
+
245
+
@@ -1,7 +1,7 @@
1
1
  <?xml version="1.0"?>
2
2
  <employee>
3
- <firstName>John</firstName>
4
- <isRockstar>true</isRockstar>
3
+ <first_name>John</first_name>
4
+ <is_rockstar>true</is_rockstar>
5
5
  <slacker>false</slacker>
6
6
  <rating>7.8</rating>
7
- </employee>
7
+ </employee>
@@ -0,0 +1,12 @@
1
+ <?xml version="1.0"?>
2
+ <userPost>
3
+ <hidden>false</hidden>
4
+ <objectId>1</objectId>
5
+ <userObjectId>1</userObjectId>
6
+ <user>
7
+ <firstName>John</firstName>
8
+ <lastName>Doe</lastName>
9
+ </user>
10
+ <body>When will world see Baby Cambridge?</body>
11
+ <createdAt>2011-10-26T17:01:52+02:00</createdAt>
12
+ </userPost>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ahora
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthijs Langenberg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-12 00:00:00.000000000 Z
11
+ date: 2013-07-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nibbler
@@ -52,20 +52,6 @@ dependencies:
52
52
  - - ~>
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.5'
55
- - !ruby/object:Gem::Dependency
56
- name: activesupport
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - '>='
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - '>='
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: fakeweb
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -105,6 +91,7 @@ files:
105
91
  - .travis.yml
106
92
  - AUTHORS
107
93
  - Gemfile
94
+ - LICENSE
108
95
  - README.md
109
96
  - Rakefile
110
97
  - ahora.gemspec
@@ -120,10 +107,12 @@ files:
120
107
  - test/ahora/resource_test.rb
121
108
  - test/ahora_test.rb
122
109
  - test/fixtures/employee.xml
110
+ - test/fixtures/user_post.xml
123
111
  - test/fixtures/user_posts.xml
124
112
  - test/test_helper.rb
125
113
  homepage: ''
126
- licenses: []
114
+ licenses:
115
+ - MIT
127
116
  metadata: {}
128
117
  post_install_message:
129
118
  rdoc_options: []