itglue 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 577a952aa71445a0982220ba9519ef3e8ff30abb
4
+ data.tar.gz: e00b1ce90a9bcd6a9b56935b72ad3953b85dcde0
5
+ SHA512:
6
+ metadata.gz: 430a99fea58b66419afbefa28449d4bc3cedf0b3e457c9e61bce8e3b6b131c6585d94b0dacb39e8b22bb5acd5019c3993dc7d5b0012cb0711d06c6f4ac049285
7
+ data.tar.gz: 1ca0c09f3127a634d5dd087a38666ed8bbbb9a8cd6007569bfa86a6d539dd3a1e9c23409777e767c63ecf8191ef49f811cda42538b2f1db47f086806120f9ae7
@@ -0,0 +1,12 @@
1
+ Gemfile.lock
2
+ .DS_Store
3
+ /.bundle/
4
+ /.yardoc
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
11
+ .rspec_status
12
+ .ruby-version
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.0
5
+ before_install: gem install bundler -v 1.16.1
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in itglue.gemspec
6
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Ben Silva
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,104 @@
1
+ # ITGlue
2
+
3
+ A wrapper for the [ITGlue API](https://api.itglue.com/developer/).
4
+
5
+ ## Installation
6
+
7
+ ```ruby
8
+ gem 'itglue'
9
+ ```
10
+
11
+ ## Requirements
12
+
13
+ * Ruby 2.0.0 or higher
14
+
15
+ ## Setup
16
+
17
+ ### Authentication
18
+
19
+ For now this gem only supports API Key authentication.
20
+
21
+ ### Configuration
22
+
23
+ ```ruby
24
+ require 'itglue'
25
+
26
+ ITGlue.configure do |config|
27
+ config.itglue_api_key = 'ITG.b94e901420fe7cb163a364b451f172d9.P3nMIV9EDp1Xb7h4-sO7WDU0S2R5DgC-fu2DsTxBkW7eZHRp0y4ODRQ51se1c24m' config.itglue_api_base_uri = 'https://api.itglue.com'
28
+ config.logger = ::Logger.new(STDOUT)
29
+ end
30
+ ```
31
+
32
+ ## Usage
33
+
34
+ ### Basics
35
+
36
+ Get all organizations
37
+ ```ruby
38
+ organizations = ITGlue::Organization.get
39
+ #=> [#<ITGlue::Organization id: 123 name: "Happy Frog", description: nil, ...>, <ITGlue::Organization id: 124 name: "Vancity Superstars", description: nil, ...>, ...]
40
+ ```
41
+ Get organizations with a filter
42
+ ```ruby
43
+ organizations = ITGlue::Organization.filter(name: 'Happy Frog')
44
+ #=> [#<ITGlue::Organization id: 123 name: "Happy Frog", description: nil, ...>]
45
+ ```
46
+ Get organization by id
47
+ ```ruby
48
+ organization = ITGlue::Organization.find(123)
49
+ #=> #<ITGlue::Organization id: 123 name: "Ben's Gem Test", description: nil, ...>]
50
+ ```
51
+ Get configurations for a specific organization
52
+ ```ruby
53
+ configuration = ITGlue::Organization.get_nested(organization)
54
+ ```
55
+
56
+ ### Client
57
+
58
+ You can also directly instantiate a client and handle the data and response directly.
59
+ ```ruby
60
+ client = ITGlue::Client.new
61
+ #=> #<ITGlue::Client:0x007fd7eb032d00 ...>
62
+ query = { filter: { name: 'HP' } }
63
+ client.get(:configurations, { parent: organization }, { query: query })
64
+ # => [
65
+ # {
66
+ # id: 456,
67
+ # type: "configurations",
68
+ # attributes: {
69
+ # organization_id: 123,
70
+ # organization_name: "Happy Frog",
71
+ # ...
72
+ # }
73
+ # },
74
+ # ...
75
+ # ]
76
+ ```
77
+ A get request such as the one above will handle generating the route and pagination. If you want to handle these yourself, you can use 'execute'
78
+ ```ruby
79
+ client.execute(:get, '/organizations/31131/relationships/configurations', nil, {query: {filter: {name: 'HP'}}})
80
+ # => {
81
+ # "data"=> [
82
+ # {
83
+ # "id"=>"23943",
84
+ # "type"=>"configurations",
85
+ # "attributes"=> {
86
+ # "organization-id"=>31131,
87
+ # "organization-name"=>"Ben's Gem Test",
88
+ # ...
89
+ # }
90
+ # },
91
+ # ...
92
+ # ],
93
+ # "links"=>{},
94
+ # "meta"=>{"current-page"=>1, "next-page"=>nil, "prev-page"=>nil, "total-pages"=>1, "total-count"=>1, "filters"=>{}}
95
+ # }
96
+ ```
97
+
98
+ ## Contributing
99
+
100
+ Bug reports and pull requests are welcome on GitHub at https://github.com/b-loyola/itglue.
101
+
102
+ ## License
103
+
104
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "itglue"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,30 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "itglue/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "itglue"
8
+ spec.version = ITGlue::VERSION
9
+ spec.authors = ["Ben Silva"]
10
+ spec.email = ["berna.loyola@gmail.com"]
11
+
12
+ spec.summary = %q{A simple wrapper for the IT Glue API}
13
+ spec.description = %q{This gem provides a client for interactiong with the IT Glue API}
14
+ spec.homepage = "https://github.com/b-loyola/itglue"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.16"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rspec", "~> 3.0"
27
+
28
+ spec.add_dependency "httparty", "~> 0.16", ">= 0.15.7"
29
+ spec.add_dependency "activesupport", "~> 5.2", ">= 3.0.0"
30
+ end
@@ -0,0 +1,29 @@
1
+ module ITGlue
2
+ class ITGlueError < StandardError; end
3
+
4
+ class << self
5
+ attr_writer :config
6
+
7
+ def config
8
+ @config ||= Config.new
9
+ end
10
+
11
+ def configure
12
+ yield(config)
13
+ config
14
+ end
15
+ end
16
+
17
+ class Config
18
+ DEFAULT_PAGE_SIZE = 500
19
+ attr_accessor :itglue_api_key, :itglue_api_base_uri, :logger, :default_page_size
20
+
21
+ def initialize
22
+ @default_page_size = DEFAULT_PAGE_SIZE
23
+ end
24
+ end
25
+ end
26
+
27
+ require 'itglue/version'
28
+ require 'itglue/client'
29
+ require 'itglue/asset'
@@ -0,0 +1,8 @@
1
+ Dir[File.join(File.dirname(__FILE__), 'asset/*.rb')].each {|file| require file }
2
+
3
+ module ITGlue
4
+ module Asset
5
+ class ITGlueAssetError < ITGlueError; end
6
+ class MethodNotAvailable < ITGlueAssetError; end
7
+ end
8
+ end
@@ -0,0 +1,180 @@
1
+ require 'active_support/core_ext/string/inflections'
2
+ require 'itglue/asset/base/relatable'
3
+ require 'itglue/asset/base/attributes'
4
+
5
+ module ITGlue
6
+ module Asset
7
+ class Base
8
+ extend Relatable
9
+
10
+ class << self
11
+ # Override in subclasses if required
12
+ def asset_type
13
+ raise ITGlueAssetError.new('no asset_type for base') if self == Base
14
+ self.name.demodulize.pluralize.underscore.to_sym
15
+ end
16
+
17
+ # Instantiates a record from data payload
18
+ # @param data [Hash] the data payload
19
+ # E.g.: { id: 1, type: 'organizations', attributes: {name: 'Happy Frog', ...} }
20
+ # @return [ITGlue::Asset] the record instance
21
+ def new_from_payload(data)
22
+ raise_method_not_available(__method__, 'not available for Base') if self == Base
23
+ asset = self.new(data[:attributes])
24
+ asset.id = data[:id]
25
+ asset.type = data[:type]
26
+ asset
27
+ end
28
+
29
+ # Executes a get request through the top-level path
30
+ # E.g. GET '/configurations'
31
+ # @return [Array<ITGlue::Asset>] an array of asset instances
32
+ def get
33
+ raise_method_not_available(__method__, 'is nested asset') if nested_asset?
34
+ assets = client.get(asset_type)
35
+ assets.map { |data| self.new_from_payload(data) }
36
+ end
37
+
38
+ # Executes a get request through the nested asset path
39
+ # E.g. GET 'organizations/:organization_id/relationships/configurations'
40
+ # @param parent [ITGlue::Asset] the parent asset
41
+ # @return [Array<ITGlue::Asset>] an array of asset instances
42
+ def get_nested(parent)
43
+ raise_method_not_available(__method__, 'is top-level asset') unless parent_type
44
+ path_options = { parent: parent }
45
+ assets = client.get(asset_type, path_options)
46
+ assets.map { |data| self.new_from_payload(data) }
47
+ end
48
+
49
+ # Executes a get request through the top-level path, with a filter query
50
+ # E.g. GET '/configurations?filter[name]=HP-01'
51
+ # @param filter [Hash|String] the parameters to filter by
52
+ # @return [Array<ITGlue::Asset>] an array of asset instances
53
+ def filter(filter)
54
+ raise_method_not_available(__method__, 'is nested asset') if nested_asset?
55
+ assets = client.get(asset_type, {}, { query: { filter: filter } })
56
+ assets.map { |data| self.new_from_payload(data) }
57
+ end
58
+
59
+ # Executes a get request through the top-level path for a specific asset
60
+ # E.g. GET '/configurations/1'
61
+ # @param id [Integer] the id of the asset
62
+ # @return [ITGlue::Asset] the asset instance
63
+ def find(id)
64
+ data = client.get(asset_type, id: id )
65
+ self.new_from_payload(data)
66
+ end
67
+
68
+ def client
69
+ @@client ||= Client.new
70
+ end
71
+
72
+ protected
73
+
74
+ def raise_method_not_available(method_name, reason)
75
+ error_msg = "method '#{method_name}' is not available for #{asset_type}: #{reason}"
76
+ raise MethodNotAvailable.new(error_msg)
77
+ end
78
+ end
79
+
80
+ attr_accessor :id, :type, :attributes
81
+
82
+ def initialize(attributes = {})
83
+ raise ITGlueAssetError.new('cannot instantiate base') if self == Base
84
+ @attributes = Attributes.new(attributes)
85
+ end
86
+
87
+ def asset_type
88
+ self.class.asset_type
89
+ end
90
+
91
+ def inspect
92
+ string = "#<#{self.class.name} id: #{self.id || 'nil'} "
93
+ fields = @attributes.keys.map { |field| "#{field}: #{@attributes.inspect_field(field)}" }
94
+ string << fields.join(", ") << ">"
95
+ end
96
+
97
+ def dup
98
+ dup = self.class.new(self.attributes)
99
+ dup.type = self.type
100
+ dup
101
+ end
102
+
103
+ def assign_attributes(attributes)
104
+ raise ArgumentError.new('attributtes must be a Hash') unless attributes.is_a?(Hash)
105
+ attributes.each do |attribute, value|
106
+ @attributes[attribute] = value
107
+ end
108
+ end
109
+
110
+ def changed_attributes
111
+ @attributes.changes
112
+ end
113
+
114
+ def remove_attribute(key)
115
+ @attributes.remove_attribute(key)
116
+ end
117
+
118
+ def new_asset?
119
+ !self.id
120
+ end
121
+
122
+ def save
123
+ new_asset? ? create : update
124
+ end
125
+
126
+ def changed?
127
+ !changed_attributes.empty?
128
+ end
129
+
130
+ def [](attribute)
131
+ @attributes[attribute]
132
+ end
133
+
134
+ def []=(attribute, value)
135
+ @attributes.assign_attribute(attribute, value)
136
+ end
137
+
138
+ def method_missing(method, *args)
139
+ method_name = method.to_s
140
+ arg_count = args.length
141
+ if method_name.chomp!('=')
142
+ raise ArgumentError.new("wrong number of arguments (#{arg_count} for 1)") if arg_count != 1
143
+ @attributes.assign_attribute(method_name, args[0])
144
+ elsif arg_count == 0
145
+ @attributes[method]
146
+ else
147
+ super
148
+ end
149
+ end
150
+
151
+ private
152
+
153
+ def create
154
+ data = self.class.client.post(asset_type, payload)
155
+ reload_from_data(data)
156
+ end
157
+
158
+ def update
159
+ data = self.class.client.patch(asset_type, payload, id: id )
160
+ reload_from_data(data)
161
+ end
162
+
163
+ def payload
164
+ {
165
+ data: {
166
+ type: asset_type,
167
+ attributes: attributes.attributes_hash
168
+ }
169
+ }
170
+ end
171
+
172
+ def reload_from_data(data)
173
+ @attributes = Attributes.new(data[:attributes])
174
+ self.type = data[:type]
175
+ self.id = data[:id]
176
+ self
177
+ end
178
+ end
179
+ end
180
+ end
@@ -0,0 +1,44 @@
1
+ module ITGlue
2
+ module Asset
3
+ class Attributes < OpenStruct
4
+ def initialize(*args)
5
+ @changed_attribute_keys = []
6
+ super
7
+ end
8
+
9
+ def assign_attribute(key, value)
10
+ @changed_attribute_keys << key.to_sym
11
+ self[key] = value
12
+ end
13
+
14
+ def remove_attribute(key)
15
+ @changed_attribute_keys.delete(key)
16
+ self.delete_field(key)
17
+ end
18
+
19
+ def keys
20
+ self.to_h.keys
21
+ end
22
+
23
+ def attributes_hash
24
+ self.to_h
25
+ end
26
+
27
+ def inspect_field(field)
28
+ value = self[field]
29
+ if value.is_a?(String)
30
+ value.length > 100 ? "\"#{value[0..100]}...\"" : "\"#{value}\""
31
+ else
32
+ value.inspect
33
+ end
34
+ end
35
+
36
+ def changes
37
+ attributes_hash = self.attributes_hash
38
+ @changed_attribute_keys.each_with_object({}) do |key, changes|
39
+ changes[key] = attributes_hash[key]
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,37 @@
1
+ module ITGlue
2
+ module Asset
3
+ module Relatable
4
+ def parent(parent_type, options = {})
5
+ @parent_type = parent_type.to_s.pluralize
6
+ unless options[:no_association]
7
+ define_method parent_type do
8
+ parent_id = self.send("#{parent_type}_id")
9
+ "ITGlue::#{parent_type.to_s.classify}".constantize.find(parent_id)
10
+ end
11
+ end
12
+ end
13
+
14
+ def children(*child_types)
15
+ child_types.each do |child_type|
16
+ define_method child_type do |options = {}|
17
+ "ITGlue::#{child_type.to_s.classify}".constantize.get_nested(self, options)
18
+ end
19
+ end
20
+ end
21
+
22
+ protected
23
+
24
+ def nested_asset
25
+ @nested_asset = true
26
+ end
27
+
28
+ def nested_asset?
29
+ !!@nested_asset
30
+ end
31
+
32
+ def parent_type
33
+ @parent_type
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,6 @@
1
+ module ITGlue
2
+ class Configuration < Asset::Base
3
+ parent :organization
4
+ children :configuration_interfaces
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module ITGlue
2
+ class ConfigurationInterface < Asset::Base
3
+ parent :configuration, no_association: true
4
+ nested_asset
5
+ end
6
+ end
@@ -0,0 +1,4 @@
1
+ module ITGlue
2
+ class ConfigurationStatus < Asset::Base
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module ITGlue
2
+ class ConfigurationType < Asset::Base
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module ITGlue
2
+ class Organization < Asset::Base
3
+ end
4
+ end
@@ -0,0 +1,119 @@
1
+ require 'httparty'
2
+ require 'itglue/client/mapper'
3
+ require 'itglue/client/path_processor'
4
+
5
+ module ITGlue
6
+ class ClientError < ITGlueError; end
7
+ class AssetNotFoundError < ClientError; end
8
+ class ServerError < ClientError; end
9
+ class UnexpectedResponseError < ClientError; end
10
+
11
+ class Client
12
+ include HTTParty
13
+
14
+ def initialize
15
+ raise ClientError.new('itglue_api_key not configured') unless ITGlue.config.itglue_api_key
16
+ raise ClientError.new('itglue_api_base_uri not configured') unless ITGlue.config.itglue_api_base_uri
17
+ @itglue_api_key = ITGlue.config.itglue_api_key
18
+ @default_page_size = ITGlue.config.default_page_size
19
+ self.class.base_uri ITGlue.config.itglue_api_base_uri
20
+ self.class.logger ITGlue.config.logger
21
+ end
22
+
23
+ def execute(http_method, path, payload = nil, options = {})
24
+ process_request(http_method, path, payload, options)
25
+ end
26
+
27
+ def get(asset_type, path_options = {}, options = {})
28
+ response = process_request(:get, process_path(asset_type, path_options), nil, options)
29
+ data = get_remaining_data(response, options)
30
+ prepare_data(data)
31
+ end
32
+
33
+ def patch(asset_type, payload, path_options = {}, options = {})
34
+ response = process_request(:patch, process_path(asset_type, path_options), payload, options)
35
+ prepare_data(response['data'])
36
+ end
37
+
38
+ def post(asset_type, payload, path_options = {}, options = {})
39
+ response = process_request(:post, process_path(asset_type, path_options), payload, options)
40
+ prepare_data(response['data'])
41
+ end
42
+
43
+ private
44
+
45
+ def get_remaining_data(response, options)
46
+ return response['data'] unless response['data'].is_a?(Array)
47
+ data = response['data']
48
+ loop do
49
+ break if response['meta'] && response['meta']['next-page'].nil?
50
+ response = process_request(:get, response['links']['next'], nil, options)
51
+ data += response['data']
52
+ end
53
+ data
54
+ end
55
+
56
+ def default_headers
57
+ @default_headers ||= {
58
+ 'Content-Type' => 'application/vnd.api+json',
59
+ 'x-api-key' => @itglue_api_key
60
+ }
61
+ end
62
+
63
+ def process_path(asset_type, path_options)
64
+ PathProcessor.process(asset_type, path_options)
65
+ end
66
+
67
+ def prepare_data(data)
68
+ Mapper.map(data)
69
+ end
70
+
71
+ def process_request(http_method, path, payload, options)
72
+ options = process_options(options, payload)
73
+ response = self.class.send(http_method, path, options)
74
+ response.success? ? response : handle_response_errors(response)
75
+ end
76
+
77
+ def process_options(options, payload)
78
+ options.merge!(body: payload.to_json) if payload
79
+ options[:headers] = process_header_options(options[:headers])
80
+ options[:query] = process_query_options(options[:query])
81
+ options
82
+ end
83
+
84
+ def process_header_options(header_options)
85
+ return default_headers unless header_options
86
+ raise ClientError.new('header option must be a Hash') unless header_options.is_a?(Hash)
87
+ default_headers.merge(header_options)
88
+ end
89
+
90
+ def process_query_options(query_options)
91
+ return { page: { size: @default_page_size } } unless query_options
92
+ raise ClientError.new('query option must be a Hash') unless query_options.is_a?(Hash)
93
+ if query_options[:page]
94
+ raise ClientError.new('query page option must be a Hash') unless query_options[:page].is_a?(Hash)
95
+ query_options[:page][:size] ||= @default_page_size
96
+ else
97
+ query_options[:page] = { size: @default_page_size }
98
+ end
99
+ query_options
100
+ end
101
+
102
+ def handle_response_errors(response)
103
+ if response.not_found?
104
+ raise AssetNotFoundError.new(error_message(response))
105
+ elsif response.client_error?
106
+ raise ClientError.new(error_message(response))
107
+ elsif response.server_error?
108
+ raise ServerError.new(error_message(response))
109
+ else
110
+ raise UnexpectedResponseError.new(error_message(response))
111
+ end
112
+ end
113
+
114
+ def error_message(response)
115
+ message = "Request failed with error code #{response.code}"
116
+ response.nil? ? message : "#{message} and body: #{response.parsed_response}"
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,41 @@
1
+ require 'active_support/core_ext/string/inflections'
2
+
3
+ module ITGlue
4
+ class Client
5
+ class Mapper
6
+ def self.map(raw_data)
7
+ self.new(raw_data).format
8
+ end
9
+
10
+ def initialize(raw_data)
11
+ @raw_data = raw_data
12
+ end
13
+
14
+ def format
15
+ collection? ? format_collection(@raw_data) : format_object(@raw_data)
16
+ end
17
+
18
+ private
19
+
20
+ def collection?
21
+ @raw_data.is_a?(Array)
22
+ end
23
+
24
+ def format_collection(data)
25
+ data.map { |d| format_object(d) }
26
+ end
27
+
28
+ def format_object(data)
29
+ {
30
+ id: data['id'].to_i,
31
+ type: data['type'],
32
+ attributes: transform_keys(data['attributes'])
33
+ }
34
+ end
35
+
36
+ def transform_keys(attributes)
37
+ attributes.map { |key, value| [key.underscore.to_sym, value] }.to_h
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,56 @@
1
+ module ITGlue
2
+ class Client
3
+ class PathProcessor
4
+ def self.process(asset_type, options = {})
5
+ self.new(asset_type, options).path
6
+ end
7
+
8
+ # @param asset_type [Symbol|String] the pluralized asset type name
9
+ # @param options [Hash] valid options:
10
+ # parent [ITGlue::Asset] the parent instance
11
+ # id [Integer] the asset id
12
+ def initialize(asset_type, options = {})
13
+ @asset_type = asset_type
14
+ @options = options
15
+ @path_array = []
16
+ end
17
+
18
+ def path
19
+ @path ||= path_array.unshift('').join('/')
20
+ end
21
+
22
+ private
23
+
24
+ def parent
25
+ @options[:parent]
26
+ end
27
+
28
+ def id
29
+ @options[:id]
30
+ end
31
+
32
+ def path_array
33
+ return @path_array if @processed
34
+ append_parent if parent
35
+ append_asset_type
36
+ append_id if id
37
+ @processed = true
38
+ @path_array
39
+ end
40
+
41
+ def append_parent
42
+ @path_array << parent.asset_type
43
+ @path_array << parent.id
44
+ @path_array << :relationships
45
+ end
46
+
47
+ def append_asset_type
48
+ @path_array << @asset_type
49
+ end
50
+
51
+ def append_id
52
+ @path_array << id
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,3 @@
1
+ module ITGlue
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,150 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: itglue
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ben Silva
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-05-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: httparty
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.16'
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 0.15.7
65
+ type: :runtime
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - "~>"
70
+ - !ruby/object:Gem::Version
71
+ version: '0.16'
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 0.15.7
75
+ - !ruby/object:Gem::Dependency
76
+ name: activesupport
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '5.2'
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 3.0.0
85
+ type: :runtime
86
+ prerelease: false
87
+ version_requirements: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - "~>"
90
+ - !ruby/object:Gem::Version
91
+ version: '5.2'
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: 3.0.0
95
+ description: This gem provides a client for interactiong with the IT Glue API
96
+ email:
97
+ - berna.loyola@gmail.com
98
+ executables: []
99
+ extensions: []
100
+ extra_rdoc_files: []
101
+ files:
102
+ - ".gitignore"
103
+ - ".rspec"
104
+ - ".travis.yml"
105
+ - Gemfile
106
+ - LICENSE.txt
107
+ - README.md
108
+ - Rakefile
109
+ - bin/console
110
+ - bin/setup
111
+ - itglue.gemspec
112
+ - lib/itglue.rb
113
+ - lib/itglue/asset.rb
114
+ - lib/itglue/asset/base.rb
115
+ - lib/itglue/asset/base/attributes.rb
116
+ - lib/itglue/asset/base/relatable.rb
117
+ - lib/itglue/asset/configuration.rb
118
+ - lib/itglue/asset/configuration_interface.rb
119
+ - lib/itglue/asset/configuration_status.rb
120
+ - lib/itglue/asset/configuration_type.rb
121
+ - lib/itglue/asset/organization.rb
122
+ - lib/itglue/client.rb
123
+ - lib/itglue/client/mapper.rb
124
+ - lib/itglue/client/path_processor.rb
125
+ - lib/itglue/version.rb
126
+ homepage: https://github.com/b-loyola/itglue
127
+ licenses:
128
+ - MIT
129
+ metadata: {}
130
+ post_install_message:
131
+ rdoc_options: []
132
+ require_paths:
133
+ - lib
134
+ required_ruby_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ required_rubygems_version: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ requirements: []
145
+ rubyforge_project:
146
+ rubygems_version: 2.5.1
147
+ signing_key:
148
+ specification_version: 4
149
+ summary: A simple wrapper for the IT Glue API
150
+ test_files: []