reamaze_api 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8e117f4f567c26ad33a009c651600dacefdeaaa2
4
+ data.tar.gz: b617e08ac63b8c0792f64da222a6c0d422c2714c
5
+ SHA512:
6
+ metadata.gz: 029895529560b1eb8e71e42120f517ca85359ab7e0d2476f62d80a8ae8f5f5e5301773947632f4434e592e741739bf21c0de337b7a84860baf46a7ffa433226f
7
+ data.tar.gz: aafe067d2ea6a1e0537c5943a204b2fd216305ab13e53c994bfbe5bdacf69afbb6a3727da2bf48c8a010d7ca482d382667b84a297757d0beff379ed5dd4d33c3
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.2.5
5
+ before_install: gem install bundler -v 1.12.5
6
+ script: bundle exec rake
7
+ notifications:
8
+ email:
9
+ recipients:
10
+ - jpriddle@me.com
11
+ on_success: never
12
+ on_failure: always
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in reamaze_api.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,95 @@
1
+ # ReamazeAPI
2
+
3
+ Ruby library for working with the [Reamaze API][].
4
+
5
+ [Reamaze API]: https://www.reamaze.com/api
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'reamaze_api'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install reamaze_api
22
+
23
+ ## Usage
24
+
25
+ First initialize a new client instance:
26
+
27
+ ```ruby
28
+ client = ReamazeAPI.new(
29
+ brand: "brand", # Your Reamaze subdomain
30
+ login: "me@example.com", # Your Reamaze login
31
+ token: "somehash" # Your Reamaze API token
32
+ )
33
+ ```
34
+
35
+ If you use a single brand in your application, you can configure these
36
+ globally:
37
+
38
+ ```ruby
39
+ ReamazeAPI.config do |c|
40
+ c.brand = "brand" # Your Reamaze subdomain
41
+ c.login = "me@example.com" # Your Reamaze login
42
+ c.token = "somehash" # Your Reamaze API token
43
+ end
44
+
45
+ client = ReamazeAPI.new # Authenticate with the defaults provided above
46
+ ```
47
+
48
+ To work with a resource:
49
+
50
+ ```ruby
51
+ client.articles.all
52
+ client.articles.create(params)
53
+
54
+ client.channels.all
55
+ client.channels.find(id)
56
+
57
+ client.contact.all
58
+ client.contact.create
59
+ client.contact.update
60
+
61
+ client.conversations.all
62
+ client.conversations.find
63
+ client.conversations.create
64
+
65
+ client.messages.all
66
+ client.messages.create
67
+ ```
68
+
69
+ ReamazeAPI uses the [Faraday][] library for HTTP interactions, and by default,
70
+ Net::HTTP. To configure a different HTTP adapter you can set
71
+ `Faraday.default_adapter`:
72
+
73
+ ```ruby
74
+ Faraday.default_adapter = :httpclient
75
+ ```
76
+
77
+ [Faraday]: https://github.com/lostisland/faraday
78
+
79
+ ## Development
80
+
81
+ After checking out the repo, run `bin/setup` to install dependencies. Then,
82
+ run `rake test` to run the tests. You can also run `bin/console` for an
83
+ interactive prompt that will allow you to experiment.
84
+
85
+ To install this gem onto your local machine, run `bundle exec rake install`.
86
+ To release a new version, update the version number in `version.rb`, and then
87
+ run `bundle exec rake release`, which will create a git tag for the version,
88
+ push git commits and tags, and push the `.gem` file to
89
+ [rubygems.org](https://rubygems.org).
90
+
91
+ ## Contributing
92
+
93
+ Bug reports and pull requests are welcome on GitHub at
94
+ https://github.com/itspriddle/reamaze_api.
95
+
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+ require "rake-tomdoc"
4
+
5
+ Rake::TestTask.new :test do |test|
6
+ test.libs << "test"
7
+ test.pattern = "test/**/*_test.rb"
8
+ test.verbose = ENV.has_key?("VERBOSE")
9
+ end
10
+
11
+ task default: :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "reamaze_api"
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,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,44 @@
1
+ require "reamaze_api/version"
2
+ require "reamaze_api/utils"
3
+ require "reamaze_api/client"
4
+ require "reamaze_api/resource"
5
+ require "reamaze_api/article"
6
+ require "reamaze_api/channel"
7
+ require "reamaze_api/contact"
8
+ require "reamaze_api/conversation"
9
+ require "reamaze_api/message"
10
+
11
+ module ReamazeAPI
12
+ # Public: Configuration class
13
+ Config = Struct.new(:brand, :login, :token)
14
+
15
+ # Public: Optional default configuration used to authenticate with the
16
+ # Reamaze API.
17
+ #
18
+ # Yields the Config instance if a block is given.
19
+ #
20
+ # Returns a Config instance.
21
+ def self.config
22
+ @config ||= Config.new
23
+ yield @config if block_given?
24
+ @config
25
+ end
26
+
27
+ # Public: Initializes a new API Client instance.
28
+ #
29
+ # **credentials - Credentials used with the Reamaze API (optional)
30
+ # :brand - Brand name (subdomain from your Reamaze URL)
31
+ # :login - Reamaze login
32
+ # :token - Reamaze API token
33
+ #
34
+ # The credentials passed to the API can be configured globally via
35
+ # `ReamazeAPI.config` or passed to this method. Credentials passed directly
36
+ # to this method take precedence over those configured globally.
37
+ #
38
+ # Raises ArgumentError if a brand, login or token cannot be found.
39
+ #
40
+ # Returns a ReamazeAPI::Client instance.
41
+ def self.new(**credentials)
42
+ Client.new(**config.to_h.select { |_, value| value }.merge(credentials))
43
+ end
44
+ end
@@ -0,0 +1,86 @@
1
+ module ReamazeAPI
2
+ class Article < Resource
3
+ # Public: Retrieves KB articles.
4
+ #
5
+ # params - Hash of parameters to pass to the API
6
+ #
7
+ # API Routes
8
+ #
9
+ # GET /articles
10
+ # GET /topics/{slug}/articles
11
+ #
12
+ # See also: https://www.reamaze.com/api/get_articles
13
+ #
14
+ # Returns a Hash.
15
+ def all(params = {})
16
+ params = Utils.symbolize_hash(params)
17
+
18
+ get articles_path(params.delete(:topic))
19
+ end
20
+
21
+ # Public: Retrieves a specific KB article.
22
+ #
23
+ # slug - Article slug
24
+ #
25
+ # API Routes
26
+ #
27
+ # GET /articles/{slug}
28
+ #
29
+ # See also: https://www.reamaze.com/api/get_article
30
+ #
31
+ # Returns a Hash.
32
+ def find(slug)
33
+ get "/articles/#{slug}"
34
+ end
35
+
36
+ # Public: Create a new KB article.
37
+ #
38
+ # params - Hash of parameters to pass to the API
39
+ #
40
+ # API Routes
41
+ #
42
+ # POST /articles (no topic)
43
+ # POST /topics/{slug}/articles
44
+ #
45
+ # See also: https://www.reamaze.com/api/post_article
46
+ #
47
+ # Returns a Hash.
48
+ def create(params)
49
+ params = Utils.symbolize_hash(params)
50
+
51
+ post articles_path(params.delete(:topic)), params
52
+ end
53
+
54
+ # Public: Update an existing KB article.
55
+ #
56
+ # slug - Article slug
57
+ # params - Hash of parameters to pass to the API
58
+ #
59
+ # API Routes
60
+ #
61
+ # PUT /articles/{slug}
62
+ #
63
+ # See also: https://www.reamaze.com/api/put_article
64
+ #
65
+ # Returns a Hash.
66
+ def update(slug, params)
67
+ put "/articles/#{slug}", params
68
+ end
69
+
70
+ private
71
+
72
+ # Private: Articles API path. If a topic slug is supplied the returned
73
+ # path is prefixed with "/topic/#{topic}".
74
+ #
75
+ # topic_slug - The topic slug
76
+ #
77
+ # Returns a String.
78
+ def articles_path(topic_slug = nil)
79
+ if topic_slug
80
+ "/topics/#{topic_slug}/articles"
81
+ else
82
+ "/articles"
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,33 @@
1
+ module ReamazeAPI
2
+ class Channel < Resource
3
+ # Public: Retrieves channels.
4
+ #
5
+ # params - Hash of parameters to pass to the API
6
+ #
7
+ # API Routes
8
+ #
9
+ # GET /channels
10
+ #
11
+ # See also: https://www.reamaze.com/api/get_channels
12
+ #
13
+ # Returns a Hash.
14
+ def all(params = {})
15
+ get "/channels", params
16
+ end
17
+
18
+ # Public: Retrieve a specific channel.
19
+ #
20
+ # slug - Channel slug
21
+ #
22
+ # API Routes
23
+ #
24
+ # GET /channels/{slug}
25
+ #
26
+ # See also: https://www.reamaze.com/api/get_channel
27
+ #
28
+ # Returns a Hash.
29
+ def find(slug)
30
+ get "/channels/#{slug}"
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,116 @@
1
+ require "faraday_middleware"
2
+ require "uri"
3
+
4
+ module ReamazeAPI
5
+ class Client
6
+ # Reamaze's API doesn't always return JSON. If there's an error parsing
7
+ # the response as JSON, just return the raw body.
8
+ class Middleware < FaradayMiddleware::ParseJson
9
+ define_parser do |body|
10
+ begin
11
+ JSON.parse(body) unless body.strip.empty?
12
+ rescue
13
+ body
14
+ end
15
+ end
16
+ end
17
+
18
+ Faraday::Response.register_middleware reamaze_api: lambda { Middleware }
19
+
20
+ # Public: HTTP methods used by the API
21
+ #
22
+ # Returns an Array.
23
+ HTTP_METHODS = %i(get put post)
24
+
25
+ # Public: URL for Reamaze API.
26
+ #
27
+ # Returns a String.
28
+ API_URL = "https://%{brand}.reamaze.com/api/v1".freeze
29
+
30
+ # Public: Initialize a new Client instance.
31
+ #
32
+ # brand: Brand name (subdomain from your Reamaze URL)
33
+ # login: Reamaze login
34
+ # token: Reamaze API token
35
+ #
36
+ # Returns nothing.
37
+ def initialize(brand:, login:, token:)
38
+ @url = URI.parse(API_URL % { brand: brand })
39
+
40
+ @http = Faraday.new(url: @url, ssl: { verify: true }) do |builder|
41
+ builder.request :json
42
+ builder.response :json
43
+ builder.adapter Faraday.default_adapter
44
+ builder.basic_auth login, token
45
+ end
46
+ end
47
+
48
+ # Public: Article resource.
49
+ #
50
+ # Returns an Article instance.
51
+ def articles
52
+ @articles ||= Article.new(self)
53
+ end
54
+
55
+ # Public: Channel resource.
56
+ #
57
+ # Returns a Channel instance.
58
+ def channels
59
+ @channels ||= Channel.new(self)
60
+ end
61
+
62
+
63
+ # Public: Contact resource.
64
+ #
65
+ # Returns a Contact instance.
66
+ def contacts
67
+ @contacts ||= Contact.new(self)
68
+ end
69
+
70
+ # Public: Conversation resource.
71
+ #
72
+ # Returns a Conversation instance.
73
+ def conversations
74
+ @conversations ||= Conversation.new(self)
75
+ end
76
+
77
+ # Public: Message resource.
78
+ #
79
+ # Returns a Message instance.
80
+ def messages
81
+ @messages ||= Message.new(self)
82
+ end
83
+
84
+ private
85
+
86
+ # Private: Submits an HTTP request to the upstream API.
87
+ #
88
+ # method: HTTP method (eg: :get, :post)
89
+ # path: API path (without `/api/v1` prefix, eg: "/messages")
90
+ # params: Hash of parameters to send with the request (default: {})
91
+ #
92
+ # Returns a Hash.
93
+ def commit(method:, path:, params: {})
94
+ path = "#{@url.path}#{path}"
95
+
96
+ response = @http.run_request(method, path, params, {})
97
+
98
+ Utils.symbolize_hash(success: response.success?, payload: response.body)
99
+ rescue => e
100
+ Utils.error_hash(e)
101
+ end
102
+
103
+ # Private: `get`, `put`, and `post` helper methods. These submit an HTTP
104
+ # request to the upstream API.
105
+ #
106
+ # path: API path (without `/api/v1` prefix, eg: "/messages")
107
+ # params: Hash of parameters to send with the request (default: {})
108
+ #
109
+ # Returns a Hash.
110
+ HTTP_METHODS.each do |method|
111
+ define_method method do |path, params = {}|
112
+ commit method: method, path: path, params: params
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,49 @@
1
+ module ReamazeAPI
2
+ class Contact < Resource
3
+ # Public: Retrieve contacts.
4
+ #
5
+ # params - Hash of parameters to pass to the API
6
+ #
7
+ # API Routes
8
+ #
9
+ # GET /contacts
10
+ #
11
+ # See also: https://www.reamaze.com/api/get_contacts
12
+ #
13
+ # Returns a Hash.
14
+ def all(params = {})
15
+ get "/contacts", params
16
+ end
17
+
18
+ # Public: Create a new contact.
19
+ #
20
+ # params - Hash of parameters to pass to the API
21
+ #
22
+ # API Routes
23
+ #
24
+ # POST /contacts
25
+ #
26
+ # See also: https://www.reamaze.com/api/post_contacts
27
+ #
28
+ # Returns a Hash.
29
+ def create(params)
30
+ post "/contacts", params
31
+ end
32
+
33
+ # Public: Update an existing contact.
34
+ #
35
+ # slug - Contact slug (email)
36
+ # params - Hash of parameters to pass to the API
37
+ #
38
+ # API Routes
39
+ #
40
+ # PUT /contacts/{slug}
41
+ #
42
+ # See also: https://www.reamaze.com/api/put_contacts
43
+ #
44
+ # Returns a Hash.
45
+ def update(slug, params)
46
+ put "/contacts/#{slug}", params
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,48 @@
1
+ module ReamazeAPI
2
+ class Conversation < Resource
3
+ # Public: Retrieve conversations.
4
+ #
5
+ # params - Hash of parameters to pass to the API
6
+ #
7
+ # API Routes
8
+ #
9
+ # GET /conversations
10
+ #
11
+ # See also: https://www.reamaze.com/api/get_conversations
12
+ #
13
+ # Returns a Hash.
14
+ def all(params = {})
15
+ get "/conversations", params
16
+ end
17
+
18
+ # Public: Retrieve a specific conversation.
19
+ #
20
+ # slug - Conversation slug
21
+ #
22
+ # API Routes
23
+ #
24
+ # GET /conversations/{slug}
25
+ #
26
+ # See also: https://www.reamaze.com/api/get_conversation
27
+ #
28
+ # Returns a Hash.
29
+ def find(slug)
30
+ get "/conversations/#{slug}"
31
+ end
32
+
33
+ # Public: Create a new conversation (on behalf of a customer).
34
+ #
35
+ # params - Hash of parameters to pass to the API
36
+ #
37
+ # API Routes
38
+ #
39
+ # POST /conversations
40
+ #
41
+ # See also: https://www.reamaze.com/api/post_conversations
42
+ #
43
+ # Returns a Hash.
44
+ def create(params)
45
+ post "/conversations", params
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,63 @@
1
+ module ReamazeAPI
2
+ class Message < Resource
3
+ # Public: Retrieves messages.
4
+ #
5
+ # params - Hash of parameters (those not listed below are passed directly
6
+ # to the API):
7
+ # :conversation_slug - Optional conversation slug
8
+ #
9
+ # API Routes
10
+ #
11
+ # GET /messages
12
+ # GET /conversations/{slug}/messages
13
+ #
14
+ # See also: https://www.reamaze.com/api/get_messages
15
+ #
16
+ # Returns a Hash.
17
+ def all(params = {})
18
+ params = Utils.symbolize_hash(params)
19
+
20
+ get message_path(params.delete(:conversation_slug)), params
21
+ end
22
+
23
+ # Public: Create a new message under the given conversation.
24
+ #
25
+ # params - Hash of parameters (those not listed below are passed directly
26
+ # to the API):
27
+ # :conversation_slug - Required conversation slug
28
+ #
29
+ # API Routes
30
+ #
31
+ # POST /conversations/{slug}/messages
32
+ #
33
+ # See also: https://www.reamaze.com/api/post_messages
34
+ #
35
+ # Returns a Hash.
36
+ def create(params)
37
+ params = Utils.symbolize_hash(params)
38
+ slug = params.fetch(:conversation_slug)
39
+
40
+ params.delete :conversation_slug
41
+
42
+ post message_path(slug), params
43
+ rescue KeyError => e
44
+ Utils.error_hash(e)
45
+ end
46
+
47
+ private
48
+
49
+ # Private: Messages API path. If a conversation slug is supplied the
50
+ # returned path is prefixed with "/conversations/#{slug}".
51
+ #
52
+ # conversation_slug - The conversation slug
53
+ #
54
+ # Returns a String.
55
+ def message_path(conversation_slug = nil)
56
+ if conversation_slug
57
+ "/conversations/#{conversation_slug}/messages"
58
+ else
59
+ "/messages"
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,20 @@
1
+ require "forwardable"
2
+
3
+ module ReamazeAPI
4
+ class Resource
5
+ extend Forwardable
6
+
7
+ # Delegate HTTP actions back to the given Client.
8
+ def_delegators :@client, *Client::HTTP_METHODS
9
+
10
+ # Public: Initialize a new Resource instance. API resources should inherit
11
+ # from this class.
12
+ #
13
+ # client - ReamazeAPI::Client instance.
14
+ #
15
+ # Returns nothing.
16
+ def initialize(client)
17
+ @client = client
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,41 @@
1
+ require "reamaze_api/utils/hash_keys"
2
+
3
+ module ReamazeAPI
4
+ module Utils
5
+ extend self
6
+
7
+ # Public: Deep-symbolize keys in the given Hash.
8
+ #
9
+ # hash - a Hash instance
10
+ #
11
+ # Returns a Hash.
12
+ def symbolize_hash(hash)
13
+ HashKeys.deep_symbolize_keys(hash)
14
+ end
15
+
16
+ # Public: Hash used for success responses.
17
+ #
18
+ # payload - Payload from API
19
+ #
20
+ # Returns a Hash.
21
+ def success_hash(payload, success = true)
22
+ symbolize_hash(
23
+ success: success,
24
+ payload: payload
25
+ )
26
+ end
27
+
28
+ # Public: Hash used for error responses.
29
+ #
30
+ # exception - An Exception instance
31
+ #
32
+ # Returns a Hash.
33
+ def error_hash(exception)
34
+ {
35
+ success: false,
36
+ error: exception.class.name,
37
+ message: exception.message
38
+ }
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,182 @@
1
+ module ReamazeAPI
2
+ module Utils
3
+ module HashKeys
4
+ refine ::Hash do
5
+ # Returns a new hash with all keys converted using the +block+ operation.
6
+ #
7
+ # hash = { name: 'Rob', age: '28' }
8
+ #
9
+ # hash.transform_keys { |key| key.to_s.upcase } # => {"NAME"=>"Rob", "AGE"=>"28"}
10
+ #
11
+ # If you do not provide a +block+, it will return an Enumerator
12
+ # for chaining with other methods:
13
+ #
14
+ # hash.transform_keys.with_index { |k, i| [k, i].join } # => {"name0"=>"Rob", "age1"=>"28"}
15
+ def transform_keys
16
+ return enum_for(:transform_keys) { size } unless block_given?
17
+ result = {}
18
+ each_key do |key|
19
+ result[yield(key)] = self[key]
20
+ end
21
+ result
22
+ end
23
+
24
+ # Destructively converts all keys using the +block+ operations.
25
+ # Same as +transform_keys+ but modifies +self+.
26
+ def transform_keys!
27
+ return enum_for(:transform_keys!) { size } unless block_given?
28
+ keys.each do |key|
29
+ self[yield(key)] = delete(key)
30
+ end
31
+ self
32
+ end
33
+
34
+ # Returns a new hash with all keys converted to strings.
35
+ #
36
+ # hash = { name: 'Rob', age: '28' }
37
+ #
38
+ # hash.stringify_keys
39
+ # # => {"name"=>"Rob", "age"=>"28"}
40
+ def stringify_keys
41
+ transform_keys(&:to_s)
42
+ end
43
+
44
+ # Destructively converts all keys to strings. Same as
45
+ # +stringify_keys+, but modifies +self+.
46
+ def stringify_keys!
47
+ transform_keys!(&:to_s)
48
+ end
49
+
50
+ # Returns a new hash with all keys converted to symbols, as long as
51
+ # they respond to +to_sym+.
52
+ #
53
+ # hash = { 'name' => 'Rob', 'age' => '28' }
54
+ #
55
+ # hash.symbolize_keys
56
+ # # => {:name=>"Rob", :age=>"28"}
57
+ def symbolize_keys
58
+ transform_keys{ |key| key.to_sym rescue key }
59
+ end
60
+ alias_method :to_options, :symbolize_keys
61
+
62
+ # Destructively converts all keys to symbols, as long as they respond
63
+ # to +to_sym+. Same as +symbolize_keys+, but modifies +self+.
64
+ def symbolize_keys!
65
+ transform_keys!{ |key| key.to_sym rescue key }
66
+ end
67
+ alias_method :to_options!, :symbolize_keys!
68
+
69
+ # Validates all keys in a hash match <tt>*valid_keys</tt>, raising
70
+ # +ArgumentError+ on a mismatch.
71
+ #
72
+ # Note that keys are treated differently than HashWithIndifferentAccess,
73
+ # meaning that string and symbol keys will not match.
74
+ #
75
+ # { name: 'Rob', years: '28' }.assert_valid_keys(:name, :age) # => raises "ArgumentError: Unknown key: :years. Valid keys are: :name, :age"
76
+ # { name: 'Rob', age: '28' }.assert_valid_keys('name', 'age') # => raises "ArgumentError: Unknown key: :name. Valid keys are: 'name', 'age'"
77
+ # { name: 'Rob', age: '28' }.assert_valid_keys(:name, :age) # => passes, raises nothing
78
+ def assert_valid_keys(*valid_keys)
79
+ valid_keys.flatten!
80
+ each_key do |k|
81
+ unless valid_keys.include?(k)
82
+ raise ArgumentError.new("Unknown key: #{k.inspect}. Valid keys are: #{valid_keys.map(&:inspect).join(', ')}")
83
+ end
84
+ end
85
+ end
86
+
87
+ # Returns a new hash with all keys converted by the block operation.
88
+ # This includes the keys from the root hash and from all
89
+ # nested hashes and arrays.
90
+ #
91
+ # hash = { person: { name: 'Rob', age: '28' } }
92
+ #
93
+ # hash.deep_transform_keys{ |key| key.to_s.upcase }
94
+ # # => {"PERSON"=>{"NAME"=>"Rob", "AGE"=>"28"}}
95
+ def deep_transform_keys(&block)
96
+ _deep_transform_keys_in_object(self, &block)
97
+ end
98
+
99
+ # Destructively converts all keys by using the block operation.
100
+ # This includes the keys from the root hash and from all
101
+ # nested hashes and arrays.
102
+ def deep_transform_keys!(&block)
103
+ _deep_transform_keys_in_object!(self, &block)
104
+ end
105
+
106
+ # Returns a new hash with all keys converted to strings.
107
+ # This includes the keys from the root hash and from all
108
+ # nested hashes and arrays.
109
+ #
110
+ # hash = { person: { name: 'Rob', age: '28' } }
111
+ #
112
+ # hash.deep_stringify_keys
113
+ # # => {"person"=>{"name"=>"Rob", "age"=>"28"}}
114
+ def deep_stringify_keys
115
+ deep_transform_keys(&:to_s)
116
+ end
117
+
118
+ # Destructively converts all keys to strings.
119
+ # This includes the keys from the root hash and from all
120
+ # nested hashes and arrays.
121
+ def deep_stringify_keys!
122
+ deep_transform_keys!(&:to_s)
123
+ end
124
+
125
+ # Returns a new hash with all keys converted to symbols, as long as
126
+ # they respond to +to_sym+. This includes the keys from the root hash
127
+ # and from all nested hashes and arrays.
128
+ #
129
+ # hash = { 'person' => { 'name' => 'Rob', 'age' => '28' } }
130
+ #
131
+ # hash.deep_symbolize_keys
132
+ # # => {:person=>{:name=>"Rob", :age=>"28"}}
133
+ def deep_symbolize_keys
134
+ deep_transform_keys{ |key| key.to_sym rescue key }
135
+ end
136
+
137
+ # Destructively converts all keys to symbols, as long as they respond
138
+ # to +to_sym+. This includes the keys from the root hash and from all
139
+ # nested hashes and arrays.
140
+ def deep_symbolize_keys!
141
+ deep_transform_keys!{ |key| key.to_sym rescue key }
142
+ end
143
+
144
+ private
145
+ # support methods for deep transforming nested hashes and arrays
146
+ def _deep_transform_keys_in_object(object, &block)
147
+ case object
148
+ when Hash
149
+ object.each_with_object({}) do |(key, value), result|
150
+ result[yield(key)] = _deep_transform_keys_in_object(value, &block)
151
+ end
152
+ when Array
153
+ object.map {|e| _deep_transform_keys_in_object(e, &block) }
154
+ else
155
+ object
156
+ end
157
+ end
158
+
159
+ def _deep_transform_keys_in_object!(object, &block)
160
+ case object
161
+ when Hash
162
+ object.keys.each do |key|
163
+ value = object.delete(key)
164
+ object[yield(key)] = _deep_transform_keys_in_object!(value, &block)
165
+ end
166
+ object
167
+ when Array
168
+ object.map! {|e| _deep_transform_keys_in_object!(e, &block)}
169
+ else
170
+ object
171
+ end
172
+ end
173
+ end
174
+
175
+ using self unless {}.respond_to? :transform_keys
176
+
177
+ def self.deep_symbolize_keys(hash)
178
+ hash.deep_symbolize_keys
179
+ end
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,3 @@
1
+ module ReamazeAPI
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,25 @@
1
+ require_relative "lib/reamaze_api/version"
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "reamaze_api"
5
+ spec.version = ReamazeAPI::VERSION
6
+ spec.authors = ["Joshua Priddle"]
7
+ spec.email = ["jpriddle@me.com"]
8
+
9
+ spec.summary = %q{Reamaze API client}
10
+ spec.description = %q{Reamaze API client}
11
+ spec.homepage = "https://github.com/itspriddle/reamaze_api"
12
+
13
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\Atest/}) }
14
+ spec.bindir = "exe"
15
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
16
+ spec.require_paths = ["lib"]
17
+
18
+ spec.add_dependency "faraday", "~> 0.9.2"
19
+ spec.add_dependency "faraday_middleware", "~> 0.10.0"
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.12"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "minitest", "~> 5.9.0"
24
+ spec.add_development_dependency "rake-tomdoc", "~> 0.0.2"
25
+ end
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: reamaze_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Joshua Priddle
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-06-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.9.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.9.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday_middleware
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.10.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.10.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.12'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.12'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: minitest
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 5.9.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 5.9.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake-tomdoc
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.0.2
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.0.2
97
+ description: Reamaze API client
98
+ email:
99
+ - jpriddle@me.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - ".gitignore"
105
+ - ".travis.yml"
106
+ - Gemfile
107
+ - README.md
108
+ - Rakefile
109
+ - bin/console
110
+ - bin/setup
111
+ - lib/reamaze_api.rb
112
+ - lib/reamaze_api/article.rb
113
+ - lib/reamaze_api/channel.rb
114
+ - lib/reamaze_api/client.rb
115
+ - lib/reamaze_api/contact.rb
116
+ - lib/reamaze_api/conversation.rb
117
+ - lib/reamaze_api/message.rb
118
+ - lib/reamaze_api/resource.rb
119
+ - lib/reamaze_api/utils.rb
120
+ - lib/reamaze_api/utils/hash_keys.rb
121
+ - lib/reamaze_api/version.rb
122
+ - reamaze_api.gemspec
123
+ homepage: https://github.com/itspriddle/reamaze_api
124
+ licenses: []
125
+ metadata: {}
126
+ post_install_message:
127
+ rdoc_options: []
128
+ require_paths:
129
+ - lib
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ requirements: []
141
+ rubyforge_project:
142
+ rubygems_version: 2.4.5.1
143
+ signing_key:
144
+ specification_version: 4
145
+ summary: Reamaze API client
146
+ test_files: []
147
+ has_rdoc: