govdelivery-tms 0.8.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 +15 -0
- data/Gemfile +14 -0
- data/README.md +324 -0
- data/Rakefile +20 -0
- data/govdelivery-tms.gemspec +30 -0
- data/lib/govdelivery-tms.rb +43 -0
- data/lib/govdelivery-tms/base.rb +37 -0
- data/lib/govdelivery-tms/client.rb +97 -0
- data/lib/govdelivery-tms/collection_resource.rb +54 -0
- data/lib/govdelivery-tms/connection.rb +34 -0
- data/lib/govdelivery-tms/errors.rb +58 -0
- data/lib/govdelivery-tms/instance_resource.rb +219 -0
- data/lib/govdelivery-tms/link_header.rb +223 -0
- data/lib/govdelivery-tms/logger.rb +36 -0
- data/lib/govdelivery-tms/mail/delivery_method.rb +63 -0
- data/lib/govdelivery-tms/resource/collections.rb +98 -0
- data/lib/govdelivery-tms/resource/command.rb +25 -0
- data/lib/govdelivery-tms/resource/command_action.rb +17 -0
- data/lib/govdelivery-tms/resource/command_type.rb +20 -0
- data/lib/govdelivery-tms/resource/email_message.rb +81 -0
- data/lib/govdelivery-tms/resource/email_recipient.rb +31 -0
- data/lib/govdelivery-tms/resource/email_recipient_click.rb +8 -0
- data/lib/govdelivery-tms/resource/email_recipient_open.rb +8 -0
- data/lib/govdelivery-tms/resource/email_template.rb +15 -0
- data/lib/govdelivery-tms/resource/from_address.rb +10 -0
- data/lib/govdelivery-tms/resource/inbound_sms_message.rb +8 -0
- data/lib/govdelivery-tms/resource/ipaws_acknowledgement.rb +9 -0
- data/lib/govdelivery-tms/resource/ipaws_alert.rb +38 -0
- data/lib/govdelivery-tms/resource/ipaws_category.rb +7 -0
- data/lib/govdelivery-tms/resource/ipaws_cog_profile.rb +29 -0
- data/lib/govdelivery-tms/resource/ipaws_event_code.rb +7 -0
- data/lib/govdelivery-tms/resource/ipaws_nwem_area.rb +18 -0
- data/lib/govdelivery-tms/resource/ipaws_nwem_authorization.rb +9 -0
- data/lib/govdelivery-tms/resource/ipaws_nwem_auxilary_data.rb +8 -0
- data/lib/govdelivery-tms/resource/ipaws_response_type.rb +7 -0
- data/lib/govdelivery-tms/resource/ipaws_static_resource.rb +8 -0
- data/lib/govdelivery-tms/resource/keyword.rb +30 -0
- data/lib/govdelivery-tms/resource/recipient.rb +10 -0
- data/lib/govdelivery-tms/resource/sms_message.rb +35 -0
- data/lib/govdelivery-tms/resource/webhook.rb +20 -0
- data/lib/govdelivery-tms/util/core_ext.rb +27 -0
- data/lib/govdelivery-tms/util/hal_link_parser.rb +50 -0
- data/lib/govdelivery-tms/version.rb +3 -0
- data/spec/client_spec.rb +41 -0
- data/spec/command_types_spec.rb +29 -0
- data/spec/email_message_spec.rb +102 -0
- data/spec/email_template_spec.rb +149 -0
- data/spec/errors_spec.rb +13 -0
- data/spec/from_address_spec.rb +86 -0
- data/spec/inbound_sms_messages_spec.rb +19 -0
- data/spec/instance_resource_spec.rb +61 -0
- data/spec/ipaws_acknowledgement_spec.rb +16 -0
- data/spec/ipaws_alerts_spec.rb +192 -0
- data/spec/ipaws_cog_profile_spec.rb +75 -0
- data/spec/ipaws_event_codes_spec.rb +35 -0
- data/spec/ipaws_nwem_areas_spec.rb +58 -0
- data/spec/ipaws_nwem_authorization_spec.rb +16 -0
- data/spec/keyword_spec.rb +62 -0
- data/spec/keywords_spec.rb +21 -0
- data/spec/mail/delivery_method_spec.rb +52 -0
- data/spec/sms_message_spec.rb +63 -0
- data/spec/sms_messages_spec.rb +21 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/tms_spec.rb +7 -0
- metadata +172 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
module TMS #:nodoc:
|
2
|
+
module Base
|
3
|
+
def self.included(base)
|
4
|
+
base.send(:include, TMS::Util::HalLinkParser)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
base.send(:include, InstanceMethods)
|
7
|
+
base.send(:include, TMS::CoreExt)
|
8
|
+
base.send(:extend, TMS::CoreExt)
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_accessor :client, :href, :errors, :new_record
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
def to_param
|
15
|
+
tmsify(self)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module InstanceMethods
|
20
|
+
def initialize(client, href)
|
21
|
+
self.client = client
|
22
|
+
self.href = href
|
23
|
+
end
|
24
|
+
|
25
|
+
def new_record?
|
26
|
+
!!self.new_record
|
27
|
+
end
|
28
|
+
|
29
|
+
def href=(href)
|
30
|
+
self.new_record=false
|
31
|
+
@href=href
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'logger'
|
2
|
+
# The client class to connect and talk to the TMS REST API.
|
3
|
+
class TMS::Client
|
4
|
+
include TMS::Util::HalLinkParser
|
5
|
+
include TMS::CoreExt
|
6
|
+
|
7
|
+
attr_accessor :connection, :href, :api_root, :logger
|
8
|
+
|
9
|
+
DEFAULTS = {:api_root => 'https://tms.govdelivery.com', :logger => nil}.freeze
|
10
|
+
|
11
|
+
# Create a new client and issue a request for the available resources for a given account.
|
12
|
+
#
|
13
|
+
# @param [String] auth_token The auth_token of your account
|
14
|
+
# @param [Hash] options
|
15
|
+
# @option options [String] :api_root The root URL of the TMS api. Defaults to localhost:3000
|
16
|
+
# @option options [Logger] :logger An instance of a Logger class (http transport information will be logged here) - defaults to nil
|
17
|
+
#
|
18
|
+
# @example
|
19
|
+
# client = TMS::Client.new("auth_token", {
|
20
|
+
# :api_root => "https://tms.govdelivery.com",
|
21
|
+
# :logger => Logger.new(STDOUT)})
|
22
|
+
# client = TMS::Client.new("auth_token", {
|
23
|
+
# api_root: "https://tms.govdelivery.com",
|
24
|
+
# logger: false})
|
25
|
+
def initialize(auth_token, options = DEFAULTS)
|
26
|
+
@api_root = options[:api_root]
|
27
|
+
@logger = options.fetch(:logger, setup_logging(options[:debug]))
|
28
|
+
connect!(auth_token, options.except(:api_root, :logger, :debug))
|
29
|
+
discover!
|
30
|
+
end
|
31
|
+
|
32
|
+
def connect!(auth_token, options={})
|
33
|
+
self.connection = TMS::Connection.new({:auth_token => auth_token, :api_root => api_root, :logger => logger}.merge!(options))
|
34
|
+
end
|
35
|
+
|
36
|
+
def discover!
|
37
|
+
services = get('/').body
|
38
|
+
parse_links(services['_links'])
|
39
|
+
end
|
40
|
+
|
41
|
+
def get(href)
|
42
|
+
response = raw_connection.get(href)
|
43
|
+
case response.status
|
44
|
+
when 500..599
|
45
|
+
raise TMS::Request::Error.new(response.status)
|
46
|
+
when 401..499
|
47
|
+
raise TMS::Request::Error.new(response.status)
|
48
|
+
when 202
|
49
|
+
raise TMS::Request::InProgress.new(response.body['message'])
|
50
|
+
else
|
51
|
+
return response
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def post(obj)
|
56
|
+
raw_connection.post do |req|
|
57
|
+
req.url @api_root + obj.href
|
58
|
+
req.headers['Content-Type'] = 'application/json'
|
59
|
+
req.body = obj.to_json
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def put(obj)
|
64
|
+
raw_connection.put do |req|
|
65
|
+
req.url @api_root + obj.href
|
66
|
+
req.headers['Content-Type'] = 'application/json'
|
67
|
+
req.body = obj.to_json
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def delete(href)
|
72
|
+
response = raw_connection.delete(href)
|
73
|
+
case response.status
|
74
|
+
when 200...299
|
75
|
+
return response
|
76
|
+
else
|
77
|
+
raise TMS::Request::Error.new(response.status)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def raw_connection
|
82
|
+
connection.connection
|
83
|
+
end
|
84
|
+
|
85
|
+
def client
|
86
|
+
self
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def setup_logging(debug)
|
92
|
+
logger = Logger.new(STDOUT)
|
93
|
+
logger.level = debug ? Logger::DEBUG : Logger::INFO
|
94
|
+
logger
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module TMS::CollectionResource
|
2
|
+
def self.included(base)
|
3
|
+
base.send(:include, InstanceMethods)
|
4
|
+
end
|
5
|
+
|
6
|
+
module InstanceMethods
|
7
|
+
include TMS::Base
|
8
|
+
attr_accessor :collection
|
9
|
+
|
10
|
+
def initialize(client, href, items=nil)
|
11
|
+
super(client, href)
|
12
|
+
if items
|
13
|
+
initialize_collection_from_items(items)
|
14
|
+
else
|
15
|
+
self.collection = []
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
def get
|
21
|
+
response = client.get(href)
|
22
|
+
initialize_collection_from_items(response.body)
|
23
|
+
#setup page links from header
|
24
|
+
links = LinkHeader.parse(response.headers['link']).to_a.collect do |a|
|
25
|
+
{a[1][0].last => a[0]}
|
26
|
+
end
|
27
|
+
parse_links(links)
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def build(attributes=nil)
|
32
|
+
thing = instance_class(self.class).new(client, self.href, attributes || {})
|
33
|
+
thing.new_record = true
|
34
|
+
self.collection << thing
|
35
|
+
thing
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_json
|
39
|
+
@collection.map(&:to_json)
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_s
|
43
|
+
"<#{self.class.inspect} href=#{self.href} collection=#{self.collection.inspect}>"
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def initialize_collection_from_items(items)
|
49
|
+
self.collection = items.map do |attrs|
|
50
|
+
instance_class(self.class).new(client, nil, attrs)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class TMS::Connection
|
2
|
+
attr_accessor :auth_token, :api_root, :connection, :logger
|
3
|
+
|
4
|
+
def get(href)
|
5
|
+
resp = connection.get("#{href}.json")
|
6
|
+
if resp.status != 200
|
7
|
+
raise RecordNotFound.new("Could not find resource at #{href} (status #{resp.status})")
|
8
|
+
else
|
9
|
+
resp.body
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(opts={})
|
14
|
+
self.auth_token = opts[:auth_token]
|
15
|
+
self.api_root = opts[:api_root]
|
16
|
+
self.logger = opts[:logger]
|
17
|
+
setup_connection
|
18
|
+
end
|
19
|
+
|
20
|
+
def setup_connection
|
21
|
+
self.connection = Faraday.new(:url => self.api_root) do |faraday|
|
22
|
+
faraday.use TMS::Logger, self.logger if self.logger
|
23
|
+
faraday.request :json
|
24
|
+
faraday.headers['X-AUTH-TOKEN'] = auth_token
|
25
|
+
faraday.headers[:user_agent] = "GovDelivery Ruby TMS::Client #{TMS::VERSION}"
|
26
|
+
faraday.response :json, :content_type => /\bjson$/
|
27
|
+
faraday.adapter :net_http
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def dump_headers(headers)
|
32
|
+
headers.map { |k, v| "#{k}: #{v.inspect}" }.join("\n")
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module TMS
|
2
|
+
module Request
|
3
|
+
# The generic TMS error class
|
4
|
+
class Error < StandardError
|
5
|
+
attr_reader :code
|
6
|
+
|
7
|
+
def initialize(code)
|
8
|
+
super("HTTP Error: #{code}")
|
9
|
+
@code=code
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Raised when a recipient list is still being constructed and a request is made to view the
|
14
|
+
# recipient list for a message.
|
15
|
+
class InProgress < StandardError;end
|
16
|
+
end
|
17
|
+
|
18
|
+
module Errors
|
19
|
+
class ServerError < StandardError
|
20
|
+
def initialize(response)
|
21
|
+
super("TMS client encountered a server error: #{response.status} \n#{response.body}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
class NoRelation < StandardError
|
25
|
+
def initialize(rel=nil, obj=nil)
|
26
|
+
message = "no link relation "
|
27
|
+
message << "'#{rel}' " if rel
|
28
|
+
message << 'is available'
|
29
|
+
message << " for #{obj}" if obj
|
30
|
+
super(message)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
class InvalidVerb < StandardError
|
34
|
+
attr_reader :record
|
35
|
+
|
36
|
+
def initialize(record_or_string)
|
37
|
+
if record_or_string.respond_to?(:href)
|
38
|
+
@record = record_or_string
|
39
|
+
super("Couldn't POST #{record.class} to #{record.href}: #{record.errors.map { |k, v| "#{k} #{v.join(' and ')}" }.join(', ')}")
|
40
|
+
else
|
41
|
+
super(record_or_string)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
class InvalidPost < InvalidVerb
|
47
|
+
end
|
48
|
+
class InvalidPut < InvalidVerb
|
49
|
+
end
|
50
|
+
class InvalidDelete < InvalidVerb
|
51
|
+
end
|
52
|
+
class InvalidGet < StandardError
|
53
|
+
def initialize(message=nil)
|
54
|
+
super(message || "Can't GET a resource after an invalid POST; either create a new object or fix errors")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,219 @@
|
|
1
|
+
module TMS::InstanceResource
|
2
|
+
def self.included(base)
|
3
|
+
base.send(:include, TMS::Base)
|
4
|
+
base.extend(ClassMethods)
|
5
|
+
base.send(:include, InstanceMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_accessor :response
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
##
|
12
|
+
# Writeable attributes are sent on POST/PUT.
|
13
|
+
#
|
14
|
+
def writeable_attributes(*attrs)
|
15
|
+
@writeable_attributes ||= []
|
16
|
+
if attrs.any?
|
17
|
+
@writeable_attributes.map!(&:to_sym).concat(attrs).uniq! if attrs.any?
|
18
|
+
setup_attributes(@writeable_attributes, false)
|
19
|
+
end
|
20
|
+
@writeable_attributes
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# Linkable attributes are sent on POST/PUT.
|
25
|
+
#
|
26
|
+
def linkable_attributes(*attrs)
|
27
|
+
@linkable_attributes ||= []
|
28
|
+
if attrs.any?
|
29
|
+
@linkable_attributes.map!(&:to_sym).concat(attrs).uniq! if attrs.any?
|
30
|
+
end
|
31
|
+
@linkable_attributes
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Readonly attributes don't get POSTed.
|
36
|
+
# (timestamps are included by default)
|
37
|
+
#
|
38
|
+
def readonly_attributes(*attrs)
|
39
|
+
@readonly_attributes ||= [:created_at, :updated_at, :completed_at]
|
40
|
+
if attrs.any?
|
41
|
+
@readonly_attributes.map!(&:to_sym).concat(attrs).uniq!
|
42
|
+
setup_attributes(@readonly_attributes, true)
|
43
|
+
end
|
44
|
+
@readonly_attributes
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# For collections that are represented as attributes (i.e. inline, no href)
|
49
|
+
#
|
50
|
+
# @example
|
51
|
+
# collection_attributes :recipients
|
52
|
+
#
|
53
|
+
def collection_attributes(*attrs)
|
54
|
+
@collection_attributes ||= []
|
55
|
+
if attrs.any?
|
56
|
+
@collection_attributes.map!(&:to_sym).concat(attrs).uniq!
|
57
|
+
@collection_attributes.each { |a| setup_collection(a) }
|
58
|
+
end
|
59
|
+
@collection_attributes
|
60
|
+
end
|
61
|
+
|
62
|
+
def custom_class_names
|
63
|
+
@custom_class_names ||= {}
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# For collections that are represented as attributes (i.e. inline, no href)
|
68
|
+
# and that have a class name other than the one we would infer.
|
69
|
+
#
|
70
|
+
# @example
|
71
|
+
# collection_attributes :recipients, 'EmailRecipient'
|
72
|
+
#
|
73
|
+
def collection_attribute(attr, tms_class)
|
74
|
+
@collection_attributes ||= []
|
75
|
+
@collection_attributes.push(attr).uniq!
|
76
|
+
setup_collection(attr, TMS.const_get(tms_class))
|
77
|
+
end
|
78
|
+
|
79
|
+
##
|
80
|
+
# Read-only collection attributes don't get POSTed.
|
81
|
+
# Use this for collections that are represented as attributes, but cannot be modified.
|
82
|
+
#
|
83
|
+
# @example
|
84
|
+
# readonly_collection_attribute :opens
|
85
|
+
#
|
86
|
+
def readonly_collection_attribute(attr, tms_class)
|
87
|
+
@readonly_collection_attributes ||= []
|
88
|
+
@readonly_collection_attributes.push(attr).uniq!
|
89
|
+
setup_collection(attr, TMS.const_get(tms_class))
|
90
|
+
end
|
91
|
+
|
92
|
+
def setup_attributes(attrs, readonly=false)
|
93
|
+
attrs.map(&:to_sym).each do |property|
|
94
|
+
self.send :define_method, :"#{property}=", &lambda { |v| @attributes[property] = v } unless readonly
|
95
|
+
self.send :define_method, property.to_sym, &lambda { @attributes[property] }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def setup_collection(property, klass=nil)
|
100
|
+
if klass
|
101
|
+
custom_class_names[property] = klass
|
102
|
+
else
|
103
|
+
klass ||= TMS.const_get(property.to_s.capitalize)
|
104
|
+
end
|
105
|
+
|
106
|
+
self.send :define_method, property.to_sym, &lambda { @attributes[property] ||= klass.new(self.client, nil, nil) }
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
module InstanceMethods
|
111
|
+
attr_reader :links
|
112
|
+
|
113
|
+
def initialize(client, href=nil, attrs=nil)
|
114
|
+
super(client, href)
|
115
|
+
@attributes = {}
|
116
|
+
@links = {}
|
117
|
+
set_attributes_from_hash(attrs) if attrs
|
118
|
+
end
|
119
|
+
|
120
|
+
def attributes
|
121
|
+
@attributes
|
122
|
+
end
|
123
|
+
|
124
|
+
def get
|
125
|
+
raise TMS::Errors::InvalidGet if self.new_record?
|
126
|
+
process_response(client.get(self.href), :get) && self
|
127
|
+
end
|
128
|
+
alias_method :get!, :get
|
129
|
+
|
130
|
+
def post
|
131
|
+
self.errors = nil
|
132
|
+
process_response(client.post(self), :post)
|
133
|
+
end
|
134
|
+
|
135
|
+
def post!
|
136
|
+
self.post or raise TMS::Errors::InvalidPost.new(self)
|
137
|
+
end
|
138
|
+
|
139
|
+
def put
|
140
|
+
process_response(client.put(self), :put)
|
141
|
+
end
|
142
|
+
|
143
|
+
def put!
|
144
|
+
process_response(client.put(self), :put) or raise TMS::Errors::InvalidPut.new(self)
|
145
|
+
end
|
146
|
+
|
147
|
+
def delete
|
148
|
+
process_response(client.delete(self.href), :delete)
|
149
|
+
end
|
150
|
+
|
151
|
+
def delete!
|
152
|
+
process_response(client.delete(self.href), :delete) or raise TMS::Errors::InvalidDelete.new(self)
|
153
|
+
end
|
154
|
+
|
155
|
+
def to_s
|
156
|
+
"<#{self.class.inspect}#{' href=' + self.href if self.href} attributes=#{@attributes.inspect}>"
|
157
|
+
end
|
158
|
+
|
159
|
+
def to_json
|
160
|
+
json_hash = {}
|
161
|
+
self.class.writeable_attributes.each do |attr|
|
162
|
+
json_hash[attr] = self.send(attr)
|
163
|
+
end
|
164
|
+
self.class.collection_attributes.each do |coll|
|
165
|
+
json_hash[coll] = self.send(coll).to_json
|
166
|
+
end
|
167
|
+
self.class.linkable_attributes.each do |attr|
|
168
|
+
json_hash[:_links] ||= {}
|
169
|
+
json_hash[:_links][attr] = @links[attr]
|
170
|
+
end
|
171
|
+
json_hash
|
172
|
+
end
|
173
|
+
|
174
|
+
protected
|
175
|
+
|
176
|
+
def relation_class(rel)
|
177
|
+
self.class.custom_class_names[rel.to_sym] || super
|
178
|
+
end
|
179
|
+
|
180
|
+
def process_response(response, method)
|
181
|
+
self.response = response
|
182
|
+
error_class = TMS::Errors.const_get("Invalid#{method.to_s.capitalize}")
|
183
|
+
case response.status
|
184
|
+
when 204
|
185
|
+
return true
|
186
|
+
when 200..299
|
187
|
+
set_attributes_from_hash(response.body) if response.body.is_a?(Hash)
|
188
|
+
@links = {}
|
189
|
+
self.new_record=false
|
190
|
+
return true
|
191
|
+
when 401
|
192
|
+
raise error_class.new("401 Not Authorized")
|
193
|
+
when 404
|
194
|
+
raise(error_class.new("Can't POST to #{self.href}"))
|
195
|
+
when 500..599
|
196
|
+
raise(TMS::Errors::ServerError.new(response))
|
197
|
+
else # 422?
|
198
|
+
if response.body['errors']
|
199
|
+
self.errors = response.body['errors']
|
200
|
+
end
|
201
|
+
end
|
202
|
+
return false
|
203
|
+
end
|
204
|
+
|
205
|
+
def set_attributes_from_hash(hash)
|
206
|
+
hash.reject { |k, _| k=~/^_/ }.each do |property, value|
|
207
|
+
if self.class.collection_attributes.include?(property.to_sym)
|
208
|
+
klass = self.class.custom_class_names[property] || TMS.const_get(property.to_s.capitalize)
|
209
|
+
@attributes[property.to_sym] = klass.new(client, nil, value)
|
210
|
+
else
|
211
|
+
@attributes[property.to_sym] = value
|
212
|
+
end
|
213
|
+
end
|
214
|
+
self.errors = hash['errors']
|
215
|
+
parse_links(hash['_links'])
|
216
|
+
end
|
217
|
+
|
218
|
+
end
|
219
|
+
end
|