hypertext_client 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/CHANGELOG CHANGED
@@ -1,3 +1,6 @@
1
+ ## 0.0.2 (September 24, 2010)
2
+
3
+ Support belongs_to for parent/child relationships, client classes in module.
1
4
 
2
5
  ## 0.0.1 (September 23, 2010)
3
6
 
@@ -18,16 +18,20 @@
18
18
 
19
19
  # Hypertext provides an HTTP client based on HTTParty, with a few assumptions baked in.
20
20
  module HypertextClient
21
- VERSION = '0.0.1'
21
+ VERSION = '0.0.2'
22
22
 
23
23
  extend ActiveSupport::Concern
24
24
  # Include HTTParty
25
25
  @_dependencies = [HTTParty, ActiveModel::Conversion, ActiveModel::Validations]
26
26
 
27
27
  class NotFoundException < HTTParty::ResponseError; end
28
+ class MissingArgumentError < ArgumentError; end
28
29
 
29
30
  included do
30
31
  extend ActiveModel::Naming
32
+ class_attribute :parents
33
+ class_attribute :base_endpoint
34
+ self.parents = []
31
35
  raise 'HypertextClient depends on ObjectStruct. Inherit from ObjectStruct.' unless self.ancestors.include? ObjectStruct
32
36
  end
33
37
 
@@ -68,7 +72,7 @@ module HypertextClient
68
72
 
69
73
  # Get a related property.
70
74
  def get_related(related)
71
- klass = related.to_s.singularize.classify.constantize
75
+ klass = (self.class.name.split('::').first + '::' + related.to_s.singularize.classify).constantize
72
76
  result = klass.get(send (related.to_s+'_url').to_sym)
73
77
 
74
78
  (class << self; self; end).instance_eval do
@@ -86,7 +90,13 @@ module HypertextClient
86
90
 
87
91
  # Specify a base url for the client.
88
92
  def base_url(base)
89
- base_uri base + '/' + self.to_s.parameterize.pluralize
93
+ self.base_endpoint = base
94
+ base_uri self.base_endpoint + '/' + self.name.split('::').last.parameterize.pluralize
95
+ end
96
+
97
+ def belongs_to(*classes)
98
+ self.parents += classes.select {|c| c.respond_to? :model_name}
99
+ base_url self.base_endpoint + '/' + self.parents.map {|parent| parent.model_name.split('::').last.parameterize}.map{|name| "#{name.pluralize}/|#{name.singularize}|"} * '/'
90
100
  end
91
101
 
92
102
  # Override HTTParty's methods to allow assumptions about a '/' path.
@@ -104,6 +114,16 @@ module HypertextClient
104
114
  path = ''
105
115
  end
106
116
 
117
+ if self.parents.count > 0
118
+ options = args.first
119
+ raise MissingArgumentError.new("Options hash required; must include parent ids") unless options.is_a? Hash
120
+ self.parents.each do |parent|
121
+ key = parent.model_name.split('::').last.parameterize.singularize.to_sym
122
+ raise MissingArgumentError.new("Missing required argument: #{key}") unless options.has_key? key
123
+ base_uri self.base_uri.gsub("|#{key}|", options[key])
124
+ end
125
+ end
126
+
107
127
  response = super(path, *args)
108
128
  case response.code
109
129
  when (200..299)
@@ -16,6 +16,7 @@
16
16
  #
17
17
  # ---------------------------------------------------------------------------
18
18
 
19
+ require 'active_support/core_ext/class/attribute'
19
20
  require 'active_support/inflector'
20
21
  require 'active_support/concern'
21
22
  require 'active_model'
@@ -8,7 +8,7 @@ begin; require 'redgreen'; rescue LoadError; end
8
8
 
9
9
  require 'hypertext_client'
10
10
 
11
- FAKE_ENDPOINT = "http://api.widgetsinc.com"
11
+ FAKE_ENDPOINT = "http://api.skynetinc.com"
12
12
 
13
13
  FakeWeb.allow_net_connect = false
14
14
  FakeWeb.register_uri(:get,
@@ -26,6 +26,11 @@ FakeWeb.register_uri(:get,
26
26
  :body => {:name => 'Frobby Widget', :knob_url => FAKE_ENDPOINT + '/knobs/excellent_knob'}.to_json,
27
27
  :content_type => 'application/json')
28
28
 
29
+ FakeWeb.register_uri(:get,
30
+ FAKE_ENDPOINT + '/widgets/frobby_widget/buttons/red_button',
31
+ :body => {:description => 'Scary Red Button'}.to_json,
32
+ :content_type => 'application/json')
33
+
29
34
  FakeWeb.register_uri(:get,
30
35
  FAKE_ENDPOINT + '/widgets/not_there',
31
36
  :status => ['404', 'Not Found'],
@@ -33,47 +38,69 @@ FakeWeb.register_uri(:get,
33
38
  :content_type => 'application/json')
34
39
 
35
40
 
36
- class Widget < ObjectStruct
37
- include HypertextClient
38
- base_url FAKE_ENDPOINT
39
- headers 'Accept' => 'application/json'
41
+ module SkynetClient
42
+ extend ActiveSupport::Concern
43
+ @_dependencies = [HypertextClient]
44
+ included do
45
+ base_url FAKE_ENDPOINT
46
+ headers 'Accept' => 'application/json'
47
+ end
40
48
  end
41
49
 
42
- class Knob < ObjectStruct
43
- include HypertextClient
44
- base_url FAKE_ENDPOINT
45
- headers 'Accept' => 'application/json'
50
+ class SkynetClient::Widget < ObjectStruct
51
+ include SkynetClient
46
52
  end
47
53
 
54
+ class SkynetClient::Knob < ObjectStruct
55
+ include SkynetClient
56
+ end
57
+
58
+ class SkynetClient::Button < ObjectStruct
59
+ include SkynetClient
60
+ belongs_to Widget
61
+ end
62
+
63
+
48
64
  class HypertextClientTest < MiniTest::Unit::TestCase
49
65
  include ActiveModel::Lint::Tests
50
66
 
51
67
  def setup
52
68
  # For ActiveModel tests
53
- @model = Widget.get('frobby_widget')
69
+ @model = SkynetClient::Widget.get('frobby_widget')
54
70
  end
55
71
 
56
72
  def test_get_basic_resource
57
- assert_equal 'Frobby Widget', Widget.get('frobby_widget').name
73
+ assert_equal 'Frobby Widget', SkynetClient::Widget.get('frobby_widget').name
58
74
  end
59
75
 
60
76
  def test_should_raise_not_found
61
- assert_raises HypertextClient::NotFoundException do Widget.get('not_there') end
77
+ assert_raises HypertextClient::NotFoundException do SkynetClient::Widget.get('not_there') end
62
78
  end
63
79
 
64
80
  def test_should_get_index_array
65
- response = Widget.get
81
+ response = SkynetClient::Widget.get
66
82
  assert_instance_of Array, response
67
- assert response.all? {|e| e.instance_of? Widget}
83
+ assert response.all? {|e| e.instance_of? SkynetClient::Widget}
68
84
  end
69
85
 
70
86
  def test_traverse_related
71
- knob = Widget.get('frobby_widget').knob
87
+ knob = SkynetClient::Widget.get('frobby_widget').knob
72
88
  assert_equal 'Adjustormatic', knob.label
73
89
  end
74
90
 
75
91
  def test_has_related?
76
- assert Widget.get('frobby_widget').has_knob?
77
- refute Widget.get('frobby_widget').has_lever?
92
+ assert SkynetClient::Widget.get('frobby_widget').has_knob?
93
+ refute SkynetClient::Widget.get('frobby_widget').has_lever?
94
+ end
95
+
96
+ def test_request_child_resources
97
+ button = SkynetClient::Button.get 'red_button', :widget => 'frobby_widget'
98
+ assert_equal "Scary Red Button", button.description
99
+ end
100
+
101
+ def test_complain_if_no_parent_id_specified
102
+ assert_raises HypertextClient::MissingArgumentError do
103
+ SkynetClient::Button.get 'red_button'
104
+ end
78
105
  end
79
106
  end
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
  - Quid, Inc.
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-09-23 00:00:00 -07:00
17
+ date: 2010-09-24 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency