delighted 1.0.0.alpha

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5713c3b8bbf569d4ea070698eb71615529769c64
4
+ data.tar.gz: 85fb1b406babe39d9560674a80562952f05e93b4
5
+ SHA512:
6
+ metadata.gz: dcd088106f462f56a3bad2f6a339c3c0f1ad0d434ce65253d68e85c5194a70960f6a913cbf56ad83e378972ae34c14154330cd79c481c3cc791cda0739630399
7
+ data.tar.gz: dd86b0f081e36e4515a761a8e7b0cff16516ba498454b1c9b0891f2a5ed7bcff2617e163f02f21b35bd77eed4dc042609f81094fb4ffd5202507524b28afb9d6
@@ -0,0 +1 @@
1
+ Gemfile.lock
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - 1.9.3
5
+ - 1.9.2
6
+ - 1.8.7
7
+ - jruby-18mode
8
+ - jruby-19mode
9
+ - rbx-18mode
10
+ - rbx-19mode
11
+ - ree
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Delighted Inc.
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,20 @@
1
+ # Delighted API client for Ruby
2
+
3
+ Official Ruby client for the [Delighted API](https://delightedapp.com).
4
+
5
+ For installation and usage instructions, please [sign in to your Delighted account](https://delightedapp.com/signin) and follow the API documentation under Settings.
6
+
7
+ ## Supported Rubies
8
+
9
+ - Ruby MRI (1.8.7+)
10
+ - JRuby (1.8 + 1.9 modes)
11
+ - RBX (1.8 + 1.9 modes)
12
+ - REE (1.8.7-2012.02)
13
+
14
+ ## Contributing
15
+
16
+ 1. Fork it
17
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
18
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
19
+ 4. Push to the branch (`git push origin my-new-feature`)
20
+ 5. Create new Pull Request
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |task|
4
+ task.libs << 'test'
5
+ task.test_files = FileList['test/**/*_test.rb']
6
+ end
7
+
8
+ task default: :test
@@ -0,0 +1,24 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'delighted/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "delighted"
7
+ spec.version = Delighted::VERSION
8
+ spec.authors = ["Mark Dodwell"]
9
+ spec.email = ["mark@madeofcode.com"]
10
+ spec.description = "Delighted API client for Ruby."
11
+ spec.summary = "Delighted is the easiest and most beautiful way to measure customer happiness. Are your customers delighted?"
12
+ spec.homepage = "https://github.com/delighted/delighted-ruby"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files`.split($/)
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^test/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_dependency "multi_json"
21
+ spec.add_development_dependency "rake"
22
+ spec.add_development_dependency "minitest"
23
+ spec.add_development_dependency "mocha"
24
+ end
@@ -0,0 +1,25 @@
1
+ require 'net/https'
2
+ require 'uri'
3
+ require 'cgi'
4
+ require 'multi_json'
5
+ require 'set'
6
+
7
+ require 'delighted/utils'
8
+ require 'delighted/json'
9
+
10
+ require 'delighted/enumerable_resource_collection'
11
+ require 'delighted/resource'
12
+ require 'delighted/operations'
13
+ require 'delighted/operations/all'
14
+ require 'delighted/operations/create'
15
+ require 'delighted/operations/retrieve'
16
+
17
+ require 'delighted/resources/metrics'
18
+ require 'delighted/resources/person'
19
+ require 'delighted/resources/survey_responses'
20
+
21
+ require 'delighted/errors'
22
+ require 'delighted/resource_interface'
23
+ require 'delighted/http_response'
24
+ require 'delighted/http_adapter'
25
+ require 'delighted/client'
@@ -0,0 +1,65 @@
1
+ module Delighted
2
+ class Client
3
+ DEFAULT_API_BASE_URL = "https://api.delightedapp.com/v1"
4
+ DEFAULT_HTTP_ADAPTER = HTTPAdapter.new
5
+
6
+ def initialize(opts = {})
7
+ @api_key = opts[:api_key] or raise ArgumentError, "You must pass an :api_key."
8
+ @api_base_url = opts[:api_base_url] || DEFAULT_API_BASE_URL
9
+ @http_adapter = opts[:http_adapter] || DEFAULT_HTTP_ADAPTER
10
+ end
11
+
12
+ Resource.resources.each do |resource|
13
+ class_eval <<-END, __FILE__, __LINE__
14
+ def #{resource.interface_name}
15
+ @#{resource.interface_name} ||= ResourceInterface.new(self, #{resource.name})
16
+ end
17
+ END
18
+ end
19
+
20
+ def get_json(path, params = {})
21
+ headers = default_headers.dup.merge('Accept' => 'application/json')
22
+
23
+ uri = URI.parse(File.join(@api_base_url, path))
24
+ uri.query = Utils.to_query(params) unless params.empty?
25
+
26
+ response = @http_adapter.request(:get, uri, headers)
27
+ handle_json_response(response)
28
+ end
29
+
30
+ def post_json(path, params = {})
31
+ headers = default_headers.dup.merge('Accept' => 'application/json', 'Content-Type' => 'application/json')
32
+
33
+ uri = URI.parse(File.join(@api_base_url, path))
34
+ data = JSON.dump(params) unless params.empty?
35
+
36
+ response = @http_adapter.request(:post, uri, headers, data)
37
+ handle_json_response(response)
38
+ end
39
+
40
+ private
41
+
42
+ def handle_json_response(response)
43
+ case response.status_code
44
+ when 200, 201, 202
45
+ Utils.symbolize_keys(JSON.load(response.body))
46
+ when 401
47
+ raise AuthenticationError, response
48
+ when 406
49
+ raise UnsupportedFormatRequestedError, response
50
+ when 422
51
+ raise ResourceValidationError, response
52
+ when 503
53
+ raise ServiceUnavailableError, response
54
+ else
55
+ raise GeneralAPIError, response
56
+ end
57
+ end
58
+
59
+ def default_headers
60
+ @default_headers ||= {
61
+ 'Authorization' => "Basic #{["#{@api_key}:"].pack('m0')}"
62
+ }.freeze
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,4 @@
1
+ module Delighted
2
+ class EnumerableResourceCollection < Array
3
+ end
4
+ end
@@ -0,0 +1,31 @@
1
+ module Delighted
2
+ class Error < StandardError
3
+ def initialize(response)
4
+ @response = response
5
+ end
6
+
7
+ def to_s
8
+ "#{@response.status_code}: #{@response.body}"
9
+ end
10
+ end
11
+
12
+ class AuthenticationError < Error
13
+ # 401, api auth missing or incorrect
14
+ end
15
+
16
+ class UnsupportedFormatRequestedError < Error
17
+ # 406, invalid format in Accept header
18
+ end
19
+
20
+ class ResourceValidationError < Error
21
+ # 422, validation errors
22
+ end
23
+
24
+ class GeneralAPIError < Error
25
+ # 500, general/unknown error
26
+ end
27
+
28
+ class ServiceUnavailableError < Error
29
+ # 503, maintenance or overloaded
30
+ end
31
+ end
@@ -0,0 +1,21 @@
1
+ module Delighted
2
+ class HTTPAdapter
3
+ REQUEST_CLASSES = {
4
+ get: Net::HTTP::Get,
5
+ post: Net::HTTP::Post,
6
+ }
7
+
8
+ def request(method, uri, headers = {}, data = nil)
9
+ http = Net::HTTP.new(uri.host, uri.port)
10
+ http.use_ssl = true
11
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
12
+
13
+ request = REQUEST_CLASSES[method].new(uri.request_uri)
14
+ headers.each { |k,v| request[k] = v }
15
+ request.body = data
16
+
17
+ response = http.request(request)
18
+ HTTPResponse.new(response.code, response.to_hash, response.body)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ module Delighted
2
+ class HTTPResponse
3
+ attr_reader :status_code, :headers, :body
4
+
5
+ def initialize(raw_status_code, raw_headers, raw_body)
6
+ @status_code = raw_status_code.to_i
7
+ @headers = raw_headers
8
+ @body = raw_body
9
+ end
10
+
11
+ def content_type
12
+ @headers.values_at('content-type', 'Content-Type')[0]
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,23 @@
1
+ module Delighted
2
+ class JSON
3
+ class << self
4
+ if MultiJson.respond_to?(:dump)
5
+ def dump(*args)
6
+ MultiJson.dump(*args)
7
+ end
8
+
9
+ def load(*args)
10
+ MultiJson.load(*args)
11
+ end
12
+ else
13
+ def dump(*args)
14
+ MultiJson.encode(*args)
15
+ end
16
+
17
+ def load(*args)
18
+ MultiJson.decode(*args)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,8 @@
1
+ module Delighted
2
+ module Operations
3
+ def self.add_operations(klass, operation_module)
4
+ klass.extend(operation_module)
5
+ operation_module.instance_methods.each { |operation| klass.operations << operation }
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,21 @@
1
+ module Delighted
2
+ module Operations
3
+ module All
4
+ def self.included(klass)
5
+ klass.extend(AuxiliaryClassMethods)
6
+ Operations.add_operations(klass, OperationClassMethods)
7
+ end
8
+
9
+ module OperationClassMethods
10
+ def all(client, opts = {})
11
+ json = client.get_json(path, opts)
12
+ EnumerableResourceCollection.new(json.map { |attributes| new(attributes) })
13
+ end
14
+ end
15
+
16
+ module AuxiliaryClassMethods
17
+ # pagination, enumerable stuff etc.
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ module Delighted
2
+ module Operations
3
+ module Create
4
+ def self.included(klass)
5
+ Operations.add_operations(klass, OperationClassMethods)
6
+ end
7
+
8
+ module OperationClassMethods
9
+ def create(client, attributes = {})
10
+ params = Utils.hash_removing_key(attributes, :id)
11
+ json = client.post_json(path, params)
12
+ new(json)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,38 @@
1
+ module Delighted
2
+ module Operations
3
+ module Retrieve
4
+ def self.included(klass)
5
+ if klass.singleton_resource?
6
+ Operations.add_operations(klass, Singleton::OperationClassMethods)
7
+ else
8
+ klass.extend(Pluralton::AuxiliaryClassMethods)
9
+ Operations.add_operations(klass, Pluralton::OperationClassMethods)
10
+ end
11
+ end
12
+
13
+ module Pluralton
14
+ module OperationClassMethods
15
+ def retrieve(client, id)
16
+ json = client.get_json(path(id))
17
+ new(json)
18
+ end
19
+ end
20
+
21
+ module AuxiliaryClassMethods
22
+ def path(id = nil)
23
+ id ? "#{@path}/#{id}" : @path
24
+ end
25
+ end
26
+ end
27
+
28
+ module Singleton
29
+ module OperationClassMethods
30
+ def retrieve(client, opts = {})
31
+ json = client.get_json(path, opts)
32
+ new(json)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,75 @@
1
+ module Delighted
2
+ class Resource
3
+ class << self
4
+ def interface_name=(interface_name)
5
+ @interface_name = interface_name
6
+ end
7
+
8
+ def interface_name
9
+ @interface_name
10
+ end
11
+
12
+ def path=(path)
13
+ @path = path
14
+ end
15
+
16
+ def path
17
+ @path
18
+ end
19
+
20
+ def singleton_resource=(singleton_resource)
21
+ @singleton_resource = singleton_resource
22
+ end
23
+
24
+ def singleton_resource?
25
+ !!@singleton_resource
26
+ end
27
+
28
+ def operations
29
+ @operations ||= Set.new
30
+ end
31
+
32
+ def resources
33
+ @resources ||= Set.new
34
+ end
35
+
36
+ def inherited(klass)
37
+ resources << klass
38
+ end
39
+ end
40
+
41
+ undef :id if method_defined?(:id)
42
+ attr_reader :attributes
43
+ private :attributes
44
+
45
+ def initialize(attributes = {})
46
+ @id = attributes[:id]
47
+ define_id_reader if @id
48
+ @attributes = Utils.hash_removing_key(attributes, :id)
49
+ define_attribute_accessors(@attributes.keys)
50
+ end
51
+
52
+ def to_hash
53
+ attributes
54
+ end
55
+ alias_method :to_h, :to_hash
56
+
57
+ private
58
+
59
+ def define_id_reader
60
+ Utils.eigenclass(self).instance_eval do
61
+ attr_reader :id
62
+ end
63
+ end
64
+
65
+ def define_attribute_accessors(keys)
66
+ Utils.eigenclass(self).instance_eval do
67
+ keys.each do |key|
68
+ define_method(key) do
69
+ attributes[key]
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,19 @@
1
+ module Delighted
2
+ class ResourceInterface
3
+ def initialize(client, resource)
4
+ @resource = resource # more helpful inspect
5
+
6
+ Utils.eigenclass(self).instance_eval do
7
+ resource.operations.each do |operation|
8
+ define_method(operation) do |*args, &block|
9
+ resource.send(operation, *args.unshift(client), &block)
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ def to_s
16
+ inspect
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,9 @@
1
+ module Delighted
2
+ class Metrics < Resource
3
+ self.interface_name = "metrics"
4
+ self.path = "/metrics"
5
+ self.singleton_resource = true
6
+
7
+ include Operations::Retrieve
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ module Delighted
2
+ class Person < Resource
3
+ self.interface_name = "people"
4
+ self.path = "/people"
5
+
6
+ include Operations::Create
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ module Delighted
2
+ class SurveyResponse < Resource
3
+ self.interface_name = "survey_responses"
4
+ self.path = "/survey_responses"
5
+
6
+ include Operations::Create
7
+ include Operations::All
8
+ end
9
+ end
@@ -0,0 +1,45 @@
1
+ module Delighted
2
+ module Utils
3
+ def self.eigenclass(object)
4
+ class << object; self; end
5
+ end
6
+
7
+ def self.hash_removing_key(hash, key)
8
+ hash.reject { |k,v| k == key }.inject({}) { |memo,(k,v)| memo[k] = v; memo }
9
+ end
10
+
11
+ def self.to_query(hash_or_array, namespace = nil)
12
+ hash_or_array.map { |object|
13
+ k, v = case hash_or_array
14
+ when Hash then object
15
+ when Array then [nil, object[0]]
16
+ else raise ArgumentError, "must pass Hash or Array"
17
+ end
18
+
19
+ namespaced_k = namespace ? "#{namespace}[#{k}]" : k
20
+
21
+ case v
22
+ when Hash, Array then to_query(v, namespaced_k)
23
+ else "#{CGI.escape(namespaced_k.to_s)}=#{CGI.escape(v.to_s)}"
24
+ end
25
+ }.join("&")
26
+ end
27
+
28
+ def self.symbolize_keys(object)
29
+ case object
30
+ when Hash
31
+ object.inject({}) { |memo,(k,v)|
32
+ memo[(k.to_sym rescue k)] = Hash === v ? symbolize_keys(v) : v
33
+ memo
34
+ }
35
+ when Array
36
+ object.map { |v| symbolize_keys(v) }
37
+ else
38
+ object
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ # Delighted::Utils.symbolize_keys([1, {'goo' => { 'bar' => 1, :gyp => ['x'] }, foo: Object.new }])
45
+ # URI.unescape Delighted::Utils.to_query(foo: 1, gyp: { sum: 1, welp: ['a','b'] })
@@ -0,0 +1,3 @@
1
+ module Delighted
2
+ VERSION = "1.0.0.alpha"
3
+ end
@@ -0,0 +1,78 @@
1
+ require 'test_helper'
2
+
3
+ class Delighted::ClientTest < Delighted::TestCase
4
+ def test_instantiating_client_requires_api_key
5
+ assert_raises(ArgumentError) { Delighted::Client.new }
6
+ Delighted::Client.new(:api_key => '123abc')
7
+ end
8
+ end
9
+
10
+ class Delighted::MetricsTest < Delighted::TestCase
11
+ def test_retrieving_metrics
12
+ uri = URI.parse("https://api.delightedapp.com/v1/metrics")
13
+ headers = { 'Authorization' => "Basic #{["123abc:"].pack('m0')}", "Accept" => "application/json" }
14
+ response = Delighted::HTTPResponse.new(200, {}, Delighted::JSON.dump({ :nps => 10 }))
15
+ mock_http_adapter.expects(:request).with(:get, uri, headers).once.returns(response)
16
+
17
+ client = Delighted::Client.new(:api_key => '123abc', :http_adapter => mock_http_adapter)
18
+ metrics = client.metrics.retrieve
19
+ assert_kind_of Delighted::Metrics, metrics
20
+ assert_equal({ :nps => 10 }, metrics.to_hash)
21
+ assert_equal 10, metrics.nps
22
+ assert_raises(NoMethodError) { metrics.id }
23
+ end
24
+ end
25
+
26
+ class Delighted::PeopleTest < Delighted::TestCase
27
+ def test_creating_or_updating_a_person
28
+ uri = URI.parse("https://api.delightedapp.com/v1/people")
29
+ headers = { 'Authorization' => "Basic #{["123abc:"].pack('m0')}", "Accept" => "application/json", 'Content-Type' => 'application/json' }
30
+ data = Delighted::JSON.dump({ :email => 'foo@bar.com' })
31
+ response = Delighted::HTTPResponse.new(200, {}, Delighted::JSON.dump({ :id => '123', :email => 'foo@bar.com' }))
32
+ mock_http_adapter.expects(:request).with(:post, uri, headers, data).once.returns(response)
33
+
34
+ client = Delighted::Client.new(:api_key => '123abc', :http_adapter => mock_http_adapter)
35
+ person = client.people.create(:email => 'foo@bar.com')
36
+ assert_kind_of Delighted::Person, person
37
+ assert_equal({ :email => 'foo@bar.com' }, person.to_hash)
38
+ assert_equal 'foo@bar.com', person.email
39
+ assert_equal '123', person.id
40
+ end
41
+ end
42
+
43
+ class Delighted::SurveyResponseTest < Delighted::TestCase
44
+ def test_creating_a_survey_response
45
+ uri = URI.parse("https://api.delightedapp.com/v1/survey_responses")
46
+ headers = { 'Authorization' => "Basic #{["123abc:"].pack('m0')}", "Accept" => "application/json", 'Content-Type' => 'application/json' }
47
+ data = Delighted::JSON.dump({ :person => '123', :score => 10 })
48
+ response = Delighted::HTTPResponse.new(200, {}, Delighted::JSON.dump({ :id => '456', :person => '123', :score => 10 }))
49
+ mock_http_adapter.expects(:request).with(:post, uri, headers, data).once.returns(response)
50
+
51
+ client = Delighted::Client.new(:api_key => '123abc', :http_adapter => mock_http_adapter)
52
+ survey_response = client.survey_responses.create(:person => '123', :score => 10)
53
+ assert_kind_of Delighted::SurveyResponse, survey_response
54
+ assert_equal({ :person => '123', :score => 10 }, survey_response.to_hash)
55
+ assert_equal '123', survey_response.person
56
+ assert_equal 10, survey_response.score
57
+ assert_equal '456', survey_response.id
58
+ end
59
+
60
+ def test_listing_all_survey_responses
61
+ uri = URI.parse("https://api.delightedapp.com/v1/survey_responses")
62
+ headers = { 'Authorization' => "Basic #{["123abc:"].pack('m0')}", "Accept" => "application/json" }
63
+ response = Delighted::HTTPResponse.new(200, {}, Delighted::JSON.dump([{ :id => '123', :comment => 'One' }, { :id => '456', :comment => 'Two' }]))
64
+ mock_http_adapter.expects(:request).with(:get, uri, headers).once.returns(response)
65
+
66
+ client = Delighted::Client.new(:api_key => '123abc', :http_adapter => mock_http_adapter)
67
+ survey_responses = client.survey_responses.all
68
+ assert_kind_of Delighted::EnumerableResourceCollection, survey_responses
69
+ assert_kind_of Delighted::SurveyResponse, survey_responses[0]
70
+ assert_equal({ :comment => 'One' }, survey_responses[0].to_hash)
71
+ assert_equal 'One', survey_responses[0].comment
72
+ assert_equal '123', survey_responses[0].id
73
+ assert_kind_of Delighted::SurveyResponse, survey_responses[1]
74
+ assert_equal({ :comment => 'Two' }, survey_responses[1].to_hash)
75
+ assert_equal 'Two', survey_responses[1].comment
76
+ assert_equal '456', survey_responses[1].id
77
+ end
78
+ end
@@ -0,0 +1,11 @@
1
+ require 'delighted'
2
+ require 'minitest/autorun'
3
+ require 'mocha/setup'
4
+
5
+ class Delighted::TestCase < Minitest::Test
6
+ include Mocha
7
+
8
+ def mock_http_adapter
9
+ @mock ||= mock
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,130 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: delighted
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0.alpha
5
+ platform: ruby
6
+ authors:
7
+ - Mark Dodwell
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-11-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: multi_json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: mocha
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Delighted API client for Ruby.
70
+ email:
71
+ - mark@madeofcode.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - .travis.yml
78
+ - Gemfile
79
+ - LICENSE
80
+ - README.md
81
+ - Rakefile
82
+ - delighted.gemspec
83
+ - lib/delighted.rb
84
+ - lib/delighted/client.rb
85
+ - lib/delighted/enumerable_resource_collection.rb
86
+ - lib/delighted/errors.rb
87
+ - lib/delighted/http_adapter.rb
88
+ - lib/delighted/http_response.rb
89
+ - lib/delighted/json.rb
90
+ - lib/delighted/operations.rb
91
+ - lib/delighted/operations/all.rb
92
+ - lib/delighted/operations/create.rb
93
+ - lib/delighted/operations/retrieve.rb
94
+ - lib/delighted/resource.rb
95
+ - lib/delighted/resource_interface.rb
96
+ - lib/delighted/resources/metrics.rb
97
+ - lib/delighted/resources/person.rb
98
+ - lib/delighted/resources/survey_responses.rb
99
+ - lib/delighted/utils.rb
100
+ - lib/delighted/version.rb
101
+ - test/delighted_test.rb
102
+ - test/test_helper.rb
103
+ homepage: https://github.com/delighted/delighted-ruby
104
+ licenses:
105
+ - MIT
106
+ metadata: {}
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - '>'
119
+ - !ruby/object:Gem::Version
120
+ version: 1.3.1
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 2.0.3
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: Delighted is the easiest and most beautiful way to measure customer happiness.
127
+ Are your customers delighted?
128
+ test_files:
129
+ - test/delighted_test.rb
130
+ - test/test_helper.rb