simple_shipping 0.4.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.metrics +6 -0
- data/.rspec +4 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.simplecov +43 -0
- data/Gemfile +26 -0
- data/Gemfile.lock +201 -0
- data/LICENSE.txt +21 -0
- data/README.markdown +207 -0
- data/Rakefile +68 -0
- data/VERSION +1 -0
- data/coverage/.resultset.json +1579 -0
- data/lib/colorized_text.rb +34 -0
- data/lib/simple_shipping.rb +27 -0
- data/lib/simple_shipping/abstract.rb +11 -0
- data/lib/simple_shipping/abstract/builder.rb +47 -0
- data/lib/simple_shipping/abstract/client.rb +111 -0
- data/lib/simple_shipping/abstract/model.rb +40 -0
- data/lib/simple_shipping/abstract/request.rb +27 -0
- data/lib/simple_shipping/abstract/response.rb +26 -0
- data/lib/simple_shipping/address.rb +22 -0
- data/lib/simple_shipping/contact.rb +24 -0
- data/lib/simple_shipping/demo.rb +9 -0
- data/lib/simple_shipping/demo/base.rb +71 -0
- data/lib/simple_shipping/demo/fedex.rb +46 -0
- data/lib/simple_shipping/demo/ups.rb +68 -0
- data/lib/simple_shipping/exceptions.rb +40 -0
- data/lib/simple_shipping/fedex.rb +14 -0
- data/lib/simple_shipping/fedex/client.rb +41 -0
- data/lib/simple_shipping/fedex/package_builder.rb +24 -0
- data/lib/simple_shipping/fedex/party_builder.rb +50 -0
- data/lib/simple_shipping/fedex/request.rb +54 -0
- data/lib/simple_shipping/fedex/response.rb +5 -0
- data/lib/simple_shipping/fedex/shipment_builder.rb +123 -0
- data/lib/simple_shipping/fedex/shipment_request.rb +14 -0
- data/lib/simple_shipping/fedex/shipment_response.rb +12 -0
- data/lib/simple_shipping/package.rb +43 -0
- data/lib/simple_shipping/party.rb +21 -0
- data/lib/simple_shipping/shipment.rb +42 -0
- data/lib/simple_shipping/ups.rb +24 -0
- data/lib/simple_shipping/ups/client.rb +46 -0
- data/lib/simple_shipping/ups/package_builder.rb +101 -0
- data/lib/simple_shipping/ups/party_builder.rb +38 -0
- data/lib/simple_shipping/ups/request.rb +27 -0
- data/lib/simple_shipping/ups/response.rb +63 -0
- data/lib/simple_shipping/ups/ship_accept_request.rb +21 -0
- data/lib/simple_shipping/ups/ship_accept_response.rb +6 -0
- data/lib/simple_shipping/ups/ship_client.rb +70 -0
- data/lib/simple_shipping/ups/ship_confirm_request.rb +22 -0
- data/lib/simple_shipping/ups/ship_confirm_response.rb +6 -0
- data/lib/simple_shipping/ups/shipment_builder.rb +66 -0
- data/lib/simple_shipping/ups/shipment_request.rb +22 -0
- data/lib/simple_shipping/ups/shipment_response.rb +6 -0
- data/lib/simple_shipping/ups/void_client.rb +50 -0
- data/lib/simple_shipping/ups/void_request.rb +42 -0
- data/lib/simple_shipping/ups/void_response.rb +6 -0
- data/lib/tasks/demo.rake +58 -0
- data/script/ups_certification.rb +140 -0
- data/simple_shipping.gemspec +168 -0
- data/spec/fixtures/fedex_shipment_request.soap.xml.erb +85 -0
- data/spec/fixtures/fedex_shipment_response.soap.xml.erb +182 -0
- data/spec/fixtures/ups_shipment_request.soap.xml.erb +88 -0
- data/spec/fixtures/ups_shipment_response.soap.xml.erb +58 -0
- data/spec/fixtures/ups_shipment_response_with_faked_label_data.soap.xml.erb +54 -0
- data/spec/fixtures/ups_void_request.soap.xml.erb +29 -0
- data/spec/fixtures/ups_void_response.soap.xml.erb +21 -0
- data/spec/lib/simple_shipping/address_spec.rb +19 -0
- data/spec/lib/simple_shipping/contact_spec.rb +28 -0
- data/spec/lib/simple_shipping/exceptions_spec.rb +58 -0
- data/spec/lib/simple_shipping/fedex/package_builder_spec.rb +5 -0
- data/spec/lib/simple_shipping/fedex/party_builder_spec.rb +5 -0
- data/spec/lib/simple_shipping/fedex/response/shipment_reponse_spec.rb +5 -0
- data/spec/lib/simple_shipping/fedex/response_spec.rb +5 -0
- data/spec/lib/simple_shipping/fedex/shipment_builder_spec.rb +23 -0
- data/spec/lib/simple_shipping/package_spec.rb +32 -0
- data/spec/lib/simple_shipping/party_spec.rb +18 -0
- data/spec/lib/simple_shipping/shipment_spec.rb +35 -0
- data/spec/lib/simple_shipping/ups/package_builder_spec.rb +26 -0
- data/spec/lib/simple_shipping/ups/party_builder_spec.rb +47 -0
- data/spec/lib/simple_shipping/ups/response/shipment_response_spec.rb +5 -0
- data/spec/lib/simple_shipping/ups/response_spec.rb +33 -0
- data/spec/lib/simple_shipping/ups/shipment_builder_spec.rb +19 -0
- data/spec/requests/fedex_spec.rb +47 -0
- data/spec/requests/ups_spec.rb +75 -0
- data/spec/spec_helper.rb +47 -0
- data/spec/support/custom_matchers/basic_matcher.rb +13 -0
- data/spec/support/custom_matchers/have_attribute_matcher.rb +22 -0
- data/spec/support/custom_matchers/have_default_value_matcher.rb +26 -0
- data/spec/support/custom_matchers/have_errors_on_matcher.rb +23 -0
- data/spec/support/custom_matchers/validate_inclusion_of_matcher.rb +37 -0
- data/spec/support/custom_matchers/validate_presence_of_matcher.rb +24 -0
- data/spec/support/custom_matchers/validate_submodel_matcher.rb +44 -0
- data/spec/support/shared_behaviours/builders_behaviour.rb +9 -0
- data/spec/support/shared_behaviours/responses_behaviour.rb +10 -0
- data/tmp/metric_fu/_data/20131210.yml +9964 -0
- data/wsdl/fedex/ship_service_v10.wsdl +5566 -0
- data/wsdl/ups/Ship.wsdl +120 -0
- data/wsdl/ups/Void.wsdl +58 -0
- metadata +308 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module SimpleShipping::Ups
|
4
|
+
describe PartyBuilder do
|
5
|
+
it_should_behave_like "builders"
|
6
|
+
|
7
|
+
it 'validate account number if party is shipper' do
|
8
|
+
shipper = SimpleShipping::Party.new
|
9
|
+
|
10
|
+
shipper.stub!(:valid? => true)
|
11
|
+
lambda {
|
12
|
+
PartyBuilder.build(shipper, :shipper => true)
|
13
|
+
}.should raise_error SimpleShipping::ValidationError
|
14
|
+
|
15
|
+
shipper.stub!(:account_number => '123')
|
16
|
+
lambda {
|
17
|
+
PartyBuilder.build(shipper, :shipper => true)
|
18
|
+
}.should_not raise_error SimpleShipping::ValidationError
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "build" do
|
23
|
+
it "should include all addresses" do
|
24
|
+
contact = SimpleShipping::Contact.new(:phone_number => "5555555555", :person_name => "Frank")
|
25
|
+
address = SimpleShipping::Address.new(:country_code => "US", :state_code => "IL", :city => "Chicago", :postal_code => "60622")
|
26
|
+
address.street_line = "foo"
|
27
|
+
address.street_line_2 = "bar"
|
28
|
+
address.street_line_3 = "baz"
|
29
|
+
|
30
|
+
shipper = SimpleShipping::Party.new(:contact => contact, :address => address)
|
31
|
+
party = PartyBuilder.build(shipper)
|
32
|
+
party['Address']['AddressLine'].should have(3).addresses
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should exclude nil addresses" do
|
36
|
+
contact = SimpleShipping::Contact.new(:phone_number => "5555555555", :person_name => "Frank")
|
37
|
+
address = SimpleShipping::Address.new(:country_code => "US", :state_code => "IL", :city => "Chicago", :postal_code => "60622")
|
38
|
+
address.street_line = "foo"
|
39
|
+
address.street_line_2 = nil
|
40
|
+
address.street_line_3 = "baz"
|
41
|
+
|
42
|
+
shipper = SimpleShipping::Party.new(:contact => contact, :address => address)
|
43
|
+
party = PartyBuilder.build(shipper)
|
44
|
+
party['Address']['AddressLine'].should have(2).addresses
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SimpleShipping::Ups::Response do
|
4
|
+
it_should_behave_like "responses"
|
5
|
+
|
6
|
+
context "when success response is received" do
|
7
|
+
subject { response }
|
8
|
+
|
9
|
+
let(:response_fixture) { fixture("ups_shipment_response") }
|
10
|
+
let(:http_response) { ::HTTPI::Response.new(200, {}, response_fixture) }
|
11
|
+
let(:savon_response) do
|
12
|
+
::Savon::Response.new(
|
13
|
+
http_response,
|
14
|
+
{
|
15
|
+
strip_namespaces: true,
|
16
|
+
convert_response_tags_to: ->(tag) { tag.snakecase.to_sym }
|
17
|
+
},
|
18
|
+
{}
|
19
|
+
)
|
20
|
+
end
|
21
|
+
let(:response) { ::SimpleShipping::Ups::ShipmentResponse.new(savon_response) }
|
22
|
+
|
23
|
+
its(:shipment_identification_number) { should eq("1Z35679R0294268838") }
|
24
|
+
its(:tracking_number) { should eq("1Z35679R0294268838") }
|
25
|
+
|
26
|
+
describe "label image" do
|
27
|
+
let(:response_fixture) { fixture("ups_shipment_response_with_faked_label_data") }
|
28
|
+
|
29
|
+
# HTML_IMAGE_DATA is the Base64 decoded version of SFRNTF9JTUFHRV9EQVRB
|
30
|
+
its(:label_html) { should eq("HTML_IMAGE_DATA") }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SimpleShipping::Ups::ShipmentBuilder do
|
4
|
+
it_should_behave_like "builders"
|
5
|
+
|
6
|
+
describe 'validation' do
|
7
|
+
it 'validates inclusion of service_types' do
|
8
|
+
shipment = SimpleShipping::Shipment.new
|
9
|
+
shipment.stub!(:valid? => true)
|
10
|
+
|
11
|
+
lambda {
|
12
|
+
SimpleShipping::Ups::ShipmentBuilder.build(shipment, :service_type => :ground)
|
13
|
+
}.should_not raise_error SimpleShipping::ValidationError
|
14
|
+
lambda {
|
15
|
+
SimpleShipping::Ups::ShipmentBuilder.build(shipment, :service_type => :bad)
|
16
|
+
}.should raise_error SimpleShipping::ValidationError
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "FedEx integration test" do
|
4
|
+
before { Timecop.freeze }
|
5
|
+
after { Timecop.return }
|
6
|
+
|
7
|
+
#let(:credentials) do
|
8
|
+
# YAML.load_file(SimpleShipping::DEMO_CREDENTIALS_FILE)['fedex'].symbolize_keys!
|
9
|
+
#end
|
10
|
+
|
11
|
+
let(:credentials) {{
|
12
|
+
:key => 'fedex key',
|
13
|
+
:password => 'secret word',
|
14
|
+
:account_number => '101010101',
|
15
|
+
:meter_number => '202020202'
|
16
|
+
}}
|
17
|
+
|
18
|
+
let(:demo) do
|
19
|
+
options = credentials.merge(:live => false)
|
20
|
+
SimpleShipping::Demo::Fedex.new(options)
|
21
|
+
end
|
22
|
+
|
23
|
+
context "#shipment_request" do
|
24
|
+
it "builds correct SOAP request envelope" do
|
25
|
+
req_matcher = lambda do |req|
|
26
|
+
expected = Nokogiri::XML(fixture(:fedex_shipment_request, credentials))
|
27
|
+
actual = Nokogiri::XML(req.body)
|
28
|
+
|
29
|
+
actual.root.should be_equivalent_to(expected.root).respecting_element_order
|
30
|
+
|
31
|
+
req.headers['Soapaction'].should == %{"processShipment"}
|
32
|
+
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
req = stub_http_request(:post, demo.fedex_client.class.testing_address).
|
37
|
+
with(&req_matcher).
|
38
|
+
to_return(:body => fixture(:fedex_shipment_response), :status => 200, :headers => {})
|
39
|
+
|
40
|
+
resp = demo.shipment_request
|
41
|
+
|
42
|
+
resp.label_image_base64.should be_present
|
43
|
+
|
44
|
+
req.should have_been_made
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "UPS test" do
|
4
|
+
let(:credentials) {{
|
5
|
+
:username => "Joe13",
|
6
|
+
:password => "JoesSecretWord",
|
7
|
+
:account_number => "1010101",
|
8
|
+
:access_license_number => "Joe's license"
|
9
|
+
}}
|
10
|
+
|
11
|
+
let(:demo) do
|
12
|
+
options = credentials.merge!(:live => false)
|
13
|
+
SimpleShipping::Demo::Ups.new(options)
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:erb_request_vars) do
|
17
|
+
credentials.merge(:shipment_identification_number => demo.shipment_identification_number)
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "ship_client" do
|
21
|
+
describe "#shipment_request" do
|
22
|
+
it "builds correct SOAP request envelope" do
|
23
|
+
req_matcher = lambda do |req|
|
24
|
+
expected = Nokogiri::XML(fixture(:ups_shipment_request, erb_request_vars))
|
25
|
+
actual = Nokogiri::XML(req.body)
|
26
|
+
|
27
|
+
actual.root.should be_equivalent_to(expected.root)
|
28
|
+
#actual.root.to_s.should == expected.root.to_s
|
29
|
+
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
req = stub_http_request(:post, demo.ship_client.class.testing_address).
|
34
|
+
with(&req_matcher).
|
35
|
+
to_return(:body => fixture(:ups_shipment_response), :status => 200, :headers => {})
|
36
|
+
|
37
|
+
resp = demo.shipment_request(
|
38
|
+
|
39
|
+
)
|
40
|
+
|
41
|
+
|
42
|
+
resp.label_image_base64.should be_present
|
43
|
+
|
44
|
+
req.should have_been_made
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "void client" do
|
50
|
+
describe "#void_request" do
|
51
|
+
it "builds correct SOAP request envelope" do
|
52
|
+
req_matcher = lambda do |req|
|
53
|
+
expected = Nokogiri::XML(fixture(:ups_void_request, erb_request_vars))
|
54
|
+
actual = Nokogiri::XML(req.body)
|
55
|
+
|
56
|
+
actual.root.should be_equivalent_to(expected.root)
|
57
|
+
#actual.root.to_s.should == expected.root.to_s
|
58
|
+
|
59
|
+
true
|
60
|
+
end
|
61
|
+
|
62
|
+
req = stub_http_request(:post, demo.void_client.class.testing_address).
|
63
|
+
with(&req_matcher).
|
64
|
+
to_return(:body => fixture(:ups_void_response), :status => 200, :headers => {})
|
65
|
+
|
66
|
+
expect{ demo.void_request }.to(
|
67
|
+
# NOTE: Exception message is important! This is how we can find out whether SOAP request was made correct -- aignatyev 20130204
|
68
|
+
raise_exception(SimpleShipping::RequestError, /No shipment found within the allowed void period/)
|
69
|
+
)
|
70
|
+
|
71
|
+
req.should have_been_made
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'simple_shipping'
|
5
|
+
|
6
|
+
require "simplecov"
|
7
|
+
require "simplecov-rcov-text"
|
8
|
+
|
9
|
+
SimpleCov.formatter = SimpleCov::Formatter::RcovTextFormatter
|
10
|
+
SimpleCov.start do
|
11
|
+
add_filter "/spec/"
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
require "savon/mock/spec_helper"
|
16
|
+
require 'webmock/rspec'
|
17
|
+
require "timecop"
|
18
|
+
require "erubis"
|
19
|
+
require 'equivalent-xml'
|
20
|
+
|
21
|
+
# Requires supporting files with custom matchers and macros, etc,
|
22
|
+
# in ./support/ and its subdirectories.
|
23
|
+
require File.expand_path("../support/custom_matchers/basic_matcher", __FILE__)
|
24
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
25
|
+
|
26
|
+
RSpec.configure do |config|
|
27
|
+
config.include SimpleShipping::CustomMatchers
|
28
|
+
config.include Savon::SpecHelper
|
29
|
+
config.after(:each) { savon.unmock! }
|
30
|
+
|
31
|
+
config.before(:each) do
|
32
|
+
# We are going to enable webmock in some spec on-demand.
|
33
|
+
# This is the reason why this config directive is placed in before(:each) hook -- aignatyev 20130204
|
34
|
+
WebMock.disable_net_connect!(:allow_localhost => true)
|
35
|
+
end
|
36
|
+
|
37
|
+
def fixtures_dir
|
38
|
+
Pathname.new(File.expand_path('../fixtures', __FILE__))
|
39
|
+
end
|
40
|
+
|
41
|
+
def fixture(name, vars = {})
|
42
|
+
path = fixtures_dir.join(name.to_s + ".soap.xml.erb")
|
43
|
+
template = File.open(path).read
|
44
|
+
|
45
|
+
Erubis::Eruby.new(template).result(vars)
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
module CustomMatchers
|
3
|
+
class HaveAttributeMatcher < BasicMatcher
|
4
|
+
def initialize(attribute)
|
5
|
+
@attribute = attribute.to_sym
|
6
|
+
end
|
7
|
+
|
8
|
+
def matches?(model)
|
9
|
+
model.respond_to?(@attribute) &&
|
10
|
+
model.respond_to?("#{@attribute}=")
|
11
|
+
end
|
12
|
+
|
13
|
+
def description
|
14
|
+
"have attribute #{@attribute.inspect}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def have_attribute(attr_name)
|
19
|
+
HaveAttributeMatcher.new(attr_name)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
module CustomMatchers
|
3
|
+
class HaveDefaultValueMatcher < BasicMatcher
|
4
|
+
def initialize(value)
|
5
|
+
@value = value
|
6
|
+
end
|
7
|
+
|
8
|
+
def matches?(model)
|
9
|
+
model.send(@attribute) == @value
|
10
|
+
end
|
11
|
+
|
12
|
+
def for_attribute(attribute)
|
13
|
+
@attribute = attribute.to_sym
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
17
|
+
def description
|
18
|
+
"have default value #{@value.inspect} for attribute #{@attribute.inspect}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def have_default_value(value)
|
23
|
+
HaveDefaultValueMatcher.new(value)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
module CustomMatchers
|
3
|
+
class HaveErrorsOnMatcher < BasicMatcher
|
4
|
+
|
5
|
+
def initialize(attribute)
|
6
|
+
@attribute = attribute.to_sym
|
7
|
+
end
|
8
|
+
|
9
|
+
def matches?(model)
|
10
|
+
model.valid?
|
11
|
+
!!model.errors.messages[@attribute]
|
12
|
+
end
|
13
|
+
|
14
|
+
def description
|
15
|
+
"have errors on #{@attribute.inspect}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def have_errors_on(attr_name)
|
20
|
+
HaveErrorsOnMatcher.new(attr_name)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
module CustomMatchers
|
3
|
+
class ValidateInclusionOfMatcher < BasicMatcher
|
4
|
+
def initialize(attribute)
|
5
|
+
@attribute = attribute.to_sym
|
6
|
+
end
|
7
|
+
|
8
|
+
def matches?(model)
|
9
|
+
@enumeration.each do |value|
|
10
|
+
model.send("#{@attribute}=", value)
|
11
|
+
return false if has_error?(model)
|
12
|
+
end
|
13
|
+
model.send("#{@attribute}=", "ANOTHER_VALUE_#{rand}")
|
14
|
+
has_error?(model)
|
15
|
+
end
|
16
|
+
|
17
|
+
def in(*enumeration)
|
18
|
+
@enumeration = enumeration
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def description
|
23
|
+
"validate inclusion of #{@attribute.inspect} in #{@enumeration.inspect}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def has_error?(model)
|
27
|
+
model.valid?
|
28
|
+
model.errors.messages[@attribute] and
|
29
|
+
model.errors.messages[@attribute].include?("is not included in the list")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def validate_inclusion_of(attr_name)
|
34
|
+
ValidateInclusionOfMatcher.new(attr_name)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
module CustomMatchers
|
3
|
+
class ValidatePresenceOfMatcher < BasicMatcher
|
4
|
+
def initialize(attribute)
|
5
|
+
@attribute = attribute.to_sym
|
6
|
+
end
|
7
|
+
|
8
|
+
def matches?(model)
|
9
|
+
model.send("#{@attribute}=", nil)
|
10
|
+
model.valid?
|
11
|
+
model.errors.messages[@attribute] and
|
12
|
+
model.errors.messages[@attribute].include? "can't be blank"
|
13
|
+
end
|
14
|
+
|
15
|
+
def description
|
16
|
+
"validate presence of #{@attribute.inspect}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate_presence_of(attr_name)
|
21
|
+
ValidatePresenceOfMatcher.new(attr_name)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
module CustomMatchers
|
3
|
+
class ValidateSubmodelMatcher < BasicMatcher
|
4
|
+
def initialize(attribute)
|
5
|
+
@attribute = attribute.to_sym
|
6
|
+
end
|
7
|
+
|
8
|
+
def matches?(model)
|
9
|
+
@model = model
|
10
|
+
|
11
|
+
@model.send("#{@attribute}=", Class.new.new)
|
12
|
+
return false unless has_error?
|
13
|
+
|
14
|
+
submodel = @class.new
|
15
|
+
submodel.stub!(:valid? => false)
|
16
|
+
@model.send("#{@attribute}=", submodel)
|
17
|
+
return false unless has_error?
|
18
|
+
|
19
|
+
submodel.stub!(:valid? => true)
|
20
|
+
@model.send("#{@attribute}=", submodel)
|
21
|
+
!has_error?
|
22
|
+
end
|
23
|
+
|
24
|
+
def as(klass)
|
25
|
+
@class = klass
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def description
|
30
|
+
"validate submodel #{@attribute.inspect} as instance of #{@class}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def has_error?
|
34
|
+
@model.valid?
|
35
|
+
!!@model.errors.messages[@attribute]
|
36
|
+
end
|
37
|
+
private :has_error?
|
38
|
+
end
|
39
|
+
|
40
|
+
def validate_submodel(attr_name)
|
41
|
+
ValidateSubmodelMatcher.new(attr_name)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|