party_resource 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # party_resource
2
+
3
+ Simple REST interface for ruby objects.
4
+
5
+ party_resource is a framework for building ruby objects which interact with a REST api. Built on top of HTTParty.
6
+
7
+ HTTParty is great for adding a couple of methods that fetch data from an HTTP api, but becomes cumbersome if you have
8
+ lots of objects that all need to connect to several routes on the api. ActiveResource doesn't give you enough control.
9
+
10
+ ## Usage
11
+
12
+ For detailed usage instructions, please see the [API Documentation](http://yardoc.org/docs/edendevelopment-party_resource).
13
+
14
+ PartyResource::Connector.add(:library, :base_uri => 'http://www.example.com/library')
15
+
16
+ class Author
17
+ include PartyResource
18
+
19
+ property :name
20
+ property :slug
21
+
22
+ connect :books, :get => '/authors/:slug/books', :as => Book, :on => :instance
23
+
24
+ def initialize(params = {})
25
+ populate_properties(params)
26
+ end
27
+ end
28
+
29
+ class Book
30
+ include PartyResource
31
+
32
+ property :title
33
+ property :author, :as => Author
34
+
35
+ connect :search, :get => '/search/:query', :with => :query
36
+
37
+ def initialize(params = {})
38
+ populate_properties(name)
39
+ end
40
+ end
41
+
42
+ book = Book.search('Lord of the Rings')
43
+
44
+ book.title #=> 'Lord of the Rings Trilogy'
45
+ book.author.class #=> Author
46
+ book.author.name #=> 'J. R. R. Tolkein'
47
+
48
+ author = book.author
49
+
50
+ author.books.map(&:title) #=> ['Lord of the Rings Trilogy', 'The Hobbit', 'The Silmarillion']
51
+
52
+ ## Issues
53
+
54
+ Please use the [github issues tracker](http://github.com/edendevelopment/party_resource/issues).
55
+
56
+ ## Note on Patches/Pull Requests
57
+
58
+ * Fork the project.
59
+ * Make your feature addition or bug fix.
60
+ * Add tests for it. This is important so I don't break it in a
61
+ future version unintentionally.
62
+ * Commit, do not mess with rakefile, version, or history.
63
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
64
+ * Send me a pull request. Bonus points for topic branches.
65
+
66
+ ## Copyright
67
+
68
+ Copyright (c) 2010 Eden Development (UK) LTD. See LICENSE for details.
@@ -13,7 +13,7 @@ module PartyResource
13
13
  def fetch(request)
14
14
  response = HTTParty.send(request.verb, request.path, request.http_data(options))
15
15
  unless (200..399).include? response.code
16
- raise PartyResource::ConnectionError.build(response)
16
+ raise PartyResource::Exceptions::ConnectionError.build(response)
17
17
  end
18
18
  response
19
19
  end
@@ -1,27 +1,29 @@
1
1
  require 'party_resource/connector/base'
2
2
  module PartyResource
3
- def self.Connector(name = nil)
4
- Connector.lookup(name)
5
- end
6
-
7
3
  module Connector
8
- def self.lookup(name)
9
- name ||= repository.default
10
- connector = repository.connectors[name]
11
- raise NoConnector.new(name) if connector.nil?
12
- connector
13
- end
4
+ class << self
5
+ # Find connector by name
6
+ # @return [Connector::Base] the requested connector
7
+ def lookup(name)
8
+ name ||= repository.default
9
+ connector = repository.connectors[name]
10
+ raise Exceptions::NoConnector.new(name) if connector.nil?
11
+ connector
12
+ end
14
13
 
15
- def self.default=(name)
16
- repository.default = name
17
- end
14
+ # Add a new named connector
15
+ def add(name, options)
16
+ repository.new_connector(name, options)
17
+ end
18
18
 
19
- def self.add(name, options)
20
- repository.new_connector(name, options)
21
- end
19
+ private
20
+ def default=(name)
21
+ repository.default = name
22
+ end
22
23
 
23
- def self.repository
24
- @repository ||= Repository.new
24
+ def repository
25
+ @repository ||= Repository.new
26
+ end
25
27
  end
26
28
 
27
29
  class Repository
@@ -1,57 +1,59 @@
1
1
  module PartyResource
2
2
 
3
- Error = Class.new(StandardError)
3
+ module Exceptions
4
+ Error = Class.new(StandardError)
4
5
 
5
- class MissingParameter < Error
6
- def initialize(parameter, context)
7
- @parameter = parameter
8
- @context = context
9
- end
6
+ class MissingParameter < Error
7
+ def initialize(parameter, context)
8
+ @parameter = parameter
9
+ @context = context
10
+ end
10
11
 
11
- def to_s
12
- "No value for #{@parameter} is available in #{@context}"
12
+ def to_s
13
+ "No value for #{@parameter} is available in #{@context}"
14
+ end
13
15
  end
14
- end
15
16
 
16
- class NoConnector < Error
17
- def initialize(name)
18
- @name = name
19
- end
17
+ class NoConnector < Error
18
+ def initialize(name)
19
+ @name = name
20
+ end
20
21
 
21
- def to_s
22
- "Connector '#{@name}' has not been defined"
22
+ def to_s
23
+ "Connector '#{@name}' has not been defined"
24
+ end
23
25
  end
24
- end
25
26
 
26
- class ConnectionError < Error;
27
- attr_reader :data
28
-
29
- def self.build(data=nil)
30
- klass = case data.code
31
- when 404: ResourceNotFound
32
- when 422: ResourceInvalid
33
- when 400..499: ClientError
34
- when 500..599: ServerError
35
- else self
27
+ class ConnectionError < Error;
28
+ attr_reader :data
29
+
30
+ def self.build(data=nil)
31
+ klass = case data.code
32
+ when 404: ResourceNotFound
33
+ when 422: ResourceInvalid
34
+ when 400..499: ClientError
35
+ when 500..599: ServerError
36
+ else self
37
+ end
38
+ klass.new(data)
36
39
  end
37
- klass.new(data)
38
- end
39
40
 
40
- def initialize(data=nil)
41
- super()
42
- @data = data
43
- end
41
+ def initialize(data=nil)
42
+ super()
43
+ @data = data
44
+ end
44
45
 
45
- def to_s
46
- code = ''
47
- code = "#{data.code} " rescue nil
48
- "A #{code}connection error occured"
46
+ def to_s
47
+ code = ''
48
+ code = "#{data.code} " rescue nil
49
+ "A #{code}connection error occured"
50
+ end
49
51
  end
50
- end
51
52
 
52
- ClientError = Class.new(ConnectionError) # 4xx
53
- ServerError = Class.new(ConnectionError) # 5xx
53
+ ClientError = Class.new(ConnectionError) # 4xx
54
+ ServerError = Class.new(ConnectionError) # 5xx
54
55
 
55
- ResourceNotFound = Class.new(ClientError) # 404
56
- ResourceInvalid = Class.new(ClientError) # 422
56
+ ResourceNotFound = Class.new(ClientError) # 404
57
+ ResourceInvalid = Class.new(ClientError) # 422
58
+ end
57
59
  end
@@ -6,6 +6,8 @@ module PartyResource
6
6
  module ClassMethods
7
7
  include MethodDefine
8
8
 
9
+ # Connect a method call to a restful uri
10
+ # @return [nil]
9
11
  def connect(name, options={})
10
12
  level = options.delete(:on)
11
13
  options = {:as => :self, :connector => @party_connector}.merge(options)
@@ -14,8 +16,35 @@ module PartyResource
14
16
  define_method_on(level, name) do |*args|
15
17
  route.call(self, *args)
16
18
  end
19
+ nil
17
20
  end
18
21
 
22
+ # Define a property
23
+ # @overload property(*names, options={})
24
+ # @param [Symbol] names list of property names
25
+ # @param [Hash] options the options to use to create the property
26
+ # @option options :as (:self) How to build property
27
+ #
28
+ # :raw - raw data
29
+ #
30
+ # :self - self.new(data)
31
+ #
32
+ # class - class.new(data)
33
+ #
34
+ # Array(class, :method) - class.method(data)
35
+ #
36
+ # lambda - lambda.call(data)
37
+ # @option options :from (property name) where to find property value in incomming data hash
38
+ #
39
+ # symbol - name
40
+ #
41
+ # array - list of nested hash keys
42
+ # @option options :to (from value) where to put property value in outgoing incomming data hash
43
+ #
44
+ # symbol - name
45
+ #
46
+ # array - list of nested hash keys
47
+ # @return [nil]
19
48
  def property(*names)
20
49
  options = names.pop if names.last.is_a?(Hash)
21
50
  names.each do |name|
@@ -26,10 +55,14 @@ module PartyResource
26
55
  @property_list ||= []
27
56
  @property_list << Property.new(name, options)
28
57
  end
58
+ nil
29
59
  end
30
60
 
61
+ # Set the name of the connector to use for this class
62
+ # @return [nil]
31
63
  def party_connector(name)
32
64
  @party_connector = name
65
+ nil
33
66
  end
34
67
 
35
68
  private
@@ -49,19 +82,22 @@ module PartyResource
49
82
  begin
50
83
  out[var] = send(var)
51
84
  rescue
52
- raise MissingParameter.new(var, self)
85
+ raise Exceptions::MissingParameter.new(var, self)
53
86
  end
54
87
  out
55
88
  end
56
89
  end
57
90
  end
58
91
 
92
+ # Converts the objects properties to a hash
93
+ # @return [Hash] a hash of all the properties
59
94
  def to_properties_hash
60
95
  self.class.send(:property_list).inject({}) do |hash, property|
61
96
  hash.merge(property.to_hash(self))
62
97
  end
63
98
  end
64
99
 
100
+ # Test if all properties are equal
65
101
  def properties_equal?(other)
66
102
  begin
67
103
  self.class.send(:property_list).all? {|property| self.send(property.name) == other.send(property.name) }
@@ -15,7 +15,7 @@ module PartyResource
15
15
  raise ArgumentError, "wrong number of arguments (#{args.size} for #{expected_args.size})" unless expected_args.size == args.size
16
16
  begin
17
17
  builder.call(connector.fetch(request(context, args, options)), context, included(context))
18
- rescue Error => e
18
+ rescue Exceptions::Error => e
19
19
  name = e.class.name.split(/::/).last
20
20
  return @options[:rescue][name] if @options[:rescue].has_key?(name)
21
21
  raise
@@ -23,7 +23,7 @@ module PartyResource
23
23
  end
24
24
 
25
25
  def connector
26
- PartyResource::Connector(@options[:connector])
26
+ PartyResource::Connector.lookup(@options[:connector])
27
27
  end
28
28
 
29
29
  private
@@ -71,22 +71,22 @@ describe TestClass do
71
71
  context 'error cases' do
72
72
  it 'raises ResourceNotFound' do
73
73
  stub_request(:delete, "http://fred:pass@myserver/path/delete").to_return(:status => 404)
74
- lambda { TestClass.destroy }.should raise_error(PartyResource::ResourceNotFound)
74
+ lambda { TestClass.destroy }.should raise_error(PartyResource::Exceptions::ResourceNotFound)
75
75
  end
76
76
 
77
77
  it 'raises ResourceInvalid' do
78
78
  stub_request(:delete, "http://fred:pass@myserver/path/delete").to_return(:status => 422)
79
- lambda { TestClass.destroy }.should raise_error(PartyResource::ResourceInvalid)
79
+ lambda { TestClass.destroy }.should raise_error(PartyResource::Exceptions::ResourceInvalid)
80
80
  end
81
81
 
82
82
  it 'raises ClientError' do
83
83
  stub_request(:delete, "http://fred:pass@myserver/path/delete").to_return(:status => 405)
84
- lambda { TestClass.destroy }.should raise_error(PartyResource::ClientError)
84
+ lambda { TestClass.destroy }.should raise_error(PartyResource::Exceptions::ClientError)
85
85
  end
86
86
 
87
87
  it 'raises ServerError' do
88
88
  stub_request(:delete, "http://fred:pass@myserver/path/delete").to_return(:status => 501)
89
- lambda { TestClass.destroy }.should raise_error(PartyResource::ServerError)
89
+ lambda { TestClass.destroy }.should raise_error(PartyResource::Exceptions::ServerError)
90
90
  end
91
91
 
92
92
  it 'rescues exceptions' do
@@ -74,7 +74,7 @@ describe PartyResource::Connector::Base do
74
74
  it 'raises an exception' do
75
75
  return_data = mock(:data, :code => 404)
76
76
  HTTParty.should_receive(:get).and_return(return_data)
77
- lambda{ subject.fetch(request) }.should raise_error(PartyResource::ConnectionError)
77
+ lambda{ subject.fetch(request) }.should raise_error(PartyResource::Exceptions::ConnectionError)
78
78
  end
79
79
  end
80
80
 
@@ -8,7 +8,7 @@ describe PartyResource::Connector do
8
8
  let(:connectors) { { :test => test_connector, :other => default_connector } }
9
9
 
10
10
  before do
11
- PartyResource::Connector.repository.stub(:connectors => connectors)
11
+ PartyResource::Connector.send(:repository).stub(:connectors => connectors)
12
12
  end
13
13
 
14
14
  it "returns the named connectors" do
@@ -16,21 +16,13 @@ describe PartyResource::Connector do
16
16
  end
17
17
 
18
18
  it "returns the default connector for nil name" do
19
- PartyResource::Connector.repository.stub(:default => :other)
19
+ PartyResource::Connector.send(:repository).stub(:default => :other)
20
20
 
21
21
  PartyResource::Connector.lookup(nil).should == default_connector
22
22
  end
23
23
 
24
24
  it 'raises a NoConnector error it the connector could not be found' do
25
- lambda { PartyResource::Connector.lookup(:missing_name) }.should raise_error(PartyResource::NoConnector)
26
- end
27
- end
28
-
29
- describe '#default=' do
30
- it 'sets the default connector name' do
31
- name = mock(:name)
32
- PartyResource::Connector.default = name
33
- PartyResource::Connector.repository.default.should == name
25
+ lambda { PartyResource::Connector.lookup(:missing_name) }.should raise_error(PartyResource::Exceptions::NoConnector)
34
26
  end
35
27
  end
36
28
 
@@ -49,16 +41,16 @@ describe PartyResource::Connector do
49
41
  it 'creates a new connector' do
50
42
  PartyResource::Connector::Base.should_receive(:new).with(name, options).and_return(connector)
51
43
  PartyResource::Connector.add(name, options)
52
- PartyResource::Connector(name).should == connector
44
+ PartyResource::Connector.lookup(name).should == connector
53
45
  end
54
46
 
55
47
  it 'sets the default if it is currently unset' do
56
48
  name2 = mock(:name2)
57
49
  PartyResource::Connector.add(name, options)
58
- PartyResource::Connector.repository.default.should == name
50
+ PartyResource::Connector.send(:repository).default.should == name
59
51
 
60
52
  PartyResource::Connector.add(name2, options)
61
- PartyResource::Connector.repository.default.should == name
53
+ PartyResource::Connector.send(:repository).default.should == name
62
54
  end
63
55
 
64
56
  it 'sets the default if the default option is set' do
@@ -2,8 +2,8 @@ require 'spec_helper'
2
2
 
3
3
  describe 'Exceptions' do
4
4
 
5
- describe PartyResource::ConnectionError do
6
- subject { PartyResource::ConnectionError }
5
+ describe PartyResource::Exceptions::ConnectionError do
6
+ subject { PartyResource::Exceptions::ConnectionError }
7
7
 
8
8
  describe 'build' do
9
9
  let(:built) { subject.build(data) }
@@ -11,22 +11,22 @@ describe 'Exceptions' do
11
11
 
12
12
  it 'builds ResourceNotFound' do
13
13
  data.stub(:code => 404)
14
- built.should be_a(PartyResource::ResourceNotFound)
14
+ built.should be_a(PartyResource::Exceptions::ResourceNotFound)
15
15
  end
16
16
 
17
17
  it 'builds ResourceInvalid' do
18
18
  data.stub(:code => 422)
19
- built.should be_a(PartyResource::ResourceInvalid)
19
+ built.should be_a(PartyResource::Exceptions::ResourceInvalid)
20
20
  end
21
21
 
22
22
  it 'builds ClientError' do
23
23
  data.stub(:code => 400)
24
- built.should be_a(PartyResource::ClientError)
24
+ built.should be_a(PartyResource::Exceptions::ClientError)
25
25
  end
26
26
 
27
27
  it 'builds ServerError' do
28
28
  data.stub(:code => 500)
29
- built.should be_a(PartyResource::ServerError)
29
+ built.should be_a(PartyResource::Exceptions::ServerError)
30
30
  end
31
31
  end
32
32
  end
@@ -84,25 +84,6 @@ describe "PartyResource" do
84
84
  end
85
85
  end
86
86
 
87
- describe '.Connector' do
88
- context 'with name == nil' do
89
- it 'returns the default connector' do
90
- connector = mock(:connector)
91
- PartyResource::Connector.should_receive(:lookup).with(nil).and_return(connector)
92
- PartyResource::Connector(nil).should == connector
93
- end
94
- end
95
-
96
- context 'with a name given' do
97
- it 'returns the requested connector' do
98
- connector = mock(:connector)
99
- name = mock(:name)
100
- PartyResource::Connector.should_receive(:lookup).with(name).and_return(connector)
101
- PartyResource::Connector(name).should == connector
102
- end
103
- end
104
- end
105
-
106
87
  describe '.parameter_values' do
107
88
  let_mock(:v1)
108
89
  let_mock(:v2)
@@ -114,7 +95,7 @@ describe "PartyResource" do
114
95
 
115
96
  it 'raises a MissingParameter error' do
116
97
  subject.stub(:v1 => v1)
117
- lambda { subject.parameter_values([:v1, :vx]) }.should raise_error(PartyResource::MissingParameter)
98
+ lambda { subject.parameter_values([:v1, :vx]) }.should raise_error(PartyResource::Exceptions::MissingParameter)
118
99
  end
119
100
  end
120
101
 
@@ -12,7 +12,7 @@ describe PartyResource::Route do
12
12
  let(:options) { { :get => path, :as => klass } }
13
13
 
14
14
  before do
15
- PartyResource.stub(:Connector => connector)
15
+ PartyResource::Connector.stub(:lookup => connector)
16
16
  end
17
17
 
18
18
  describe ".call" do
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 1
9
- version: 0.0.1
8
+ - 2
9
+ version: 0.0.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Tristan Harris
@@ -19,8 +19,6 @@ date: 2010-05-26 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: httparty
23
- prerelease: false
24
22
  requirement: &id001 !ruby/object:Gem::Requirement
25
23
  requirements:
26
24
  - - ">="
@@ -30,11 +28,11 @@ dependencies:
30
28
  - 5
31
29
  - 2
32
30
  version: 0.5.2
31
+ name: httparty
32
+ prerelease: false
33
33
  type: :runtime
34
34
  version_requirements: *id001
35
35
  - !ruby/object:Gem::Dependency
36
- name: activesupport
37
- prerelease: false
38
36
  requirement: &id002 !ruby/object:Gem::Requirement
39
37
  requirements:
40
38
  - - ">="
@@ -44,11 +42,11 @@ dependencies:
44
42
  - 3
45
43
  - 5
46
44
  version: 2.3.5
45
+ name: activesupport
46
+ prerelease: false
47
47
  type: :runtime
48
48
  version_requirements: *id002
49
49
  - !ruby/object:Gem::Dependency
50
- name: rspec
51
- prerelease: false
52
50
  requirement: &id003 !ruby/object:Gem::Requirement
53
51
  requirements:
54
52
  - - ">="
@@ -58,11 +56,11 @@ dependencies:
58
56
  - 2
59
57
  - 9
60
58
  version: 1.2.9
59
+ name: rspec
60
+ prerelease: false
61
61
  type: :development
62
62
  version_requirements: *id003
63
63
  - !ruby/object:Gem::Dependency
64
- name: yard
65
- prerelease: false
66
64
  requirement: &id004 !ruby/object:Gem::Requirement
67
65
  requirements:
68
66
  - - ">="
@@ -70,11 +68,11 @@ dependencies:
70
68
  segments:
71
69
  - 0
72
70
  version: "0"
71
+ name: yard
72
+ prerelease: false
73
73
  type: :development
74
74
  version_requirements: *id004
75
75
  - !ruby/object:Gem::Dependency
76
- name: webmock
77
- prerelease: false
78
76
  requirement: &id005 !ruby/object:Gem::Requirement
79
77
  requirements:
80
78
  - - ">="
@@ -82,6 +80,8 @@ dependencies:
82
80
  segments:
83
81
  - 0
84
82
  version: "0"
83
+ name: webmock
84
+ prerelease: false
85
85
  type: :development
86
86
  version_requirements: *id005
87
87
  description: party_resource is a framework for building ruby objects which interact with a REST api. Built on top of HTTParty.
@@ -92,7 +92,7 @@ extensions: []
92
92
 
93
93
  extra_rdoc_files:
94
94
  - LICENSE
95
- - README.rdoc
95
+ - README.md
96
96
  files:
97
97
  - lib/party_resource.rb
98
98
  - lib/party_resource/buildable.rb
@@ -105,7 +105,7 @@ files:
105
105
  - lib/party_resource/request.rb
106
106
  - lib/party_resource/route.rb
107
107
  - LICENSE
108
- - README.rdoc
108
+ - README.md
109
109
  has_rdoc: true
110
110
  homepage: http://github.com/edendevelopment/party_resource.git
111
111
  licenses: []
data/README.rdoc DELETED
@@ -1,19 +0,0 @@
1
- = party_resource
2
-
3
- Simple REST interface for ruby objects.
4
-
5
- party_resource is a framework for building ruby objects which interact with a REST api. Built on top of HTTParty.
6
-
7
- == Note on Patches/Pull Requests
8
-
9
- * Fork the project.
10
- * Make your feature addition or bug fix.
11
- * Add tests for it. This is important so I don't break it in a
12
- future version unintentionally.
13
- * Commit, do not mess with rakefile, version, or history.
14
- (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
15
- * Send me a pull request. Bonus points for topic branches.
16
-
17
- == Copyright
18
-
19
- Copyright (c) 2010 Eden Development (UK) LTD. See LICENSE for details.