alpha_card 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +4 -4
  3. data/CHANGELOG.md +21 -3
  4. data/Gemfile +0 -2
  5. data/Gemfile.lock +6 -24
  6. data/README.md +115 -85
  7. data/ROADMAP.md +13 -9
  8. data/alpha_card.gemspec +3 -4
  9. data/lib/alpha_card.rb +44 -72
  10. data/lib/alpha_card/account.rb +51 -0
  11. data/lib/alpha_card/attribute.rb +337 -0
  12. data/lib/alpha_card/data/credit_card_codes.yml +54 -54
  13. data/lib/alpha_card/errors/invalid_attribute_format.rb +14 -0
  14. data/lib/alpha_card/errors/invalid_attribute_type.rb +14 -0
  15. data/lib/alpha_card/errors/invalid_attribute_value.rb +14 -0
  16. data/lib/alpha_card/errors/{invalid_object_error.rb → validation_error.rb} +1 -1
  17. data/lib/alpha_card/{alpha_card_object.rb → resource.rb} +14 -28
  18. data/lib/alpha_card/resources/billing.rb +29 -0
  19. data/lib/alpha_card/{objects → resources}/order.rb +8 -8
  20. data/lib/alpha_card/{objects → resources}/shipping.rb +15 -13
  21. data/lib/alpha_card/{alpha_card_response.rb → response.rb} +21 -6
  22. data/lib/alpha_card/transaction.rb +30 -0
  23. data/lib/alpha_card/transactions/auth.rb +18 -0
  24. data/lib/alpha_card/transactions/capture.rb +32 -0
  25. data/lib/alpha_card/transactions/credit.rb +18 -0
  26. data/lib/alpha_card/{objects → transactions}/refund.rb +9 -2
  27. data/lib/alpha_card/transactions/sale.rb +91 -0
  28. data/lib/alpha_card/transactions/update.rb +61 -0
  29. data/lib/alpha_card/transactions/validate.rb +21 -0
  30. data/lib/alpha_card/transactions/void.rb +26 -0
  31. data/lib/alpha_card/version.rb +1 -1
  32. data/spec/alpha_card/attribute_spec.rb +126 -0
  33. data/spec/alpha_card/response_spec.rb +8 -4
  34. data/spec/alpha_card/transactions/auth_spec.rb +43 -0
  35. data/spec/alpha_card/{objects → transactions}/capture_spec.rb +11 -12
  36. data/spec/alpha_card/transactions/credit_spec.rb +102 -0
  37. data/spec/alpha_card/{objects → transactions}/refund_spec.rb +4 -4
  38. data/spec/alpha_card/{objects → transactions}/sale_spec.rb +42 -41
  39. data/spec/alpha_card/{objects → transactions}/update_spec.rb +4 -4
  40. data/spec/alpha_card/transactions/validate_spec.rb +100 -0
  41. data/spec/alpha_card/{objects → transactions}/void_spec.rb +11 -11
  42. data/spec/spec_helper.rb +4 -0
  43. metadata +36 -47
  44. data/lib/alpha_card/errors/alpha_card_error.rb +0 -29
  45. data/lib/alpha_card/objects/account.rb +0 -48
  46. data/lib/alpha_card/objects/billing.rb +0 -31
  47. data/lib/alpha_card/objects/capture.rb +0 -51
  48. data/lib/alpha_card/objects/sale.rb +0 -82
  49. data/lib/alpha_card/objects/update.rb +0 -54
  50. data/lib/alpha_card/objects/void.rb +0 -45
  51. data/spec/alpha_card/objects/account_spec.rb +0 -20
  52. data/spec/alpha_card/objects/deprecated_methods_spec.rb +0 -32
data/ROADMAP.md CHANGED
@@ -1,12 +1,16 @@
1
1
  # TODO
2
2
 
3
- * Own `Attribute` class with validations and etc:
4
- - default value
5
- - writable: `true` / `false`
6
- - presence: `true` / `false`
7
- - values: `['1', '2']`
8
- - coerce ?
9
- * Configuration with `Account` setup
10
- - all objects can use global or local account
3
+ ## 0.4.0
4
+
5
+ * ~~Own `Attribute` class with validations and etc~~:
6
+ - ~~default value~~
7
+ - ~~writable: true` / `false`~~
8
+ - ~~required: `true / `false~~
9
+ - ~~format: regex~~
10
+ - ~~values: ['1', '2']`~~
11
+ - ~~type(s)~~
12
+ * ~~Configuration with `Account` setup~~
13
+ - ~~all objects can use global or local account~~
11
14
  * Add new transactions:
12
- - Authorization/Credit/Validate/Offline
15
+ - ~~Authorization~~/~~Credit~~/~~Validate~~/Offline
16
+ * ~~Change all resources return value to AlphaCard::Response~~
@@ -5,7 +5,7 @@ require 'alpha_card/version'
5
5
  Gem::Specification.new do |gem|
6
6
  gem.name = 'alpha_card'
7
7
  gem.version = AlphaCard.gem_version
8
- gem.date = '2016-09-22'
8
+ gem.date = '2016-10-07'
9
9
  gem.summary = 'Alpha Card Services API for Ruby'
10
10
  gem.description = 'Gem for creating sales with Alpha Card Services'
11
11
  gem.authors = ['Nikita Bulaj']
@@ -14,10 +14,9 @@ Gem::Specification.new do |gem|
14
14
  gem.files = `git ls-files`.split($RS)
15
15
  gem.homepage = 'http://github.com/nbulaj/alpha_card'
16
16
  gem.license = 'MIT'
17
- gem.required_ruby_version = '>= 2.0.0'
17
+ gem.required_ruby_version = '>= 2.2.2'
18
18
 
19
- gem.add_runtime_dependency 'virtus', '~> 1.0', '>= 1.0.5'
20
- gem.add_runtime_dependency 'rack', '~> 1.2', '>= 1.2'
19
+ gem.add_runtime_dependency 'rack', '~> 2.0', '>= 2.0'
21
20
 
22
21
  gem.add_development_dependency 'rspec', '~> 3.5'
23
22
  end
@@ -1,6 +1,5 @@
1
1
  # encoding:utf-8
2
2
  require 'yaml'
3
- require 'virtus'
4
3
  require 'net/http'
5
4
  require 'uri'
6
5
  require 'rack/utils'
@@ -8,24 +7,33 @@ require 'rack/utils'
8
7
  # Version
9
8
  require 'alpha_card/version'
10
9
 
11
- require 'alpha_card/alpha_card_object'
12
- require 'alpha_card/alpha_card_response'
10
+ require 'alpha_card/account'
11
+ require 'alpha_card/attribute'
12
+ require 'alpha_card/resource'
13
+ require 'alpha_card/response'
14
+ require 'alpha_card/transaction'
13
15
 
14
16
  # Errors
15
- require 'alpha_card/errors/alpha_card_error'
16
17
  require 'alpha_card/errors/api_connection_error'
17
- require 'alpha_card/errors/invalid_object_error'
18
+ require 'alpha_card/errors/invalid_attribute_value'
19
+ require 'alpha_card/errors/invalid_attribute_format'
20
+ require 'alpha_card/errors/invalid_attribute_type'
21
+ require 'alpha_card/errors/validation_error'
18
22
 
19
23
  # Alpha Card Resources
20
- require 'alpha_card/objects/account'
21
- require 'alpha_card/objects/billing'
22
- require 'alpha_card/objects/capture'
23
- require 'alpha_card/objects/shipping'
24
- require 'alpha_card/objects/order'
25
- require 'alpha_card/objects/void'
26
- require 'alpha_card/objects/refund'
27
- require 'alpha_card/objects/sale'
28
- require 'alpha_card/objects/update'
24
+ require 'alpha_card/resources/billing'
25
+ require 'alpha_card/resources/shipping'
26
+ require 'alpha_card/resources/order'
27
+
28
+ # Alpha Card Transactions
29
+ require 'alpha_card/transactions/capture'
30
+ require 'alpha_card/transactions/void'
31
+ require 'alpha_card/transactions/refund'
32
+ require 'alpha_card/transactions/sale'
33
+ require 'alpha_card/transactions/update'
34
+ require 'alpha_card/transactions/auth'
35
+ require 'alpha_card/transactions/credit'
36
+ require 'alpha_card/transactions/validate'
29
37
 
30
38
  ##
31
39
  # AlphaCard is a library for processing payments with Alpha Card Services, Inc.
@@ -49,88 +57,55 @@ module AlphaCard
49
57
  # specified account. Request must contains params - Alpha Card
50
58
  # transaction variables.
51
59
  #
52
- # @param [Hash] params
53
- # Alpha Card transaction variables.
54
- # @param [AlphaCard::Account] account
55
- # An <code>AlphaCard::Account</code> credentials object.
60
+ # @param params [Hash]
61
+ # hash with Alpha Card transaction variables and it's values
56
62
  #
57
- # @return [AlphaCard::AlphaCardResponse]
63
+ # @param credentials [Hash]
64
+ # Alpha Card merchant account credentials
65
+ #
66
+ # @return [AlphaCard::Response]
58
67
  # Response from Alpha Card Gateway.
59
68
  #
60
- # @raise [AlphaCard::AlphaCardError]
61
- # AlphaCardError Exception if request failed.
69
+ # @raise [APIConnectionError] HTTP request error
62
70
  #
63
71
  # @example
64
- # account = AlphaCard::Account.new('demo', 'password')
65
72
  # response = AlphaCard.request(
66
- # account,
67
73
  # {
68
74
  # cexp: '0720',
69
75
  # ccnumber: '4111111111111111',
70
76
  # amount: '10.00'
77
+ # },
78
+ # {
79
+ # username: 'demo',
80
+ # password: 'password'
71
81
  # }
72
82
  # )
73
83
  #
74
- # #=> #<AlphaCard::AlphaCardResponse:0x1a0fda8 @data={"response"=>"1",
84
+ # #=> #<AlphaCard::Response:0x1a0fda8 @data={"response"=>"1",
75
85
  # "responsetext"=>"SUCCESS", "authcode"=>"123", "transactionid"=>"123",
76
86
  # "avsresponse"=>"", "cvvresponse"=>"N", "orderid"=>"", "type"=>"",
77
87
  # "response_code"=>"100"}>
78
88
  #
79
- # account = AlphaCard::Account.new('demo', 'password')
80
- # response = AlphaCard.request(
81
- # account,
82
- # {
83
- # cexp: '0720',
84
- # ccnumber: '123',
85
- # amount: '10.00'
86
- # }
87
- # )
88
- #
89
- # #=> AlphaCard::AlphaCardError: AlphaCard::AlphaCardError
90
- def request(account, params = {})
91
- raise AlphaCardError, 'You must set credentials to create the sale!' unless account.filled?
89
+ def request(params = {}, credentials = Account.credentials)
90
+ raise ArgumentError, 'You must pass a Hash with Account credentials!' unless Account.valid_credentials?(credentials)
92
91
 
93
92
  begin
94
- response = http_post_request(@api_base, params.merge(account.attributes))
93
+ response = http_post_request(@api_base, params.merge(credentials))
95
94
  rescue => e
96
95
  handle_connection_errors(e)
97
96
  end
98
97
 
99
- alpha_card_response = AlphaCardResponse.new(response.body)
100
- handle_alpha_card_errors(alpha_card_response)
101
-
102
- alpha_card_response
103
- end
104
-
105
- ##
106
- # Raises an exception if Alpha Card Gateway return an error or
107
- # decline code for the request. Message is taken from the Global
108
- # Payment Systems Credit Card Authorization Codes (codes.yml).
109
- # If code wasn't found in <code>CREDIT_CARD_CODES</code>, then
110
- # message = Alpha Card response text.
111
- #
112
- # @param [AlphaCard::AlphaCardResponse] response
113
- # Alpha Card Response object.
114
- #
115
- # @raise [AlphaCard::AlphaCardError]
116
- # AlphaCardError Exception if request failed.
117
- #
118
- # @return [String]
119
- # Alpha Card Services response text.
120
- def handle_alpha_card_errors(response)
121
- code = response.text
122
- raise AlphaCardError.new(CREDIT_CARD_CODES[code] || code, response) unless response.success?
98
+ Response.new(response.body)
123
99
  end
124
100
 
125
101
  ##
126
102
  # Raises an exception if a network error occurs. It
127
103
  # could be request timeout, socket error or anything else.
128
104
  #
129
- # @param [StandardError]
130
- # Exception object.
105
+ # @param error [Exception] exception object
131
106
  #
132
- # @raise [AlphaCard::AlphaCardError]
133
- # AlphaCardError Exception.
107
+ # @raise [APIConnectionError]
108
+ # Failed request exception.
134
109
  def handle_connection_errors(error)
135
110
  case error
136
111
  when Timeout::Error, Errno::EINVAL, Errno::ECONNRESET
@@ -150,13 +125,10 @@ module AlphaCard
150
125
  end
151
126
 
152
127
  ##
153
- # Send secure HTTP(S) request with params
154
- # to requested URL.
128
+ # Send secure HTTP(S) request with params to requested URL.
155
129
  #
156
- # @param [String] url
157
- # URL
158
- # @param [Hash] params
159
- # Hash of params for the request
130
+ # @param url [String] URL
131
+ # @param params [Hash] hash of params for the request
160
132
  #
161
133
  # @return [HTTPResponse]
162
134
  # Response of the request as HTTPResponse object
@@ -0,0 +1,51 @@
1
+ module AlphaCard
2
+ # AlphaCard Account class for global credentials settings
3
+ class Account
4
+ class << self
5
+ # Global Alpha Card Merchant account credentials
6
+ #
7
+ # @return [String] username
8
+ # @return [String] password
9
+ #
10
+ # @example
11
+ # AlphaCard::Account.username = 'demo'
12
+ # AlphaCard::Account.password = 'password'
13
+ #
14
+ attr_accessor :username, :password
15
+
16
+ ##
17
+ # Setups demo Alpha Card credentials
18
+ def use_demo_credentials!
19
+ self.username = 'demo'
20
+ self.password = 'password'
21
+ end
22
+
23
+ ##
24
+ # Checks credentials not to be nil or empty string
25
+ #
26
+ # @param credentials [Hash] hash with :username and :password keys
27
+ #
28
+ # @return [Bool] true if credentials present, false in other cases
29
+ #
30
+ def valid_credentials?(credentials)
31
+ !credentials[:username].to_s.empty? && !credentials[:password].to_s.empty?
32
+ end
33
+
34
+ ##
35
+ # Returns hash with Alpha Card credentials
36
+ #
37
+ # @return [Hash] credentials
38
+ #
39
+ # @example
40
+ # AlphaCard::Account.username = 'john.doe'
41
+ # AlphaCard::Account.password = '123qwe!s'
42
+ #
43
+ # AlphaCard::Account.credentials
44
+ # #=> { username: "john.doe", password: "123qwe!s" }
45
+ #
46
+ def credentials
47
+ { username: username, password: password }
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,337 @@
1
+ module AlphaCard
2
+ # Attribute DSL for Alpha Card transaction variables
3
+ module Attribute
4
+ # Extends base class with Attributes DSL.
5
+ #
6
+ # @param base [Class] baseclass
7
+ #
8
+ # @example
9
+ # class User
10
+ # include AlphaCard::Attribute
11
+ # end
12
+ #
13
+ def self.included(base)
14
+ base.extend(ClassMethods)
15
+ base.send(:include, InstanceMethods)
16
+ end
17
+
18
+ # Attributes class methods
19
+ # * attribute
20
+ # * remove_attribute
21
+ # * attributes_set
22
+ #
23
+ module ClassMethods
24
+ # Defines Attributes Set for the class.
25
+ # Attributes set contains all the attributes names as key
26
+ # and it's options as the value.
27
+ #
28
+ # @return [Hash] attributes set with options
29
+ def attributes_set
30
+ @attributes_set ||= {}
31
+ end
32
+
33
+ # Adds attribute to the class.
34
+ # Defines reader and writer methods based on options hash.
35
+ # Adds attribute to the global Attributes Set.
36
+ #
37
+ # @param name [Symbol, String] attribute name
38
+ # @param options [Hash] attribute options
39
+ #
40
+ # @example
41
+ # class User
42
+ # include AlphaCard::Attribute
43
+ #
44
+ # attribute :id, type: Integer, required: true, writable: false
45
+ # attribute :email, required: true, format: /.+@.+/
46
+ # attribute :name, type: String
47
+ # attribute :role, default: 'admin', values: ['admin', 'regular']
48
+ # attribute :status, types: [String, Symbol]
49
+ #
50
+ # attribute :metadata, type: Hash
51
+ # attribute :additional_info
52
+ # end
53
+ #
54
+ def attribute(name, options = {})
55
+ define_reader(name)
56
+ define_writer(name, options) if options[:writable].nil? || options[:writable]
57
+
58
+ attributes_set[name.to_sym] = options
59
+ end
60
+
61
+ # Removes attribute from the class (reader, writer and entry in Attributes Set).
62
+ #
63
+ # @param name [String, Symbol] attribute name
64
+ #
65
+ # @example
66
+ # class User
67
+ # include AlphaCard::Attribute
68
+ #
69
+ # attribute :email
70
+ # attribute :name, default: 'John'
71
+ # end
72
+ #
73
+ # class Person < User
74
+ # attribute :email
75
+ # remove_attribute :name
76
+ # end
77
+ #
78
+ def remove_attribute(name)
79
+ symbolized_name = name.to_sym
80
+
81
+ if attributes_set.keys.include?(symbolized_name)
82
+ undef_method(symbolized_name)
83
+ undef_method("#{name}=") if method_defined?("#{name}=")
84
+
85
+ attributes_set.delete(symbolized_name)
86
+ end
87
+ end
88
+
89
+ private
90
+
91
+ # Writes Attributes Set to the superclass on inheritance.
92
+ #
93
+ # @private
94
+ #
95
+ # @param subclass [Class] inherited class
96
+ #
97
+ def inherited(subclass)
98
+ subclass.instance_variable_set(:@attributes_set, attributes_set.dup)
99
+ end
100
+
101
+ # Creates a reader method for the attribute.
102
+ #
103
+ # @private
104
+ #
105
+ # @param name [String, Symbol] attribute name
106
+ #
107
+ def define_reader(name)
108
+ attr_reader name.to_sym
109
+ end
110
+
111
+ # Creates a writer method for the attribute with validation
112
+ # of setting value if options[:values] was passed.
113
+ #
114
+ # @private
115
+ #
116
+ # @raise [InvalidAttributeValue] when value is not included in the possible values list
117
+ # @raise [InvalidAttributeFormat] when value doesn't match the required format
118
+ # @raise [InvalidAttributeType] when value is not of valid type
119
+ #
120
+ # @param name [Symbol] attribute name
121
+ # @param options [Hash] attribute options
122
+ #
123
+ def define_writer(name, options = {})
124
+ values = extract_values_from(options)
125
+ format = extract_format_from(options)
126
+ types = extract_types_from(options)
127
+
128
+ define_method("#{name}=") do |value|
129
+ raise InvalidAttributeValue.new(value, values) if values && !values.include?(value)
130
+
131
+ raise InvalidAttributeFormat.new(value, format) if !format.nil? && value !~ format
132
+
133
+ raise InvalidAttributeType.new(value, types) if value && types && types.none? { |klass| value.is_a?(klass) }
134
+
135
+ instance_variable_set(:"@#{name}", value)
136
+ end
137
+ end
138
+
139
+ # Extract and validate possible attribute values from options hash.
140
+ #
141
+ # @private
142
+ #
143
+ # @param options [Hash] attribute options
144
+ #
145
+ # @return [Array] possible attribute values
146
+ #
147
+ def extract_values_from(options = {})
148
+ values = options[:values] || return
149
+ raise ArgumentError, ':values option must be an Array or respond to .to_a!' unless values.is_a?(Array) || values.respond_to?(:to_a)
150
+ raise ArgumentError, ":values option can't be empty!" if values.empty?
151
+
152
+ values.to_a
153
+ end
154
+
155
+ # Extract and validate attribute value format from options hash.
156
+ #
157
+ # @private
158
+ #
159
+ # @param options [Hash] attribute options
160
+ #
161
+ # @return [Regexp] attribute value format
162
+ #
163
+ def extract_format_from(options = {})
164
+ format = options[:format] || return
165
+ raise ArgumentError, ':format must be Regexp!' unless format.is_a?(Regexp)
166
+
167
+ format
168
+ end
169
+
170
+ # Extract and validate attribute type class from options hash.
171
+ #
172
+ # @private
173
+ #
174
+ # @param options [Hash] attribute options
175
+ #
176
+ # @return [Object] possible attribute type(s)
177
+ #
178
+ def extract_types_from(options = {})
179
+ types = Array(options[:type] || options[:types])
180
+ return if types.empty?
181
+
182
+ raise ArgumentError, 'attribute type must be a Class!' if types.any? { |type| !type.is_a?(Class) }
183
+
184
+ types
185
+ end
186
+ end
187
+
188
+ # Attributes class methods
189
+ # * initialize
190
+ # * attributes
191
+ # * []
192
+ module InstanceMethods
193
+ # Constructor supports setting attributes when creating a new instance of the class.
194
+ # Sets default values for the attributes if they are present.
195
+ #
196
+ # @param attributes [Hash] attributes hash
197
+ #
198
+ # @example
199
+ # class User
200
+ # include AlphaCard::Attribute
201
+ #
202
+ # attribute :email
203
+ # attribute :name, default: 'John'
204
+ # end
205
+ #
206
+ # User.new(email: 'john.doe@gmail.com')
207
+ # #=> #<User:0x29cca00 @email='john.doe@gmail.com', @name="John">
208
+ #
209
+ def initialize(attributes = {})
210
+ set_attributes_defaults!
211
+
212
+ attributes.each do |name, value|
213
+ set_attribute_safely(name, value)
214
+ end
215
+ end
216
+
217
+ # Returns class instance attributes.
218
+ #
219
+ # @return [Hash] attributes of the instance object
220
+ #
221
+ # @example
222
+ # class User
223
+ # include AlphaCard::Attribute
224
+ #
225
+ # attribute :email
226
+ # attribute :name, default: 'John'
227
+ # end
228
+ #
229
+ # User.new.attributes
230
+ # #=> { email: nil, name: 'John' }
231
+ #
232
+ def attributes
233
+ self.class.attributes_set.each_with_object({}) do |(name, _), attributes|
234
+ attributes[name] = __send__(name)
235
+ end
236
+ end
237
+
238
+ # Returns attribute value by it's name.
239
+ #
240
+ # @param name [String, Symbol] attribute name
241
+ #
242
+ # @return [Object] attribute value
243
+ #
244
+ # @example
245
+ # class User
246
+ # include AlphaCard::Attribute
247
+ #
248
+ # attribute :email
249
+ # end
250
+ #
251
+ # u = User.new(email: 'john@email.com')
252
+ # u[:email]
253
+ # #=> 'john@email.com'
254
+ #
255
+ def [](name)
256
+ __send__(name)
257
+ end
258
+
259
+ # Returns names of the attributes that was marked as :required.
260
+ #
261
+ # @return [Array] array of attributes names
262
+ #
263
+ # @example
264
+ # class User
265
+ # include AlphaCard::Attribute
266
+ #
267
+ # attribute :id
268
+ # attribute :email, required: true
269
+ # attribute :name, required: true
270
+ # end
271
+ #
272
+ # u = User.new
273
+ # u.required_attributes
274
+ # #=> [:email, :name]
275
+ #
276
+ def required_attributes
277
+ self.class.attributes_set.select { |_, options| options[:required] }.keys
278
+ end
279
+
280
+ # Indicates if all the attributes with option required: true
281
+ # are filled with non-nil value.
282
+ #
283
+ # @return [Bool]
284
+ #
285
+ # @example
286
+ # class User
287
+ # include AlphaCard::Attribute
288
+ #
289
+ # attribute :email, required: true
290
+ # attribute :name
291
+ # end
292
+ #
293
+ # u = User.new
294
+ # u.required_attributes?
295
+ # #=> false
296
+ #
297
+ # u.email = 'john.doe@gmail.com'
298
+ # u.required_attributes?
299
+ # #=> true
300
+ #
301
+ def required_attributes?
302
+ required_attributes.all? { |attr| !self[attr].nil? }
303
+ end
304
+
305
+ protected
306
+
307
+ # Set attribute value only if attribute writable
308
+ #
309
+ # @param name [String, Symbol] attribute name
310
+ # @param value [Object] attribute value
311
+ #
312
+ def set_attribute_safely(name, value)
313
+ __send__("#{name}=", value) if attribute_writable?(name)
314
+ end
315
+
316
+ # Checks if attribute is writable by it's options in the Attributes Set.
317
+ #
318
+ # @param name [String, Symbol] attribute name
319
+ #
320
+ # @return [Boolean]
321
+ #
322
+ def attribute_writable?(name)
323
+ attribute_options = self.class.attributes_set[name.to_sym]
324
+ return false if attribute_options.nil?
325
+
326
+ attribute_options[:writable].nil? || attribute_options[:writable]
327
+ end
328
+
329
+ # Sets default values for the attributes, based on Attributes Set.
330
+ def set_attributes_defaults!
331
+ self.class.attributes_set.each do |attr_name, options|
332
+ instance_variable_set(:"@#{attr_name}", options[:default])
333
+ end
334
+ end
335
+ end
336
+ end
337
+ end