reamaze_api 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: 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: