prx_hyperresource 1.0.0

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.
@@ -0,0 +1,243 @@
1
+ require "hyper_resource/attributes"
2
+ require "hyper_resource/configuration"
3
+ require "hyper_resource/exceptions"
4
+ require "hyper_resource/link"
5
+ require "hyper_resource/links"
6
+ require "hyper_resource/objects"
7
+ require "hyper_resource/version"
8
+
9
+ require "hyper_resource/adapter"
10
+ require "hyper_resource/adapter/hal_json"
11
+
12
+ require "hyper_resource/modules/data_type"
13
+ require "hyper_resource/modules/deprecations"
14
+ require "hyper_resource/modules/http"
15
+ require "hyper_resource/modules/config_attributes"
16
+ require "hyper_resource/modules/internal_attributes"
17
+
18
+ require "rubygems" if RUBY_VERSION[0..2] == "1.8"
19
+
20
+ require "pp"
21
+
22
+ ## HyperResource is the main resource base class. Normally it will be used
23
+ ## through subclassing, though it may also be used directly.
24
+
25
+ class HyperResource
26
+ include HyperResource::Modules::ConfigAttributes
27
+ include HyperResource::Modules::DataType
28
+ include HyperResource::Modules::Deprecations
29
+ include HyperResource::Modules::InternalAttributes
30
+ include Enumerable
31
+
32
+ private
33
+
34
+ DEFAULT_HEADERS = {"Accept" => "application/json"}
35
+
36
+ public
37
+
38
+ ## Create a new HyperResource, given a hash of options. These options
39
+ ## include:
40
+ ##
41
+ ## [root] The root URL of the resource.
42
+ ##
43
+ ## [auth] Authentication information. Currently only +{basic:
44
+ ## ['key', 'secret']}+ is supported.
45
+ ##
46
+ ## [namespace] Class or class name, into which resources should be
47
+ ## instantiated.
48
+ ##
49
+ ## [headers] Headers to send along with requests for this resource (as
50
+ ## well as its eventual child resources, if any).
51
+ ##
52
+ ## [faraday_options] Configuration passed to +Faraday::Connection.initialize+,
53
+ ## such as +{request: {timeout: 30}}+.
54
+ ##
55
+ def initialize(opts = {})
56
+ self.root = opts[:root] if opts[:root]
57
+ self.href = opts[:href] if opts[:href]
58
+
59
+ self.hr_config = self.class.hr_config.clone
60
+
61
+ self.adapter = opts[:adapter] if opts[:adapter]
62
+ self.faraday_options = opts[:faraday_options] if opts[:faraday_options]
63
+ self.auth = opts[:auth] if opts[:auth]
64
+
65
+ self.headers = DEFAULT_HEADERS
66
+ .merge(self.class.headers || {})
67
+ .merge(opts[:headers] || {})
68
+
69
+ self.namespace = opts[:namespace] if opts[:namespace]
70
+ if !namespace && self.class != HyperResource
71
+ self.namespace = self.class.namespace || self.class.to_s
72
+ end
73
+
74
+ ## There's a little acrobatics in getting Attributes, Links, and Objects
75
+ ## into the correct subclass.
76
+ if self.class != HyperResource
77
+ if self.class::Attributes == HyperResource::Attributes
78
+ Object.module_eval(
79
+ "class #{self.class}::Attributes < HyperResource::Attributes; end", __FILE__, __LINE__
80
+ )
81
+ end
82
+ if self.class::Links == HyperResource::Links
83
+ Object.module_eval(
84
+ "class #{self.class}::Links < HyperResource::Links; end", __FILE__, __LINE__
85
+ )
86
+ end
87
+ if self.class::Objects == HyperResource::Objects
88
+ Object.module_eval(
89
+ "class #{self.class}::Objects < HyperResource::Objects; end", __FILE__, __LINE__
90
+ )
91
+ end
92
+ end
93
+
94
+ self.attributes = self.class::Attributes.new(self)
95
+ self.links = self.class::Links.new(self)
96
+ self.objects = self.class::Objects.new(self)
97
+ self.loaded = false
98
+ end
99
+
100
+ ## Creates a new resource given args :link, :resource, :href, :response, :url,
101
+ ## and :body. Either :link or (:resource and :href and :url) are required.
102
+ # @private
103
+ def self.new_from(args)
104
+ link = args[:link]
105
+ resource = args[:resource] || link.resource
106
+ href = begin
107
+ args[:href] || link.href
108
+ rescue
109
+ nil
110
+ end
111
+ url = args[:url] || URI.join(resource.root, href || "")
112
+ response = args[:response]
113
+ body = args[:body] || {}
114
+
115
+ old_rsrc = resource
116
+ new_class = old_rsrc.get_data_type_class(resource: old_rsrc,
117
+ link: link,
118
+ url: url,
119
+ response: response,
120
+ body: body)
121
+ new_rsrc = new_class.new(root: old_rsrc.root,
122
+ href: href)
123
+ new_rsrc.hr_config = old_rsrc.hr_config.clone
124
+ new_rsrc.response = response
125
+ new_rsrc.body = body
126
+ new_rsrc.adapter.apply(body, new_rsrc)
127
+ new_rsrc.loaded = true
128
+ new_rsrc
129
+ end
130
+
131
+ # @private
132
+ def new_from(args)
133
+ self.class.new_from(args)
134
+ end
135
+
136
+ ## Returns true if one or more of this object's attributes has been
137
+ ## reassigned.
138
+ def changed?(*args)
139
+ attributes.changed?(*args)
140
+ end
141
+
142
+ #### Filters
143
+
144
+ ## +incoming_body_filter+ filters a hash of attribute keys and values
145
+ ## on their way from a response body to a HyperResource. Override this
146
+ ## in a subclass of HyperResource to implement filters on incoming data.
147
+ def incoming_body_filter(attr_hash)
148
+ attr_hash
149
+ end
150
+
151
+ ## +outgoing_body_filter+ filters a hash of attribute keys and values
152
+ ## on their way from a HyperResource to a request body. Override this
153
+ ## in a subclass of HyperResource to implement filters on outgoing data.
154
+ def outgoing_body_filter(attr_hash)
155
+ attr_hash
156
+ end
157
+
158
+ ## +outgoing_uri_filter+ filters a hash of attribute keys and values
159
+ ## on their way from a HyperResource to a URL. Override this
160
+ ## in a subclass of HyperResource to implement filters on outgoing URI
161
+ ## parameters.
162
+ def outgoing_uri_filter(attr_hash)
163
+ attr_hash
164
+ end
165
+
166
+ #### Enumerable support
167
+
168
+ ## Returns the *i*th object in the first collection of objects embedded
169
+ ## in this resource. Returns nil on failure.
170
+ def [](i)
171
+ get unless loaded
172
+ begin
173
+ objects.first[1][i]
174
+ rescue
175
+ nil
176
+ end
177
+ end
178
+
179
+ ## Iterates over the objects in the first collection of embedded objects
180
+ ## in this resource.
181
+ def each(&block)
182
+ get unless loaded
183
+ begin
184
+ objects.first[1].each(&block)
185
+ rescue
186
+ nil
187
+ end
188
+ end
189
+
190
+ #### Magic
191
+
192
+ ## method_missing will load this resource if not yet loaded, then
193
+ ## attempt to delegate to +attributes+, then +objects+, then +links+.
194
+ ## Override with extreme care.
195
+ def method_missing(method, *args) # standard:disable Style/MissingRespondToMissing
196
+ ## If not loaded, load and retry.
197
+ unless loaded
198
+ return get.send(method, *args)
199
+ end
200
+
201
+ ## Otherwise, try to match against attributes, then objects, then links.
202
+ method = method.to_s
203
+ if method[-1, 1] == "="
204
+ return attributes[method[0..-2]] = args.first if attributes&.has_key?(method[0..-2])
205
+ else
206
+ return attributes[method] if attributes&.has_key?(method.to_s)
207
+ return objects[method] if objects && objects[method]
208
+ if links && links[method]
209
+ if args.count > 0
210
+ return links[method].where(*args)
211
+ else
212
+ return links[method]
213
+ end
214
+ end
215
+ end
216
+
217
+ raise NoMethodError, "undefined method `#{method}' for #{inspect}"
218
+ end
219
+
220
+ ## respond_to? is patched to return +true+ if +method_missing+ would
221
+ ## successfully delegate a method call to +attributes+, +links+, or
222
+ ## +objects+.
223
+ def respond_to?(method, *args)
224
+ return true if links&.respond_to?(method)
225
+ return true if attributes&.respond_to?(method)
226
+ return true if objects&.respond_to?(method)
227
+ super
228
+ end
229
+
230
+ def inspect # @private
231
+ "#<#{self.class}:0x#{"%x" % object_id} @root=#{root.inspect} " \
232
+ "@href=#{href.inspect} @loaded=#{loaded} " \
233
+ "@namespace=#{namespace.inspect} ...>"
234
+ end
235
+
236
+ def self.user_agent # @private
237
+ "HyperResource #{HyperResource::VERSION}"
238
+ end
239
+
240
+ def user_agent # @private
241
+ self.class.user_agent
242
+ end
243
+ end
@@ -0,0 +1 @@
1
+ require "hyper_resource"
@@ -0,0 +1 @@
1
+ require "hyper_resource"
metadata ADDED
@@ -0,0 +1,220 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: prx_hyperresource
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Pete Gamache
8
+ - Andrew Kuklewicz - PRX
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 1980-01-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: uri_template
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.5.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 0.5.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.8.6
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.8.6
41
+ - !ruby/object:Gem::Dependency
42
+ name: json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: cgi
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
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 10.0.4
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 10.0.4
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '6.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '6.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: mocha
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '2.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '2.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: sinatra
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: 1.4.0
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: 1.4.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: rackup
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: webrick
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: standard
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ description: |2
168
+ HyperResource is a hypermedia client library for Ruby. Its goals are to
169
+ interface directly with well-behaved hypermedia APIs, to allow the data
170
+ returned from these APIs to optionally be extended by client-side code,
171
+ and to present a modern replacement for ActiveResource.
172
+ email: andrew@prx.org
173
+ executables: []
174
+ extensions: []
175
+ extra_rdoc_files: []
176
+ files:
177
+ - CHANGELOG.md
178
+ - LICENSE.txt
179
+ - README.md
180
+ - lib/hyper_resource.rb
181
+ - lib/hyper_resource/adapter.rb
182
+ - lib/hyper_resource/adapter/hal_json.rb
183
+ - lib/hyper_resource/attributes.rb
184
+ - lib/hyper_resource/configuration.rb
185
+ - lib/hyper_resource/exceptions.rb
186
+ - lib/hyper_resource/link.rb
187
+ - lib/hyper_resource/links.rb
188
+ - lib/hyper_resource/modules/config_attributes.rb
189
+ - lib/hyper_resource/modules/data_type.rb
190
+ - lib/hyper_resource/modules/deprecations.rb
191
+ - lib/hyper_resource/modules/http.rb
192
+ - lib/hyper_resource/modules/internal_attributes.rb
193
+ - lib/hyper_resource/objects.rb
194
+ - lib/hyper_resource/version.rb
195
+ - lib/hyperresource.rb
196
+ - lib/prx_hyperresource.rb
197
+ homepage: https://github.com/PRX/hyperresource
198
+ licenses:
199
+ - MIT
200
+ metadata:
201
+ source_code_uri: https://github.com/PRX/hyperresource
202
+ changelog_uri: https://github.com/PRX/hyperresource/blob/master/CHANGELOG.md
203
+ rdoc_options: []
204
+ require_paths:
205
+ - lib
206
+ required_ruby_version: !ruby/object:Gem::Requirement
207
+ requirements:
208
+ - - ">="
209
+ - !ruby/object:Gem::Version
210
+ version: '3.3'
211
+ required_rubygems_version: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - ">="
214
+ - !ruby/object:Gem::Version
215
+ version: '0'
216
+ requirements: []
217
+ rubygems_version: 4.0.3
218
+ specification_version: 4
219
+ summary: Extensible hypermedia client for Ruby
220
+ test_files: []