alpha_card 0.3.0 → 0.4.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.
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