dm-types 0.9.11 → 0.10.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 (59) hide show
  1. data/{History.txt → History.rdoc} +5 -4
  2. data/LICENSE +16 -14
  3. data/Manifest.txt +13 -3
  4. data/{README.txt → README.rdoc} +0 -0
  5. data/Rakefile +3 -4
  6. data/TODO +74 -0
  7. data/lib/dm-types.rb +15 -18
  8. data/lib/dm-types/bcrypt_hash.rb +1 -4
  9. data/lib/dm-types/comma_separated_list.rb +31 -0
  10. data/lib/dm-types/csv.rb +12 -18
  11. data/lib/dm-types/enum.rb +18 -15
  12. data/lib/dm-types/epoch_time.rb +6 -11
  13. data/lib/dm-types/file_path.rb +5 -4
  14. data/lib/dm-types/flag.rb +14 -13
  15. data/lib/dm-types/ip_address.rb +1 -0
  16. data/lib/dm-types/json.rb +5 -11
  17. data/lib/dm-types/regexp.rb +2 -3
  18. data/lib/dm-types/slug.rb +8 -17
  19. data/lib/dm-types/uri.rb +8 -14
  20. data/lib/dm-types/uuid.rb +9 -15
  21. data/lib/dm-types/version.rb +1 -1
  22. data/lib/dm-types/yaml.rb +4 -3
  23. data/spec/fixtures/article.rb +39 -0
  24. data/spec/fixtures/bookmark.rb +27 -0
  25. data/spec/fixtures/invention.rb +9 -0
  26. data/spec/fixtures/network_node.rb +40 -0
  27. data/spec/fixtures/person.rb +29 -0
  28. data/spec/fixtures/software_package.rb +37 -0
  29. data/spec/fixtures/ticket.rb +25 -0
  30. data/spec/fixtures/tshirt.rb +28 -0
  31. data/spec/integration/bcrypt_hash_spec.rb +37 -55
  32. data/spec/integration/comma_separated_list_spec.rb +89 -0
  33. data/spec/integration/enum_spec.rb +62 -42
  34. data/spec/integration/file_path_spec.rb +149 -17
  35. data/spec/integration/flag_spec.rb +56 -25
  36. data/spec/integration/ip_address_spec.rb +142 -17
  37. data/spec/integration/json_spec.rb +60 -17
  38. data/spec/integration/slug_spec.rb +39 -40
  39. data/spec/integration/uri_spec.rb +126 -21
  40. data/spec/integration/uuid_spec.rb +84 -30
  41. data/spec/integration/yaml_spec.rb +55 -25
  42. data/spec/shared/identity_function_group.rb +5 -0
  43. data/spec/spec.opts +1 -0
  44. data/spec/spec_helper.rb +49 -17
  45. data/spec/unit/bcrypt_hash_spec.rb +107 -64
  46. data/spec/unit/csv_spec.rb +111 -27
  47. data/spec/unit/enum_spec.rb +128 -87
  48. data/spec/unit/epoch_time_spec.rb +57 -32
  49. data/spec/unit/file_path_spec.rb +55 -34
  50. data/spec/unit/flag_spec.rb +102 -65
  51. data/spec/unit/ip_address_spec.rb +90 -40
  52. data/spec/unit/json_spec.rb +108 -41
  53. data/spec/unit/regexp_spec.rb +47 -17
  54. data/spec/unit/uri_spec.rb +57 -46
  55. data/spec/unit/yaml_spec.rb +91 -45
  56. data/tasks/install.rb +1 -1
  57. data/tasks/spec.rb +4 -4
  58. metadata +25 -32
  59. data/lib/dm-types/serial.rb +0 -8
@@ -1,46 +1,100 @@
1
- require 'pathname'
2
- require Pathname(__FILE__).dirname.parent.expand_path + 'spec_helper'
3
-
4
- begin
5
- gem 'uuidtools', '~>1.0.7'
6
- require 'uuidtools'
7
- rescue LoadError
8
- skip_tests = true
9
- end
1
+ require 'spec_helper'
2
+
3
+ try_spec do
4
+
5
+ require 'spec/fixtures/network_node'
6
+
7
+ describe DataMapper::Types::Fixtures::NetworkNode do
8
+ describe 'with UUID set as UUID object' do
9
+ before :all do
10
+ @uuid_string = 'b0fc632e-d744-4821-afe3-4ea0701859ee'
11
+ @uuid = UUIDTools::UUID.parse(@uuid_string)
12
+ @resource = DataMapper::Types::Fixtures::NetworkNode.new(:uuid => @uuid)
13
+
14
+ @resource.save.should be_true
15
+ end
16
+
17
+ describe 'when reloaded' do
18
+ before :all do
19
+ @resource.reload
20
+ end
21
+
22
+ it 'has the same UUID string' do
23
+ @resource.uuid.to_s.should == @uuid_string
24
+ end
10
25
 
11
- describe 'DataMapper::Types::UUID' do
12
- unless skip_tests
13
- before(:all) do
14
- class UUIDTest
15
- include DataMapper::Resource
26
+ it 'returns UUID as an object' do
27
+ @resource.uuid.should be_an_instance_of(UUIDTools::UUID)
28
+ end
29
+ end
30
+ end
16
31
 
17
- property :id, Serial
18
- property :uuid, ::DataMapper::Types::UUID
32
+ describe 'with UUID set as a valid UUID string' do
33
+ before :all do
34
+ @uuid = 'b0fc632e-d744-4821-afe3-4ea0701859ee'
35
+ @resource = DataMapper::Types::Fixtures::NetworkNode.new(:uuid => @uuid)
19
36
  end
20
37
 
21
- UUIDTest.auto_migrate!
38
+ describe 'when reloaded' do
39
+ before :all do
40
+ @resource.reload
41
+ end
42
+
43
+ it 'has the same UUID string' do
44
+ @resource.uuid.to_s.should == @uuid
45
+ end
46
+
47
+ it 'returns UUID as an object' do
48
+ @resource.uuid.should be_an_instance_of(UUIDTools::UUID)
49
+ end
50
+ end
22
51
  end
23
52
 
24
- it "should be settable as a uuid" do
25
- u = UUIDTest.create(:uuid => UUID.parse('b0fc632e-d744-4821-afe3-4ea0701859ee'))
53
+ describe 'with UUID set as invalid UUID string' do
54
+ before :all do
55
+ @uuid = 'meh'
56
+ @operation = lambda do
57
+ DataMapper::Types::Fixtures::NetworkNode.new(:uuid => @uuid)
58
+ end
59
+ end
26
60
 
27
- u.uuid.should be_kind_of(UUID)
28
- u.uuid.to_s.should == 'b0fc632e-d744-4821-afe3-4ea0701859ee'
61
+ describe 'when assigned UUID' do
62
+ it 'raises ArgumentError' do
63
+ @operation.should raise_error(ArgumentError, /Invalid UUID format/)
64
+ end
65
+ end
29
66
  end
30
67
 
31
- it "should be settable as a string" do
32
- u = UUIDTest.create(:uuid => 'b0fc632e-d744-4821-afe3-4ea0701859ee')
68
+ describe 'with UUID set as a blank string' do
69
+ before :all do
70
+ @uuid = ''
71
+ @operation = lambda do
72
+ DataMapper::Types::Fixtures::NetworkNode.new(:uuid => @uuid)
73
+ end
74
+ end
33
75
 
34
- u.uuid.should be_kind_of(UUID)
35
- u.uuid.to_s.should == 'b0fc632e-d744-4821-afe3-4ea0701859ee'
76
+ describe 'when assigned UUID' do
77
+ it 'raises ArgumentError' do
78
+ @operation.should raise_error(ArgumentError, /Invalid UUID format/)
79
+ end
80
+ end
36
81
  end
37
82
 
38
- it "should be allowed to be null" do
39
- u = UUIDTest.create()
83
+ describe 'with missing UUID' do
84
+ before :all do
85
+ @uuid = nil
86
+ @resource = DataMapper::Types::Fixtures::NetworkNode.new(:uuid => @uuid)
87
+ end
40
88
 
41
- u.uuid.should be_nil
89
+ describe 'when reloaded' do
90
+ before :all do
91
+ @resource.reload
92
+ end
93
+
94
+ it 'has no UUID' do
95
+ @resource.uuid.should be_nil
96
+ end
97
+ end
42
98
  end
43
- else
44
- it 'requires the uuidtools gem to test'
45
99
  end
46
100
  end
@@ -1,37 +1,67 @@
1
- require 'pathname'
2
- require Pathname(__FILE__).dirname.parent.expand_path + 'spec_helper'
1
+ require 'spec_helper'
3
2
 
4
- describe DataMapper::Types::Enum do
5
- before(:all) do
6
- class ::YamlTest
7
- include DataMapper::Resource
3
+ try_spec do
8
4
 
9
- property :id, Serial
10
- property :yaml, Yaml
5
+ require 'spec/fixtures/person'
6
+ require 'spec/fixtures/invention'
7
+
8
+ describe DataMapper::Types::Fixtures::Person do
9
+ before :all do
10
+ @resource = DataMapper::Types::Fixtures::Person.new(:name => '')
11
11
  end
12
- YamlTest.auto_migrate!
13
12
 
14
- class ::SerializeMe
15
- attr_accessor :name
13
+ describe 'with no inventions information' do
14
+ before :all do
15
+ @resource.inventions = nil
16
+ end
17
+
18
+ describe 'when dumped and loaded again' do
19
+ before :all do
20
+ @resource.save.should be_true
21
+ @resource.reload
22
+ end
23
+
24
+ it 'has nil inventions list' do
25
+ @resource.inventions.should be_nil
26
+ end
27
+ end
16
28
  end
17
- end
18
29
 
19
- it "should work" do
20
- obj = SerializeMe.new
21
- obj.name = 'Hello!'
30
+ describe 'with a few items on the inventions list' do
31
+ before :all do
32
+ @input = [ 'carbon telephone transmitter', 'light bulb', 'electric grid' ].map do |name|
33
+ DataMapper::Types::Fixtures::Invention.new(name)
34
+ end
35
+ @resource.inventions = @input
36
+ end
22
37
 
23
- repository(:default) do
24
- YamlTest.create(:yaml => [1, 2, 3])
25
- YamlTest.create(:yaml => obj)
38
+ describe 'when dumped and loaded again' do
39
+ before :all do
40
+ @resource.save.should be_true
41
+ @resource.reload
42
+ end
43
+
44
+ it 'loads inventions list to the state when it was dumped/persisted with keys being strings' do
45
+ @resource.inventions.should == @input
46
+ end
47
+ end
26
48
  end
27
49
 
28
- tests = YamlTest.all
29
- tests.first.yaml.should == [1, 2, 3]
30
- tests.last.yaml.should be_kind_of(SerializeMe)
31
- tests.last.yaml.name.should == 'Hello!'
32
- end
50
+ describe 'with inventions information given as empty list' do
51
+ before :all do
52
+ @resource.inventions = []
53
+ end
33
54
 
34
- it 'should immediately typecast supplied values' do
35
- YamlTest.new(:yaml => [1, 2, 3]).yaml.should == [1, 2, 3]
55
+ describe 'when dumped and loaded again' do
56
+ before :all do
57
+ @resource.save.should be_true
58
+ @resource.reload
59
+ end
60
+
61
+ it 'has empty inventions list' do
62
+ @resource.inventions.should == []
63
+ end
64
+ end
65
+ end
36
66
  end
37
67
  end
@@ -0,0 +1,5 @@
1
+ describe "identity function", :shared => true do
2
+ it "returns value unchanged" do
3
+ @result.should == @input
4
+ end
5
+ end
data/spec/spec.opts CHANGED
@@ -1 +1,2 @@
1
1
  --colour
2
+ --loadby random
data/spec/spec_helper.rb CHANGED
@@ -1,31 +1,63 @@
1
- require 'pathname'
2
1
  require 'rubygems'
3
2
 
4
- gem 'rspec', '~>1.2'
5
- require 'spec'
3
+ # TODO: autovalidation hooks are needed badly,
4
+ # otherwise plugin devs will have to abuse
5
+ # alising and load order even further and it kinda makes
6
+ # me sad -- MK
6
7
 
7
- require Pathname(__FILE__).dirname.parent.expand_path + 'lib/dm-types'
8
+ # use local dm-core if running from a typical dev checkout.
9
+ lib = File.join('..', '..', 'dm-core', 'lib')
10
+ $LOAD_PATH.unshift(lib) if File.directory?(lib)
11
+ require 'dm-core'
8
12
 
9
- ENV["SQLITE3_SPEC_URI"] ||= 'sqlite3::memory:'
10
- ENV["MYSQL_SPEC_URI"] ||= 'mysql://localhost/dm_core_test'
11
- ENV["POSTGRES_SPEC_URI"] ||= 'postgres://postgres@localhost/dm_more_test'
13
+ # use local dm-validations if running from a typical dev checkout.
14
+ lib = File.join('..', 'dm-validations', 'lib')
15
+ $LOAD_PATH.unshift(lib) if File.directory?(lib)
16
+ require 'dm-validations'
12
17
 
13
- # DataMapper::Logger.new(STDOUT, :debug)
18
+ # Support running specs with 'rake spec' and 'spec'
19
+ $LOAD_PATH.unshift('lib') unless $LOAD_PATH.include?('lib')
20
+
21
+ require 'dm-types'
22
+
23
+ def load_driver(name, default_uri)
24
+ return false if ENV['ADAPTER'] != name.to_s
14
25
 
15
- def setup_adapter(name, default_uri = nil)
16
26
  begin
17
- DataMapper.setup(name, ENV["#{ENV['ADAPTER'].to_s.upcase}_SPEC_URI"] || default_uri)
18
- Object.const_set('ADAPTER', ENV['ADAPTER'].to_sym) if name.to_s == ENV['ADAPTER']
27
+ DataMapper.setup(name, ENV["#{name.to_s.upcase}_SPEC_URI"] || default_uri)
28
+ DataMapper::Repository.adapters[:default] = DataMapper::Repository.adapters[name]
19
29
  true
20
- rescue Exception => e
21
- if name.to_s == ENV['ADAPTER']
22
- Object.const_set('ADAPTER', nil)
23
- warn "Could not load do_#{name}: #{e}"
24
- end
30
+ rescue LoadError => e
31
+ warn "Could not load do_#{name}: #{e}"
25
32
  false
26
33
  end
27
34
  end
28
35
 
29
36
  ENV['ADAPTER'] ||= 'sqlite3'
30
37
 
31
- setup_adapter(:default)
38
+ HAS_SQLITE3 = load_driver(:sqlite3, 'sqlite3::memory:')
39
+ HAS_MYSQL = load_driver(:mysql, 'mysql://localhost/dm_core_test')
40
+ HAS_POSTGRES = load_driver(:postgres, 'postgres://postgres@localhost/dm_core_test')
41
+
42
+
43
+ DEPENDENCIES = {
44
+ 'bcrypt' => 'bcrypt-ruby',
45
+ 'fastercsv' => 'fastercsv',
46
+ 'json' => 'json',
47
+ 'stringex' => 'stringex',
48
+ 'uuidtools' => 'uuidtools',
49
+ }
50
+
51
+ def try_spec
52
+ begin
53
+ yield
54
+ rescue NameError
55
+ # do nothing
56
+ rescue LoadError => error
57
+ raise error unless lib = error.message.match(/\Ano such file to load -- (.+)\z/)[1]
58
+
59
+ gem_location = DEPENDENCIES[lib] || raise("Unknown lib #{lib}")
60
+
61
+ warn "[WARNING] Skipping specs using #{lib}, please do: gem install #{gem_location}"
62
+ end
63
+ end
@@ -1,104 +1,147 @@
1
- require 'pathname'
2
- require Pathname(__FILE__).dirname.parent.expand_path + 'spec_helper'
1
+ require 'spec_helper'
3
2
 
4
- include DataMapper::Types
5
-
6
- begin
7
- gem 'bcrypt-ruby', '~>2.0.5'
8
- require 'bcrypt'
9
- rescue LoadError
10
- skip_tests = true
11
- end
12
-
13
- describe "DataMapper::Types::BCryptHash" do
14
- unless skip_tests
15
-
16
- before(:each) do
17
- @clear_password = "DataMapper R0cks!"
3
+ try_spec do
4
+ describe DataMapper::Types::BCryptHash do
5
+ before :all do
6
+ @clear_password = 'DataMapper R0cks!'
18
7
  @crypted_password = BCrypt::Password.create(@clear_password)
8
+
19
9
  @nonstandard_type = 1
20
10
 
21
11
  class TestType
22
12
  @a = 1
23
- @b = "Hi There"
13
+ @b = 'Hi There'
24
14
  end
25
15
  @nonstandard_type2 = TestType.new
26
16
  end
27
17
 
28
- describe ".dump" do
29
- it "should return a crypted hash as a BCrypt::Password" do
30
- BCryptHash.dump(@clear_password, :property).should be_an_instance_of(BCrypt::Password)
31
- end
18
+ describe '.dump' do
19
+ describe 'when argument is a string' do
20
+ before :all do
21
+ @input = 'DataMapper'
22
+ @result = DataMapper::Types::BCryptHash.dump(@input, :property)
23
+ end
24
+
25
+ it 'returns instance of BCrypt::Password' do
26
+ @result.should be_an_instance_of(BCrypt::Password)
27
+ end
32
28
 
33
- it "should return a string that is 60 characters long" do
34
- BCryptHash.dump(@clear_password, :property).to_s.should have(60).characters
29
+ it 'returns a string that is 60 characters long' do
30
+ @result.should have(60).characters
31
+ end
35
32
  end
36
33
 
37
- it "should return nil if nil is passed" do
38
- BCryptHash.dump(nil, :property).should be_nil
34
+ describe 'when argument is nil' do
35
+ before :all do
36
+ @input = nil
37
+ @result = DataMapper::Types::BCryptHash.dump(@input, :property)
38
+ end
39
+
40
+ it 'returns nil' do
41
+ @result.should be_nil
42
+ end
39
43
  end
40
44
  end
41
45
 
42
- describe ".load" do
43
- it "should return the password as a BCrypt::Password" do
44
- BCryptHash.load(@crypted_password, :property).should be_an_instance_of(BCrypt::Password)
45
- end
46
+ describe '.load' do
47
+ describe 'when argument is a string' do
48
+ before :all do
49
+ @input = 'DataMapper'
50
+ @result = DataMapper::Types::BCryptHash.load(@crypted_password, :property)
51
+ end
52
+
53
+ it 'returns instance of BCrypt::Password' do
54
+ @result.should be_an_instance_of(BCrypt::Password)
55
+ end
46
56
 
47
- it "should return the password as a password which matches" do
48
- BCryptHash.load(@crypted_password, :property).should == @clear_password
57
+ it 'returns a string that matches original' do
58
+ @result.should == @clear_password
59
+ end
49
60
  end
50
61
 
51
- it "should return nil if given nil" do
52
- BCryptHash.load(nil, :property).should be_nil
62
+ describe 'when argument is nil' do
63
+ before :all do
64
+ @input = nil
65
+ @result = DataMapper::Types::BCryptHash.load(@input, :property)
66
+ end
67
+
68
+ it 'returns nil' do
69
+ @result.should be_nil
70
+ end
53
71
  end
54
72
  end
55
73
 
56
- describe ".typecast" do
57
- it "should return the crypted_password as a BCrypt::Password" do
58
- BCryptHash.typecast(@crypted_password, :property).should be_an_instance_of(BCrypt::Password)
59
- end
74
+ describe '.typecast' do
75
+ describe 'when argument is a string' do
76
+ before :all do
77
+ @input = 'bcrypt hash'
78
+ @result = DataMapper::Types::BCryptHash.typecast(@input, :property)
79
+ end
60
80
 
61
- it "should match the password as a BCrypt::Password" do
62
- BCryptHash.typecast(@crypted_password, :property).should == @clear_password
63
- end
81
+ it 'casts argument to BCrypt::Password' do
82
+ @result.should be_an_instance_of(BCrypt::Password)
83
+ end
64
84
 
65
- it "should return the string value of crypted_password as a BCrypt::Password" do
66
- BCryptHash.typecast(@crypted_password.to_s, :property).should be_an_instance_of(BCrypt::Password)
85
+ it 'casts argument to value that matches input' do
86
+ @result.should == @input
87
+ end
67
88
  end
68
89
 
69
- it "should match the password as a string of the crypted_password" do
70
- BCryptHash.typecast(@crypted_password.to_s, :property).should == @clear_password
71
- end
90
+ describe 'when argument is a blank string' do
91
+ before :all do
92
+ @input = ''
93
+ @result = DataMapper::Types::BCryptHash.typecast(@input, :property)
94
+ end
72
95
 
73
- it "should return the password as a BCrypt::Password" do
74
- BCryptHash.typecast(@clear_password, :property).should be_an_instance_of(BCrypt::Password)
75
- end
96
+ it 'casts argument to BCrypt::Password' do
97
+ @result.should be_an_instance_of(BCrypt::Password)
98
+ end
76
99
 
77
- it "should match the password as clear_password" do
78
- BCryptHash.typecast(@clear_password, :property).should == @clear_password
100
+ it 'casts argument to value that matches input' do
101
+ @result.should == @input
102
+ end
79
103
  end
80
104
 
81
- it "should encrypt any type that has to_s" do
82
- BCryptHash.typecast(@nonstandard_type, :property).should be_an_instance_of(BCrypt::Password)
83
- end
105
+ describe 'when argument is integer' do
106
+ before :all do
107
+ @input = 2249
108
+ @result = DataMapper::Types::BCryptHash.typecast(@input, :property)
109
+ end
84
110
 
85
- it "should match the non-standard type" do
86
- BCryptHash.typecast(@nonstandard_type, :property).should == @nonstandard_type
87
- end
111
+ it 'casts argument to BCrypt::Password' do
112
+ @result.should be_an_instance_of(BCrypt::Password)
113
+ end
88
114
 
89
- it "should encrypt anything passed to it" do
90
- BCryptHash.typecast(@nonstandard_type2, :property).should be_an_instance_of(BCrypt::Password)
115
+ it 'casts argument to value that matches input' do
116
+ @result.should == @input
117
+ end
91
118
  end
92
119
 
93
- it "should match user-defined types" do
94
- BCryptHash.typecast(@nonstandard_type2, :property).should == @nonstandard_type2
120
+ describe 'when argument is hash' do
121
+ before :all do
122
+ @input = { :cryptic => 'obscure' }
123
+ @result = DataMapper::Types::BCryptHash.typecast(@input, :property)
124
+ end
125
+
126
+ it 'casts argument to BCrypt::Password' do
127
+ @result.should be_an_instance_of(BCrypt::Password)
128
+ end
129
+
130
+ it 'casts argument to value that matches input' do
131
+ @result.should == @input
132
+ end
95
133
  end
96
134
 
97
- it "should return nil if given nil" do
98
- BCryptHash.typecast(nil, :property).should be_nil
135
+ describe 'when argument is nil' do
136
+ before :all do
137
+ @input = nil
138
+ @result = DataMapper::Types::BCryptHash.typecast(@input, :property)
139
+ end
140
+
141
+ it 'returns nil' do
142
+ @result.should be_nil
143
+ end
99
144
  end
100
145
  end
101
- else
102
- it "requires the bcrypt-ruby gem to test"
103
146
  end
104
147
  end