braintree 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +22 -0
- data/README.rdoc +62 -0
- data/lib/braintree.rb +66 -0
- data/lib/braintree/address.rb +122 -0
- data/lib/braintree/base_module.rb +29 -0
- data/lib/braintree/configuration.rb +99 -0
- data/lib/braintree/credit_card.rb +231 -0
- data/lib/braintree/credit_card_verification.rb +31 -0
- data/lib/braintree/customer.rb +231 -0
- data/lib/braintree/digest.rb +20 -0
- data/lib/braintree/error_codes.rb +95 -0
- data/lib/braintree/error_result.rb +39 -0
- data/lib/braintree/errors.rb +29 -0
- data/lib/braintree/http.rb +105 -0
- data/lib/braintree/paged_collection.rb +55 -0
- data/lib/braintree/ssl_expiration_check.rb +28 -0
- data/lib/braintree/successful_result.rb +38 -0
- data/lib/braintree/test/credit_card_numbers.rb +50 -0
- data/lib/braintree/test/transaction_amounts.rb +10 -0
- data/lib/braintree/transaction.rb +360 -0
- data/lib/braintree/transaction/address_details.rb +15 -0
- data/lib/braintree/transaction/credit_card_details.rb +22 -0
- data/lib/braintree/transaction/customer_details.rb +13 -0
- data/lib/braintree/transparent_redirect.rb +110 -0
- data/lib/braintree/util.rb +94 -0
- data/lib/braintree/validation_error.rb +15 -0
- data/lib/braintree/validation_error_collection.rb +80 -0
- data/lib/braintree/version.rb +9 -0
- data/lib/braintree/xml.rb +12 -0
- data/lib/braintree/xml/generator.rb +80 -0
- data/lib/braintree/xml/libxml.rb +69 -0
- data/lib/braintree/xml/parser.rb +93 -0
- data/lib/ssl/securetrust_ca.crt +44 -0
- data/lib/ssl/valicert_ca.crt +18 -0
- data/spec/integration/braintree/address_spec.rb +352 -0
- data/spec/integration/braintree/credit_card_spec.rb +676 -0
- data/spec/integration/braintree/customer_spec.rb +664 -0
- data/spec/integration/braintree/http_spec.rb +201 -0
- data/spec/integration/braintree/test/transaction_amounts_spec.rb +29 -0
- data/spec/integration/braintree/transaction_spec.rb +900 -0
- data/spec/integration/spec_helper.rb +38 -0
- data/spec/script/httpsd.rb +27 -0
- data/spec/spec_helper.rb +41 -0
- data/spec/unit/braintree/address_spec.rb +86 -0
- data/spec/unit/braintree/configuration_spec.rb +190 -0
- data/spec/unit/braintree/credit_card_spec.rb +137 -0
- data/spec/unit/braintree/credit_card_verification_spec.rb +17 -0
- data/spec/unit/braintree/customer_spec.rb +103 -0
- data/spec/unit/braintree/digest_spec.rb +28 -0
- data/spec/unit/braintree/error_result_spec.rb +42 -0
- data/spec/unit/braintree/errors_spec.rb +81 -0
- data/spec/unit/braintree/http_spec.rb +42 -0
- data/spec/unit/braintree/paged_collection_spec.rb +128 -0
- data/spec/unit/braintree/ssl_expiration_check_spec.rb +92 -0
- data/spec/unit/braintree/successful_result_spec.rb +27 -0
- data/spec/unit/braintree/transaction/credit_card_details_spec.rb +22 -0
- data/spec/unit/braintree/transaction_spec.rb +136 -0
- data/spec/unit/braintree/transparent_redirect_spec.rb +154 -0
- data/spec/unit/braintree/util_spec.rb +142 -0
- data/spec/unit/braintree/validation_error_collection_spec.rb +128 -0
- data/spec/unit/braintree/validation_error_spec.rb +19 -0
- data/spec/unit/braintree/xml/libxml_spec.rb +51 -0
- data/spec/unit/braintree/xml_spec.rb +122 -0
- data/spec/unit/spec_helper.rb +1 -0
- metadata +118 -0
@@ -0,0 +1,31 @@
|
|
1
|
+
module Braintree
|
2
|
+
class CreditCardVerification
|
3
|
+
include BaseModule
|
4
|
+
|
5
|
+
attr_reader :avs_error_response_code, :avs_postal_code_response_code,
|
6
|
+
:avs_street_address_response_code, :cvv_response_code, :status
|
7
|
+
|
8
|
+
def initialize(attributes) # :nodoc:
|
9
|
+
set_instance_variables_from_hash(attributes)
|
10
|
+
end
|
11
|
+
|
12
|
+
def inspect # :nodoc:
|
13
|
+
attr_order = [
|
14
|
+
:status, :cvv_response_code, :avs_error_response_code,
|
15
|
+
:avs_postal_code_response_code, :avs_street_address_response_code
|
16
|
+
]
|
17
|
+
formatted_attrs = attr_order.map do |attr|
|
18
|
+
"#{attr}: #{send(attr).inspect}"
|
19
|
+
end
|
20
|
+
"#<#{self.class} #{formatted_attrs.join(", ")}>"
|
21
|
+
end
|
22
|
+
|
23
|
+
class << self
|
24
|
+
protected :new
|
25
|
+
end
|
26
|
+
|
27
|
+
def self._new(*args) # :nodoc:
|
28
|
+
self.new *args
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,231 @@
|
|
1
|
+
module Braintree
|
2
|
+
class Customer
|
3
|
+
include BaseModule
|
4
|
+
|
5
|
+
attr_reader :addresses, :company, :created_at, :credit_cards, :email, :fax, :first_name, :id, :last_name,
|
6
|
+
:phone, :updated_at, :website
|
7
|
+
|
8
|
+
# Returns a PagedCollection of all customers stored in the vault. Due to race conditions, this method
|
9
|
+
# may not reliably return all customers stored in the vault.
|
10
|
+
#
|
11
|
+
# page = Braintree::Customer.all
|
12
|
+
# loop do
|
13
|
+
# page.each do |customer|
|
14
|
+
# puts "Customer #{customer.id} email is #{customer.email}"
|
15
|
+
# end
|
16
|
+
# break if page.last_page?
|
17
|
+
# page = page.next_page
|
18
|
+
# end
|
19
|
+
def self.all(options = {})
|
20
|
+
page_number = options[:page] || 1
|
21
|
+
response = Http.get("/customers?page=#{page_number}")
|
22
|
+
attributes = response[:customers]
|
23
|
+
attributes[:items] = Util.extract_attribute_as_array(attributes, :customer).map do |customer_attributes|
|
24
|
+
new customer_attributes
|
25
|
+
end
|
26
|
+
PagedCollection.new(attributes) { |page_number| Customer.all(:page => page_number) }
|
27
|
+
end
|
28
|
+
|
29
|
+
# Creates a customer using the given +attributes+. If <tt>:id</tt> is not passed,
|
30
|
+
# the gateway will generate it.
|
31
|
+
#
|
32
|
+
# result = Braintree::Customer.create(
|
33
|
+
# :first_name => "John",
|
34
|
+
# :last_name => "Smith",
|
35
|
+
# :company => "Smith Co.",
|
36
|
+
# :email => "john@smith.com",
|
37
|
+
# :website => "www.smithco.com",
|
38
|
+
# :fax => "419-555-1234",
|
39
|
+
# :phone => "614-555-1234"
|
40
|
+
# )
|
41
|
+
# if result.success?
|
42
|
+
# puts "Created customer #{result.customer.id}
|
43
|
+
# else
|
44
|
+
# puts "Could not create customer, see result.errors"
|
45
|
+
# end
|
46
|
+
def self.create(attributes = {})
|
47
|
+
Util.verify_keys(_create_signature, attributes)
|
48
|
+
_do_create "/customers", :customer => attributes
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.create!(attributes = {})
|
52
|
+
return_object_or_raise(:customer) { create(attributes) }
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.create_customer_url
|
56
|
+
"#{Braintree::Configuration.base_merchant_url}/customers/all/create_via_transparent_redirect_request"
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.create_from_transparent_redirect(query_string)
|
60
|
+
params = TransparentRedirect.parse_and_validate_query_string query_string
|
61
|
+
_do_create("/customers/all/confirm_transparent_redirect_request", :id => params[:id])
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.create_customer_transparent_redirect_url
|
65
|
+
"#{Braintree::Configuration.base_merchant_url}/customers"
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.credit(customer_id, transaction_attributes)
|
69
|
+
Transaction.credit(transaction_attributes.merge(:customer_id => customer_id))
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.credit!(customer_id, transaction_attributes)
|
73
|
+
return_object_or_raise(:transaction){ credit(customer_id, transaction_attributes) }
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.delete(customer_id)
|
77
|
+
Http.delete("/customers/#{customer_id}")
|
78
|
+
SuccessfulResult.new
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.find(customer_id)
|
82
|
+
response = Http.get("/customers/#{customer_id}")
|
83
|
+
new(response[:customer])
|
84
|
+
rescue NotFoundError
|
85
|
+
raise NotFoundError, "customer with id #{customer_id.inspect} not found"
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.sale(customer_id, transaction_attributes)
|
89
|
+
Transaction.sale(transaction_attributes.merge(:customer_id => customer_id))
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.sale!(customer_id, transaction_attributes)
|
93
|
+
return_object_or_raise(:transaction){ sale(customer_id, transaction_attributes) }
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.update(customer_id, attributes)
|
97
|
+
Util.verify_keys(_update_signature, attributes)
|
98
|
+
_do_update(:put, "/customers/#{customer_id}", :customer => attributes)
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.update!(customer_id, attributes)
|
102
|
+
return_object_or_raise(:customer) { update(customer_id, attributes) }
|
103
|
+
end
|
104
|
+
|
105
|
+
def self.update_customer_url
|
106
|
+
"#{Braintree::Configuration.base_merchant_url}/customers/all/update_via_transparent_redirect_request"
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.update_from_transparent_redirect(query_string)
|
110
|
+
params = TransparentRedirect.parse_and_validate_query_string(query_string)
|
111
|
+
_do_update(:post, "/customers/all/confirm_transparent_redirect_request", :id => params[:id])
|
112
|
+
end
|
113
|
+
|
114
|
+
def initialize(attributes) # :nodoc:
|
115
|
+
set_instance_variables_from_hash(attributes)
|
116
|
+
@credit_cards = (@credit_cards || []).map { |pm| CreditCard._new pm }
|
117
|
+
@addresses = (@addresses || []).map { |addr| Address._new addr }
|
118
|
+
end
|
119
|
+
|
120
|
+
def credit(transaction_attributes)
|
121
|
+
Customer.credit(self.id, transaction_attributes)
|
122
|
+
end
|
123
|
+
|
124
|
+
def credit!(transaction_attributes)
|
125
|
+
return_object_or_raise(:transaction) { credit(transaction_attributes) }
|
126
|
+
end
|
127
|
+
|
128
|
+
def delete
|
129
|
+
Customer.delete(id)
|
130
|
+
end
|
131
|
+
|
132
|
+
def inspect # :nodoc:
|
133
|
+
first = [:id]
|
134
|
+
last = [:addresses, :credit_cards]
|
135
|
+
order = first + (self.class._attributes - first - last) + last
|
136
|
+
nice_attributes = order.map do |attr|
|
137
|
+
"#{attr}: #{send(attr).inspect}"
|
138
|
+
end
|
139
|
+
"#<#{self.class} #{nice_attributes.join(', ')}>"
|
140
|
+
end
|
141
|
+
|
142
|
+
def sale(transaction_attributes)
|
143
|
+
Customer.sale(self.id, transaction_attributes)
|
144
|
+
end
|
145
|
+
|
146
|
+
def sale!(transaction_attributes)
|
147
|
+
return_object_or_raise(:transaction) { sale(transaction_attributes) }
|
148
|
+
end
|
149
|
+
|
150
|
+
# Finds transactions associated to the customer. Returns a PagedCollection.
|
151
|
+
def transactions(options = {})
|
152
|
+
page_number = options[:page] || 1
|
153
|
+
response = Http.get "/customers/#{id}/transactions?page=#{page_number}"
|
154
|
+
attributes = response[:credit_card_transactions]
|
155
|
+
attributes[:items] = Util.extract_attribute_as_array(attributes, :transaction).map do |transaction_attributes|
|
156
|
+
Transaction._new transaction_attributes
|
157
|
+
end
|
158
|
+
PagedCollection.new(attributes) { |page_number| self.transactions(:page => page_number) }
|
159
|
+
end
|
160
|
+
|
161
|
+
def update(attributes)
|
162
|
+
response = Http.put "/customers/#{id}", :customer => attributes
|
163
|
+
if response[:customer]
|
164
|
+
set_instance_variables_from_hash response[:customer]
|
165
|
+
SuccessfulResult.new(:customer => self)
|
166
|
+
elsif response[:api_error_response]
|
167
|
+
ErrorResult.new(response[:api_error_response])
|
168
|
+
else
|
169
|
+
raise "expected :customer or :errors"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def update!(attributes)
|
174
|
+
return_object_or_raise(:customer) { update(attributes) }
|
175
|
+
end
|
176
|
+
|
177
|
+
def ==(other)
|
178
|
+
return false unless other.is_a?(Customer)
|
179
|
+
id == other.id
|
180
|
+
end
|
181
|
+
|
182
|
+
class << self
|
183
|
+
protected :new
|
184
|
+
end
|
185
|
+
|
186
|
+
def self._attributes # :nodoc:
|
187
|
+
[
|
188
|
+
:addresses, :company, :credit_cards, :email, :fax, :first_name, :id, :last_name, :phone, :website,
|
189
|
+
:created_at, :updated_at
|
190
|
+
]
|
191
|
+
end
|
192
|
+
|
193
|
+
def self._create_signature # :nodoc:
|
194
|
+
credit_card_signature = CreditCard._create_signature - [:customer_id]
|
195
|
+
[
|
196
|
+
:company, :email, :fax, :first_name, :id, :last_name, :phone, :website,
|
197
|
+
{:credit_card => credit_card_signature}
|
198
|
+
]
|
199
|
+
end
|
200
|
+
|
201
|
+
def self._do_create(url, params) # :nodoc:
|
202
|
+
response = Http.post url, params
|
203
|
+
if response[:customer]
|
204
|
+
SuccessfulResult.new(:customer => new(response[:customer]))
|
205
|
+
elsif response[:api_error_response]
|
206
|
+
ErrorResult.new(response[:api_error_response])
|
207
|
+
else
|
208
|
+
raise "expected :customer or :api_error_response"
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def self._do_update(http_verb, url, params) # :nodoc:
|
213
|
+
response = Http.send http_verb, url, params
|
214
|
+
if response[:customer]
|
215
|
+
SuccessfulResult.new(:customer => new(response[:customer]))
|
216
|
+
elsif response[:api_error_response]
|
217
|
+
ErrorResult.new(response[:api_error_response])
|
218
|
+
else
|
219
|
+
raise UnexpectedError, "expected :customer or :api_error_response"
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def self._new(*args) # :nodoc:
|
224
|
+
self.new *args
|
225
|
+
end
|
226
|
+
|
227
|
+
def self._update_signature # :nodoc:
|
228
|
+
[ :company, :email, :fax, :first_name, :id, :last_name, :phone, :website ]
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Braintree
|
2
|
+
module Digest # :nodoc:
|
3
|
+
def self.hexdigest(string)
|
4
|
+
_hmac_sha1(Configuration.private_key, string)
|
5
|
+
end
|
6
|
+
|
7
|
+
def self._hmac_sha1(key, message)
|
8
|
+
key_digest = ::Digest::SHA1.digest(key)
|
9
|
+
inner_padding = "\x36" * 64
|
10
|
+
outer_padding = "\x5c" * 64
|
11
|
+
0.upto(19) do |i|
|
12
|
+
inner_padding[i] ^= key_digest[i]
|
13
|
+
outer_padding[i] ^= key_digest[i]
|
14
|
+
end
|
15
|
+
inner_hash = ::Digest::SHA1.digest(inner_padding + message.to_s)
|
16
|
+
::Digest::SHA1.hexdigest(outer_padding + inner_hash)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Braintree
|
2
|
+
# The ErrorCodes module provides constants for validation errors.
|
3
|
+
# The constants should be used to check for a specific validation error in a ValidationErrorCollection.
|
4
|
+
# The error messages returned from the server may change, but the codes will remain the same.
|
5
|
+
module ErrorCodes
|
6
|
+
module Address
|
7
|
+
CannotBeBlank = "81801"
|
8
|
+
CompanyIsTooLong = "81802"
|
9
|
+
CountryNameIsNotAccepted = "91803"
|
10
|
+
ExtendedAddressIsTooLong = "81804"
|
11
|
+
FirstNameIsTooLong = "81805"
|
12
|
+
LastNameIsTooLong = "81806"
|
13
|
+
LocalityIsTooLong = "81807"
|
14
|
+
PostalCodeIsRequired = "81808"
|
15
|
+
PostalCodeIsTooLong = "81809"
|
16
|
+
RegionIsTooLong = "81810"
|
17
|
+
StreetAddressIsRequired = "81811"
|
18
|
+
StreetAddressIsTooLong = "81812"
|
19
|
+
end
|
20
|
+
|
21
|
+
module CreditCard
|
22
|
+
BillingAddressConflict = "91701"
|
23
|
+
BillingAddressIdIsInvalid = "91702"
|
24
|
+
CreditCardTypeIsNotAccepted = "81703"
|
25
|
+
CustomerIdIsRequired = "91704"
|
26
|
+
CustomerIdIsInvalid = "91705"
|
27
|
+
CvvIsRequired = "81706"
|
28
|
+
CvvIsInvalid = "81707"
|
29
|
+
ExpirationDateConflict = "91708"
|
30
|
+
ExpirationDateIsRequired = "81709"
|
31
|
+
ExpirationDateIsInvalid = "81710"
|
32
|
+
ExpirationDateYearIsInvalid = "81711"
|
33
|
+
ExpirationMonthIsInvalid = "81712"
|
34
|
+
ExpirationYearIsInvalid = "81713"
|
35
|
+
NumberIsRequired = "81714"
|
36
|
+
NumberIsInvalid = "81715"
|
37
|
+
NumberInvalidLength = "81716"
|
38
|
+
NumberMustBeTestNumber = "81717"
|
39
|
+
TokenInvalid = "91718"
|
40
|
+
TokenIsInUse = "91719"
|
41
|
+
TokenIsTooLong = "91720"
|
42
|
+
TokenIsNotAllowed = "91721"
|
43
|
+
TokenIsRequired = "91722"
|
44
|
+
end
|
45
|
+
|
46
|
+
module Customer
|
47
|
+
CompanyisTooLong = "81601"
|
48
|
+
CustomFieldIsInvalid = "91602"
|
49
|
+
CustomFieldIsTooLong = "81603"
|
50
|
+
EmailIsInvalid = "81604"
|
51
|
+
EmailIsTooLong = "81605"
|
52
|
+
EmailIsRequired = "81606"
|
53
|
+
FaxIsTooLong = "81607"
|
54
|
+
FirstNameIsTooLong = "81608"
|
55
|
+
IdIsInUse = "91609"
|
56
|
+
IdIsInvaild = "91610"
|
57
|
+
IdIsNotAllowed = "91611"
|
58
|
+
IdIsTooLong = "91612"
|
59
|
+
LastNameIsTooLong = "81613"
|
60
|
+
PhoneIsTooLong = "81614"
|
61
|
+
WebsiteIsTooLong = "81615"
|
62
|
+
WebsiteIsInvalid = "81616"
|
63
|
+
end
|
64
|
+
|
65
|
+
module Transaction
|
66
|
+
AmountCannotBeNegative = "81501"
|
67
|
+
AmountIsRequired = "81502"
|
68
|
+
AmountIsInvalid = "81503"
|
69
|
+
CannotBeVoided = "91504"
|
70
|
+
CannotRefundCredit = "91505"
|
71
|
+
CannotRefundUnlessSettled = "91506"
|
72
|
+
CannotSubmitForSettlement = "91507"
|
73
|
+
CreditCardIsRequired = "91508"
|
74
|
+
CustomerDefaultPaymentMethodCardTypeIsNotAccepted = "81509"
|
75
|
+
CustomerIdIsInvalid = "91510"
|
76
|
+
CustomerDoesNotHaveCreditCard = "91511"
|
77
|
+
HasAlreadyBeenRefunded = "91512"
|
78
|
+
MerchantAccountNameIsInvalid = "91513"
|
79
|
+
MerchantAccountIsSuspended = "91514"
|
80
|
+
PaymentMethodConflict = "91515"
|
81
|
+
PaymentMethodDoesNotBelongToCustomer = "91516"
|
82
|
+
PaymentMethodTokenCardTypeIsNotAccepted = "91517"
|
83
|
+
PaymentMethodTokenIsInvalid = "91518"
|
84
|
+
ProcessorAuthorizationCodeCannotBeSet = "91519"
|
85
|
+
ProcessorAuthorizationCodeIsInvalid = "81520"
|
86
|
+
RefundAmountIsTooLarge = "91521"
|
87
|
+
SettlementAmountIsTooLarge = "91522"
|
88
|
+
TypeIsInvalid = "91523"
|
89
|
+
TypeIsRequired = "91524"
|
90
|
+
module Options
|
91
|
+
VaultIsDisabled = "91525"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Braintree
|
2
|
+
# An ErrorResult will be returned from non-bang methods when
|
3
|
+
# validations fail. It will provide access to the params passed
|
4
|
+
# to the server. The params are primarily useful for re-populaing
|
5
|
+
# web forms when using transparent redirect. ErrorResult also
|
6
|
+
# provides access to the validation errors.
|
7
|
+
#
|
8
|
+
# result = Braintree::Customer.create(:email => "invalid.email.address")
|
9
|
+
# if result.success?
|
10
|
+
# # have a SuccessfulResult
|
11
|
+
# else
|
12
|
+
# # have an ErrorResult
|
13
|
+
# puts "Validations failed when attempting to create customer."
|
14
|
+
# result.errors.for(:customer).each do |error|
|
15
|
+
# puts error.message
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
class ErrorResult
|
19
|
+
|
20
|
+
attr_reader :credit_card_verification, :errors, :params
|
21
|
+
|
22
|
+
def initialize(data) # :nodoc:
|
23
|
+
@params = data[:params]
|
24
|
+
if data[:verification]
|
25
|
+
@credit_card_verification = CreditCardVerification._new(data[:verification])
|
26
|
+
end
|
27
|
+
@errors = Errors.new(data[:errors])
|
28
|
+
end
|
29
|
+
|
30
|
+
def inspect # :nodoc:
|
31
|
+
"#<#{self.class} params:{...} errors:<#{@errors._inner_inspect}>>"
|
32
|
+
end
|
33
|
+
|
34
|
+
# Always returns false.
|
35
|
+
def success?
|
36
|
+
false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Braintree
|
2
|
+
# Provides access to errors from an ErrorResult.
|
3
|
+
class Errors
|
4
|
+
def initialize(data = {}) # :nodoc:
|
5
|
+
@errors = ValidationErrorCollection.new(data.merge(:errors => []))
|
6
|
+
end
|
7
|
+
|
8
|
+
# Accesses validation errors for the given +scope+.
|
9
|
+
def for(scope)
|
10
|
+
@errors.for(scope)
|
11
|
+
end
|
12
|
+
|
13
|
+
def inspect # :nodoc:
|
14
|
+
"#<#{self.class} #{_inner_inspect}>"
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the total number of validation errors at all levels of nesting. For example,
|
18
|
+
# if creating a customer with a credit card and a billing address, and each of the customer,
|
19
|
+
# credit card, and billing address has 1 error, this method will return 3.
|
20
|
+
def size
|
21
|
+
@errors.deep_size
|
22
|
+
end
|
23
|
+
|
24
|
+
def _inner_inspect # :nodoc:
|
25
|
+
@errors._inner_inspect
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|