axel 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +21 -0
  3. data/.octopolo.yml +2 -0
  4. data/.rspec +2 -0
  5. data/.ruby-gemset +1 -0
  6. data/.ruby-version +1 -0
  7. data/.travis.yml +23 -0
  8. data/Gemfile +4 -0
  9. data/LICENSE.txt +22 -0
  10. data/README.md +271 -0
  11. data/Rakefile +13 -0
  12. data/app/models/axel/api_proxy.rb +86 -0
  13. data/app/models/axel/associations/base.rb +64 -0
  14. data/app/models/axel/associations/belongs_to.rb +43 -0
  15. data/app/models/axel/associations/has_many.rb +29 -0
  16. data/app/models/axel/associations/has_one.rb +30 -0
  17. data/app/models/axel/payload.rb +4 -0
  18. data/app/models/axel/payload/base.rb +107 -0
  19. data/app/models/axel/payload/errors.rb +62 -0
  20. data/app/models/axel/payload/metadata.rb +57 -0
  21. data/app/models/axel/querier.rb +166 -0
  22. data/app/models/axel/router.rb +119 -0
  23. data/app/models/axel/service_resource.rb +4 -0
  24. data/app/models/axel/service_resource/associations.rb +80 -0
  25. data/app/models/axel/service_resource/attributes.rb +23 -0
  26. data/app/models/axel/service_resource/automatic_resource.rb +23 -0
  27. data/app/models/axel/service_resource/base.rb +47 -0
  28. data/app/models/axel/service_resource/builder.rb +40 -0
  29. data/app/models/axel/service_resource/inspects.rb +17 -0
  30. data/app/models/axel/service_resource/payload_parser.rb +46 -0
  31. data/app/models/axel/service_resource/queries.rb +25 -0
  32. data/app/models/axel/service_resource/requesters.rb +49 -0
  33. data/app/models/axel/service_resource/routes.rb +19 -0
  34. data/app/models/axel/service_resource/typhoid_extensions.rb +134 -0
  35. data/app/views/axel/base/empty.json.erb +0 -0
  36. data/app/views/axel/base/empty.xml.builder +0 -0
  37. data/app/views/layouts/axel.json.jbuilder +7 -0
  38. data/app/views/layouts/axel.xml.builder +12 -0
  39. data/axel.gemspec +42 -0
  40. data/lib/axel.rb +56 -0
  41. data/lib/axel/application_extensions.rb +13 -0
  42. data/lib/axel/application_helper.rb +27 -0
  43. data/lib/axel/base_controller.rb +6 -0
  44. data/lib/axel/cascadable_attribute.rb +33 -0
  45. data/lib/axel/configurations/resource.rb +29 -0
  46. data/lib/axel/configurations/service.rb +28 -0
  47. data/lib/axel/configurator.rb +54 -0
  48. data/lib/axel/configurators/services.rb +29 -0
  49. data/lib/axel/controller_base.rb +27 -0
  50. data/lib/axel/controller_helpers.rb +209 -0
  51. data/lib/axel/controller_parameters.rb +32 -0
  52. data/lib/axel/engine.rb +14 -0
  53. data/lib/axel/inspector.rb +91 -0
  54. data/lib/axel/payload/remote_error.rb +14 -0
  55. data/lib/axel/request_options.rb +26 -0
  56. data/lib/axel/uri.rb +47 -0
  57. data/lib/axel/version.rb +3 -0
  58. data/lib/generators/axel/install_generator.rb +16 -0
  59. data/lib/generators/templates/README.md +22 -0
  60. data/lib/generators/templates/axel.rb +81 -0
  61. data/script/rails +5 -0
  62. data/spec/controllers/pages_controller_spec.rb +217 -0
  63. data/spec/dummy/README.rdoc +261 -0
  64. data/spec/dummy/Rakefile +7 -0
  65. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  66. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  67. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  68. data/spec/dummy/app/controllers/pages_controller.rb +6 -0
  69. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  70. data/spec/dummy/app/mailers/.gitkeep +0 -0
  71. data/spec/dummy/app/models/.gitkeep +0 -0
  72. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  73. data/spec/dummy/config.ru +4 -0
  74. data/spec/dummy/config/application.rb +62 -0
  75. data/spec/dummy/config/boot.rb +10 -0
  76. data/spec/dummy/config/database.yml +25 -0
  77. data/spec/dummy/config/environment.rb +5 -0
  78. data/spec/dummy/config/environments/development.rb +37 -0
  79. data/spec/dummy/config/environments/production.rb +67 -0
  80. data/spec/dummy/config/environments/test.rb +37 -0
  81. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  82. data/spec/dummy/config/initializers/inflections.rb +15 -0
  83. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  84. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  85. data/spec/dummy/config/initializers/session_store.rb +8 -0
  86. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  87. data/spec/dummy/config/locales/en.yml +5 -0
  88. data/spec/dummy/config/routes.rb +3 -0
  89. data/spec/dummy/db/development.sqlite3 +0 -0
  90. data/spec/dummy/db/test.sqlite3 +0 -0
  91. data/spec/dummy/lib/assets/.gitkeep +0 -0
  92. data/spec/dummy/log/.gitignore +1 -0
  93. data/spec/dummy/log/.gitkeep +0 -0
  94. data/spec/dummy/public/404.html +26 -0
  95. data/spec/dummy/public/422.html +26 -0
  96. data/spec/dummy/public/500.html +25 -0
  97. data/spec/dummy/public/favicon.ico +0 -0
  98. data/spec/dummy/script/rails +6 -0
  99. data/spec/envelope_integration_check.rb +96 -0
  100. data/spec/helpers/axel/application_helper_spec.rb +31 -0
  101. data/spec/lib/axel/associations/base_spec.rb +28 -0
  102. data/spec/lib/axel/associations/belongs_to_spec.rb +62 -0
  103. data/spec/lib/axel/associations/has_many_spec.rb +23 -0
  104. data/spec/lib/axel/associations/has_one_spec.rb +23 -0
  105. data/spec/lib/axel/configurations/resource_spec.rb +15 -0
  106. data/spec/lib/axel/configurations/service_spec.rb +31 -0
  107. data/spec/lib/axel/configurator_spec.rb +26 -0
  108. data/spec/lib/axel/configurators/services_spec.rb +37 -0
  109. data/spec/lib/axel/controller_base_spec.rb +16 -0
  110. data/spec/lib/axel/controller_parameters_spec.rb +31 -0
  111. data/spec/lib/axel/inspector_spec.rb +45 -0
  112. data/spec/lib/axel/request_options_spec.rb +50 -0
  113. data/spec/lib/axel/uri_spec.rb +42 -0
  114. data/spec/lib/axel_spec.rb +64 -0
  115. data/spec/models/axel/api_proxy_spec.rb +66 -0
  116. data/spec/models/axel/payload/errors_spec.rb +165 -0
  117. data/spec/models/axel/payload/metadata_spec.rb +141 -0
  118. data/spec/models/axel/querier_spec.rb +158 -0
  119. data/spec/models/axel/router_spec.rb +115 -0
  120. data/spec/models/axel/service_resource/base_spec.rb +244 -0
  121. data/spec/models/axel/service_resource/builder_spec.rb +64 -0
  122. data/spec/models/axel/service_resource/payload_parser_spec.rb +60 -0
  123. data/spec/spec_helper.rb +39 -0
  124. data/spec/support/address.rb +5 -0
  125. data/spec/support/persona.rb +15 -0
  126. data/spec/support/user.rb +6 -0
  127. data/spec/views/axel/base/empty_spec.rb +34 -0
  128. metadata +508 -0
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZjgxOWQxNTg1OTVmYjU3OWZhMWFhZGUxMjczNDY0M2Q0Y2NlNDJkOQ==
5
+ data.tar.gz: !binary |-
6
+ MTE2MjQ1ZDUwNDc4MTQyZTBmY2EwYzU0NjdmN2VhOWM5ZWY4MjZiMA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ Nzc5ODRlOWZhZjU2M2ExNTYyZmM5YTdjMWUwMmIwYWE3M2IwNjY0MmIyNmIw
10
+ NGVmZDRiMWRkMWRmZmFlOGM4ZTE5MmUzYjNkMjdkZDUxMzNlMmQ4Yjk3NjQ1
11
+ YjQ1ZGQzODczYWJiNTExMTdhYTkyZDBkNWY4ODgwNjU0YWZiM2U=
12
+ data.tar.gz: !binary |-
13
+ ZWZlYWVhM2VjZGNjMjBlNGY3ODM1ZTczNTVjZWE5ZWRiZTY4OGYwYmRhN2Yx
14
+ MWUwN2JjM2UxZTk2MGU4MjQ5ODUwMTExOWMwY2NjNGJjNGMwNzgzNTA5MzI4
15
+ ZjE5MWI2NDdmMGMzNjYyM2NmODZkNGRmMmRlMWI2YWY0ZmFjMGY=
@@ -0,0 +1,21 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ InstalledFiles
7
+ _yardoc
8
+ coverage
9
+ doc/
10
+ lib/bundler/man
11
+ pkg
12
+ rdoc
13
+ spec/reports
14
+ test/tmp
15
+ test/version_tmp
16
+ tmp
17
+ .idea
18
+
19
+ cache
20
+
21
+ Gemfile.lock
@@ -0,0 +1,2 @@
1
+ deploy_branch: master
2
+ github_repo: sportngin/axel
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
@@ -0,0 +1 @@
1
+ axel
@@ -0,0 +1 @@
1
+ 1.9.3
@@ -0,0 +1,23 @@
1
+ sudo: false
2
+ branches:
3
+ only:
4
+ - master
5
+
6
+ notifications:
7
+ slack: sportngin:Yr24DXJUvIOegSPwKMG099D1
8
+
9
+ after_script:
10
+ - uptime && vmstat -S M
11
+
12
+ language: ruby
13
+ rvm:
14
+ - 1.9.3
15
+ - 2.0.0
16
+ - 2.1.0
17
+ - 2.2
18
+
19
+ cache: bundler
20
+
21
+ script:
22
+ - bundle exec rake spec
23
+
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in axel.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Sport Ngin
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,271 @@
1
+ # Axel
2
+ [![Build Status](https://magnum.travis-ci.com/sportngin/axel.svg?token=JKgYC4kfXqjpwsFoBpzq)](https://magnum.travis-ci.com/sportngin/axel)
3
+
4
+ The building blocks for building a Sport Ngin Back-end API service:
5
+
6
+ * add some error helpers (error object)
7
+ * standardized XML/JSON envelope (metadata/error/result objects)
8
+ * adding `suppress_response_codes` to params will force a 200 and will only show errors
9
+ in the error object of the response body
10
+ * standard controller responders to ensure JSON is always prefered, XML is acceptable, and
11
+ the response always has a correct body that handles all errors
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ ```ruby
18
+ source 'https://D9W5miiTyaf8EzrkWdTy@gem.fury.io/me/' # BELOW THE `source rubygems`
19
+ gem 'axel'
20
+ ```
21
+
22
+ Then execute:
23
+
24
+ ```bash
25
+ $ bundle
26
+ ```
27
+
28
+ In your `app/controllers/application_controller.rb` (or wherever your base class is that will
29
+ use these helpers) change to:
30
+
31
+ ```ruby
32
+ class ApplicationController < ActionController::Base
33
+ include Axel::ControllerHelpers
34
+ end
35
+ ```
36
+
37
+ ## Usage
38
+
39
+ ### Controller Specific Helpers
40
+
41
+ #### Errors
42
+
43
+ Errors object is available (as `errors`) from any controller:
44
+
45
+ ```ruby
46
+ errors.header_status # suppress_response_codes param will set to 200 by default
47
+ errors << "Error message!" # add error messages
48
+ errors.display # { status: errors.status_code, messages: errors.messages }
49
+ errors.display? # Display errors? (was there an error added or status changed?)
50
+ errors.messages
51
+ errors.messages = []
52
+ errors.status = :not_found
53
+ errors.status_code # => 404
54
+ errors.status = 403
55
+ errors.status_code # => 403
56
+ errors.new_error(status, *m) # set status, add an error or list of errors (not in an array object)
57
+
58
+ # Can also set on the fly:
59
+ rescue_error status: :not_found, message: "Error!"
60
+ rescue_error status: :unproccessable_entity, messages: ["Error!", "Error2!"]
61
+ ```
62
+
63
+ #### Metadata
64
+
65
+ Metadata object that will be placed on every outgoing response body. You can add to the object like
66
+ so:
67
+
68
+ ```ruby
69
+ metadata[:current_user] = current_user
70
+
71
+ # the body will then set this on the outgoing body:
72
+ # => { "metadata": { "current_user": "..." }, "result": "...", "...": "..." }
73
+ ```
74
+
75
+ #### Responders
76
+ At the top of each controller (for APIs) should be:
77
+
78
+ ```ruby
79
+ respond_to_json_xml
80
+ ```
81
+
82
+ This defines `respond_to :json, :xml`.
83
+
84
+ making these responders good to use for defaults:
85
+
86
+ ```ruby
87
+ respond_with_action :show # Good for the end of a create to show the created object
88
+ render_action :show
89
+ respond_to_empty # Render empty `result`, fill in `metadata`, `error` if necessary
90
+ render_empty
91
+ ```
92
+
93
+ #### Resource finder
94
+
95
+ `find_resource` will automatically find a resource:
96
+
97
+ ```ruby
98
+ class PostsController < ApplicationController
99
+ before_filter :find_resource
100
+ def show
101
+ respond_with
102
+ end
103
+ end
104
+
105
+ curl http://localhost:3000/posts/1 # finds Post 1 and renders
106
+ curl http://localhost:3000/posts/1
107
+ # => {"metadata":{},"error":{"status":404,"messages":["Record not found"]},"result":null}
108
+
109
+ # can also customize the find_resource with `finder` and `value`
110
+ # were `finder` is column and `value` is the value of the column
111
+ ```
112
+
113
+ #### Param helpers
114
+
115
+ ```ruby
116
+ query_params # Only params on the query string
117
+ post_params # POST params
118
+ object_params # Either params under the object name (ie. {"user":".."} or all POST params
119
+ object_name # singularized controller name for finding object_params
120
+ ```
121
+
122
+ #### General workflow helpers
123
+
124
+ Helpers:
125
+
126
+ ```ruby
127
+ force_ssl! # raises Errors::ForceSSL
128
+ drop_meta! # we don't want the requester to get data like current_user, etc.
129
+ drop_meta? # Did we call `drop_meta!`?
130
+ format # The format passed from the request OR JSON
131
+ render_nil_format # This is for rendering nils in json or XML (XML is blank, JSON is "null")
132
+ safe_json_load # If you've already manually rendered some to json this helper safely loads it to a hash for re-JSONing
133
+ ```
134
+
135
+ Errors are rescued to make for easier API workflow and responding:
136
+
137
+ ```ruby
138
+ Axel::Errors::ForceSSL # Drop meta
139
+ # Status: Forbidden
140
+ # Message: SSL is required
141
+
142
+ ActiveRecord::RecordNotFound # Status: 404
143
+ # Message: Record not found
144
+
145
+ Axel::Errors::NotAuthorized # Status: 401
146
+ # Message: User not authorized
147
+
148
+ ActiveModel::MassAssignmentSecurity::Error # Status: 422
149
+ # Message: Unacceptable parameter being used
150
+ ```
151
+
152
+ ### Interservice Helpers
153
+
154
+ #### Some setup examples
155
+
156
+ ```ruby
157
+ Axel.config do |config|
158
+ config.add_resource :user_service,
159
+ :group,
160
+ service: { url: "https://user-service.your-platform.com" }
161
+
162
+ # Custom Path (otherwise defaults to plural of the resource_name (:user => "/users"))
163
+ # config.add_resource :user_service,
164
+ # :user,
165
+ # service: { url: "https://user-service.your-platform.com" },
166
+ # attributes: [:user_name, :first_name],
167
+ # path: "owner"
168
+ end
169
+
170
+ class Group < Axel::ServiceResource::Base
171
+ # Let's say your class doesn't match the configured resource, you can:
172
+ resource_name :group
173
+
174
+ # Setup fields (gets accessors, all available in #attributes)
175
+ field :name
176
+ field :owner_id
177
+ field :owner_type
178
+ field :uri
179
+
180
+ route "/groups/mine", :mine
181
+ route "/user/:user_id/groups", :by_user_id
182
+
183
+ # Attached to every Group request, you can define instance defaults as well
184
+ def self.default_request_options
185
+ { headers: { "Accepts" => "stuff!", Authorization: "Bearer #{some_access_token}" } }
186
+ end
187
+ end
188
+
189
+ group = Group.new name: "test", owner_id: 1, owner_type: "Organization", uri: "blargh"
190
+ group.save
191
+
192
+ my_groups = Group.mine
193
+ user_groups = Group.by_user_id(1)
194
+ user_groups = Group.by_user_id(user_id: 1)
195
+
196
+ a_group = Group.find(1)
197
+ ```
198
+
199
+ #### Related data!
200
+
201
+ ```ruby
202
+ class User < Axel::ServiceResource::Base
203
+ has_many :personas
204
+ has_one :email_address, class: Email, included: true
205
+ end
206
+
207
+ class Email < Axel::ServiceResource::Base
208
+ belongs_to :user, find_nested: true
209
+ end
210
+
211
+ class Persona < Axel::ServiceResource::Base
212
+ belongs_to :user
213
+ end
214
+
215
+ u = User.find(1)
216
+ u.personas # => API call to /users/1/personas puts data in an array of Persona objects
217
+ u.email_address # => Uses `email_address` in the User data to put into Email objects
218
+ Persona.find(1).user # => API call to /users/#{persona.user_id} fills User object
219
+ Email.find(1).user # => API call to /personas/1/user fills User Object
220
+ ```
221
+
222
+ #### Some Chainable Query methods
223
+ ```ruby
224
+ Group.where(name: "test")
225
+ # => https://user-service.your-platform.com/groups?name=test
226
+
227
+ Group.all params: { name: "test" }, body: jsonified_stuffs, headers: {}, method: :post
228
+
229
+ Group.uri("https://user-service.dev/groups").where(name: "Jon").all(headers: {})
230
+ # => http://user-service.dev/groups?name=Jon
231
+
232
+ Group.uri("https://user-service.dev").at_path("/other_groups_path").where name: "test"
233
+ # => http://user-service.dev/other_groups_path?name=test
234
+
235
+ Group.where(name: "Jon").all(headers: {}).none
236
+ # => [] # Will always be empty array
237
+
238
+ Group.none.where(name: "Jon")
239
+ # => [] # can chain
240
+
241
+ Group.without_default_path.at_path("groupies")
242
+ # => https://user-service.your-platform.com/groupies
243
+
244
+ # Enumerable works!
245
+ Groups.where(name: "test").each { |g| puts e.attributes.inspect }
246
+ groups = Groups.where(name: "test").to_a
247
+
248
+ # drop cached JSON, then you can requery
249
+ groups.reload.where(owner_id: 1)
250
+ ```
251
+
252
+ #### More General Usage
253
+ ``` ruby
254
+ new_user.metadata # => { .. } # Metadata section of JSON output
255
+ new_user.metadata[:current_user] # => { "id"=>1, "user_name"=>"admin", "first_name"=>"Happy", "last_name"=>"Gilmore", "uri"=>"http://user-service.dev/users/1"}
256
+ new_user.errors.status_code # => 200
257
+ new_user.errors.messages # => []
258
+ new_user.result # => { ... } # Main envelope JSON body
259
+ ```
260
+ For more info on what the requester is and can do check out
261
+ [Axel::ServiceResource::Base][srb]
262
+
263
+ ## Contributing
264
+
265
+ 1. Fork it
266
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
267
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
268
+ 4. Push to the branch (`git push origin my-new-feature`)
269
+ 5. Create new Pull Request
270
+
271
+ [srb]: http://github.com/sportngin/axel/tree/master/app/models/axel/service_resource/base.rb
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env rake
2
+ require "rspec/core/rake_task"
3
+ require "bundler/gem_tasks"
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ namespace :spec do
8
+ RSpec::Core::RakeTask.new(:docs) do |t|
9
+ t.rspec_opts = ["--format doc"]
10
+ end
11
+ end
12
+
13
+ task :default => :spec
@@ -0,0 +1,86 @@
1
+ module Axel
2
+ class ApiProxy < ServiceResource::Base
3
+ attr_reader :endpoint
4
+ attr_reader :services
5
+ attr_reader :request_options
6
+
7
+ def self.cache_file
8
+ cache_dir.join("api_registry_cache.json")
9
+ end
10
+
11
+ def self.cache_dir
12
+ Rails.root.join("cache")
13
+ end
14
+
15
+ def self.build(_, response)
16
+ if response.success?
17
+ MultiJson.load(response.body)
18
+ else
19
+ {}
20
+ end
21
+ rescue MultiJson::DecodeError
22
+ {}
23
+ end
24
+
25
+ def initialize(endpoint, request_options = {})
26
+ @endpoint = endpoint
27
+ @request_options = {}
28
+ end
29
+
30
+ def register!
31
+ resource_settings.each do |resource_setting|
32
+ Axel.config do |config|
33
+ config.add_resource extract_service_name(resource_setting["service"]),
34
+ extract_resource_name(resource_setting["path"]),
35
+ service: { url: resource_setting["service"] }
36
+ end
37
+ end
38
+ end
39
+
40
+ def make_cache
41
+ Dir.exists?(self.class.cache_dir) ? true : Dir.mkdir(self.class.cache_dir)
42
+ end
43
+ private :make_cache
44
+
45
+ def write_cache(to_cache)
46
+ make_cache
47
+ File.open(self.class.cache_file, 'w') { |file| file.write to_cache.to_json }
48
+ to_cache
49
+ end
50
+ private :write_cache
51
+
52
+ def open_json(string_data)
53
+ begin
54
+ MultiJson.load string_data
55
+ rescue MultiJson::DecodeError
56
+ []
57
+ end
58
+ end
59
+ private :open_json
60
+
61
+ def read_cache
62
+ File.exists?(self.class.cache_file) ? open_json(File.open(self.class.cache_file).read) : []
63
+ end
64
+ private :read_cache
65
+
66
+ def resource_settings
67
+ fresh = self.class.request(endpoint, "/registry.json", request_options)
68
+ if fresh.has_key? "routes"
69
+ write_cache fresh["routes"]
70
+ else
71
+ read_cache
72
+ end
73
+ end
74
+ private :resource_settings
75
+
76
+ def extract_service_name(service_url)
77
+ service_url.gsub(/http[s]*\:\/\//,"").gsub(/\..*$/, "").underscore
78
+ end
79
+ private :extract_service_name
80
+
81
+ def extract_resource_name(resource_path)
82
+ resource_path.gsub(/^\//, "")
83
+ end
84
+ private :extract_resource_name
85
+ end
86
+ end