Skip to content
Browse files

Merge pull request #2 from technoweenie/resource-handling

Resource handling enhancements
  • Loading branch information...
2 parents 3c9e7d8 + 123da27 commit 2e4865d131be9c51f37fc6d678be36c2eb942ed3 @pengwynn pengwynn committed Nov 6, 2012
Showing with 98 additions and 8 deletions.
  1. +6 −1 lib/sawyer/relation.rb
  2. +50 −5 lib/sawyer/resource.rb
  3. +1 −2 lib/sawyer/response.rb
  4. +17 −0 test/relation_test.rb
  5. +14 −0 test/resource_test.rb
  6. +10 −0 test/response_test.rb
View
7 lib/sawyer/relation.rb
@@ -82,7 +82,12 @@ def self.from_links(agent, index, rels = Map.new)
#
# Returns a Relation.
def self.from_link(agent, name, options)
- new agent, name, options[:href], options[:method]
+ case options
+ when Hash
+ new agent, name, options[:href], options[:method]
+ when String
+ new agent, name, options
+ end
end
# A Relation represents an available next action for a resource.
View
55 lib/sawyer/resource.rb
@@ -2,19 +2,22 @@ module Sawyer
class Resource
SPECIAL_METHODS = Set.new(%w(agent rels fields))
attr_reader :_agent, :_rels, :_fields
+ attr_reader :attrs
+ alias to_hash attrs
# Initializes a Resource with the given data.
#
# agent - The Sawyer::Agent that made the API request.
# data - Hash of key/value properties.
- def initialize(agent, data)
+ def initialize(agent, data = {})
@_agent = agent
@_rels = Relation.from_links(agent, data.delete(:_links))
@_fields = Set.new
@_metaclass = (class << self; self; end)
+ @attrs = {}
data.each do |key, value|
@_fields << key
- instance_variable_set "@#{key}", process_value(value)
+ @attrs[key.to_sym] = process_value(value)
end
@_metaclass.send(:attr_accessor, *data.keys)
end
@@ -42,6 +45,29 @@ def key?(key)
@_fields.include? key
end
+ # Allow fields to be retrieved via Hash notation
+ #
+ # method - key name
+ #
+ # Returns the value from attrs if exists
+ def [](method)
+ send(method.to_sym)
+ rescue NoMethodError
+ nil
+ end
+
+ # Allow fields to be set via Hash notation
+ #
+ # method - key name
+ # value - value to set for the attr key
+ #
+ # Returns - value
+ def []=(method, value)
+ send("#{method}=", value)
+ rescue NoMethodError
+ nil
+ end
+
ATTR_SETTER = '='.freeze
ATTR_PREDICATE = '?'.freeze
@@ -51,9 +77,9 @@ def method_missing(method, *args)
if suffix == ATTR_SETTER
@_metaclass.send(:attr_accessor, attr_name)
@_fields << attr_name.to_sym
- instance_variable_set("@#{attr_name}", args.first)
- elsif @_fields.include?(attr_name.to_sym)
- value = instance_variable_get("@#{attr_name}")
+ send(method, args.first)
+ elsif attr_name && @_fields.include?(attr_name.to_sym)
+ value = @attrs[attr_name.to_sym]
case suffix
when nil
@_metaclass.send(:attr_accessor, attr_name)
@@ -66,6 +92,25 @@ def method_missing(method, *args)
super
end
end
+
+ # Wire up accessor methods to pull from attrs
+ def self.attr_accessor(*attrs)
+ attrs.each do |attribute|
+ class_eval do
+ define_method attribute do
+ @attrs[attribute.to_sym]
+ end
+
+ define_method "#{attribute}=" do |value|
+ @attrs[attribute.to_sym] = value
+ end
+
+ define_method "#{attribute}?" do
+ !!@attrs[attribute.to_sym]
+ end
+ end
+ end
+ end
end
end
View
3 lib/sawyer/response.rb
@@ -29,8 +29,7 @@ def process_data(data)
when Hash then Resource.new(agent, data)
when Array then data.map { |hash| process_data(hash) }
when nil then nil
- else
- raise ArgumentError, "Unable to process #{data.inspect}. Want a Hash or Array"
+ else data
end
end
View
17 test/relation_test.rb
@@ -28,6 +28,23 @@ def test_builds_multiple_rels_from_multiple_methods
assert_kind_of URITemplate, rel.href_template
end
+ def test_builds_rels_from_hash
+ index = {
+ 'self' => '/users/1'
+ }
+
+ rels = Sawyer::Relation.from_links(nil, index)
+
+ assert_equal 1, rels.size
+ assert_equal [:self], rels.keys
+ assert rel = rels[:self]
+ assert_equal :self, rel.name
+ assert_equal '/users/1', rel.href
+ assert_equal :get, rel.method
+ assert_equal [:get], rel.available_methods.to_a
+ assert_kind_of URITemplate, rel.href_template
+ end
+
def test_builds_rels_from_hash_index
index = {
'self' => {:href => '/users/1'}
View
14 test/resource_test.rb
@@ -95,5 +95,19 @@ def test_dynamic_attribute_methods_from_setter
assert res.respond_to?(:b)
assert res.respond_to?(:b=)
end
+
+ def test_attrs
+ res = Resource.new :agent, :a => 1
+ hash = {:a => 1 }
+ assert_equal hash, res.attrs
+ end
+
+ def test_handle_hash_notation_with_string_key
+ res = Resource.new :agent, :a => 1
+ assert_equal 1, res['a']
+
+ res[:b] = 2
+ assert_equal 2, res.b
+ end
end
end
View
10 test/response_test.rb
@@ -16,6 +16,11 @@ def setup
}
)]
end
+
+ stub.get '/emails' do
+ emails = %w(rick@example.com technoweenie@example.com)
+ [200, {'Content-Type' => 'application/json'}, Sawyer::Agent.encode(emails)]
+ end
end
end
@@ -55,6 +60,11 @@ def test_makes_request_from_relation
assert_equal 201, res.status
assert_nil res.data
end
+
+ def test_handles_arrays_of_strings
+ res = @agent.call(:get, '/emails')
+ assert_equal 'rick@example.com', res.data.first
+ end
end
end

0 comments on commit 2e4865d

Please sign in to comment.
Something went wrong with that request. Please try again.