Module: Eipiai::Resource
- Includes:
- Objectifiable, Representable
- Included in:
- ApiResource, HealthResource
- Defined in:
- lib/eipiai/resources/base.rb,
lib/eipiai/resources/concerns/objectifiable.rb,
lib/eipiai/resources/concerns/representable.rb
Overview
Resource
The base resource which can be included in regular Webmachine::Resource objects. It provides sensible defaults for a full-features REST API endpoint.
Defined Under Namespace
Modules: Objectifiable, Representable
Class Method Summary collapse
-
.included(base) ⇒ Object
Includes the correct resource into the class, depending on its name.
Instance Method Summary collapse
- #base_uri ⇒ Object
- #content_types_accepted ⇒ Object
- #content_types_provided ⇒ Object
- #create_uri ⇒ Object
- #finish_request ⇒ Object
-
#malformed_request? ⇒ true, false
malformed_request?.
-
#new_object ⇒ Object?
new_object.
-
#params(body = request.body.to_s) ⇒ Hash
params.
- #post_is_create? ⇒ Boolean
-
#query_keys ⇒ Array<String>
query_keys.
-
#resource_relation ⇒ String
resource_relation.
-
#service_available? ⇒ true, false
service_available?.
-
#to_h(obj = object) ⇒ Hash
to_h.
- #to_hal_json ⇒ Object
- #to_json ⇒ Object
-
#top_level_relation? ⇒ true, false
top_level_relation?.
-
#unprocessable_entity? ⇒ true, false
unprocessable_entity?.
Class Method Details
.included(base) ⇒ Object
Includes the correct resource into the class, depending on its name.
If the resource is called ‘ItemResource`, the `Item` part is considered singular, and thus the `SingularResource` is included into the class.
24 25 26 27 28 29 30 31 32 |
# File 'lib/eipiai/resources/base.rb', line 24 def self.included(base) subject_class_name = base.name.demodulize.chomp('Resource') if subject_class_name == subject_class_name.singularize base.send(:include, SingularResource) else base.send(:include, CollectionResource) end end |
Instance Method Details
#base_uri ⇒ Object
236 237 238 |
# File 'lib/eipiai/resources/base.rb', line 236 def base_uri request.base_uri end |
#content_types_accepted ⇒ Object
147 148 149 |
# File 'lib/eipiai/resources/base.rb', line 147 def content_types_accepted [['application/json', :from_json]] end |
#content_types_provided ⇒ Object
143 144 145 |
# File 'lib/eipiai/resources/base.rb', line 143 def content_types_provided [['application/hal+json', :to_hal_json], ['application/json', :to_json]] end |
#create_uri ⇒ Object
240 241 242 |
# File 'lib/eipiai/resources/base.rb', line 240 def create_uri Addressable::URI.join(base_uri, create_path) end |
#finish_request ⇒ Object
155 156 157 |
# File 'lib/eipiai/resources/base.rb', line 155 def finish_request response.headers['Cache-Control'] = cache_control_header_value end |
#malformed_request? ⇒ true, false
malformed_request?
return ‘true` if content_type is of type `application/json`, and the JSON request body cannot be parsed.
114 115 116 117 118 119 120 |
# File 'lib/eipiai/resources/base.rb', line 114 def malformed_request? return false unless request.json? && request.body.to_s.present? JSON.parse(request.body.to_s) && false rescue JSON::ParserError json_error_body(:invalid_json) end |
#new_object ⇒ Object?
new_object
New object, instantiated by passing the provided ‘params` into the object’s ‘#from_hash` method.
The only requirement is that the object responds to ‘#from_hash`, that method accepts a hash of parameters, and it returns the object itself.
230 231 232 233 234 |
# File 'lib/eipiai/resources/base.rb', line 230 def new_object return if object_class.nil? @new_object ||= object_class.new.from_hash(params) end |
#params(body = request.body.to_s) ⇒ Hash
params
Given a string in JSON format, returns the hash representation of that object.
If the input is invalid JSON, an empty hash is returned.
If no argument is given, ‘request.body` is used as the JSON input.
177 178 179 180 181 |
# File 'lib/eipiai/resources/base.rb', line 177 def params(body = request.body.to_s) @params ||= JSON.parse(body) rescue JSON::ParserError {} end |
#post_is_create? ⇒ Boolean
151 152 153 |
# File 'lib/eipiai/resources/base.rb', line 151 def post_is_create? true end |
#query_keys ⇒ Array<String>
query_keys
Returns an array of optional query component keys this resource accepts. The keys are added to the link relation as templated variables.
Defaults to an empty array, not exposing any optional query keys.
74 75 76 |
# File 'lib/eipiai/resources/base.rb', line 74 def query_keys [] end |
#resource_relation ⇒ String
resource_relation
The name to be used when linking to this resource as a relation.
The string returned from this method will become the name of the link in the HAL+JSON representation of this resource.
46 47 48 |
# File 'lib/eipiai/resources/base.rb', line 46 def resource_relation resource_name.demodulize.underscore end |
#service_available? ⇒ true, false
service_available?
If the service is unavailable, this method should return false. By default, this method calls the ‘HealthCheck#healthy?` method, which in turn returns `true` or `false`, depending on the state of the service and its dependencies.
When the service is unavailable, the ‘Cache-Control` header is set to not allow any caching by proxies/clients, and sets the `Retry-After` header to tell the client to retry again in 60 seconds.
91 92 93 94 95 96 97 |
# File 'lib/eipiai/resources/base.rb', line 91 def service_available? return true if Eipiai::HealthCheck.new.healthy? response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate, private' response.headers['Retry-After'] = '60' false end |
#to_h(obj = object) ⇒ Hash
to_h
Given an object, calls ‘#to_h` on that object,
If the object’s ‘to_h` implementation accepts any arguments, the hash `{ request: request }` is sent as its first argument.
In practice, this method is used without any parameters, causing the method to call ‘represented`, which represents a Roar representer. This in turn converts the represented object to a HAL/JSON compatible hash representation.
203 204 205 206 207 |
# File 'lib/eipiai/resources/base.rb', line 203 def to_h(obj = object) obj.method(:to_h).arity.zero? ? obj.to_h : obj.to_h(request: request) rescue obj end |
#to_hal_json ⇒ Object
213 214 215 |
# File 'lib/eipiai/resources/base.rb', line 213 def to_hal_json to_h.to_json end |
#to_json ⇒ Object
209 210 211 |
# File 'lib/eipiai/resources/base.rb', line 209 def to_json to_h.to_json end |
#top_level_relation? ⇒ true, false
top_level_relation?
return ‘true` if the link relation to this resource should be added to the top-level API entrypoint.
It is good practice to keep most link relations out of the top-level entrypoint, instead opting for nesting the resource within its parent resource links relations.
61 62 63 |
# File 'lib/eipiai/resources/base.rb', line 61 def top_level_relation? false end |
#unprocessable_entity? ⇒ true, false
unprocessable_entity?
return ‘true` if content_type is of type `application/json`, and the newly generated object reports back as “invalid”.
137 138 139 140 141 |
# File 'lib/eipiai/resources/base.rb', line 137 def unprocessable_entity? return false unless request.json? && new_object.respond_to?(:invalid?) new_object.invalid? && json_error_body(*new_object.errors) end |