layer-ruby 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6b2e92f9be129ac6265ff24ab73852387a9e438a
4
- data.tar.gz: 1f3911782934d15e49f0feeb3964357acd28873c
3
+ metadata.gz: 78be9a887246783d87ee5441bb6d713d7d11e0e9
4
+ data.tar.gz: c96c5872a9539077b4c86abc8fcda78bace25fcf
5
5
  SHA512:
6
- metadata.gz: 57229aa42c27f78cef0f959c68d24299792cee2803142cfa304bab995a9c1268decd4b055abae6d8ed5c49ce014139de36129c9ba3c21d31a9d375a1266c0d46
7
- data.tar.gz: 9681349bdb101b4ec80219bcc69990454353b8c9b9f72c33896e9673f555c7f932a5128655fe773a2131f7df060775aedc61700999338d35b2e7985ded664203
6
+ metadata.gz: 7d02be7b2d37304b8d8e18f4ebc8afba4b697c9272ef357e7bee0244f642294553565a09f59482fd04e1ea260c0ee90250b012bef36e7509aedc39d3eceb457b
7
+ data.tar.gz: f5ca37c2018d18ab8052b2b9df63e15b24d9e396cd92a504b8ac6a5b6ca5391987259969f5f8b7e790d91a960c88eaacd81af5992e904c76dcdf9f98a6d952ed
data/.gitignore CHANGED
@@ -7,3 +7,4 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ .env
data/Gemfile CHANGED
@@ -2,3 +2,8 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in layer-ruby.gemspec
4
4
  gemspec
5
+
6
+ gem 'dotenv', '~> 2.0'
7
+ gem 'layer-identity_token', '~> 0.0'
8
+ gem 'guard-rspec', '~> 4.5'
9
+ gem 'guard-yard', '~> 2.1'
data/Guardfile CHANGED
@@ -14,3 +14,7 @@ guard :rspec, cmd: "bundle exec rspec" do
14
14
  ruby = dsl.ruby
15
15
  dsl.watch_spec_files_for(ruby.lib_files)
16
16
  end
17
+
18
+ guard 'yard', :cli => '--reload' do
19
+ watch(%r{lib/.+\.rb})
20
+ end
data/README.md CHANGED
@@ -1,9 +1,10 @@
1
- # Layer Platform API
1
+ # Ruby Client for Layer
2
2
 
3
- [![Build Status](https://travis-ci.org/benedikt/layer-ruby.svg)](https://travis-ci.org/benedikt/layer-ruby)
3
+ [![Build Status](https://travis-ci.org/benedikt/layer-ruby.svg?branch=master)](https://travis-ci.org/benedikt/layer-ruby)
4
4
  [![Gem Version](https://badge.fury.io/rb/layer-ruby.svg)](http://badge.fury.io/rb/layer-ruby)
5
+ [![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](http://rubydoc.info/gems/layer-ruby)
5
6
 
6
- Ruby bindings for the [Layer Platform API](https://developer.layer.com/docs/platform).
7
+ Ruby client for the [Layer Platform API](https://developer.layer.com/docs/platform) and [Layer Client REST API](https://developer.layer.com/docs/client/rest).
7
8
 
8
9
  ## Installation
9
10
 
@@ -23,11 +24,11 @@ Or install it yourself as:
23
24
 
24
25
  ## Usage
25
26
 
26
- Please refer to the [Layer Platform API documentation](https://developer.layer.com/docs/platform) for details about the required payloads and responses.
27
+ Please refer to the [Layer Platform API documentation](https://developer.layer.com/docs/platform) and [Layer Client REST API documentation](https://developer.layer.com/docs/client/rest) for details about the required payloads and responses.
27
28
 
28
29
  ### Configuration
29
30
 
30
- To use interact with the Layer Platform API, you need your Layer APP ID as well as a Layer Platform API Token. The gem reads both values from the `LAYER_APP_ID` and `LAYER_PLATFORM_TOKEN` environment variables. Alternatively you can specify the values by configuring the `Layer::Client` like this:
31
+ To use the Layer Platform API, you need your Layer APP ID as well as a Layer Platform API Token. The gem reads both values from the `LAYER_APP_ID` and `LAYER_PLATFORM_TOKEN` environment variables. Alternatively you can specify the values by configuring the `Layer::Client` like this:
31
32
 
32
33
  ```ruby
33
34
  Layer::Client.configure do |config|
@@ -36,70 +37,34 @@ Layer::Client.configure do |config|
36
37
  end
37
38
  ```
38
39
 
39
- ### Creating Conversations
40
-
41
- ```ruby
42
- conversation = Layer::Conversation.create({ participants: ['1', '2'] })
43
- ```
44
-
45
- ### Retrieving Conversations
46
-
47
- To retrieve a existing conversation, just use `Conversation.find` passing it the conversation id:
48
-
49
- ```ruby
50
- conversation = Layer::Conversation.find('CONVERSATION_ID_HERE')
51
- ```
52
-
53
- ### Updating Conversations
40
+ ### Using the gem with multiple applications at once
54
41
 
55
- To update a conversation, just update the conversation's attributes and call `save`.
42
+ It's possible to create a new instance of `Layer::Client` and passing both the app id and the token to the initializer:
56
43
 
57
44
  ```ruby
58
- conversation = Layer::Conversation.find('CONVERSATION_ID_HERE')
59
- conversation.participants << 3
60
- conversation.metadata[:foo] = 'bar'
61
- conversation.save
45
+ client = Layer::Client.new('YOUR_APP_ID_HERE', 'YOUR_PLATFORM_TOKEN_HERE')
62
46
  ```
63
47
 
48
+ The client will not use any global configuration. You can pass the client as a second parameter to any operations (`create`, `find`) described above.
64
49
 
65
- ### Sending Messages
66
-
67
- In order to send messages, you first have to load (or create) a Conversation. Afterwards you can send a message to the conversation like this:
68
-
69
- ```ruby
70
- conversation = Layer::Conversation.find('CONVERSATION_ID_HERE')
71
- conversation.messages.create({ sender: { name: 'Server' }, parts: [{ body: 'Hello!', mime_type: 'text/plain' }]})
72
- ```
73
-
74
- ### Sending Announcements
50
+ ### Using the Layer Client REST API
75
51
 
76
- You can send a announcements like this:
52
+ To use the Layer Client REST API, you need a way to generate identitiy tokens. You might want to use the [layer-identity_token](https://github.com/dreimannzelt/layer-identity_token) gem for that. Using this gem, you can create a new client using the REST API like this:
77
53
 
78
54
  ```ruby
79
- Layer::Announcement.create({ recipients: 'everyone', sender: { name: 'Server' }, parts: [{ body: 'Hello!', mime_type: 'text/plain' }]})
55
+ client = Layer::Client.authenticate { |nonce| Layer::IdentityToken.new('user_id_here', nonce) }
80
56
  ```
81
57
 
82
- ### Managing block lists
83
-
84
- Managing block lists is also possible:
58
+ Afterwards, pass the client as an additional argument to the resource's methods:
85
59
 
86
60
  ```ruby
87
- user = Layer::User.find('user_id')
88
- user.blocks.all # Returns a list of blocks
89
- user.blocks.create({ user_id: 'other_user' }) # Adds the other user to the block list
90
- user.blocks.delete('other_user') # Removes the other user from the block list
91
- user.blocks.all.first.delete # Removes the first entry from the block list
61
+ # Finds all conversations of the authenticated user
62
+ Layer::Conversation.all(client)
92
63
  ```
93
64
 
94
- ### Using the gem with multiple applications at once
65
+ ### Documentation
95
66
 
96
- It's possible to create a new instance of `Layer::Client` and passing both the app id and the token to the initializer:
97
-
98
- ```ruby
99
- client = Layer::Client.new('YOUR_APP_ID_HERE', 'YOUR_PLATFORM_TOKEN_HERE')
100
- ```
101
-
102
- The client will not use any global configuration. You can pass the client as a second parameter to any operations (`create`, `find`) described above.
67
+ Please refer to [the full documentation](http://rubydoc.info/gems/layer-ruby) for details on how to use Announcements, Block Lists, Conversations, Messages, Rich Content, and WebHooks.
103
68
 
104
69
  ## Development
105
70
 
data/layer-ruby.gemspec CHANGED
@@ -23,6 +23,6 @@ Gem::Specification.new do |spec|
23
23
 
24
24
  spec.add_development_dependency "bundler", "~> 1.10"
25
25
  spec.add_development_dependency "rake", "~> 10.0"
26
- spec.add_development_dependency "rspec"
27
- spec.add_development_dependency "guard-rspec"
26
+ spec.add_development_dependency "rspec", "~> 3.3"
27
+ spec.add_development_dependency "yard", "~> 0.8"
28
28
  end
data/lib/layer.rb CHANGED
@@ -1,14 +1,31 @@
1
1
  require 'layer/version'
2
+ require 'layer/exceptions'
2
3
  require 'layer/client'
3
4
  require 'layer/patch'
4
5
  require 'layer/operations'
5
6
  require 'layer/resource'
7
+ require 'layer/resource_collection'
6
8
  require 'layer/relation_proxy'
7
9
  require 'layer/conversation'
10
+ require 'layer/content'
8
11
  require 'layer/message'
9
12
  require 'layer/user'
10
13
  require 'layer/block'
11
14
  require 'layer/announcement'
15
+ require 'layer/webhook'
16
+
17
+
18
+ # @!macro [new] platform-api
19
+ # @note This is only available via the Platform API.
20
+
21
+ # @!macro [new] rest-api
22
+ # @note This is only available via the REST API.
23
+ # @see file:README.md#label-Using+the+Layer+Client+REST+API Using the Client REST API
24
+
25
+ # @!macro [new] various-apis
26
+ # @note This is available in both the REST and the Platform API. Please refer to the respective documentation to see which methods are available.
27
+ # @see file:README.md#label-Using+the+Layer+Client+REST+API Using the Client REST API
12
28
 
13
29
  module Layer
30
+
14
31
  end
@@ -1,11 +1,17 @@
1
1
  module Layer
2
+ # @example
3
+ # Layer::Announcement.create({ recipients: 'everyone', sender: { name: 'Server' }, parts: [{ body: 'Hello!', mime_type: 'text/plain' }]})
4
+ #
5
+ # @see https://developer.layer.com/docs/platform#send-an-announcement Layer Platform API Documentation about announcements
6
+ # @!macro platform-api
2
7
  class Announcement < Resource
3
8
  include Operations::Create
4
9
 
10
+ # @!parse extend Layer::Operations::Create::ClassMethods
11
+
5
12
  def sent_at
6
13
  Time.parse(attributes['sent_at'])
7
14
  end
8
15
 
9
16
  end
10
17
  end
11
-
data/lib/layer/block.rb CHANGED
@@ -1,5 +1,19 @@
1
1
  module Layer
2
+ # Managing block lists is also possible:
3
+ #
4
+ # @example
5
+ # user = Layer::User.find('user_id')
6
+ # user.blocks.all # Returns a list of blocks
7
+ # user.blocks.create({ user_id: 'other_user' }) # Adds the other user to the block list
8
+ # user.blocks.delete('other_user') # Removes the other user from the block list
9
+ # user.blocks.all.first.delete # Removes the first entry from the block list
10
+ #
11
+ # @see https://developer.layer.com/docs/platform#block-users Layer Platform API Documentation about block lists
12
+ # @!macro platform-api
2
13
  class Block < Resource
3
14
  include Operations::Delete
15
+
16
+ # @!parse extend Layer::Operations::Delete::ClassMethods
17
+
4
18
  end
5
19
  end
data/lib/layer/client.rb CHANGED
@@ -1,6 +1,9 @@
1
1
  require 'rest-client'
2
2
  require 'securerandom'
3
3
 
4
+ require 'layer/client/platform'
5
+ require 'layer/client/rest'
6
+
4
7
  module Layer
5
8
  class Client
6
9
  class << self
@@ -21,13 +24,10 @@ module Layer
21
24
  def normalize_id(id)
22
25
  id.to_s.split('/').last
23
26
  end
24
- end
25
27
 
26
- attr_reader :app_id, :token
27
-
28
- def initialize(app_id = self.class.app_id, token = self.class.token)
29
- @app_id = self.class.normalize_id(app_id)
30
- @token = token
28
+ def authenticate(app_id = self.app_id, &block)
29
+ Layer::Client::REST.new(app_id, &block)
30
+ end
31
31
  end
32
32
 
33
33
  def get(*args)
@@ -63,10 +63,9 @@ module Layer
63
63
  private
64
64
 
65
65
  def request(method, url, payload = {}, headers = {})
66
- url = "https://api.layer.com/apps/#{app_id}#{url}" unless url.start_with?('https://api.layer.com')
66
+ url = "https://api.layer.com#{url}" unless url.start_with?('https://api.layer.com')
67
67
 
68
68
  headers = {
69
- 'Authorization' => "Bearer #{token}",
70
69
  'Accept' => 'application/vnd.layer+json; version=1.0',
71
70
  'Content-Type' => 'application/json',
72
71
  'If-None-Match' => SecureRandom.uuid
@@ -76,6 +75,8 @@ module Layer
76
75
 
77
76
  response = RestClient::Request.execute(method: method, url: url, payload: payload, headers: headers)
78
77
  response.empty? ? nil : JSON.parse(response)
78
+ rescue RestClient::Exception
79
+ raise Layer::Exceptions::Exceptions.build_exception($!)
79
80
  end
80
81
 
81
82
  end
@@ -0,0 +1,22 @@
1
+ module Layer
2
+ class Client
3
+ class Platform < Layer::Client
4
+
5
+ attr_reader :app_id, :token
6
+
7
+ def initialize(app_id = self.class.app_id, token = self.class.token)
8
+ @app_id = self.class.normalize_id(app_id)
9
+ @token = token
10
+ end
11
+
12
+ private
13
+
14
+ def request(method, url, payload = {}, headers = {})
15
+ url = "https://api.layer.com/apps/#{app_id}#{url}" unless url.start_with?('https://api.layer.com')
16
+ headers['Authorization'] ||= "Bearer #{token}"
17
+
18
+ super
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,41 @@
1
+ module Layer
2
+ class Client
3
+ class REST < Layer::Client
4
+
5
+ def self.authenticate(app_id, nonce = nil)
6
+ client = Layer::Client.new
7
+
8
+ nonce ||= client.post('/nonces')['nonce']
9
+
10
+ identity_token = yield(nonce)
11
+
12
+ response = client.post('/sessions', { identity_token: identity_token, app_id: app_id })
13
+ response['session_token']
14
+ end
15
+
16
+ attr_reader :token, :app_id, :block
17
+
18
+ def initialize(app_id = self.class.app_id, &block)
19
+ @app_id = self.class.normalize_id(app_id)
20
+ @block = block
21
+ authenticate
22
+ end
23
+
24
+ private
25
+
26
+ def request(method, url, payload = {}, headers = {})
27
+ url = "https://api.layer.com#{url}" unless url.start_with?('https://api.layer.com')
28
+ headers['Authorization'] ||= "Layer session-token=\"#{token}\""
29
+
30
+ super
31
+ rescue Layer::Exceptions::Exceptions::AuthenticationRequired => exception
32
+ authenticate(exception.response_json['data']['nonce'])
33
+ retry
34
+ end
35
+
36
+ def authenticate(nonce = nil)
37
+ @token = self.class.authenticate(app_id, nonce, &block)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,50 @@
1
+ module Layer
2
+ # @example
3
+ # content = Layer::Content.create('image/png', File.open('photo.png'))
4
+ #
5
+ # message = Layer::Message.create({
6
+ # sender: { name: 'Server' },
7
+ # parts: [
8
+ # { body: content.to_json, mime_type: content.mime_type }
9
+ # ]
10
+ # })
11
+ #
12
+ # @see https://developer.layer.com/docs/client/rest#rich-content Layer REST API documentation about rich content
13
+ # @!macro rest-api
14
+ class Content < Resource
15
+ include Operations::Create
16
+ include Operations::Find
17
+
18
+ # @!parse extend Layer::Operations::Create::ClassMethods
19
+ # @!parse extend Layer::Operations::Find::ClassMethods
20
+
21
+ def self.create(mime_type, file, client = self.client)
22
+ response = client.post(url, {}, headers = {
23
+ 'Upload-Content-Type' => mime_type,
24
+ 'Upload-Content-Length' => file.size
25
+ })
26
+
27
+ attributes = response.merge('size' => file.size)
28
+
29
+ from_response(attributes, client).tap do |content|
30
+ content.upload(file)
31
+ end
32
+ end
33
+
34
+ def self.url
35
+ '/content'
36
+ end
37
+
38
+ def upload(file)
39
+ RestClient.put(upload_url, file)
40
+ end
41
+
42
+ def url
43
+ attributes['refresh_url'] || "#{self.class.url}/#{Layer::Client.normalize_id(id)}"
44
+ end
45
+
46
+ def to_json(*args)
47
+ { id: id, size: size }.to_json(*args)
48
+ end
49
+ end
50
+ end
@@ -1,20 +1,82 @@
1
1
  module Layer
2
+ # @example Creating a new conversation
3
+ # conversation = Layer::Conversation.create({ participants: ['1', '2'] })
4
+ #
5
+ # @example Finding an existing conversation
6
+ # conversation = Layer::Conversation.find('CONVERSATION_ID_HERE')
7
+ #
8
+ # @example Updating an existing conversation
9
+ # conversation = Layer::Conversation.find('CONVERSATION_ID_HERE')
10
+ # conversation.participants << 3
11
+ # conversation.metadata[:foo] = 'bar'
12
+ # conversation.save
13
+ #
14
+ # @see https://developer.layer.com/docs/platform#retrieving-conversations Layer Platform API Documentation about conversations
15
+ # @see https://developer.layer.com/docs/client/rest#conversations Layer REST API Documentation about conversations
16
+ # @!macro various-apis
2
17
  class Conversation < Resource
3
18
  include Operations::Find
19
+ include Operations::Paginate
4
20
  include Operations::Create
21
+ include Operations::Delete
5
22
  include Operations::Patch
6
23
 
24
+ # @!parse extend Layer::Operations::Find::ClassMethods
25
+ # @!parse extend Layer::Operations::Paginate::ClassMethods
26
+ # @!parse extend Layer::Operations::Create::ClassMethods
27
+ # @!parse extend Layer::Operations::Delete::ClassMethods
28
+
29
+ # Destroys the conversation with the given id for all participants
30
+ #
31
+ # @param [String] id of the conversation to destroy
32
+ # @!macro rest-api
33
+ def self.destroy(id, client = self.client)
34
+ id = Layer::Client.normalize_id(id)
35
+ client.delete("#{url}/#{id}", {}, { params: { destroy: true } })
36
+ end
37
+
38
+ # Returns the converations messages
39
+ #
40
+ # @return [Layer::RelationProxy] the conversation's messages
41
+ # @!macro various-apis
7
42
  def messages
8
- RelationProxy.new(self, Message, [Operations::Create])
43
+ RelationProxy.new(self, Message, [Operations::Create, Operations::Paginate, Operations::Find])
44
+ end
45
+
46
+ # Returns the conversations metadata
47
+ #
48
+ # @return [Layer::Patch::Hash] the metadata hash
49
+ def metadata
50
+ attributes['metadata'] ||= {}
9
51
  end
10
52
 
53
+ # Returns the conversations metadata
54
+ #
55
+ # @return [Layer::Patch::Array] the participants array
56
+ def participants
57
+ attributes['participants'] ||= []
58
+ end
59
+
60
+ # Whether the conversation is distinct
61
+ #
62
+ # @return [Boolean] whether the conversation is distinct
11
63
  def distinct?
12
64
  attributes['distinct']
13
65
  end
14
66
 
67
+ # Returns the time the conversation was created at
68
+ #
69
+ # @return [Time] the time the conversation was created at
15
70
  def created_at
16
71
  Time.parse(attributes['created_at'])
17
72
  end
18
73
 
74
+ # Destroys the conversation for all participants
75
+ #
76
+ # @!macro rest-api
77
+ def destroy
78
+ client.delete(url, {}, { params: { destroy: true } })
79
+ end
80
+
19
81
  end
20
82
  end
@@ -0,0 +1,52 @@
1
+ module Layer
2
+ module Exceptions
3
+
4
+ def self.build_exception(original_exception)
5
+ identifier = JSON.parse(original_exception.http_body)['id']
6
+ identifier.gsub!(/(?:_|(\/)|^)([a-z\d]*)/i) { $2.capitalize }
7
+
8
+ exception = const_get(identifier) rescue Exception
9
+ exception.new(original_exception)
10
+ rescue
11
+ original_exception
12
+ end
13
+
14
+ class Exception < RuntimeError
15
+ attr_reader :original_exception
16
+
17
+ def initialize(original_exception = nil)
18
+ @original_exception = original_exception
19
+ end
20
+
21
+ def message
22
+ "#{original_exception.message}\n\n#{JSON.pretty_generate(response_json)}\n\n"
23
+ end
24
+
25
+ def response_json
26
+ JSON.parse(original_exception.http_body)
27
+ end
28
+ end
29
+
30
+ class ClientException < Exception; end
31
+ class ServiceUnavailable < ClientException; end
32
+ class InvalidAppId< ClientException; end
33
+ class InvalidRequestId < ClientException; end
34
+ class AuthenticationRequired < ClientException; end
35
+ class AppSuspended < ClientException; end
36
+ class UserSuspended < ClientException; end
37
+ class RateLimitExceeded < ClientException; end
38
+ class RequestTimeout < ClientException; end
39
+ class InvalidOperation < ClientException; end
40
+ class InvalidRequest < ClientException; end
41
+ class InvalidEndpoint < ClientException; end
42
+ class InvalidHeader < ClientException; end
43
+
44
+ class ResourceException < Exception; end
45
+ class AccessDenied < ResourceException; end
46
+ class NotFound < ResourceException; end
47
+ class ObjectDeleted < ResourceException; end
48
+ class MissingProperty < ResourceException; end
49
+ class InvalidProperty < ResourceException; end
50
+ class Conflict < ResourceException; end
51
+ end
52
+ end
data/lib/layer/message.rb CHANGED
@@ -1,13 +1,51 @@
1
1
  module Layer
2
+ # @example Sending messages
3
+ # conversation = Layer::Conversation.find('CONVERSATION_ID_HERE')
4
+ # conversation.messages.create({ sender: { name: 'Server' }, parts: [{ body: 'Hello!', mime_type: 'text/plain' }]})
5
+ #
6
+ # @see https://developer.layer.com/docs/platform#send-a-message Layer Platform API Documentation about messages
7
+ # @see https://developer.layer.com/docs/client/rest#messages Layer REST API Documentation about messages
8
+ # @see Layer::Content Sending rich content using Layer::Content
9
+ #
10
+ # @!macro various-apis
2
11
  class Message < Resource
12
+ include Operations::Find
3
13
 
14
+ # @!parse extend Layer::Operations::Find::ClassMethods
15
+
16
+ # Returns the conversation this message belongs to
17
+ #
18
+ # @return [Layer::Conversation] the message's conversation
4
19
  def conversation
5
20
  Conversation.from_response(attributes['conversation'], client)
6
21
  end
7
22
 
23
+ # Returns the time the message was sent at
24
+ #
25
+ # @return [Time] the time the message was sent at
8
26
  def sent_at
9
27
  Time.parse(attributes['sent_at'])
10
28
  end
11
29
 
30
+ # Marks the message as read by the current user
31
+ #
32
+ # @!macro rest-api
33
+ def read!
34
+ client.post(receipts_url, { type: 'read' })
35
+ end
36
+
37
+ # Marks the message as delivered to the current user
38
+ # @!macro rest-api
39
+ def delivered!
40
+ client.post(receipts_url, { type: 'delivery' })
41
+ end
42
+
43
+ # The endpoint to send read and delivered receipts to
44
+ #
45
+ # @return [String] the url of the endpoint
46
+ # @!macro rest-api
47
+ def receipts_url
48
+ attributes['receipts_url'] || "#{url}/receipts"
49
+ end
12
50
  end
13
51
  end
@@ -1,5 +1,6 @@
1
1
  require 'layer/operations/create'
2
2
  require 'layer/operations/find'
3
3
  require 'layer/operations/list'
4
+ require 'layer/operations/paginate'
4
5
  require 'layer/operations/delete'
5
6
  require 'layer/operations/patch'
@@ -3,12 +3,19 @@ module Layer
3
3
  module Create
4
4
 
5
5
  module ClassMethods
6
+ # Creates the resource with the given attributes
7
+ #
8
+ # @param attributes [Hash] the resource's attributes
9
+ # @param client [Layer::Client] the client to use to make this request
10
+ # @return [Layer::Resource] the created resource
11
+ # @raise [Layer::Exceptions::Exception] a subclass of Layer::Exceptions::Exception describing the error
6
12
  def create(attributes = {}, client = self.client)
7
13
  response = client.post(url, attributes)
8
14
  from_response(response, client)
9
15
  end
10
16
  end
11
17
 
18
+ # @!visibility private
12
19
  def self.included(base)
13
20
  base.extend(ClassMethods)
14
21
  end
@@ -3,16 +3,25 @@ module Layer
3
3
  module Delete
4
4
 
5
5
  module ClassMethods
6
+ # Deletes the resource with the given id
7
+ #
8
+ # @param id [String] the resource's id
9
+ # @param client [Layer::Client] the client to use to make this request
10
+ # @raise [Layer::Exceptions::Exception] a subclass of Layer::Exceptions::Exception describing the error
6
11
  def delete(id, client = self.client)
7
12
  id = Layer::Client.normalize_id(id)
8
13
  client.delete("#{url}/#{id}")
9
14
  end
10
15
  end
11
16
 
17
+ # @!visibility private
12
18
  def self.included(base)
13
19
  base.extend(ClassMethods)
14
20
  end
15
21
 
22
+ # Deletes the resource
23
+ #
24
+ # @raise [Layer::Exceptions::Exception] a subclass of Layer::Exceptions::Exception describing the error
16
25
  def delete
17
26
  client.delete(url)
18
27
  end
@@ -3,6 +3,12 @@ module Layer
3
3
  module Find
4
4
 
5
5
  module ClassMethods
6
+ # Finds the resource with the given id
7
+ #
8
+ # @param id [String] the resource's id
9
+ # @param client [Layer::Client] the client to use to make this request
10
+ # @return [Layer::Resource] the found resource
11
+ # @raise [Layer::Exceptions::Exception] a subclass of Layer::Exceptions::Exception describing the error
6
12
  def find(id, client = self.client)
7
13
  id = Layer::Client.normalize_id(id)
8
14
  response = client.get("#{url}/#{id}")
@@ -10,10 +16,15 @@ module Layer
10
16
  end
11
17
  end
12
18
 
19
+ # @!visibility private
13
20
  def self.included(base)
14
21
  base.extend(ClassMethods)
15
22
  end
16
23
 
24
+ # Reloads the resource
25
+ #
26
+ # @return [Layer::Resource] the resource itself
27
+ # @raise [Layer::Exceptions::Exception] a subclass of Layer::Exceptions::Exception describing the error
17
28
  def reload
18
29
  self.attributes = client.get(url)
19
30
  self
@@ -3,12 +3,18 @@ module Layer
3
3
  module List
4
4
 
5
5
  module ClassMethods
6
+ # Finds all resources
7
+ #
8
+ # @param client [Layer::Client] the client to use to make this request
9
+ # @return [Enumerable] the found resources
10
+ # @raise [Layer::Exceptions::Exception] a subclass of Layer::Exceptions::Exception describing the error
6
11
  def all(client = self.client)
7
12
  response = client.get(url)
8
13
  response.map { |attributes| from_response(attributes, client) }
9
14
  end
10
15
  end
11
16
 
17
+ # @!visibility private
12
18
  def self.included(base)
13
19
  base.extend(ClassMethods)
14
20
  end
@@ -0,0 +1,23 @@
1
+ module Layer
2
+ module Operations
3
+ module Paginate
4
+
5
+ module ClassMethods
6
+ # Finds all resources from a paginated endpoint
7
+ #
8
+ # @param client [Layer::Client] the client to use to make this request
9
+ # @return [Layer::ResourceCollection] the found resources
10
+ # @raise [Layer::Exceptions::Exception] a subclass of Layer::Exceptions::Exception describing the error
11
+ def all(client = self.client)
12
+ Layer::ResourceCollection.new(self, client)
13
+ end
14
+ end
15
+
16
+ # @!visibility private
17
+ def self.included(base)
18
+ base.extend(ClassMethods)
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -2,12 +2,20 @@ module Layer
2
2
  module Operations
3
3
  module Patch
4
4
 
5
+ # Creates the resource with the given attributes
6
+ #
7
+ # @return [Boolean] whether saving was successful
8
+ # @raise [Layer::Exceptions::Exception] a subclass of Layer::Exceptions::Exception describing the error
5
9
  def save
6
10
  client.patch(url, patch.operations)
7
11
  patch.reset
8
12
  true
9
13
  end
10
14
 
15
+ # Updates the resource's attributes to the given ones
16
+ #
17
+ # @param [Hash] attributes the new attributes
18
+ # @return [Layer::Patch::Hash] the resources new attributes
11
19
  def attributes=(attributes)
12
20
  @attributes = Layer::Patch::Hash.new(patch, attributes)
13
21
  end
@@ -10,7 +10,7 @@ module Layer
10
10
 
11
11
  def []=(key, value)
12
12
  patch.set(key, value)
13
- super
13
+ super(key, wrap(key, value))
14
14
  end
15
15
  alias :store :[]=
16
16
 
@@ -7,7 +7,7 @@ module Layer
7
7
  @resource_type = resource_type
8
8
  @base = base
9
9
 
10
- operations.each { |operation| singleton_class.include(operation::ClassMethods) }
10
+ operations.each { |operation| singleton_class.send(:include, operation::ClassMethods) }
11
11
 
12
12
  instance_eval(&block) if block_given?
13
13
  end
@@ -17,7 +17,7 @@ module Layer
17
17
  end
18
18
 
19
19
  def client
20
- @client ||= Client.new
20
+ @client ||= Client::Platform.new
21
21
  end
22
22
  end
23
23
 
@@ -29,7 +29,7 @@ module Layer
29
29
  end
30
30
 
31
31
  def url
32
- attributes['url']
32
+ attributes['url'] || (id && "#{self.class.url}/#{Layer::Client.normalize_id(id)}")
33
33
  end
34
34
 
35
35
  def id
@@ -37,13 +37,18 @@ module Layer
37
37
  end
38
38
 
39
39
  def respond_to_missing?(method, include_private = false)
40
- attributes.has_key?(method.to_s) || super
40
+ attribute = method.to_s.sub(/=$/, '')
41
+
42
+ attributes.has_key?(attribute) || super
41
43
  end
42
44
 
43
45
  private
44
46
 
45
47
  def method_missing(method, *args, &block)
46
- if attributes.has_key?(method.to_s)
48
+ if method.to_s =~ /=$/
49
+ attribute = method.to_s.sub(/=$/, '')
50
+ attributes[attribute] = args.first
51
+ elsif attributes.has_key?(method.to_s)
47
52
  attributes[method.to_s]
48
53
  else
49
54
  super
@@ -0,0 +1,30 @@
1
+ module Layer
2
+ class ResourceCollection < Enumerator
3
+
4
+ def initialize(resource, client)
5
+ @resource = resource
6
+ @client = client
7
+ @params = { page_size: 100 }
8
+
9
+ super() do |yielder|
10
+ while response = next_page
11
+ response.map do |attributes|
12
+ yielder << resource.from_response(attributes, client)
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :resource, :client, :params
21
+
22
+ def next_page
23
+ response = client.get(resource.url, {}, { params: params })
24
+ return nil if response.empty?
25
+ params[:from_id] = Layer::Client.normalize_id(response.last['id'])
26
+ response
27
+ end
28
+
29
+ end
30
+ end
data/lib/layer/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Layer
2
- VERSION = '0.4.1'
2
+ VERSION = '0.5.0'
3
3
  end
@@ -0,0 +1,59 @@
1
+ module Layer
2
+ # @example
3
+ # webhook = Layer::Webhook.create({
4
+ # target_config: { foo: :bar },
5
+ # secret: 'my-secret',
6
+ # event_types: ['message.sent'],
7
+ # target_url: 'http://example.com/layer/webhook'
8
+ # })
9
+ # @see https://gist.github.com/vtrehan/9ef1e16db5e74305ddf3 Layer Webhook documentation (Prerelease)
10
+ # @note This feature is still in beta at Layer. Please contact Layer to enable webhooks for your account.
11
+ #
12
+ # @!macro platform-api
13
+ class Webhook < Resource
14
+ include Operations::Find
15
+ include Operations::List
16
+ include Operations::Create
17
+ include Operations::Delete
18
+
19
+ # @!parse extend Layer::Operations::Find::ClassMethods
20
+ # @!parse extend Layer::Operations::List::ClassMethods
21
+ # @!parse extend Layer::Operations::Create::ClassMethods
22
+ # @!parse extend Layer::Operations::Delete::ClassMethods
23
+
24
+ # Activate this webhook
25
+ def activate!
26
+ client.post("#{url}/activate")
27
+ end
28
+
29
+ # Deactivate this webhook
30
+ def deactivate!
31
+ client.post("#{url}/deactivate")
32
+ end
33
+
34
+ # Check if this webhook is unverified
35
+ # @return [Boolean] whether the webhook is unverified
36
+ def unverified?
37
+ status == 'unverified'
38
+ end
39
+
40
+ # Check if this webhook is active
41
+ # @return [Boolean] whether the webhook is active
42
+ def active?
43
+ status == 'active'
44
+ end
45
+
46
+ # Check if this webhook is inactive
47
+ # @return [Boolean] whether the webhook is inactive
48
+ def inactive?
49
+ status == 'inactive'
50
+ end
51
+
52
+ # Returns the time the webhook was created at
53
+ # @return [Time] the time the webhook was created at
54
+ def created_at
55
+ Time.parse(attributes['created_at'])
56
+ end
57
+
58
+ end
59
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: layer-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Benedikt Deicke
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-07-29 00:00:00.000000000 Z
11
+ date: 2015-11-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client
@@ -56,30 +56,30 @@ dependencies:
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '3.3'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: '3.3'
69
69
  - !ruby/object:Gem::Dependency
70
- name: guard-rspec
70
+ name: yard
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
75
+ version: '0.8'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '0'
82
+ version: '0.8'
83
83
  description: Ruby bindings for the Layer Platform API
84
84
  email:
85
85
  - benedikt@benediktdeicke.com
@@ -103,13 +103,18 @@ files:
103
103
  - lib/layer/announcement.rb
104
104
  - lib/layer/block.rb
105
105
  - lib/layer/client.rb
106
+ - lib/layer/client/platform.rb
107
+ - lib/layer/client/rest.rb
108
+ - lib/layer/content.rb
106
109
  - lib/layer/conversation.rb
110
+ - lib/layer/exceptions.rb
107
111
  - lib/layer/message.rb
108
112
  - lib/layer/operations.rb
109
113
  - lib/layer/operations/create.rb
110
114
  - lib/layer/operations/delete.rb
111
115
  - lib/layer/operations/find.rb
112
116
  - lib/layer/operations/list.rb
117
+ - lib/layer/operations/paginate.rb
113
118
  - lib/layer/operations/patch.rb
114
119
  - lib/layer/patch.rb
115
120
  - lib/layer/patch/array.rb
@@ -117,9 +122,11 @@ files:
117
122
  - lib/layer/patch/hash.rb
118
123
  - lib/layer/relation_proxy.rb
119
124
  - lib/layer/resource.rb
125
+ - lib/layer/resource_collection.rb
120
126
  - lib/layer/ruby.rb
121
127
  - lib/layer/user.rb
122
128
  - lib/layer/version.rb
129
+ - lib/layer/webhook.rb
123
130
  homepage: https://github.com/benedikt/layer-ruby
124
131
  licenses:
125
132
  - MIT