jm81-dm-address 0.1.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.
- data/.document +5 -0
- data/.gitignore +7 -0
- data/LICENSE +20 -0
- data/README.rdoc +7 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/lib/dm-address/phone_number.rb +26 -0
- data/lib/dm-address/us.rb +73 -0
- data/lib/dm-address/zip_code.rb +19 -0
- data/lib/dm-address.rb +37 -0
- data/lib/dm-types/phone_number.rb +28 -0
- data/lib/dm-types/zip_code.rb +28 -0
- data/spec/dm-address/phone_number_spec.rb +39 -0
- data/spec/dm-address/us_spec.rb +224 -0
- data/spec/dm-address/zip_code_spec.rb +36 -0
- data/spec/dm-address_spec.rb +24 -0
- data/spec/dm-types/phone_number_spec.rb +56 -0
- data/spec/dm-types/zip_code_spec.rb +56 -0
- data/spec/spec_helper.rb +9 -0
- metadata +117 -0
data/.document
ADDED
data/.gitignore
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Jared Morgan
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "dm-address"
|
8
|
+
gem.summary = %Q{TODO}
|
9
|
+
gem.email = "jmorgan@morgancreative.net"
|
10
|
+
gem.homepage = "http://github.com/jm81/dm-address"
|
11
|
+
gem.authors = ["Jared Morgan"]
|
12
|
+
gem.add_dependency('extlib')
|
13
|
+
gem.add_dependency('dm-core')
|
14
|
+
gem.add_dependency('dm-types')
|
15
|
+
gem.add_dependency('dm-validations')
|
16
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
17
|
+
end
|
18
|
+
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'spec/rake/spectask'
|
24
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
25
|
+
spec.libs << 'lib' << 'spec'
|
26
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
27
|
+
end
|
28
|
+
|
29
|
+
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
30
|
+
spec.libs << 'lib' << 'spec'
|
31
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
32
|
+
spec.rcov = true
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
task :default => :spec
|
37
|
+
|
38
|
+
require 'rake/rdoctask'
|
39
|
+
Rake::RDocTask.new do |rdoc|
|
40
|
+
if File.exist?('VERSION.yml')
|
41
|
+
config = YAML.load(File.read('VERSION.yml'))
|
42
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
43
|
+
else
|
44
|
+
version = ""
|
45
|
+
end
|
46
|
+
|
47
|
+
rdoc.rdoc_dir = 'rdoc'
|
48
|
+
rdoc.title = "dm-address #{version}"
|
49
|
+
rdoc.rdoc_files.include('README*')
|
50
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
51
|
+
end
|
52
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Address
|
3
|
+
class PhoneNumber < String
|
4
|
+
DEFAULT_FORMAT = '(%A) %P-%S'
|
5
|
+
|
6
|
+
# Remove all non-digits from given phone number
|
7
|
+
def initialize(s)
|
8
|
+
super((s || '').gsub(/\D+/, ''))
|
9
|
+
end
|
10
|
+
|
11
|
+
alias base to_s
|
12
|
+
|
13
|
+
# %A is area code, %P is prefix, %S is last 4 digits (suffix)
|
14
|
+
# Default is "(%A) %P-%S" -> (###) ###-####
|
15
|
+
def to_s(format = nil)
|
16
|
+
unless format
|
17
|
+
format = DataMapper::Address.config[:phone_format] || DEFAULT_FORMAT
|
18
|
+
end
|
19
|
+
return '' if base.nil? || base.empty?
|
20
|
+
format.gsub(/\%A/, base[0..2]).
|
21
|
+
gsub(/\%P/, base[3..5]).
|
22
|
+
gsub(/\%S/, base[6..9])
|
23
|
+
end
|
24
|
+
end # class PhoneNumber
|
25
|
+
end # module Address
|
26
|
+
end # module DataMapper
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Address
|
3
|
+
# Include in a DataMapper::Resource model to add fields and methods for
|
4
|
+
# a US-style address.
|
5
|
+
module US
|
6
|
+
DEFAULT_REQUIRED_FIELDS = [
|
7
|
+
:street, :city, :state, :postal_code, :country
|
8
|
+
]
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def included(klass)
|
12
|
+
klass.extend(ClassMethods)
|
13
|
+
end
|
14
|
+
end # class << self
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
|
18
|
+
# Setup properties. Already added properties are not overriden.
|
19
|
+
# options:
|
20
|
+
# - +prefix+: Add a prefix to field names
|
21
|
+
# - +required_fields+: Override DataMapper::Address.config[:us_required_fields]
|
22
|
+
def address_properties(options = {})
|
23
|
+
reqs = options[:required_fields] ||
|
24
|
+
DataMapper::Address.config[:us_required_fields] ||
|
25
|
+
DEFAULT_REQUIRED_FIELDS
|
26
|
+
|
27
|
+
[
|
28
|
+
[:id, DataMapper::Types::Serial],
|
29
|
+
[:name, String, {:length => 100}],
|
30
|
+
[:company, String, {:length => 100}],
|
31
|
+
[:street, String, {:length => 100}],
|
32
|
+
[:street_2, String],
|
33
|
+
[:city, String, {:length => 100}],
|
34
|
+
[:state, String, {:length => 2}],
|
35
|
+
[:postal_code, DataMapper::Types::ZipCode, {
|
36
|
+
:format => Proc.new { |zc| zc.nil? || zc.length == 5 || zc.length == 9 },
|
37
|
+
:messages => { :format => "Postal code should be 5 digits or 9 digits (ZIP+4)" }}],
|
38
|
+
[:country, String, {:nullable => false, :length => 50, :default => 'USA'}],
|
39
|
+
[:phone, DataMapper::Types::PhoneNumber, {
|
40
|
+
:format => Proc.new { |ph| ph.blank? || ph.length == 10 },
|
41
|
+
:messages => { :format => "Phone number should be 10 digits (include area code)" }}],
|
42
|
+
[:created_at, DateTime],
|
43
|
+
[:updated_at, DateTime]
|
44
|
+
].each do |args|
|
45
|
+
unless self.properties.has_property?(args[0])
|
46
|
+
args[0] = "#{options[:prefix]}#{args[0]}" if options[:prefix]
|
47
|
+
args[2] ||= {}
|
48
|
+
args[2][:nullable] = !reqs.include?(args[0])
|
49
|
+
self.property(*args)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end # module ClassMethods
|
54
|
+
|
55
|
+
# Nicely formatted address block (optionally includes country and phone)
|
56
|
+
def block(newline = "\n",
|
57
|
+
include_country = DataMapper::Address.config[:include_country],
|
58
|
+
include_phone = DataMapper::Address.config[:include_phone])
|
59
|
+
|
60
|
+
fields = []
|
61
|
+
%w{ name company street street_2 }.each do |fld|
|
62
|
+
value = attribute_get(fld)
|
63
|
+
fields << value unless value.blank?
|
64
|
+
end
|
65
|
+
fields << "#{self.city}, #{self.state} #{self.postal_code.to_s}"
|
66
|
+
fields << self.country if include_country
|
67
|
+
fields << self.phone.to_s if include_phone && !self.phone.blank?
|
68
|
+
fields.join(newline)
|
69
|
+
end
|
70
|
+
|
71
|
+
end # module US
|
72
|
+
end # module Address
|
73
|
+
end # module DataMapper
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Address
|
3
|
+
class ZipCode < String
|
4
|
+
# Remove all non-digits from given phone number
|
5
|
+
def initialize(s)
|
6
|
+
super((s || '').gsub(/\D+/, ''))
|
7
|
+
end
|
8
|
+
|
9
|
+
alias base to_s
|
10
|
+
|
11
|
+
# ZipCode formatted as #####-#### or #####
|
12
|
+
def to_s(format = nil)
|
13
|
+
return '' if base.nil? || base.empty?
|
14
|
+
return base if base.length == 5
|
15
|
+
"#{base[0..4]}-#{base[5..8]}"
|
16
|
+
end
|
17
|
+
end # class ZipCode
|
18
|
+
end # module Address
|
19
|
+
end # module DataMapper
|
data/lib/dm-address.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'dm-core'
|
2
|
+
require 'dm-types'
|
3
|
+
require 'dm-validations'
|
4
|
+
|
5
|
+
# Require dm-address files
|
6
|
+
%w{ phone_number zip_code us }.each do |file|
|
7
|
+
require File.dirname(__FILE__) + '/dm-address/' + file
|
8
|
+
end
|
9
|
+
|
10
|
+
module DataMapper
|
11
|
+
module Address
|
12
|
+
DEFAULTS = {
|
13
|
+
:phone_format => PhoneNumber::DEFAULT_FORMAT.dup,
|
14
|
+
:include_country => false,
|
15
|
+
:include_phone => false,
|
16
|
+
:us_required_fields => US::DEFAULT_REQUIRED_FIELDS.dup
|
17
|
+
}
|
18
|
+
|
19
|
+
class << self
|
20
|
+
# Address::config method returns Hash that can be edited.
|
21
|
+
def config
|
22
|
+
@config ||= DEFAULTS.dup
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end # module Address
|
26
|
+
end # module DataMapper
|
27
|
+
|
28
|
+
if defined?(Merb::Plugins)
|
29
|
+
# Make config accessible through Merb's Merb::Plugins.config hash
|
30
|
+
Merb::Plugins.config[:dm_address] = DataMapper::Address.config
|
31
|
+
end
|
32
|
+
|
33
|
+
# Require dm-types files
|
34
|
+
%w{ phone_number zip_code }.each do |file|
|
35
|
+
require File.dirname(__FILE__) + '/dm-types/' + file
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Types
|
3
|
+
class PhoneNumber < DataMapper::Type
|
4
|
+
primitive String
|
5
|
+
|
6
|
+
def self.load(value, property)
|
7
|
+
if value.nil?
|
8
|
+
nil
|
9
|
+
elsif value.is_a?(String)
|
10
|
+
DataMapper::Address::PhoneNumber.new(value)
|
11
|
+
else
|
12
|
+
raise ArgumentError.new("+value+ must be nil or a String")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.dump(value, property)
|
17
|
+
return nil if value.nil?
|
18
|
+
value.base
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.typecast(value, property)
|
22
|
+
value.kind_of?(DataMapper::Address::PhoneNumber) ?
|
23
|
+
value :
|
24
|
+
load(value, property)
|
25
|
+
end
|
26
|
+
end # class PhoneNumber
|
27
|
+
end # module Types
|
28
|
+
end # module DataMapper
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Types
|
3
|
+
class ZipCode < DataMapper::Type
|
4
|
+
primitive String
|
5
|
+
|
6
|
+
def self.load(value, property)
|
7
|
+
if value.nil?
|
8
|
+
nil
|
9
|
+
elsif value.is_a?(String)
|
10
|
+
DataMapper::Address::ZipCode.new(value)
|
11
|
+
else
|
12
|
+
raise ArgumentError.new("+value+ must be nil or a String")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.dump(value, property)
|
17
|
+
return nil if value.nil?
|
18
|
+
value.base
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.typecast(value, property)
|
22
|
+
value.kind_of?(DataMapper::Address::ZipCode) ?
|
23
|
+
value :
|
24
|
+
load(value, property)
|
25
|
+
end
|
26
|
+
end # class ZipCode
|
27
|
+
end # module Types
|
28
|
+
end # module DataMapper
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe DataMapper::Address::PhoneNumber do
|
4
|
+
before(:all) do
|
5
|
+
@klass = DataMapper::Address::PhoneNumber
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '.new' do
|
9
|
+
it 'should strip out non-digits' do
|
10
|
+
@klass.new('405-555-5555').should == '4055555555'
|
11
|
+
@klass.new('(405) 555.5556').should == '4055555556'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#base' do
|
16
|
+
it 'should not be formatted (digits only)' do
|
17
|
+
@klass.new('405-555-5555').base.should == '4055555555'
|
18
|
+
@klass.new('(405) 555.5556').base.should == '4055555556'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#to_s' do
|
23
|
+
it 'should return empty String if #phone is blank' do
|
24
|
+
@klass.new('').to_s.should == ''
|
25
|
+
@klass.new(nil).to_s.should == ''
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should format as (###) ###-#### by default' do
|
29
|
+
@klass.new('1234567899').to_s.should == '(123) 456-7899'
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should format based on argument' do
|
33
|
+
@klass.new('1234567899').to_s('(%A)%P-%S').
|
34
|
+
should == '(123)456-7899'
|
35
|
+
@klass.new('1234567899').to_s('%A.%P.%S').
|
36
|
+
should == '123.456.7899'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,224 @@
|
|
1
|
+
require File.join( File.dirname(__FILE__), '..', "spec_helper" )
|
2
|
+
|
3
|
+
DataMapper.setup(:default, 'sqlite3::memory:')
|
4
|
+
require 'dm-timestamps' # Only needed to make #created_at and #updated_at auto-update
|
5
|
+
|
6
|
+
module DataMapper::Address::Spec
|
7
|
+
class US
|
8
|
+
include DataMapper::Resource
|
9
|
+
include DataMapper::Address::US
|
10
|
+
address_properties
|
11
|
+
end
|
12
|
+
|
13
|
+
US.auto_migrate!
|
14
|
+
end
|
15
|
+
|
16
|
+
describe DataMapper::Address::US do
|
17
|
+
before(:each) do
|
18
|
+
@klass = DataMapper::Address::Spec::US
|
19
|
+
|
20
|
+
@attrs = {
|
21
|
+
:name => 'Jane Doe',
|
22
|
+
:company => 'Widgets, Inc.',
|
23
|
+
:street => '123 Lane Ave.',
|
24
|
+
:street_2 => 'Suite A',
|
25
|
+
:city => 'Nowhere',
|
26
|
+
:state => 'OK',
|
27
|
+
:postal_code => '123456789',
|
28
|
+
:country => 'USA',
|
29
|
+
:phone => '1235556789'
|
30
|
+
}
|
31
|
+
|
32
|
+
@address = @klass.new(@attrs)
|
33
|
+
end
|
34
|
+
|
35
|
+
def should_validate(field, *values)
|
36
|
+
values.each do |v|
|
37
|
+
@address.__send__("#{field}=", v)
|
38
|
+
@address.should be_valid
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def should_not_validate(field, *values)
|
43
|
+
values.each do |v|
|
44
|
+
@address.__send__("#{field}=", v)
|
45
|
+
@address.should_not be_valid
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should be valid' do
|
50
|
+
@address.should be_valid
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '#name' do
|
54
|
+
it 'should note be required' do
|
55
|
+
should_validate(:name, '', nil)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#street' do
|
60
|
+
it 'should be required' do
|
61
|
+
should_not_validate(:street, '', nil)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe '#city' do
|
66
|
+
it 'should be required' do
|
67
|
+
should_not_validate(:city, '', nil)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe '#state' do
|
72
|
+
it 'should be required' do
|
73
|
+
should_not_validate(:state, '', nil)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '#postal_code' do
|
78
|
+
it 'should be required' do
|
79
|
+
should_not_validate(:postal_code, '', nil)
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should be 5 or 9 characters' do
|
83
|
+
should_not_validate(:postal_code, '1234', '123456', '12345678', '1234567890')
|
84
|
+
should_not_validate(:postal_code, '12345-678') # would be valid if dashes weren't stripped
|
85
|
+
should_validate(:postal_code, '12345', '123456789', '12345-6789')
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe '#postal_code=' do
|
90
|
+
it 'should strip out non-digits' do
|
91
|
+
@address.postal_code = '12345-6789'
|
92
|
+
@address.postal_code.should == '123456789'
|
93
|
+
@address.postal_code = '(12345 -67s80z'
|
94
|
+
@address.postal_code.should == '123456780'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe '#postal_code.to_s' do
|
99
|
+
it 'should return empty String if #postal_code is blank' do
|
100
|
+
@address.postal_code = ''
|
101
|
+
@address.postal_code.to_s.should == ''
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should format 5-digit code as #####' do
|
105
|
+
@address.postal_code = '12345'
|
106
|
+
@address.postal_code.to_s.should == '12345'
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should format 9-digit code as #####-####' do
|
110
|
+
@address.postal_code = '123456789'
|
111
|
+
@address.postal_code.to_s.should == '12345-6789'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe '#country' do
|
116
|
+
it 'should be required' do
|
117
|
+
should_not_validate(:country, '', nil)
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'should default to USA' do
|
121
|
+
@klass.new.country.should == 'USA'
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe '#phone' do
|
126
|
+
it 'should not be required' do
|
127
|
+
should_validate(:phone, '', nil)
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'should be 10 characters' do
|
131
|
+
should_not_validate(:phone, '123456789', '12345678900')
|
132
|
+
should_not_validate(:phone, '123-456-89')
|
133
|
+
should_validate(:phone, '1234567890')
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe '#phone=' do
|
138
|
+
it 'should strip out non-digits' do
|
139
|
+
@address.phone = '405-555-5555'
|
140
|
+
@address.phone.should == '4055555555'
|
141
|
+
@address.phone = '(405) 555.5556'
|
142
|
+
@address.phone.should == '4055555556'
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
describe '#phone.to_s' do
|
147
|
+
it 'should return empty String if #phone is blank' do
|
148
|
+
@address.phone = ''
|
149
|
+
@address.phone.to_s.should == ''
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'should format as (###) ###-####' do
|
153
|
+
@address.phone = '1234567899'
|
154
|
+
@address.phone.to_s.should == '(123) 456-7899'
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe '#block' do
|
159
|
+
@attrs = {
|
160
|
+
:name => 'Jane Doe',
|
161
|
+
:company => 'Widgets, Inc.',
|
162
|
+
:street => '123 Lane Ave.',
|
163
|
+
:street_2 => 'Suite A',
|
164
|
+
:city => 'Nowhere',
|
165
|
+
:state => 'OK',
|
166
|
+
:postal_code => '12345-6789',
|
167
|
+
:country => 'USA',
|
168
|
+
:phone => '123-555-6789'
|
169
|
+
}
|
170
|
+
|
171
|
+
it 'should return nicely formatted block' do
|
172
|
+
@address.block.should ==
|
173
|
+
"Jane Doe\nWidgets, Inc.\n123 Lane Ave.\nSuite A\n" +
|
174
|
+
"Nowhere, OK 12345-6789"
|
175
|
+
end
|
176
|
+
|
177
|
+
it 'should include optional #company (due to blank)' do
|
178
|
+
@address.company = ''
|
179
|
+
@address.block.should ==
|
180
|
+
"Jane Doe\n123 Lane Ave.\nSuite A\n" +
|
181
|
+
"Nowhere, OK 12345-6789"
|
182
|
+
end
|
183
|
+
|
184
|
+
it 'should include optional #street_2 (due to blank)' do
|
185
|
+
@address.street_2 = ''
|
186
|
+
@address.block.should ==
|
187
|
+
"Jane Doe\nWidgets, Inc.\n123 Lane Ave.\n" +
|
188
|
+
"Nowhere, OK 12345-6789"
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'should optionally leave out #phone (due to blank)' do
|
192
|
+
@address.phone = ''
|
193
|
+
@address.block("\n", false, true).should ==
|
194
|
+
"Jane Doe\nWidgets, Inc.\n123 Lane Ave.\nSuite A\n" +
|
195
|
+
"Nowhere, OK 12345-6789"
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'should optionally add #country (due to argument)' do
|
199
|
+
@address.block("\n", true, false).should ==
|
200
|
+
"Jane Doe\nWidgets, Inc.\n123 Lane Ave.\nSuite A\n" +
|
201
|
+
"Nowhere, OK 12345-6789\nUSA"
|
202
|
+
end
|
203
|
+
|
204
|
+
it 'should optionally add #phone (due to argument)' do
|
205
|
+
@address.block("\n", false, true).should ==
|
206
|
+
"Jane Doe\nWidgets, Inc.\n123 Lane Ave.\nSuite A\n" +
|
207
|
+
"Nowhere, OK 12345-6789\n(123) 555-6789"
|
208
|
+
end
|
209
|
+
|
210
|
+
it 'should accept alternate newline' do
|
211
|
+
@address.block("<br />\n", false, false).should ==
|
212
|
+
"Jane Doe<br />\nWidgets, Inc.<br />\n123 Lane Ave.<br />\nSuite A<br />\n" +
|
213
|
+
"Nowhere, OK 12345-6789"
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
describe '#created_at and #updated_at' do
|
218
|
+
it 'should record timestamps' do
|
219
|
+
@address.save
|
220
|
+
@address.created_at.should be_kind_of(DateTime)
|
221
|
+
@address.updated_at.should be_kind_of(DateTime)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe DataMapper::Address::ZipCode do
|
4
|
+
before(:all) do
|
5
|
+
@klass = DataMapper::Address::ZipCode
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '.new' do
|
9
|
+
it 'should strip out non-digits' do
|
10
|
+
@klass.new('12345-6789').should == '123456789'
|
11
|
+
@klass.new('(12345 -67s80z').should == '123456780'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#base' do
|
16
|
+
it 'should not be formatted (digits only)' do
|
17
|
+
@klass.new('12345-6789').base.should == '123456789'
|
18
|
+
@klass.new('(12345 -67s80z').base.should == '123456780'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#to_s' do
|
23
|
+
it 'should return empty String if #phone is blank' do
|
24
|
+
@klass.new('').to_s.should == ''
|
25
|
+
@klass.new(nil).to_s.should == ''
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should format 5-digit code as #####' do
|
29
|
+
@klass.new('12345').to_s.should == '12345'
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should format based on argument' do
|
33
|
+
@klass.new('123456789').to_s.should == '12345-6789'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
|
3
|
+
describe DataMapper::Address do
|
4
|
+
describe ".config" do
|
5
|
+
before(:each) do
|
6
|
+
# Force to default state
|
7
|
+
DataMapper::Address.instance_variable_set(:@config, nil)
|
8
|
+
end
|
9
|
+
|
10
|
+
after(:all) do
|
11
|
+
# Force to default state for other specs
|
12
|
+
DataMapper::Address.instance_variable_set(:@config, nil)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should initialize with DEFAULTS' do
|
16
|
+
DataMapper::Address.config.should == DataMapper::Address::DEFAULTS
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should be writable' do
|
20
|
+
DataMapper::Address.config[:example] = 1
|
21
|
+
DataMapper::Address.instance_variable_get(:@config)[:example].should == 1
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe DataMapper::Types::PhoneNumber do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@klass = DataMapper::Types::PhoneNumber
|
7
|
+
@phone_str = "(405) 555-1234"
|
8
|
+
@phone_dump = "4055551234"
|
9
|
+
@phone = DataMapper::Address::PhoneNumber.new(@phone_str)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe ".dump" do
|
13
|
+
it "should return the Phone Number as a digits-only string" do
|
14
|
+
@klass.dump(@phone, :property).should == @phone_dump
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should return nil if the string is nil" do
|
18
|
+
@klass.dump(nil, :property).should be_nil
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return an empty String if the Phone Number is empty" do
|
22
|
+
@klass.dump(DataMapper::Address::PhoneNumber.new(''), :property).should == ""
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe ".load" do
|
27
|
+
it "should return the string as PhoneNumber" do
|
28
|
+
@klass.load(@phone_str, :property).should == @phone
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should return nil if given nil" do
|
32
|
+
@klass.load(nil, :property).should be_nil
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should return an empty Phone Number if given an empty string" do
|
36
|
+
@klass.load("", :property).should == DataMapper::Address::PhoneNumber.new('')
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should raise an ArgumentError if given something else' do
|
40
|
+
lambda {
|
41
|
+
@klass.load([], :property)
|
42
|
+
}.should raise_error(ArgumentError, '+value+ must be nil or a String')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '.typecast' do
|
47
|
+
it 'should do nothing if an PhoneNumber is provided' do
|
48
|
+
@klass.typecast(@phone, :property).should == @phone
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should defer to .load if a string is provided' do
|
52
|
+
@klass.should_receive(:load).with(@phone_str, :property)
|
53
|
+
@klass.typecast(@phone_str, :property)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe DataMapper::Types::ZipCode do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@klass = DataMapper::Types::ZipCode
|
7
|
+
@zip_str = "12345-6789"
|
8
|
+
@zip_dump = "123456789"
|
9
|
+
@zip = DataMapper::Address::ZipCode.new(@zip_str)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe ".dump" do
|
13
|
+
it "should return the Zip Number as a digits-only string" do
|
14
|
+
@klass.dump(@zip, :property).should == @zip_dump
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should return nil if the string is nil" do
|
18
|
+
@klass.dump(nil, :property).should be_nil
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return an empty String if the Zip Number is empty" do
|
22
|
+
@klass.dump(DataMapper::Address::ZipCode.new(''), :property).should == ""
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe ".load" do
|
27
|
+
it "should return the string as ZipCode" do
|
28
|
+
@klass.load(@zip_str, :property).should == @zip
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should return nil if given nil" do
|
32
|
+
@klass.load(nil, :property).should be_nil
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should return an empty Zip Code if given an empty string" do
|
36
|
+
@klass.load("", :property).should == DataMapper::Address::ZipCode.new('')
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should raise an ArgumentError if given something else' do
|
40
|
+
lambda {
|
41
|
+
@klass.load([], :property)
|
42
|
+
}.should raise_error(ArgumentError, '+value+ must be nil or a String')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '.typecast' do
|
47
|
+
it 'should do nothing if an ZipCode is provided' do
|
48
|
+
@klass.typecast(@zip, :property).should == @zip
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'should defer to .load if a string is provided' do
|
52
|
+
@klass.should_receive(:load).with(@zip_str, :property)
|
53
|
+
@klass.typecast(@zip_str, :property)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jm81-dm-address
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jared Morgan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-07-17 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: extlib
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: dm-core
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: dm-types
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: dm-validations
|
47
|
+
type: :runtime
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
description:
|
56
|
+
email: jmorgan@morgancreative.net
|
57
|
+
executables: []
|
58
|
+
|
59
|
+
extensions: []
|
60
|
+
|
61
|
+
extra_rdoc_files:
|
62
|
+
- LICENSE
|
63
|
+
- README.rdoc
|
64
|
+
files:
|
65
|
+
- .document
|
66
|
+
- .gitignore
|
67
|
+
- LICENSE
|
68
|
+
- README.rdoc
|
69
|
+
- Rakefile
|
70
|
+
- VERSION
|
71
|
+
- lib/dm-address.rb
|
72
|
+
- lib/dm-address/phone_number.rb
|
73
|
+
- lib/dm-address/us.rb
|
74
|
+
- lib/dm-address/zip_code.rb
|
75
|
+
- lib/dm-types/phone_number.rb
|
76
|
+
- lib/dm-types/zip_code.rb
|
77
|
+
- spec/dm-address/phone_number_spec.rb
|
78
|
+
- spec/dm-address/us_spec.rb
|
79
|
+
- spec/dm-address/zip_code_spec.rb
|
80
|
+
- spec/dm-address_spec.rb
|
81
|
+
- spec/dm-types/phone_number_spec.rb
|
82
|
+
- spec/dm-types/zip_code_spec.rb
|
83
|
+
- spec/spec_helper.rb
|
84
|
+
has_rdoc: false
|
85
|
+
homepage: http://github.com/jm81/dm-address
|
86
|
+
post_install_message:
|
87
|
+
rdoc_options:
|
88
|
+
- --charset=UTF-8
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: "0"
|
96
|
+
version:
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: "0"
|
102
|
+
version:
|
103
|
+
requirements: []
|
104
|
+
|
105
|
+
rubyforge_project:
|
106
|
+
rubygems_version: 1.2.0
|
107
|
+
signing_key:
|
108
|
+
specification_version: 3
|
109
|
+
summary: TODO
|
110
|
+
test_files:
|
111
|
+
- spec/dm-address/phone_number_spec.rb
|
112
|
+
- spec/dm-address/us_spec.rb
|
113
|
+
- spec/dm-address/zip_code_spec.rb
|
114
|
+
- spec/dm-address_spec.rb
|
115
|
+
- spec/dm-types/phone_number_spec.rb
|
116
|
+
- spec/dm-types/zip_code_spec.rb
|
117
|
+
- spec/spec_helper.rb
|