zendesk_api 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +7 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/.yardopts +1 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +59 -0
- data/LICENSE +19 -0
- data/Rakefile +49 -0
- data/Readme.md +178 -0
- data/lib/zendesk_api.rb +10 -0
- data/lib/zendesk_api/actions.rb +176 -0
- data/lib/zendesk_api/association.rb +267 -0
- data/lib/zendesk_api/client.rb +150 -0
- data/lib/zendesk_api/collection.rb +233 -0
- data/lib/zendesk_api/configuration.rb +52 -0
- data/lib/zendesk_api/core_ext/inflection.rb +13 -0
- data/lib/zendesk_api/core_ext/modulize.rb +10 -0
- data/lib/zendesk_api/core_ext/snakecase.rb +12 -0
- data/lib/zendesk_api/lru_cache.rb +38 -0
- data/lib/zendesk_api/middleware/request/etag_cache.rb +38 -0
- data/lib/zendesk_api/middleware/request/retry.rb +39 -0
- data/lib/zendesk_api/middleware/request/upload.rb +32 -0
- data/lib/zendesk_api/middleware/response/callback.rb +19 -0
- data/lib/zendesk_api/middleware/response/deflate.rb +18 -0
- data/lib/zendesk_api/middleware/response/gzip.rb +18 -0
- data/lib/zendesk_api/middleware/response/parse_iso_dates.rb +29 -0
- data/lib/zendesk_api/rescue.rb +44 -0
- data/lib/zendesk_api/resource.rb +133 -0
- data/lib/zendesk_api/resources/forum.rb +51 -0
- data/lib/zendesk_api/resources/misc.rb +66 -0
- data/lib/zendesk_api/resources/playlist.rb +64 -0
- data/lib/zendesk_api/resources/ticket.rb +76 -0
- data/lib/zendesk_api/resources/user.rb +44 -0
- data/lib/zendesk_api/track_changes.rb +72 -0
- data/lib/zendesk_api/trackie.rb +8 -0
- data/lib/zendesk_api/verbs.rb +43 -0
- data/lib/zendesk_api/version.rb +3 -0
- data/live/Readme.md +4 -0
- data/live/activity_spec.rb +5 -0
- data/live/audit_spec.rb +5 -0
- data/live/bookmark_spec.rb +11 -0
- data/live/category_spec.rb +12 -0
- data/live/collection_spec.rb +68 -0
- data/live/crm_spec.rb +11 -0
- data/live/custom_role_spec.rb +5 -0
- data/live/forum_spec.rb +14 -0
- data/live/forum_subscription_spec.rb +12 -0
- data/live/group_membership_spec.rb +18 -0
- data/live/group_spec.rb +14 -0
- data/live/identity_spec.rb +14 -0
- data/live/locale_spec.rb +11 -0
- data/live/macro_spec.rb +5 -0
- data/live/mobile_device_spec.rb +11 -0
- data/live/organization_spec.rb +12 -0
- data/live/satisfaction_rating_spec.rb +6 -0
- data/live/setting_spec.rb +5 -0
- data/live/suspended_ticket_spec.rb +8 -0
- data/live/ticket_field_spec.rb +12 -0
- data/live/ticket_metrics_spec.rb +6 -0
- data/live/ticket_spec.rb +88 -0
- data/live/topic_comment_spec.rb +13 -0
- data/live/topic_spec.rb +18 -0
- data/live/topic_subscription_spec.rb +12 -0
- data/live/topic_vote_spec.rb +13 -0
- data/live/upload_spec.rb +9 -0
- data/live/user_spec.rb +13 -0
- data/live/view_spec.rb +6 -0
- data/spec/association_spec.rb +210 -0
- data/spec/client_spec.rb +149 -0
- data/spec/collection_spec.rb +302 -0
- data/spec/configuration_spec.rb +24 -0
- data/spec/create_resource_spec.rb +39 -0
- data/spec/data_resource_spec.rb +229 -0
- data/spec/fixtures/Argentina.gif +0 -0
- data/spec/fixtures/Argentina2.gif +0 -0
- data/spec/fixtures/credentials.yml.example +3 -0
- data/spec/fixtures/test_resources.rb +8 -0
- data/spec/fixtures/zendesk.rb +88 -0
- data/spec/lru_cache_spec.rb +26 -0
- data/spec/macros/resource_macros.rb +157 -0
- data/spec/middleware/request/etag_cache_spec.rb +17 -0
- data/spec/middleware/request/retry_spec.rb +47 -0
- data/spec/middleware/request/test.jpg +0 -0
- data/spec/middleware/request/upload_spec.rb +74 -0
- data/spec/middleware/response/callback_spec.rb +17 -0
- data/spec/middleware/response/deflate_spec.rb +15 -0
- data/spec/middleware/response/gzip_spec.rb +19 -0
- data/spec/middleware/response/parse_iso_dates_spec.rb +44 -0
- data/spec/playlist_spec.rb +95 -0
- data/spec/read_resource_spec.rb +37 -0
- data/spec/rescue_spec.rb +94 -0
- data/spec/resource_spec.rb +332 -0
- data/spec/spec_helper.rb +120 -0
- data/spec/string_spec.rb +7 -0
- data/spec/trackie_spec.rb +39 -0
- data/zendesk_api.gemspec +38 -0
- metadata +364 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
module ZendeskAPI
|
2
|
+
class Configuration
|
3
|
+
# @return [String] The basic auth username.
|
4
|
+
attr_accessor :username
|
5
|
+
|
6
|
+
# @return [String] The basic auth password.
|
7
|
+
attr_accessor :password
|
8
|
+
|
9
|
+
# @return [String] The API url. Must be https unless {#allow_http} is set.
|
10
|
+
attr_accessor :url
|
11
|
+
|
12
|
+
# @return [Boolean] Whether to attempt to retry when rate-limited (http status: 429).
|
13
|
+
attr_accessor :retry
|
14
|
+
|
15
|
+
# @return [Logger] Logger to use when logging requests.
|
16
|
+
attr_accessor :logger
|
17
|
+
|
18
|
+
# @return [Hash] Client configurations (eg ssh config) to pass to Faraday
|
19
|
+
attr_accessor :client_options
|
20
|
+
|
21
|
+
# @return [Symbol] Faraday adapter
|
22
|
+
attr_accessor :adapter
|
23
|
+
|
24
|
+
# @return [Boolean] Whether to allow non-HTTPS connections for development purposes.
|
25
|
+
attr_accessor :allow_http
|
26
|
+
|
27
|
+
# Use this cache instead of default ZendeskAPI::LRUCache.new
|
28
|
+
# - must respond to read/write/fetch e.g. ActiveSupport::Cache::MemoryStore.new)
|
29
|
+
# - pass false to disable caching
|
30
|
+
# @return [ZendeskAPI::LRUCache]
|
31
|
+
attr_accessor :cache
|
32
|
+
|
33
|
+
def initialize
|
34
|
+
@client_options = {}
|
35
|
+
self.cache = ZendeskAPI::LRUCache.new(1000)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Sets accept and user_agent headers, and url.
|
39
|
+
#
|
40
|
+
# @return [Hash] Faraday-formatted hash of options.
|
41
|
+
def options
|
42
|
+
{
|
43
|
+
:headers => {
|
44
|
+
:accept => 'application/json',
|
45
|
+
:accept_encoding => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
46
|
+
:user_agent => "ZendeskAPI API #{ZendeskAPI::VERSION}"
|
47
|
+
},
|
48
|
+
:url => @url
|
49
|
+
}.merge(client_options)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# From https://github.com/rubyworks/facets/blob/master/lib/core/facets/string/modulize.rb
|
2
|
+
class String
|
3
|
+
def modulize
|
4
|
+
#gsub('__','/'). # why was this ever here?
|
5
|
+
gsub(/__(.?)/){ "::#{$1.upcase}" }.
|
6
|
+
gsub(/\/(.?)/){ "::#{$1.upcase}" }.
|
7
|
+
gsub(/(?:_+|-+)([a-z])/){ $1.upcase }.
|
8
|
+
gsub(/(\A|\s)([a-z])/){ $1 + $2.upcase }
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# From https://github.com/rubyworks/facets/blob/master/lib/core/facets/string/snakecase.rb
|
2
|
+
class String
|
3
|
+
def snakecase
|
4
|
+
#gsub(/::/, '/').
|
5
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
6
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
7
|
+
tr('-', '_').
|
8
|
+
gsub(/\s/, '_').
|
9
|
+
gsub(/__+/, '_').
|
10
|
+
downcase
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module ZendeskAPI
|
2
|
+
# http://codesnippets.joyent.com/posts/show/12329
|
3
|
+
class ZendeskAPI::LRUCache
|
4
|
+
attr_accessor :size
|
5
|
+
|
6
|
+
def initialize(size = 10)
|
7
|
+
@size = size
|
8
|
+
@store = {}
|
9
|
+
@lru = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def write(key, value)
|
13
|
+
@store[key] = value
|
14
|
+
set_lru(key)
|
15
|
+
@store.delete(@lru.pop) if @lru.size > @size
|
16
|
+
value
|
17
|
+
end
|
18
|
+
|
19
|
+
def read(key)
|
20
|
+
set_lru(key)
|
21
|
+
@store[key]
|
22
|
+
end
|
23
|
+
|
24
|
+
def fetch(key)
|
25
|
+
if @store.has_key? key
|
26
|
+
read key
|
27
|
+
else
|
28
|
+
write key, yield
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def set_lru(key)
|
35
|
+
@lru.unshift(@lru.delete(key) || key)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require "faraday/middleware"
|
2
|
+
|
3
|
+
module ZendeskAPI
|
4
|
+
module Middleware
|
5
|
+
module Request
|
6
|
+
# Request middleware that caches responses based on etags
|
7
|
+
# can be removed once this is merged: https://github.com/pengwynn/faraday_middleware/pull/42
|
8
|
+
class EtagCache < Faraday::Middleware
|
9
|
+
def initialize(app, options = {})
|
10
|
+
@app = app
|
11
|
+
@cache = options[:cache] ||
|
12
|
+
raise("need :cache option e.g. ActiveSupport::Cache::MemoryStore.new")
|
13
|
+
@cache_key_prefix = options.fetch(:cache_key_prefix, :faraday_etags)
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
return @app.call(env) unless [:get, :head].include?(env[:method])
|
18
|
+
cache_key = [@cache_key_prefix, env[:url].to_s]
|
19
|
+
|
20
|
+
# send known etag
|
21
|
+
if cached = @cache.read(cache_key)
|
22
|
+
env[:request_headers]["If-None-Match"] ||= cached[:response_headers]["Etag"]
|
23
|
+
end
|
24
|
+
|
25
|
+
@app.call(env).on_complete do
|
26
|
+
if cached && env[:status] == 304 # not modified
|
27
|
+
env[:body] = cached[:body]
|
28
|
+
end
|
29
|
+
|
30
|
+
if env[:status] == 200 && env[:response_headers]["Etag"] # modified and cacheable
|
31
|
+
@cache.write(cache_key, env)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require "faraday/middleware"
|
2
|
+
|
3
|
+
module ZendeskAPI
|
4
|
+
module Middleware
|
5
|
+
module Request
|
6
|
+
# Faraday middleware to handle HTTP Status 429 (rate limiting) / 503 (maintenance)
|
7
|
+
class Retry < Faraday::Middleware
|
8
|
+
DEFAULT_RETRY_AFTER = 10
|
9
|
+
ERROR_CODES = [429, 503]
|
10
|
+
|
11
|
+
def initialize(app, options={})
|
12
|
+
super(app)
|
13
|
+
@logger = options[:logger]
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
response = @app.call(env)
|
18
|
+
|
19
|
+
if ERROR_CODES.include?(response.env[:status])
|
20
|
+
seconds_left = (response.env[:response_headers][:retry_after] || DEFAULT_RETRY_AFTER).to_i
|
21
|
+
@logger.warn "You have been rate limited. Retrying in #{seconds_left} seconds..." if @logger
|
22
|
+
|
23
|
+
seconds_left.times do |i|
|
24
|
+
sleep 1
|
25
|
+
time_left = seconds_left - i
|
26
|
+
@logger.warn "#{time_left}..." if time_left > 0 && time_left % 5 == 0 && @logger
|
27
|
+
end
|
28
|
+
|
29
|
+
@logger.warn "" if @logger
|
30
|
+
|
31
|
+
@app.call(env)
|
32
|
+
else
|
33
|
+
response
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "faraday/middleware"
|
2
|
+
require "mime/types"
|
3
|
+
|
4
|
+
module ZendeskAPI
|
5
|
+
module Middleware
|
6
|
+
module Request
|
7
|
+
class Upload < Faraday::Middleware
|
8
|
+
def call(env)
|
9
|
+
if env[:body] && env[:body][:file]
|
10
|
+
file = env[:body].delete(:file)
|
11
|
+
case file
|
12
|
+
when File
|
13
|
+
path = file.path
|
14
|
+
when String
|
15
|
+
path = file
|
16
|
+
else
|
17
|
+
warn "WARNING: Passed invalid filename #{file} of type #{file.class} to upload"
|
18
|
+
end
|
19
|
+
|
20
|
+
if path
|
21
|
+
env[:body][:filename] ||= File.basename(path)
|
22
|
+
mime_type = MIME::Types.type_for(path).first || "application/octet-stream"
|
23
|
+
env[:body][:uploaded_data] = Faraday::UploadIO.new(path, mime_type)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
@app.call(env)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "faraday/response"
|
2
|
+
|
3
|
+
module ZendeskAPI
|
4
|
+
module Middleware
|
5
|
+
module Response
|
6
|
+
class Callback < Faraday::Response::Middleware
|
7
|
+
def initialize(app, client)
|
8
|
+
super(app)
|
9
|
+
@client = client
|
10
|
+
end
|
11
|
+
|
12
|
+
def on_complete(env)
|
13
|
+
super(env)
|
14
|
+
@client.callbacks.each {|c| c.call(env)}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'faraday_middleware/response_middleware'
|
2
|
+
|
3
|
+
module ZendeskAPI
|
4
|
+
module Middleware
|
5
|
+
module Response
|
6
|
+
# Faraday middleware to handle content-encoding = inflate
|
7
|
+
class Deflate < FaradayMiddleware::ResponseMiddleware
|
8
|
+
define_parser do |body|
|
9
|
+
Zlib::Inflate.inflate(body)
|
10
|
+
end
|
11
|
+
|
12
|
+
def parse_response?(env)
|
13
|
+
super && env[:response_headers]['content-encoding'] == "deflate"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'faraday_middleware/response_middleware'
|
2
|
+
|
3
|
+
module ZendeskAPI
|
4
|
+
module Middleware
|
5
|
+
module Response
|
6
|
+
# Faraday middleware to handle content-encoding = gzip
|
7
|
+
class Gzip < FaradayMiddleware::ResponseMiddleware
|
8
|
+
define_parser do |body|
|
9
|
+
Zlib::GzipReader.new(StringIO.new(body)).read
|
10
|
+
end
|
11
|
+
|
12
|
+
def parse_response?(env)
|
13
|
+
super && env[:response_headers]['content-encoding'] == "gzip"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'time'
|
2
|
+
require "faraday/response"
|
3
|
+
|
4
|
+
module ZendeskAPI
|
5
|
+
module Middleware
|
6
|
+
module Response
|
7
|
+
# Parse ISO dates from response body
|
8
|
+
class ParseIsoDates < Faraday::Response::Middleware
|
9
|
+
def call(env)
|
10
|
+
response = @app.call(env)
|
11
|
+
parse_dates! response.env[:body]
|
12
|
+
response
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def parse_dates!(value)
|
18
|
+
case value
|
19
|
+
when Hash then value.each { |key,element| value[key] = parse_dates!(element) }
|
20
|
+
when Array then value.each_with_index { |element, index| value[index] = parse_dates!(element) }
|
21
|
+
when /\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z\Z/m then Time.parse(value)
|
22
|
+
else
|
23
|
+
value
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module ZendeskAPI
|
2
|
+
module Rescue
|
3
|
+
def self.included(klass)
|
4
|
+
klass.extend(Methods)
|
5
|
+
klass.send(:include, Methods)
|
6
|
+
end
|
7
|
+
|
8
|
+
module Methods
|
9
|
+
def log_error(e, method = false)
|
10
|
+
if logger = (@client ? @client.config.logger : Kernel)
|
11
|
+
logger.warn "#{self} - #{method}" if method
|
12
|
+
logger.warn e.message
|
13
|
+
logger.warn e.backtrace.join("\n")
|
14
|
+
logger.warn "\t#{e.response[:body].inspect}" if e.response
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def rescue_client_error(*args)
|
19
|
+
opts = args.last.is_a?(Hash) ? args.pop : {}
|
20
|
+
|
21
|
+
if args.any?
|
22
|
+
args.each do |method|
|
23
|
+
class_eval("alias :orig_#{method} :#{method}")
|
24
|
+
define_method method do |*args|
|
25
|
+
begin
|
26
|
+
send("orig_#{method}", *args)
|
27
|
+
rescue Faraday::Error::ClientError => e
|
28
|
+
log_error(e, method)
|
29
|
+
opts[:with].respond_to?(:call) ? opts[:with].call : opts[:with]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
elsif block_given?
|
34
|
+
begin
|
35
|
+
yield
|
36
|
+
rescue Faraday::Error::ClientError => e
|
37
|
+
log_error(e)
|
38
|
+
opts[:with].respond_to?(:call) ? opts[:with].call : opts[:with]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'zendesk_api/trackie'
|
2
|
+
require 'zendesk_api/actions'
|
3
|
+
require 'zendesk_api/association'
|
4
|
+
require 'zendesk_api/verbs'
|
5
|
+
|
6
|
+
module ZendeskAPI
|
7
|
+
# Represents a resource that only holds data.
|
8
|
+
class Data
|
9
|
+
include Associations
|
10
|
+
include Rescue
|
11
|
+
|
12
|
+
class << self
|
13
|
+
# The singular resource name taken from the class name (e.g. ZendeskAPI::Ticket -> ticket)
|
14
|
+
def singular_resource_name
|
15
|
+
@singular_resource_name ||= to_s.split("::").last.snakecase
|
16
|
+
end
|
17
|
+
|
18
|
+
# The resource name taken from the class name (e.g. ZendeskAPI::Ticket -> tickets)
|
19
|
+
def resource_name
|
20
|
+
@resource_name ||= singular_resource_name.plural
|
21
|
+
end
|
22
|
+
|
23
|
+
alias :model_key :resource_name
|
24
|
+
|
25
|
+
# Rails tries to load dependencies, which messes up automatic resource our own loading
|
26
|
+
if method_defined?(:const_missing_without_dependencies)
|
27
|
+
alias :const_missing :const_missing_without_dependencies
|
28
|
+
end
|
29
|
+
|
30
|
+
def only_send_unnested_params
|
31
|
+
@unnested_params = true
|
32
|
+
end
|
33
|
+
|
34
|
+
def unnested_params
|
35
|
+
@unnested_params ||= false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# @return [Hash] The resource's attributes
|
40
|
+
attr_reader :attributes
|
41
|
+
# @return [ZendeskAPI::Association] The association
|
42
|
+
attr_accessor :association
|
43
|
+
|
44
|
+
# Create a new resource instance.
|
45
|
+
# @param [Client] client The client to use
|
46
|
+
# @param [Hash] attributes The optional attributes that describe the resource
|
47
|
+
def initialize(client, attributes = {})
|
48
|
+
raise "Expected a Hash for attributes, got #{attributes.inspect}" unless attributes.is_a?(Hash)
|
49
|
+
@association = attributes.delete(:association) || Association.new(:class => self.class)
|
50
|
+
@client = client
|
51
|
+
@attributes = ZendeskAPI::Trackie.new(attributes)
|
52
|
+
ZendeskAPI::Client.check_deprecated_namespace_usage @attributes, self.class.singular_resource_name
|
53
|
+
|
54
|
+
@attributes.clear_changes unless new_record?
|
55
|
+
end
|
56
|
+
|
57
|
+
# Passes the method onto the attributes hash.
|
58
|
+
# If the attributes are nested (e.g. { :tickets => { :id => 1 } }), passes the method onto the nested hash.
|
59
|
+
def method_missing(*args, &block)
|
60
|
+
raise NoMethodError, ":save is not defined" if args.first.to_sym == :save
|
61
|
+
@attributes.send(*args, &block)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Returns the resource id of the object or nil
|
65
|
+
def id
|
66
|
+
key?(:id) ? method_missing(:id) : nil
|
67
|
+
end
|
68
|
+
|
69
|
+
# Has this been object been created server-side? Does this by checking for an id.
|
70
|
+
def new_record?
|
71
|
+
id.nil?
|
72
|
+
end
|
73
|
+
|
74
|
+
# Returns the path to the resource
|
75
|
+
def path(*args)
|
76
|
+
@association.generate_path(self, *args)
|
77
|
+
end
|
78
|
+
|
79
|
+
def to_s
|
80
|
+
"#{self.class.singular_resource_name}: #{attributes.inspect}"
|
81
|
+
end
|
82
|
+
alias :inspect :to_s
|
83
|
+
|
84
|
+
def ==(other)
|
85
|
+
warn "Trying to compare #{other.class} to a Resource" if other && !other.is_a?(Data)
|
86
|
+
other.is_a?(self.class) && ((other.id && other.id == id) || (other.object_id == self.object_id))
|
87
|
+
end
|
88
|
+
alias :eql :==
|
89
|
+
alias :hash :id
|
90
|
+
|
91
|
+
def inspect
|
92
|
+
"#<#{self.class.name} #{@attributes.to_hash.inspect}>"
|
93
|
+
end
|
94
|
+
|
95
|
+
alias :to_param :attributes
|
96
|
+
end
|
97
|
+
|
98
|
+
# Indexable resource
|
99
|
+
class DataResource < Data
|
100
|
+
extend Verbs
|
101
|
+
end
|
102
|
+
|
103
|
+
# Represents a resource that can only GET
|
104
|
+
class ReadResource < DataResource
|
105
|
+
extend Read
|
106
|
+
end
|
107
|
+
|
108
|
+
# Represents a resource that can only POST
|
109
|
+
class CreateResource < DataResource
|
110
|
+
include Create
|
111
|
+
end
|
112
|
+
|
113
|
+
# Represents a resource that can only PUT
|
114
|
+
class UpdateResource < DataResource
|
115
|
+
include Update
|
116
|
+
end
|
117
|
+
|
118
|
+
# Represents a resource that can only DELETE
|
119
|
+
class DeleteResource < DataResource
|
120
|
+
include Destroy
|
121
|
+
end
|
122
|
+
|
123
|
+
# Represents a resource that can CRUD (create, read, update, delete).
|
124
|
+
class Resource < DataResource
|
125
|
+
extend Read
|
126
|
+
include Create
|
127
|
+
|
128
|
+
include Update
|
129
|
+
include Destroy
|
130
|
+
end
|
131
|
+
|
132
|
+
class SingularResource < Resource; end
|
133
|
+
end
|