itglue 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +104 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/itglue.gemspec +30 -0
- data/lib/itglue.rb +29 -0
- data/lib/itglue/asset.rb +8 -0
- data/lib/itglue/asset/base.rb +180 -0
- data/lib/itglue/asset/base/attributes.rb +44 -0
- data/lib/itglue/asset/base/relatable.rb +37 -0
- data/lib/itglue/asset/configuration.rb +6 -0
- data/lib/itglue/asset/configuration_interface.rb +6 -0
- data/lib/itglue/asset/configuration_status.rb +4 -0
- data/lib/itglue/asset/configuration_type.rb +4 -0
- data/lib/itglue/asset/organization.rb +4 -0
- data/lib/itglue/client.rb +119 -0
- data/lib/itglue/client/mapper.rb +41 -0
- data/lib/itglue/client/path_processor.rb +56 -0
- data/lib/itglue/version.rb +3 -0
- metadata +150 -0
    
        checksums.yaml
    ADDED
    
    | @@ -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
         | 
    
        data/.gitignore
    ADDED
    
    
    
        data/.rspec
    ADDED
    
    
    
        data/.travis.yml
    ADDED
    
    
    
        data/Gemfile
    ADDED
    
    
    
        data/LICENSE.txt
    ADDED
    
    | @@ -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.
         | 
    
        data/README.md
    ADDED
    
    | @@ -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).
         | 
    
        data/Rakefile
    ADDED
    
    
    
        data/bin/console
    ADDED
    
    | @@ -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__)
         | 
    
        data/bin/setup
    ADDED
    
    
    
        data/itglue.gemspec
    ADDED
    
    | @@ -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
         | 
    
        data/lib/itglue.rb
    ADDED
    
    | @@ -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'
         | 
    
        data/lib/itglue/asset.rb
    ADDED
    
    
| @@ -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,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
         | 
    
        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: []
         |