oeh-client 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4f692b3e09448980d130c5b6f9b031c4238211fe
4
+ data.tar.gz: 085a267a6504f505244e725b9081f49976f6fe35
5
+ SHA512:
6
+ metadata.gz: 92571201066617e1bc99fed7bdd627b708a91b6253d82eefc90eb399db8527aab8b7dcc4f5ccceaa24805fc6d0a075e850a0d1e7767346a3ac31483ee14c19e8
7
+ data.tar.gz: 3b02be0c9729a14531c489b267552ebe8f816ba66707b7c540524d918007905ae52ebf4880413c69a0a3f332c74c22af1bad412ed94ac5262364c5932711a018
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .DS_Store
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ before_install: gem install bundler -v 1.10.5
@@ -0,0 +1,13 @@
1
+ # Contributor Code of Conduct
2
+
3
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.
6
+
7
+ Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
8
+
9
+ Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
10
+
11
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
12
+
13
+ This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in oeh-client.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Jason Balliet
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,41 @@
1
+ # OEHClient
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/oehclient`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'oeh-client'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install oeh-client
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake false` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/oeh-client. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
36
+
37
+
38
+ ## License
39
+
40
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
41
+
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'test'
6
+ end
7
+
8
+ desc "Run tests"
9
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "oeh-client"
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
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
data/lib/oeh-client.rb ADDED
@@ -0,0 +1,2 @@
1
+ # More logical way to require 'rest-client'
2
+ require File.dirname(__FILE__) + '/oehclient'
data/lib/oeh_client.rb ADDED
@@ -0,0 +1,2 @@
1
+ # More logical way to require 'rest-client'
2
+ require File.dirname(__FILE__) + '/oehclient'
@@ -0,0 +1,59 @@
1
+ class OEHClient::Config::Space
2
+
3
+ attr_accessor :site_key, # The ONE Site KEY Value
4
+ :host, # The name of the HOST machine on thunderhead.com (ONEDEMO, EU2, NA4, etc..)
5
+ :api_key, # The API key provided in the ONE SETTINGS interface
6
+ :shared_secret, # The shared secret value provided in the ONE SETTINGS interface
7
+ :username # The fully-qualified username configured for access to the space
8
+
9
+
10
+ # ---- Class Methods
11
+
12
+ # create builds a new instance of the Site class, populats the attributes using the properties HASH provided
13
+ # and returns an instance of the class.
14
+ def self.create(properties={})
15
+
16
+ # create a new instance of the OHEClient::Space class
17
+ space_instance = OEHClient::Config::Space.new()
18
+
19
+ # assign all attributes from the passed properties hash
20
+ space_instance.site_key = properties[:site_key] if (properties.has_key?(:site_key))
21
+ space_instance.host = properties[:host] if (properties.has_key?(:host))
22
+ space_instance.api_key = properties[:api_key] if (properties.has_key?(:api_key))
23
+ space_instance.shared_secret = properties[:shared_secret] if (properties.has_key?(:shared_secret))
24
+ space_instance.username = properties[:username] if (properties.has_key?(:username))
25
+
26
+ # return the instance of the OEHClient::Site Class
27
+ space_instance
28
+
29
+ end
30
+
31
+
32
+ # ---- Instance Methods
33
+
34
+ # token is the method used to generate a new OAuth::AccessToken object based on the configuration of
35
+ # the related space
36
+ def token()
37
+
38
+ # raise the OEHClient::InvalidSpaceException the current instance is not valid
39
+ raise OEHClient::Exception::InvalidSpaceConfigException unless is_valid?
40
+
41
+ # Create the consumer and access token
42
+ oauth_consumer = OAuth::Consumer.new("#{@api_key}!#{@username}",
43
+ @shared_secret,
44
+ {:site => "#{OEHClient::Helper::Request::ONE_PROTOCOL}#{@host}#{OEHClient::Helper::Request::THUNDERHEAD_DOMAIN}",
45
+ :scheme => :header})
46
+ # return the access token
47
+ return(OAuth::AccessToken.new(oauth_consumer))
48
+
49
+ end
50
+
51
+ # is_valid determines if the current class has values for all the attributes. Each attribute is
52
+ # required with a non-nul / non-blank value to be considered valid
53
+ def is_valid?()
54
+ ((!@site_key.nil? && !@site_key.empty?) && (!@host.nil? && !@host.empty?) &&
55
+ (!@api_key.nil? && !@api_key.empty?) && (!@shared_secret.nil? && !@shared_secret.empty?) &&
56
+ (!@username.nil? && !@username.empty?))
57
+ end
58
+
59
+ end
@@ -0,0 +1,55 @@
1
+ require 'singleton'
2
+
3
+ class OEHClient::Config::SpaceManager
4
+ include Singleton
5
+
6
+
7
+ attr_accessor :spaces
8
+
9
+ # Constructor. Initialize the spaces collection as a new hash
10
+ def initialize
11
+ @spaces = Hash.new
12
+ end
13
+
14
+ # register_space is a wrapper method that converts the passed Hash object to an instance of the
15
+ # OEHClient::Config::Space object, which is passed to the register method
16
+ def register_space(space_config={})
17
+
18
+ # Pass a new instance of the space object to the register_space method
19
+ register(OEHClient::Config::Space.create(space_config))
20
+
21
+ end
22
+
23
+ # get_space returns the instance of the OEHClient::Config::Space
24
+ def get(site_key)
25
+
26
+ # raise the OEHClient::Exception::InvalidSpaceException if the space has not been registered
27
+ raise OEHClient::Exception::InvalidSpaceException unless (@spaces.has_key?(site_key))
28
+
29
+ # return the space configuration instance
30
+ @spaces[site_key]
31
+
32
+ end
33
+
34
+ private
35
+
36
+ # register adds the instance of the OEHClient::Config::Space object to the spaces hash, using the
37
+ # site_key value as the hash KEY
38
+ def register(space_instance)
39
+
40
+ # Raise OEHClient::Exception::InvalidSpaceException if the space instance is NOT valie
41
+ raise OEHClient::Exception::InvalidSpaceConfigException unless (space_instance.is_valid?)
42
+ # Raise the OEHClient::Exception::InvalidSpaceObjectException if the space_instance object is not
43
+ # the proper type of object (OEHClient::Config::Space)
44
+ raise OEHClient::Exception::InvalidSpaceObjectException unless (space_instance.kind_of?(OEHClient::Config::Space))
45
+
46
+ # Assign the space instance to the spaces collection
47
+ @spaces[space_instance.site_key] = space_instance
48
+
49
+ end
50
+
51
+
52
+
53
+
54
+
55
+ end
@@ -0,0 +1,11 @@
1
+
2
+ module OEHClient
3
+
4
+ module Config
5
+ end
6
+
7
+ end
8
+
9
+ require File.dirname(__FILE__) + '/config/space'
10
+ require File.dirname(__FILE__) + '/config/space_manager'
11
+
@@ -0,0 +1,55 @@
1
+
2
+ class OEHClient::Data::Node
3
+
4
+ attr_accessor :nodes
5
+
6
+ def initialize(data)
7
+
8
+ # Raise an exception if the data passed is not already a hash
9
+
10
+ # based on the type of object that is passed, create the proper attribute accessor
11
+ # to allow easy access to data. For example, a simple value in the structure called
12
+ # firstName will be represented in the object as my_structure.first_name. Simple
13
+ # object are represented as related node classes. For example a Preference node with
14
+ # an attribute of nonSmokingRoom will be represented as my_structure.preference.non_smoking_room
15
+ data.each do | key, value |
16
+ (value.kind_of?(Array) ? add_collection(key, value) : add_attribute(key, value))
17
+ end
18
+
19
+ end
20
+
21
+ private
22
+
23
+ # add_collection dynamically create an attr_accessor as an array of Oeh::Structure::Node
24
+ # classes related to the current instance of the object.
25
+ def add_collection(name, value_collection)
26
+
27
+ # initialize the array object that will act as the value of the attribute
28
+ node_collection = []
29
+
30
+ # for each hash in the array, add a new structure node
31
+ value_collection.each do | structure_node |
32
+ node_collection << OEHClient::Data::Structure.new(structure_node)
33
+ end
34
+ # add the arry of node objects to the accessor
35
+ add_attribute(name, node_collection)
36
+
37
+ end
38
+
39
+ # add_attribute dynamically creates an attr_accessor for the passed key_value pair either
40
+ # as a simple value attribute or as an instance of another Node class
41
+ def add_attribute(name, value)
42
+
43
+ # generate a ruby-friendly attribute accessor based on the name of the
44
+ # structure attribute
45
+ accessor_name = name.underscore
46
+ accessor_name.gsub!(/( )/, '_') if (accessor_name.match(/\s/))
47
+ # create the accessor in the current class and set the value based on the type
48
+ # of object that represents the value
49
+ self.class.send(:attr_accessor, accessor_name)
50
+ instance_variable_set("@#{accessor_name}", (value.kind_of?(Hash) ? OEHClient::Data::Node.new(value) : value))
51
+
52
+ end
53
+
54
+
55
+ end
@@ -0,0 +1,75 @@
1
+ class OEHClient::Data::Structure < OEHClient::Data::Node
2
+
3
+ API_PROFILES = "/profiles"
4
+
5
+ LABEL_CUSTOMER_KEY = "Customer Key"
6
+ LABEL_SITE_KEY = "Site Key"
7
+ LABEL_API_NAME = "API Name"
8
+
9
+ #
10
+ # Class Methods
11
+ #
12
+
13
+ # fetch makes the request to OEH for the structure and returns an instance of the structure
14
+ # based on the data in the configured structure
15
+ def self.fetch(parameters={})
16
+
17
+ # force the parameters empty hash if needed
18
+ parameters ||= Hash.new
19
+
20
+ # validate the parameters. The implementation expects a Hash object
21
+ if (!parameters.empty?)
22
+ # implementation expects a Hash that contains the Customer Key (:ck),
23
+ # Site Key (:sk), and API Name (:api) because they are required to get
24
+ # structure from OEH
25
+ if (parameters.has_key?(:ck) && parameters.has_key?(:sk) && parameters.has_key?(:api))
26
+
27
+ # set the values
28
+ customer_key = parameters[:ck]
29
+ api_name = parameters[:api]
30
+
31
+ # set the space based on the site key value that was passed
32
+ @space = OEHClient::Config::SpaceManager.instance.get(parameters[:sk]) if (parameters.has_key?(:sk))
33
+
34
+ # Use the OEHClient object to call OEH profiles API and create an instance
35
+ # of this class (OEHClient::Data::Structure) as the return value
36
+ response = OEHClient::Helper::Response.handle(OEHClient.get(@space.token,
37
+ OEHClient::Helper::Request.format_url(self.request_url(api_name), {:sk => @space.site_key, :ck => customer_key})))
38
+ # dynamically map the response object to a new OEHClient::Data::Structure class
39
+ OEHClient::Data::Structure.new(response)
40
+
41
+ else
42
+
43
+ # If the calling application passed a parameter Hash, but is missing key attributes,
44
+ # raise the Oeh::Exception::MissingParameterException with the name of each
45
+ # parameter
46
+ missing_parameters = []
47
+
48
+ missing_parameters << LABEL_CUSTOMER_KEY unless (parameters.has_key?(:ck))
49
+ missing_parameters << LABEL_SITE_KEY unless (parameters.has_key?(:sk))
50
+ missing_parameters << LABEL_API_NAME unless (parameters.has_key?(:api))
51
+
52
+ # raise the OEHClient::Exception::MIssingParameterException using the list of missing parameter
53
+ # labels that have been added to the collection
54
+ raise OEHClient::Exception::MissingParameterException.new(missing_parameters)
55
+
56
+ end
57
+
58
+ else
59
+
60
+ # if the parameters object is NIL then raise the OEHClient::Exception::MissingParameterException,
61
+ # passing the full set of expected parameter names
62
+ raise OEHClient::Exception::MissingParameterException.new([LABEL_CUSTOMER_KEY, LABEL_SITE_KEY, LABEL_API_NAME])
63
+
64
+ end
65
+
66
+
67
+ end
68
+
69
+ # request_url returns the fully-qualified URL to return a given structure
70
+ def self.request_url(api_name)
71
+ "#{OEHClient::Helper::Request::ONE_PROTOCOL}#{@space.host}#{OEHClient::Helper::Request::THUNDERHEAD_DOMAIN}#{OEHClient::Helper::Request::ONE_URI_PART}#{OEHClient::Helper::Request::API_URI_PART}#{OEHClient::Helper::Request::API_VERSION}#{API_PROFILES}/#{api_name}"
72
+ end
73
+
74
+
75
+ end
@@ -0,0 +1,10 @@
1
+
2
+ module OEHClient
3
+
4
+ module Data
5
+ end
6
+
7
+ end
8
+
9
+ require File.dirname(__FILE__) + '/data/node'
10
+ require File.dirname(__FILE__) + '/data/structure'
@@ -0,0 +1,64 @@
1
+ module OEHClient
2
+
3
+ module Exception
4
+
5
+ # Used when an invalid OAuth token is detected as part of the client-side API calls
6
+ class InvalidTokenException < ::Exception
7
+
8
+ end
9
+
10
+ # InvalidSpaceConfigException is used when a OEHClient::Space instance is missing one or more
11
+ # of the key data attributes
12
+ class InvalidSpaceConfigException < ::Exception
13
+
14
+ end
15
+
16
+ # InvalidSpaceException is used when a space is not configured
17
+ class InvalidSpaceException < ::Exception
18
+
19
+ end
20
+
21
+ # InvalideSpaceObjectException is used when a method expects a OEHClient::Config::Space object and
22
+ # the object passed is not of the same type
23
+ class InvalidSpaceObjectException < ::Exception
24
+
25
+ end
26
+
27
+ # HTTPRequestException is used to manage any REST error code that is returned by the OEH
28
+ # server
29
+ class HTTPRequestException < ::Exception
30
+
31
+ attr_accessor :http_code
32
+
33
+ # override the constructor to add the code value to exception class
34
+ def initialize(msg, code)
35
+ super(msg)
36
+ @http_code = code
37
+ end
38
+
39
+ end
40
+
41
+ # Missing ParameterException is used to identify the list of parameters that are required, but missing
42
+ # by a key method
43
+ class MissingParameterException < ::Exception
44
+
45
+ def initialize(parameter_list)
46
+
47
+ super("Missing the required parameters #{parameter_list.join(', ')}")
48
+ end
49
+
50
+ end
51
+
52
+ class IncorrectParameterTypeException < ::Exception
53
+
54
+
55
+ def initialize(expected_kind, passed_kind)
56
+
57
+ super("Incorrect Parameter Type. Expected #{expected_kind} but received #{passed_kind}")
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+
64
+ end
@@ -0,0 +1,66 @@
1
+ require 'erb'
2
+
3
+ module OEHClient
4
+
5
+ module Helper
6
+
7
+ module Request
8
+
9
+ ONE_PROTOCOL = "https://"
10
+ THUNDERHEAD_DOMAIN = ".thunderhead.com"
11
+ ONE_URI_PART = "/one/oauth1"
12
+
13
+ API_URI_PART = "/rt/api"
14
+ API_VERSION = "/2.0"
15
+
16
+ # request_url builds the target request URL with the passed parameters, URL encoding the parameters
17
+ # as necessary to create a valid request
18
+ def self.format_url(url, params)
19
+
20
+ # for each of the parameters, build a single query parameter string
21
+ parameter_part = ""
22
+ params.each do |key, value|
23
+ # if there is more than one argument, add the apppropriate separator (&) between
24
+ # query parameters
25
+ parameter_part << "&" if (parameter_part.length > 0)
26
+ # URL Encode the value of the property
27
+ parameter_part << "#{key.to_s}=#{ERB::Util.url_encode(value)}"
28
+
29
+ end
30
+ # return the fully-qualified URL with parameters (if passsed)
31
+ (parameter_part.length > 0 ? "#{url}?#{parameter_part}" : "#{url}")
32
+
33
+ end
34
+
35
+ # default_JSON_header is the default header that is passed to any OEH Request if not provided explicitly by the
36
+ # calling methods
37
+ def self.default_JSON_header()
38
+ {'Accept' => 'application/json' , 'Content-Type' =>'application/json', 'X-Requested-With' => 'XMLHttpRequest' }
39
+ end
40
+
41
+
42
+ end # module Request
43
+
44
+ module Response
45
+
46
+ def self.handle(api_response)
47
+
48
+ # raise a generic HTTPRequestException if the the status code is not 100 (Continue) or 200 (OK)
49
+ raise OEHClient::Exception::HTTPRequestException.new(api_response.message, api_response.code) if (api_response.code != "200" && api_response.code != "100")
50
+
51
+ begin
52
+ # Return the Body of the response for valid requests
53
+ ActiveSupport::JSON.decode(api_response.body)
54
+ rescue ActiveSupport::JSON.parse_error
55
+ # otherwise raise a standard processing exception
56
+ raise OEHClient::Exception::HTTPRequestException(api.body, 500)
57
+ end
58
+
59
+
60
+ end
61
+
62
+ end # module Response
63
+
64
+ end
65
+
66
+ end
@@ -0,0 +1,286 @@
1
+
2
+ class OEHClient::Interaction::Interaction
3
+
4
+ # constants used to construct the restful API Request URL
5
+ API_REALTIME = "/interaction"
6
+ API_OFFLINE = "/offline"
7
+ # ONE attributes that are either in the request and/or returned in the response
8
+ ONE_PARAM_URI = "uri"
9
+ ONE_PARAM_CK = "customerKey"
10
+ ONE_PARAM_TID = "tid"
11
+ ONE_PARAM_SESSION = "session"
12
+ ONE_PARAM_SK = "sk"
13
+ ONE_PARAM_TS = "timestamp"
14
+ ONE_PARAM_PROPERTIES = "properties"
15
+ # Property Hash Keys
16
+ ONE_PROPERTIES_NAME = "name"
17
+ ONE_PROPERTIES_VALUE = "value"
18
+ # Collection objects returned in the response
19
+ ONE_RESPONSE_OPTIMIZATIONS = "optimizations"
20
+ ONE_RESPONSE_TRACKERS = "trackers"
21
+ ONE_RESPONSE_CAPTURES = "captures"
22
+
23
+
24
+ attr_accessor :uri, # The full touchpoint/interaction URI used to post the interaction
25
+ :space, # The configured OEHClient::Config::Space object that represents the
26
+
27
+ :timestamp, # A millisecond value representing a Time value of the interaction
28
+ :customer_key, # The customer to which this interaction is related
29
+ :tid, # The Thunderhead ID (TID) to which this interaction is related
30
+ :session, # The session id to which this interaction is related
31
+
32
+ :optimizations, # The collection of optimizations that are relevent for the interaction
33
+ :trackers, # The collection of tracking point data that are relevant for the interaction
34
+ :captures, # The collection of capture point data that are relevant for the interactions
35
+
36
+ :errors
37
+
38
+ ###
39
+ ### ------------- Class Methods
40
+ ###
41
+ class << self
42
+
43
+ # post
44
+ def post(site_key, uri, timestamp=nil, tid=nil, customer_key=nil, properties={})
45
+
46
+ # setup the baseline attributes hash with the site_key and interaction URI, which are the
47
+ # minimal values needed for an interaction
48
+ attributes = {
49
+ :sk => site_key,
50
+ :uri => uri
51
+ }
52
+
53
+ # conditionally merge the rest of the attributes if they are passed
54
+ attributes.merge!(:timestamp => timestamp) if (!timestamp.nil? && !timestamp.empty?)
55
+ attributes.merge!(:tid => tid) if (!tid.nil? && !tid.empty?)
56
+ attributes.merge!(:ck => customer_key) if (!customer_key.nil? && !customer_key.empty?)
57
+
58
+
59
+ # create a new interaction using all attributes pass
60
+ new_interaction = OEHClient::Interaction::Interaction.new(attributes)
61
+ # Send the interaction for processing and return the instance of the interaction class
62
+ new_interaction.send(properties)
63
+
64
+ end
65
+
66
+ # class-level wrapper to create a new instance of the OEHClient::Interaction::Interaction class, call the
67
+ # send_update method, and return the resulting instance of the same class
68
+ def update(site_key, uri, properties={}, tid=nil, customer_key=nil)
69
+
70
+ # setup the baseline attributes hash with the site_key and interaction URI, which are the
71
+ # minimal values needed for an interaction
72
+ attributes = {
73
+ :sk => site_key,
74
+ :uri => uri
75
+ }
76
+
77
+ # conditionally merge the rest of the attributes if they are passed
78
+ attributes.merge!(:tid => tid) if (!tid.nil? && !tid.empty?)
79
+ attributes.merge!(:ck => customer_key) if (!customer_key.nil? && !customer_key.empty?)
80
+
81
+ # create a new interaction using all parameters pass
82
+ new_interaction = OEHClient::Interaction::Interaction.new(attributes)
83
+ # send the update and return the current object
84
+ new_interaction.send_update(properties)
85
+
86
+ end
87
+
88
+ end
89
+
90
+ ###
91
+ ### ------------- Instance Methods
92
+ ###
93
+
94
+ def initialize(attributes=nil)
95
+
96
+ # set the instance attributes is the parameter hash is created
97
+ if (!attributes.nil? && attributes.kind_of?(Hash))
98
+
99
+ @uri = attributes[:uri] if (attributes.has_key?(:uri))
100
+ @customer_key = attributes[:ck] if (attributes.has_key?(:ck))
101
+ @tid = attributes[:tid] if (attributes.has_key?(:tid))
102
+ @session = attributes[:session] if (attributes.has_key?(:session))
103
+ @timestamp = attributes[:timestamp] if (attributes.has_key?(:timestamp))
104
+
105
+ @space = OEHClient::Config::SpaceManager.instance.get(attributes[:sk]) if (attributes.has_key?(:sk))
106
+
107
+ end
108
+
109
+ end
110
+
111
+ # send() will post a new interaction using either the realtime (current timestamp) or the offline (historic)
112
+ # API interface based on the existence of a timestamp value
113
+ def send(parameters={})
114
+
115
+ # call the appropriate method based on the existance of the timestamp value
116
+ ((minimal_parameters? && !@timestamp.nil? && @timestamp > 0) ? send_offline(@space.token) : send_realtime(@space.token, parameters))
117
+
118
+ # return the current instance interacton
119
+ self
120
+
121
+ end
122
+
123
+ # send_new posts a new interaction using the existing instance data, but for a different touchpoint
124
+ # URI. The method returns a new instance of the OEHClient::Interaction::Interaction class
125
+ def send_new(uri, timestamp=nil, parameters={})
126
+
127
+ # protect against NIL by creating a new Hash object if the parameters, for any reason is
128
+ # NIL
129
+ parameters ||= Hash.new
130
+
131
+ # create a new interaction using all parameters from the existing other than the new touchpoint
132
+ # URI and timestamp of the current Interaction instance. The method can be used to submit new
133
+ # requests for the same customer, tid, & session
134
+ new_interaction = OHEClient::Interaction::Interaction.new({
135
+ :uri => uri,
136
+ :ck => @customer_key,
137
+ :tid => @tid,
138
+ :session => @session,
139
+ :sk => @space.site_key,
140
+ :timestamp => timestamp
141
+ })
142
+
143
+ # Send the interaction for processing and return the current instance
144
+ new_interaction.send(parameters)
145
+
146
+ end
147
+
148
+ # send_update allows the system to update the capture and tracking properties that are defined as
149
+ # part of the existing interaction
150
+ def send_update(properties={})
151
+
152
+ # force the properties object to be an empty Hash if, for any reason, it is NIL
153
+ properties ||= Hash.new
154
+
155
+ # Call the PUT method to update the
156
+ OEHClient::Helper::Response.handle(OEHClient.put(@space.token(),
157
+ OEHClient::Helper::Request.format_url(realtime_url, {:sk => @space.site_key}),
158
+ nil,
159
+ request_data(properties))) unless properties.empty?
160
+ # return the current object
161
+ self
162
+
163
+ end
164
+
165
+
166
+ private
167
+
168
+
169
+ # send_realtime posts a new interaction occuring at the moment (in realtime). The response attributes
170
+ # are mapped to the current instance attributes for all valid requests
171
+ def send_realtime(token, parameters={})
172
+
173
+ response = OEHClient::Helper::Response.handle(OEHClient.post(token,
174
+ OEHClient::Helper::Request.format_url(realtime_url, {:sk => @space.site_key}),
175
+ nil,
176
+ request_data(parameters))
177
+ )
178
+
179
+ map_response(response)
180
+
181
+
182
+ end
183
+
184
+ # send_offline posts a historic interaction, using a specified timestamp
185
+ def send_offline(token)
186
+
187
+ response = OHEClient::Helper::Response.handle(OEHClient.put(token,
188
+ OEHClient::Helper::Request.format_url(offline_url, {:sk => @space.site_key}),
189
+ nil,
190
+ request_data))
191
+ map_response(response)
192
+
193
+
194
+ end
195
+
196
+ # map_response takes the attributes returned in an interaction response and maps it to exiting
197
+ # attributes in the current instance of the interaction object
198
+ def map_response(response)
199
+
200
+
201
+ # Save the tid and session data if they where not previously used in the request
202
+ @tid = response[ONE_PARAM_TID] if (@tid.nil? || (!@tid.blank? && @tid != response[ONE_PARAM_TID]))
203
+ @session = response[ONE_PARAM_SESSION] if @session.nil?
204
+
205
+ # capture the optimizations returned from the request and map it to the OEHClient::Interaction::Optimization
206
+ # class
207
+
208
+ # initialize the optimizations collection if it is null
209
+ @optimizations ||= Array.new
210
+ # map each of the optimizations to the OEHClient::Interaction::Optmization class
211
+ response[ONE_RESPONSE_OPTIMIZATIONS].each do | response_optimization |
212
+ @optimizations << OEHClient::Interaction::Optimization.create(response_optimization)
213
+ end
214
+
215
+ # capture the trackers returned from the request and mpt it to the OEHClient::Interaction::Tracker
216
+ # class
217
+ # TODO: Create OEHClient::Interaction::Tracker class
218
+ @trackers = response[ONE_RESPONSE_TRACKERS]
219
+
220
+ # capture the capture points returned from the request and map it to the OEHClient::Interaction::Capture
221
+ # class
222
+ # TODO: Create OEHClient::Interaction::Capture class
223
+ @captures = response[ONE_RESPONSE_CAPTURES]
224
+
225
+ end
226
+
227
+ # minimal_parameters? determines if the minimal number of request parameters (uri & site_key) are
228
+ # present in the current instance of the interaction class. This is a helper method that is used
229
+ # before making any request
230
+ def minimal_parameters?()
231
+ !@uri.nil? && !@site_key.nil?
232
+ end
233
+
234
+ # request_url returns the base of the request URL used to make either a realtime or offline request
235
+ # through published API
236
+ def request_url()
237
+ "#{OEHClient::Helper::Request::ONE_PROTOCOL}#{@space.host}#{OEHClient::Helper::Request::THUNDERHEAD_DOMAIN}#{OEHClient::Helper::Request::ONE_URI_PART}#{OEHClient::Helper::Request::API_URI_PART}#{OEHClient::Helper::Request::API_VERSION}"
238
+ end
239
+
240
+ # realtime_url is the interaction part of the API URI
241
+ def realtime_url()
242
+ "#{request_url}#{API_REALTIME}"
243
+ end
244
+
245
+ # offline_url appends the /offiline URI part to add support for historic data loading of interactions
246
+ def offline_url()
247
+ "#{realtime_url}#{API_OFFLINE}"
248
+ end
249
+
250
+ # request_data creates a properly formatted Hash object that represents the body of the request needed
251
+ # for POST and PUT operations
252
+ def request_data(passed_properties={})
253
+
254
+ # protect agains a NIL value in the passed_properties Hash
255
+ passed_properties ||= Hash.new
256
+
257
+ # Initialize the parameters hash
258
+ parameters ||= Hash.new
259
+
260
+ # merge in the different parts of the request data if the values currently exist within
261
+ # the instance of the class
262
+ parameters.merge!({ONE_PARAM_URI => @uri}) if (!@uri.nil? && @uri.length > 0)
263
+
264
+ parameters.merge!({ONE_PARAM_CK => @customer_key}) if (!@customer_key.nil? && @customer_key.length > 0)
265
+ parameters.merge!({ONE_PARAM_TID => @tid}) if (!@tid.nil? && @tid.length > 0)
266
+
267
+ parameters.merge!({ONE_PARAM_SESSION => @session}) if (!@session.nil? && @session.length > 0)
268
+ parameters.merge!({ONE_PARAM_TS => @timestamp}) if (!@timestamp.nil?)
269
+
270
+ # for each of the properties hash entry, build a name/value pair in the properties collection
271
+ properties = Array.new
272
+ passed_properties.each do | key, value |
273
+ properties << {ONE_PROPERTIES_NAME => key.to_s, ONE_PROPERTIES_VALUE => value}
274
+ end
275
+ # merge the properties (name / value) connections if there are additonal values to pass
276
+ parameters.merge!({ONE_PARAM_PROPERTIES => properties}) if (properties.length > 0)
277
+
278
+ # return the full parameter hash
279
+ return(parameters)
280
+
281
+ end
282
+
283
+
284
+
285
+
286
+ end
@@ -0,0 +1,52 @@
1
+ require 'base64'
2
+ require 'cgi'
3
+
4
+ class OEHClient::Interaction::Optimization
5
+
6
+ # HASH keys based on the response data
7
+ OPT_RESPONSE_DATA = "data"
8
+ OPT_RESPONSE_PATH = "path"
9
+ OPT_RESPONSE_ID = "responseId"
10
+ OPT_RESPONSE_MIME_TYPE = "dataMimeType"
11
+ OPT_RESPONSE_DIRECTIVES = "directives"
12
+
13
+ # Localized attributes equivalent to the returned Hash object in the response
14
+ attr_accessor :data, # Base64 Encoded Asset returned by OEH
15
+ :path, # The path of the optimization based on the OEH Configuration
16
+ :response_id, # The Response ID of the asset based on the OEH Configuration
17
+ :mime_type, # The MIME Type of the asset based on the OEH Configuration
18
+ :directives
19
+
20
+
21
+ # ---- Class Methods
22
+
23
+ def self.create(properties={})
24
+
25
+ # create a new instance of the OEHClient::Interaction::Optimization class
26
+ optimization_instance = OEHClient::Interaction::Optimization.new()
27
+
28
+ # assign all data attributes based on the properties object that is passed
29
+ optimization_instance.data = properties[OPT_RESPONSE_DATA] if (properties.has_key?(OPT_RESPONSE_DATA))
30
+ optimization_instance.path = properties[OPT_RESPONSE_PATH] if (properties.has_key?(OPT_RESPONSE_PATH))
31
+ optimization_instance.response_id = properties[OPT_RESPONSE_ID] if (properties.has_key?(OPT_RESPONSE_ID))
32
+ optimization_instance.mime_type = properties[OPT_RESPONSE_MIME_TYPE] if (properties.has_key?(OPT_RESPONSE_ID))
33
+ optimization_instance.directives = properties[OPT_RESPONSE_DIRECTIVES] if (properties.has_key?(OPT_RESPONSE_DIRECTIVES))
34
+
35
+ #return the new instance of the optimzation class
36
+ optimization_instance
37
+
38
+ end
39
+
40
+ # ---- Instance Methods
41
+
42
+ # TODO: Need to create a series of methods that properly decodes the object based on Mime Type
43
+ # decodes the Base64 encoded data and returns it raw form
44
+ def decode_data()
45
+
46
+
47
+ CGI.unescapeHTML(Base64.decode64(@data.to_json))
48
+
49
+ end
50
+
51
+
52
+ end
@@ -0,0 +1,9 @@
1
+ module OEHClient
2
+
3
+ module Interaction
4
+ end
5
+
6
+ end
7
+
8
+ require File.dirname(__FILE__) + '/interaction/interaction'
9
+ require File.dirname(__FILE__) + '/interaction/optimization'
@@ -0,0 +1,3 @@
1
+ module OEHClient
2
+ VERSION = "0.1.0"
3
+ end
data/lib/oehclient.rb ADDED
@@ -0,0 +1,81 @@
1
+ require 'oauth'
2
+ require 'csv'
3
+ require 'uuidtools'
4
+ require 'json'
5
+ require 'active_support'
6
+
7
+ require File.dirname(__FILE__) + '/oehclient/helper'
8
+ require File.dirname(__FILE__) + '/oehclient/exception'
9
+ require File.dirname(__FILE__) + '/oehclient/config'
10
+
11
+ require File.dirname(__FILE__) + '/oehclient/interaction'
12
+ require File.dirname(__FILE__) + '/oehclient/data'
13
+
14
+
15
+
16
+ module OEHClient
17
+
18
+ class << self
19
+
20
+ attr_accessor :spaces, :space_mgr
21
+
22
+ # configure provides the basic interface for passing tenancy configuration to the gem
23
+ def configure_space
24
+
25
+ # if space_mgr attribute is NIL then return a new instance of the OEHClient::Config::SpaceManager
26
+ # singleton class
27
+ @space_mgr ||= OEHClient::Config::SpaceManager.instance
28
+ # yield control to the block passed in the configuration
29
+ yield(@space_mgr)
30
+
31
+ end
32
+
33
+ # get wraps the GET method of the access token and manages the response that is returned
34
+ def get(token, url, header={})
35
+
36
+ # force the new hash. Testing in RSPEC uncovered issue with the default not being followed
37
+ header ||= Hash.new
38
+
39
+ # if the token is not a proper OAuth::AccessToken, then raise the Oeh::Exception::InvalidTokenException
40
+ # exception to the calling method
41
+ raise OEHClient::Exception::InvalidTokenException unless (token.kind_of?(OAuth::AccessToken))
42
+ # send the GET request, manage the returned response, and return the body of the response to the
43
+ # calling method
44
+ token.get(url, header.empty? ? OEHClient::Helper::Request.default_JSON_header() : header)
45
+
46
+ end
47
+
48
+ # post wraps the POST method of the access token and manages the response that is returned
49
+ def post(token, url, header={}, body)
50
+
51
+ # force the new hash. Testing in RSPEC uncovered issue with the default not being followed
52
+ header ||= Hash.new
53
+
54
+ # if the token is not a proper OAuth::AccessToken, then raise the Oeh::Exception::InvalidTokenException
55
+ # exception to the calling method
56
+ raise OEHClient::Exception::InvalidTokenException unless (token.kind_of?(OAuth::AccessToken))
57
+ # send the POST request, manage the returned response, and return the body of the response to the
58
+ # calling method
59
+ token.post(url, ActiveSupport::JSON.encode(body), header.empty? ? OEHClient::Helper::Request.default_JSON_header() : header)
60
+
61
+
62
+ end
63
+
64
+ # put wraps the PUT method of the access token and manages the response that is returned
65
+ def put(token, url, header={}, body)
66
+
67
+ # force the new hash. Testing in RSPEC uncovered issue with the default not being followed
68
+ header ||= Hash.new
69
+
70
+ # if the token is not a proper OAuth::AccessToken, then raise the Oeh::Exception::InvalidTokenException
71
+ # exception to the calling method
72
+ raise OEHClient::Exception::InvalidTokenException unless (token.kind_of?(OAuth::AccessToken))
73
+ # send the PUT request, manage the returned response, and return the body of the response to the
74
+ # calling method
75
+ token.put(url, ActiveSupport::JSON.encode(body), header.empty? ? OEHClient::Helper::Request.default_JSON_header() : header)
76
+
77
+ end
78
+
79
+ end
80
+
81
+ end
Binary file
@@ -0,0 +1,40 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'oehclient/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "oeh-client"
8
+ spec.version = OEHClient::VERSION
9
+ spec.authors = ["Jason Balliet"]
10
+ spec.email = ["jballiet@thunderhead.com"]
11
+
12
+ spec.summary = %q{Simple class-based client for integration to ONE Engagement Hub}
13
+ spec.description = %q{A simple set of classes that allow access to Interactions, Documents, and Structures from within Thunderhead's ONE Enagement Hub}
14
+ spec.homepage = "https://rubygems.org/gems/oeh-client"
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
18
+ # delete this section to allow pushing this gem to any host.
19
+ #if spec.respond_to?(:metadata)
20
+ # spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
21
+ #else
22
+ # raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
23
+ #end
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+
30
+ spec.add_development_dependency "bundler", "~> 1.10"
31
+ spec.add_development_dependency "rake", "~> 10.0"
32
+ spec.add_development_dependency "rspec-rails", "~> 3.2"
33
+
34
+ spec.add_dependency "oauth"
35
+ spec.add_dependency "json"
36
+ spec.add_dependency "uuidtools"
37
+ spec.add_dependency "activesupport", "~> 4.2.0"
38
+ spec.add_dependency "railties", ">= 4.2.0"
39
+
40
+ end
metadata ADDED
@@ -0,0 +1,184 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: oeh-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jason Balliet
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-10-06 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.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
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-rails
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '3.2'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '3.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: oauth
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: json
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: uuidtools
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: activesupport
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: 4.2.0
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: 4.2.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: railties
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: 4.2.0
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: 4.2.0
125
+ description: A simple set of classes that allow access to Interactions, Documents,
126
+ and Structures from within Thunderhead's ONE Enagement Hub
127
+ email:
128
+ - jballiet@thunderhead.com
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - .gitignore
134
+ - .rspec
135
+ - .travis.yml
136
+ - CODE_OF_CONDUCT.md
137
+ - Gemfile
138
+ - LICENSE.txt
139
+ - README.md
140
+ - Rakefile
141
+ - bin/console
142
+ - bin/setup
143
+ - lib/oeh-client.rb
144
+ - lib/oeh_client.rb
145
+ - lib/oehclient.rb
146
+ - lib/oehclient/config.rb
147
+ - lib/oehclient/config/space.rb
148
+ - lib/oehclient/config/space_manager.rb
149
+ - lib/oehclient/data.rb
150
+ - lib/oehclient/data/node.rb
151
+ - lib/oehclient/data/structure.rb
152
+ - lib/oehclient/exception.rb
153
+ - lib/oehclient/helper.rb
154
+ - lib/oehclient/interaction.rb
155
+ - lib/oehclient/interaction/interaction.rb
156
+ - lib/oehclient/interaction/optimization.rb
157
+ - lib/oehclient/version.rb
158
+ - oeh-client-0.1.0.gem
159
+ - oeh-client.gemspec
160
+ homepage: https://rubygems.org/gems/oeh-client
161
+ licenses:
162
+ - MIT
163
+ metadata: {}
164
+ post_install_message:
165
+ rdoc_options: []
166
+ require_paths:
167
+ - lib
168
+ required_ruby_version: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - '>='
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ required_rubygems_version: !ruby/object:Gem::Requirement
174
+ requirements:
175
+ - - '>='
176
+ - !ruby/object:Gem::Version
177
+ version: '0'
178
+ requirements: []
179
+ rubyforge_project:
180
+ rubygems_version: 2.0.14
181
+ signing_key:
182
+ specification_version: 4
183
+ summary: Simple class-based client for integration to ONE Engagement Hub
184
+ test_files: []