Class: PathTo::DescribedRoutes::Application
- Inherits:
-
WithParams
- Object
- WithParams
- PathTo::DescribedRoutes::Application
- Defined in:
- lib/path-to/described_routes.rb
Overview
DescribedRoutes implementation of PathTo::Application.
Instance Attribute Summary collapse
-
#base ⇒ Object
readonly
Base URI of the application.
-
#default_type ⇒ Object
readonly
A Class (or at least something with a #new method) from which child objects will be created.
-
#http_client ⇒ Object
readonly
An HTTParty or similar.
-
#http_options ⇒ Object
readonly
Hash of options to be included in HTTP method calls.
-
#resource_templates ⇒ Object
readonly
An Array of DescribedRoutes::Resource objects.
Attributes inherited from WithParams
Class Method Summary collapse
Instance Method Summary collapse
-
#[](params) ⇒ Object
Creates a copy of self with additional params.
-
#application ⇒ Object
Returns self.
-
#child_class_for(instance, method, params, template) ⇒ Object
Determines whether this application &/or its child objects should respond to the given method, and if so returns a class from which a new child instance (typically Path or a subclass thereof) will be created.
-
#initialize(options) ⇒ Application
constructor
A new instance of Application.
-
#method_missing(method, *args) ⇒ Object
Tries to respond to a missing method.
-
#resource_templates_by_name ⇒ Object
Returns a hash of all ResourceTemplates (the tree flattened) keyed by name.
Methods inherited from WithParams
#child, #complete_params_hash!, #extract_params, #respond_to?
Constructor Details
#initialize(options) ⇒ Application
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/path-to/described_routes.rb', line 190 def initialize() super([:parent], [:service], [:params]) @base = [:base] @base.sub(/\/$/, '') if base @default_type = [:default_type] || TemplatedPath @http_client = [:http_client] || HTTPClient = [:http_options] @resource_templates = [:resource_templates] unless @resource_templates if (json = [:json]) @resource_templates = ResourceTemplate::ResourceTemplates.new(JSON.parse(json)) elsif (yaml = [:yaml]) @resource_templates = ResourceTemplate::ResourceTemplates.new(YAML.load(yaml)) elsif (xml = [:xml]) @resource_templates = ResourceTemplate::ResourceTemplates.parse_xml(xml) end end if parent @base ||= parent.base @default_type ||= parent.default_type @http_client ||= parent.http_client @resource_templates ||= parent.resource_templates ||= parent. end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args) ⇒ Object
Tries to respond to a missing method. We can do so if
- we have a resource template matching the method name
- #child_class_for returns a class or other factory object capable of creating a new child instance
Otherwise we invoke super in the hope of avoiding any hard-to-debug behaviour!
234 235 236 237 238 239 240 241 242 243 |
# File 'lib/path-to/described_routes.rb', line 234 def method_missing(method, *args) child_resource_template = resource_templates_by_name[method.to_s] if child_resource_template && (child_class = child_class_for(self, method, params, child_resource_template)) positional_params, params_hash = extract_params(args, params) complete_params_hash!(params_hash, child_resource_template.positional_params(nil), positional_params) child(child_class, method, params_hash, child_resource_template) else super end end |
Instance Attribute Details
#base ⇒ Object (readonly)
Base URI of the application
138 139 140 |
# File 'lib/path-to/described_routes.rb', line 138 def base @base end |
#default_type ⇒ Object (readonly)
A Class (or at least something with a #new method) from which child objects will be created
132 133 134 |
# File 'lib/path-to/described_routes.rb', line 132 def default_type @default_type end |
#http_client ⇒ Object (readonly)
An HTTParty or similar
135 136 137 |
# File 'lib/path-to/described_routes.rb', line 135 def http_client @http_client end |
#http_options ⇒ Object (readonly)
Hash of options to be included in HTTP method calls
141 142 143 |
# File 'lib/path-to/described_routes.rb', line 141 def end |
#resource_templates ⇒ Object (readonly)
An Array of DescribedRoutes::Resource objects
129 130 131 |
# File 'lib/path-to/described_routes.rb', line 129 def resource_templates @resource_templates end |
Class Method Details
.discover(url, options = {}) ⇒ Object
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/path-to/described_routes.rb', line 143 def self.discover(url, ={}) = [:http_options] || nil default_type = [:default_type] || Path http_client = [:http_client] || HTTPClient = self.(url, http_client) unless raise ProtocolError.new("no metadata link found") end json = http_client.get(.href, :format => :text, :headers => {"Accept" => "application/json"}) unless json raise ProtocolError.new("no json found") end self.new(.merge(:json => json)) end |
.discover_metadata_link(url, http_client) ⇒ Object
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/path-to/described_routes.rb', line 161 def self.(url, http_client) response = http_client.head(url, {"Accept" => "application/json"}) unless response.kind_of?(Net::HTTPOK) raise ProtocolError.new("got response #{response.inspect} from #{url}") end link_header = LinkHeader.parse(response["Link"]) app_templates_link = link_header.find_link(["rel", "describedby"], ["meta", "ResourceTemplates"]) unless app_templates_link resource_template_link = link_header.find_link(["rel", "describedby"], ["meta", "ResourceTemplate"]) if resource_template_link response = http_client.head(resource_template_link.href, {"Accept" => "application/json"}) unless response.kind_of?(Net::HTTPOK) raise ProtocolError.new("got response #{response.inspect} from #{url}") end link_header = LinkHeader.parse(response["Link"]) app_templates_link = link_header.find_link(["rel", "index"], ["meta", "ResourceTemplates"]) unless app_templates_link raise ProtocolError.new("(2) couldn't find link with rel=\"index\" and meta=\"ResourceTemplates\" at #{resource_template_link.href}") end else unless app_templates_link raise ProtocolError.new("(1) couldn't find link with rel=\"described_by\" and meta=\"ResourceTemplates\" or meta=\"ResourceTemplate\" at #{url}") end end end app_templates_link end |
Instance Method Details
#[](params) ⇒ Object
Creates a copy of self with additional params
222 223 224 |
# File 'lib/path-to/described_routes.rb', line 222 def [](params) self.class.new(:parent => self, :params => params) end |
#application ⇒ Object
Returns self. See TemplatedPath#application.
270 271 272 |
# File 'lib/path-to/described_routes.rb', line 270 def application self end |
#child_class_for(instance, method, params, template) ⇒ Object
Determines whether this application &/or its child objects should respond to the given method, and if so returns a class from which a new child instance (typically Path or a subclass thereof) will be created. This implementation (easily overridden) returns #default_type if there is a URI template defined for the method.
Parameters:
[instance] This application or (presumably) one of its child objects [method] The method invoked on the instance that has (presumably) been intercepted by instance#method_missing [params] The instance's params
256 257 258 |
# File 'lib/path-to/described_routes.rb', line 256 def child_class_for(instance, method, params, template) default_type end |
#resource_templates_by_name ⇒ Object
Returns a hash of all ResourceTemplates (the tree flattened) keyed by name
263 264 265 |
# File 'lib/path-to/described_routes.rb', line 263 def resource_templates_by_name @resource_templates_by_name ||= resource_templates.all_by_name end |