dm-types 1.1.0 → 1.2.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/dm-types/yaml.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'yaml'
2
2
  require 'dm-core'
3
+ require 'dm-types/support/dirty_minder'
3
4
 
4
5
  module DataMapper
5
6
  class Property
@@ -15,7 +16,7 @@ module DataMapper
15
16
  elsif value.is_a?(::String)
16
17
  ::YAML.load(value)
17
18
  else
18
- raise ArgumentError.new("+value+ of a property of YAML type must be nil or a String")
19
+ raise ArgumentError, '+value+ of a property of YAML type must be nil or a String'
19
20
  end
20
21
  end
21
22
 
@@ -33,6 +34,8 @@ module DataMapper
33
34
  value
34
35
  end
35
36
 
37
+ include ::DataMapper::Property::DirtyMinder
38
+
36
39
  end # class Yaml
37
40
  end # class Property
38
41
  end # module DataMapper
@@ -0,0 +1,14 @@
1
+ module DataMapper
2
+ module TypesFixtures
3
+ class APIUser
4
+
5
+ include DataMapper::Resource
6
+
7
+ property :id, Serial
8
+
9
+ property :name, String
10
+
11
+ property :api_key, APIKey
12
+ end
13
+ end
14
+ end
@@ -15,6 +15,7 @@ module DataMapper
15
15
  property :name, String
16
16
  property :positions, Json
17
17
  property :inventions, Yaml
18
+ property :birthday, EpochTime
18
19
 
19
20
  property :interests, CommaSeparatedList
20
21
 
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ try_spec do
4
+ require './spec/fixtures/api_user'
5
+
6
+ describe DataMapper::TypesFixtures::APIUser do
7
+ supported_by :all do
8
+ subject { described_class.new(:name => 'alice') }
9
+
10
+ let(:original_api_key) { subject.api_key }
11
+
12
+ it "should have a default value" do
13
+ original_api_key.should_not be_nil
14
+ end
15
+
16
+ it "should preserve the default value" do
17
+ subject.api_key.should == original_api_key
18
+ end
19
+
20
+ it "should generate unique API Keys for each resource" do
21
+ other_resource = described_class.new(:name => 'eve')
22
+
23
+ other_resource.api_key.should_not == original_api_key
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,197 @@
1
+ require 'spec_helper'
2
+
3
+ try_spec do
4
+
5
+ # FIXME: DirtyMinder is currently unsupported on RBX, because unlike the other
6
+ # supported Rubies, RBX core class (e.g. Array, Hash) methods use #send(). In
7
+ # other words, the other Rubies don't use #send() (they map directly to their
8
+ # C functions).
9
+ #
10
+ # The current methodology takes advantage of this by using #send() to forward
11
+ # method invocations we've hooked. Supporting RBX will require finding
12
+ # another way, possibly for all Rubies. In the meantime, something is better
13
+ # than nothing.
14
+ next if defined?(RUBY_ENGINE) and RUBY_ENGINE == 'rbx'
15
+
16
+ require './spec/fixtures/person'
17
+
18
+ describe DataMapper::TypesFixtures::Person do
19
+ supported_by :all do
20
+ before :all do
21
+ @resource = DataMapper::TypesFixtures::Person.new(:name => 'Thomas Edison')
22
+ end
23
+
24
+ describe 'with positions indirectly mutated as a hash' do
25
+ before :all do
26
+ @resource.positions = {
27
+ 'company' => "Soon To Be Dirty, LLC",
28
+ 'title' => "Layperson",
29
+ 'details' => { 'awesome' => true },
30
+ }
31
+ @resource.save
32
+ @resource.reload
33
+ @resource.positions['title'].should == 'Layperson'
34
+ end
35
+
36
+ describe "when I change positions" do
37
+ before :all do
38
+ @resource.clean?.should == true
39
+ @resource.positions['title'] = 'Chief Layer of People'
40
+ @resource.save
41
+ @resource.reload
42
+ end
43
+
44
+ it "should remember the new position" do
45
+ @resource.positions['title'].should == 'Chief Layer of People'
46
+ end
47
+ end
48
+
49
+ describe "when I add a new attribute of the position" do
50
+ before :all do
51
+ @resource.clean?.should == true
52
+ @resource.positions['pays_buttloads_of_money'] = true
53
+ @resource.save
54
+ @resource.reload
55
+ end
56
+
57
+ it "should remember the new attribute" do
58
+ @resource.positions['pays_buttloads_of_money'].should be(true)
59
+ end
60
+ end
61
+
62
+ describe "when I change the details of the position" do
63
+ before :all do
64
+ @resource.clean?.should == true
65
+ @resource.positions['details'].merge!('awesome' => "VERY TRUE")
66
+ @resource.save
67
+ @resource.reload
68
+ end
69
+
70
+ it "should remember the changed detail" do
71
+ pending "not supported (YET)" do
72
+ # TODO: Not supported (yet?) -- this is a much harder problem to
73
+ # solve: using mutating accessors of nested objects. We could
74
+ # detect it from #dirty? (using the #hash method), but #dirty?
75
+ # only returns the status of known-mutated properties (not full,
76
+ # on-demand scan of object dirty-ness).
77
+ @resource.positions['details']['awesome'].should == 'VERY TRUE'
78
+ end
79
+ end
80
+ end
81
+
82
+ describe "when I reload the resource while the property is dirty" do
83
+ before :all do
84
+ @resource.positions['title'] = 'Chief Layer of People'
85
+ @resource.reload
86
+ end
87
+
88
+ it "should reflect the previously set/persisted value" do
89
+ @resource.positions.should_not be_nil
90
+ @resource.positions['title'].should == 'Layperson'
91
+ end
92
+ end
93
+
94
+ end # positions indirectly mutated as a hash
95
+
96
+ describe 'with positions indirectly mutated as an array' do
97
+ before :all do
98
+ @resource.positions = [
99
+ { 'company' => "Soon To Be Dirty, LLC",
100
+ 'title' => "Layperson",
101
+ 'details' => { 'awesome' => true },
102
+ },
103
+ ]
104
+ @resource.save
105
+ @resource.reload
106
+ @resource.positions.first['title'].should == 'Layperson'
107
+ end
108
+
109
+ describe "when I remove the position" do
110
+ before :all do
111
+ @resource.clean?.should == true
112
+ @resource.positions.pop
113
+ @resource.save
114
+ @resource.reload
115
+ end
116
+
117
+ it "should know there aren't any positions" do
118
+ @resource.positions.should == []
119
+ end
120
+ end
121
+
122
+ describe "when I add a new position" do
123
+ before :all do
124
+ @resource.clean?.should == true
125
+ @resource.positions << {
126
+ 'company' => "Down and Dirty, LP",
127
+ 'title' => "Porn Star",
128
+ 'details' => { 'awesome' => "also true" },
129
+ }
130
+ @resource.save
131
+ @resource.reload
132
+ end
133
+
134
+ it "should know there's two positions" do
135
+ @resource.positions.length.should == 2
136
+ end
137
+
138
+ it "should know which position is which" do
139
+ @resource.positions.first['title'].should == "Layperson"
140
+ @resource.positions.last['title'].should == "Porn Star"
141
+ end
142
+
143
+ describe "when I change the details of one of the positions" do
144
+ before :all do
145
+ @resource.positions.last['details'].merge!('high_risk' => true)
146
+ @resource.save
147
+ @resource.reload
148
+ end
149
+
150
+ it "should remember the changed detail" do
151
+ pending "not supported (YET)" do
152
+ # TODO: Not supported (yet?) -- this is a much harder problem to
153
+ # solve: using mutating accessors of nested objects. We could
154
+ # detect it from #dirty? (using the #hash method), but #dirty?
155
+ # only returns the status of known-mutated properties (not full,
156
+ # on-demand scan of object dirty-ness).
157
+ @resource.positions.last['details']['high_risk'].should == true
158
+ end
159
+ end
160
+ end
161
+ end # when I add a new position
162
+
163
+ describe "when I remove the position with a block-based mutator" do
164
+ before :all do
165
+ @resource.clean?.should == true
166
+ @resource.positions.reject! { |_| true }
167
+ @resource.save
168
+ @resource.reload
169
+ end
170
+
171
+ it "should know there aren't any positions" do
172
+ @resource.positions.should == []
173
+ end
174
+ end
175
+
176
+ describe "when I mutate positions through a reference" do
177
+ before :all do
178
+ @resource.clean?.should == true
179
+ @positions = @resource.positions
180
+ @positions << {
181
+ 'company' => "Ooga Booga, Inc",
182
+ 'title' => "Rocker",
183
+ }
184
+ end
185
+
186
+ it "should reflect the change in both the property and the reference" do
187
+ @resource.positions.length.should == 2
188
+ @resource.positions.last['title'].should == 'Rocker'
189
+ @positions.last['title'].should == 'Rocker'
190
+ end
191
+ end
192
+
193
+ end # positions indirectly mutated as an array
194
+
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ try_spec do
4
+
5
+ require './spec/fixtures/person'
6
+
7
+ describe DataMapper::TypesFixtures::Person do
8
+ supported_by :all do
9
+ before :all do
10
+ @resource = DataMapper::TypesFixtures::Person.new(:name => '')
11
+ end
12
+
13
+ describe 'with a birthday' do
14
+ before :all do
15
+ @resource.birthday = '1983-05-03'
16
+ end
17
+
18
+ describe 'after typecasting string input' do
19
+ it 'has a valid birthday' do
20
+ @resource.birthday.should == ::Time.parse('1983-05-03')
21
+ end
22
+ end
23
+
24
+ describe 'when dumped and loaded again' do
25
+ before :all do
26
+ @resource.save.should be(true)
27
+ @resource.reload
28
+ end
29
+
30
+ it 'has a valid birthday' do
31
+ @resource.birthday.should == ::Time.parse('1983-05-03')
32
+ end
33
+ end
34
+ end
35
+
36
+ describe 'without a birthday' do
37
+ before :all do
38
+ @resource.birthday = nil
39
+ end
40
+
41
+ describe 'after typecasting nil' do
42
+ it 'has a nil value for birthday' do
43
+ @resource.birthday.should be_nil
44
+ end
45
+ end
46
+
47
+ describe 'when dumped and loaded again' do
48
+ before :all do
49
+ @resource.save.should be(true)
50
+ @resource.reload
51
+ end
52
+
53
+ it 'has a nil value for birthday' do
54
+ @resource.birthday.should be_nil
55
+ end
56
+ end
57
+ end
58
+
59
+ end
60
+ end
61
+ end
@@ -1,15 +1,11 @@
1
1
  require 'spec_helper'
2
2
 
3
- Spec::Matchers.define :run_ipv4 do |model|
4
- match do |model|
5
- model.runs_ipv4?
6
- end
3
+ Spec::Matchers.define :run_ipv4 do
4
+ match { |model| model.runs_ipv4? }
7
5
  end
8
6
 
9
- Spec::Matchers.define :run_ipv6 do |model|
10
- match do |model|
11
- model.runs_ipv6?
12
- end
7
+ Spec::Matchers.define :run_ipv6 do
8
+ match { |model| model.runs_ipv6? }
13
9
  end
14
10
 
15
11
  try_spec do
@@ -66,6 +66,7 @@ try_spec do
66
66
  end
67
67
  end
68
68
  end
69
+
69
70
  end
70
71
  end
71
72
  end
@@ -25,35 +25,39 @@ try_spec do
25
25
  end
26
26
  end
27
27
 
28
- [
29
- ['Iñtërnâtiônàlizætiøn', 'internationalizaetion' ],
30
- ["This is Dan's Blog", 'this-is-dans-blog'],
31
- ['This is My Site, and Blog', 'this-is-my-site-and-blog'],
32
- ['Google searches for holy grail of Python performance', 'google-searches-for-holy-grail-of-python-performance'],
33
- ['iPhone dev: Creating length-controlled data sources', 'iphone-dev-creating-length-controlled-data-sources'],
34
- ["Review: Nintendo's New DSi -- A Quantum Leap Forward", 'review-nintendos-new-dsi-a-quantum-leap-forward'],
35
- ["Arriva BraiVe, è l'auto-robot che si 'guida' da sola'", 'arriva-braive-e-lauto-robot-che-si-guida-da-sola'],
36
- ["La ley antipiratería reduce un 33% el tráfico online en Suecia", 'la-ley-antipirateria-reduce-un-33-percent-el-trafico-online-en-suecia'],
37
- ["L'Etat américain du Texas s'apprête à interdire Windows Vista", 'letat-americain-du-texas-sapprete-a-interdire-windows-vista']
38
- ].each do |title, slug|
39
- describe "set with title '#{title}'" do
40
- before :all do
41
- @resource = DataMapper::TypesFixtures::Article.new(:title => title)
42
- @resource.valid?.should be(true)
43
- end
44
-
45
- it "has slug equal to '#{slug}'" do
46
- @resource.slug.should == slug
47
- end
48
-
49
- describe "and persisted" do
28
+ # FIXME: when stringex fixes the problems it has with it's YAML
29
+ # files not being parsable by psych remove this conditional.
30
+ unless RUBY_PLATFORM =~ /java/ && JRUBY_VERSION >= '1.6' && RUBY_VERSION >= '1.9.2'
31
+ [
32
+ [ 'Iñtërnâtiônàlizætiøn', 'internationalizaetion' ],
33
+ [ "This is Dan's Blog", 'this-is-dans-blog' ],
34
+ [ 'This is My Site, and Blog', 'this-is-my-site-and-blog' ],
35
+ [ 'Google searches for holy grail of Python performance', 'google-searches-for-holy-grail-of-python-performance' ],
36
+ [ 'iPhone dev: Creating length-controlled data sources', 'iphone-dev-creating-length-controlled-data-sources' ],
37
+ [ "Review: Nintendo's New DSi -- A Quantum Leap Forward", 'review-nintendos-new-dsi-a-quantum-leap-forward' ],
38
+ [ "Arriva BraiVe, è l'auto-robot che si 'guida' da sola'", 'arriva-braive-e-lauto-robot-che-si-guida-da-sola' ],
39
+ [ "La ley antipiratería reduce un 33% el tráfico online en Suecia", 'la-ley-antipirateria-reduce-un-33-percent-el-trafico-online-en-suecia' ],
40
+ [ "L'Etat américain du Texas s'apprête à interdire Windows Vista", 'letat-americain-du-texas-sapprete-a-interdire-windows-vista' ],
41
+ ].each do |title, slug|
42
+ describe "set with title '#{title}'" do
50
43
  before :all do
51
- @resource.save.should be(true)
52
- @resource.reload
44
+ @resource = DataMapper::TypesFixtures::Article.new(:title => title)
45
+ @resource.valid?.should be(true)
53
46
  end
54
47
 
55
- it 'can be found by slug' do
56
- DataMapper::TypesFixtures::Article.first(:slug => slug).should == @resource
48
+ it "has slug equal to '#{slug}'" do
49
+ @resource.slug.should == slug
50
+ end
51
+
52
+ describe "and persisted" do
53
+ before :all do
54
+ @resource.save.should be(true)
55
+ @resource.reload
56
+ end
57
+
58
+ it 'can be found by slug' do
59
+ DataMapper::TypesFixtures::Article.first(:slug => slug).should == @resource
60
+ end
57
61
  end
58
62
  end
59
63
  end
@@ -21,22 +21,38 @@ describe DataMapper::Property::EpochTime do
21
21
  it { should == value.to_i }
22
22
  end
23
23
 
24
+ describe 'with nil' do
25
+ let(:value) { nil }
26
+
27
+ it { should == value }
28
+ end
29
+ end
30
+
31
+ describe '#typecast' do
32
+ subject { @property.typecast(value) }
33
+
24
34
  describe 'with a DateTime instance' do
25
35
  let(:value) { DateTime.now }
26
36
 
27
- it { should == Time.parse(value.to_s).to_i }
37
+ it { should == Time.parse(value.to_s) }
28
38
  end
29
39
 
30
40
  describe 'with a number' do
31
41
  let(:value) { Time.now.to_i }
32
42
 
33
- it { should == value }
43
+ it { should == ::Time.at(value) }
34
44
  end
35
45
 
36
- describe 'with nil' do
37
- let(:value) { nil }
46
+ describe 'with a numeric string' do
47
+ let(:value) { Time.now.to_i.to_s }
38
48
 
39
- it { should == value }
49
+ it { should == ::Time.at(value.to_i) }
50
+ end
51
+
52
+ describe 'with a DateTime string' do
53
+ let(:value) { '2011-07-11 15:00:04 UTC' }
54
+
55
+ it { should == ::Time.parse(value) }
40
56
  end
41
57
  end
42
58