active_hash 0.6.1
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 +6 -0
- data/CHANGELOG +13 -0
- data/LICENSE +20 -0
- data/README.md +202 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/active_hash.gemspec +59 -0
- data/lib/active_file/base.rb +60 -0
- data/lib/active_hash.rb +5 -0
- data/lib/active_hash/base.rb +188 -0
- data/lib/active_yaml/base.rb +16 -0
- data/spec/active_file/base_spec.rb +265 -0
- data/spec/active_hash/base_spec.rb +541 -0
- data/spec/active_yaml/base_spec.rb +20 -0
- data/spec/active_yaml/sample.yml +15 -0
- data/spec/spec_helper.rb +9 -0
- metadata +87 -0
@@ -0,0 +1,265 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe ActiveFile::Base do
|
4
|
+
before do
|
5
|
+
class Country < ActiveFile::Base
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
after do
|
10
|
+
Object.send :remove_const, :Country
|
11
|
+
end
|
12
|
+
|
13
|
+
describe ".reload_active_file" do
|
14
|
+
|
15
|
+
it "returns false by default" do
|
16
|
+
Country.reload_active_file.should be_nil
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
describe ".filename=" do
|
22
|
+
before do
|
23
|
+
Country.filename = "foo-izzle"
|
24
|
+
|
25
|
+
class Bar < ActiveFile::Base
|
26
|
+
self.filename = "bar-izzle"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
it "sets the filename on a per-subclass basis" do
|
31
|
+
Country.filename.should == "foo-izzle"
|
32
|
+
Bar.filename.should == "bar-izzle"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe ".set_filename" do
|
37
|
+
before do
|
38
|
+
Country.set_filename "foo-izzle"
|
39
|
+
|
40
|
+
class Bar < ActiveFile::Base
|
41
|
+
set_filename "bar-izzle"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it "sets the filename on a per-subclass basis" do
|
46
|
+
Country.filename.should == "foo-izzle"
|
47
|
+
Bar.filename.should == "bar-izzle"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe ".root_path=" do
|
52
|
+
before do
|
53
|
+
Country.root_path = "foo-izzle"
|
54
|
+
|
55
|
+
class Bar < ActiveFile::Base
|
56
|
+
self.root_path = "bar-izzle"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
it "sets the root_path on a per-subclass basis" do
|
61
|
+
Country.root_path.should == "foo-izzle"
|
62
|
+
Bar.root_path.should == "bar-izzle"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe ".set_root_path" do
|
67
|
+
before do
|
68
|
+
Country.set_root_path "foo-izzle"
|
69
|
+
|
70
|
+
class Bar < ActiveFile::Base
|
71
|
+
set_root_path "bar-izzle"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
it "sets the root_path on a per-subclass basis" do
|
76
|
+
Country.root_path.should == "foo-izzle"
|
77
|
+
Bar.root_path.should == "bar-izzle"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe ".full_path" do
|
82
|
+
it "defaults to the directory of the calling file" do
|
83
|
+
class Country
|
84
|
+
def self.extension() "foo" end
|
85
|
+
end
|
86
|
+
|
87
|
+
Country.full_path.should == "#{Dir.pwd}/countries.foo"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe ".all" do
|
92
|
+
before do
|
93
|
+
class MyClass
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
it "loads the data from the load_file method" do
|
98
|
+
class Country
|
99
|
+
class << self
|
100
|
+
def extension
|
101
|
+
"myfile"
|
102
|
+
end
|
103
|
+
|
104
|
+
def load_file
|
105
|
+
MyClass.load_file(full_path)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
Country.reload_active_file = true
|
111
|
+
File.stub!(:mtime).and_return(1234)
|
112
|
+
MyClass.should_receive(:load_file).and_return([{:id => 1}, {:id => 2}, {:id => 3}])
|
113
|
+
|
114
|
+
records = Country.all
|
115
|
+
records.length.should == 3
|
116
|
+
records.should =~ [Country.new(:id => 1), Country.new(:id => 2), Country.new(:id => 3)]
|
117
|
+
end
|
118
|
+
|
119
|
+
context "with reload=true" do
|
120
|
+
it "does not re-fetch the data if the file's mtime has not changed" do
|
121
|
+
class Country < ActiveFile::Base
|
122
|
+
class << self
|
123
|
+
def extension
|
124
|
+
"myfile"
|
125
|
+
end
|
126
|
+
|
127
|
+
def load_file
|
128
|
+
MyClass.load_file(full_path)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
Country.reload_active_file = true
|
134
|
+
File.stub!(:mtime).and_return(1234)
|
135
|
+
MyClass.should_receive(:load_file).once.and_return([{:foo => :bar}])
|
136
|
+
Country.all
|
137
|
+
Country.all
|
138
|
+
end
|
139
|
+
|
140
|
+
it "does re-fetch the data if the yaml file's mtime has changed" do
|
141
|
+
class Country < ActiveFile::Base
|
142
|
+
class << self
|
143
|
+
def extension
|
144
|
+
"myfile"
|
145
|
+
end
|
146
|
+
|
147
|
+
def load_file
|
148
|
+
MyClass.load_file(full_path)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
Country.reload_active_file = true
|
154
|
+
MyClass.should_receive(:load_file).twice.and_return([{:foo => :bar}])
|
155
|
+
|
156
|
+
File.stub!(:mtime).and_return(1234)
|
157
|
+
Country.all
|
158
|
+
|
159
|
+
File.stub!(:mtime).and_return(3456)
|
160
|
+
Country.all
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
context "with reload=false" do
|
165
|
+
it "does not re-fetch the data after the first call to .all" do
|
166
|
+
class Country < ActiveFile::Base
|
167
|
+
class << self
|
168
|
+
def extension
|
169
|
+
"myfile"
|
170
|
+
end
|
171
|
+
|
172
|
+
def load_file
|
173
|
+
MyClass.load_file(full_path)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
File.stub!(:mtime).once.and_return(1234)
|
179
|
+
MyClass.should_receive(:load_file).once.and_return([{:foo => :bar}])
|
180
|
+
Country.all
|
181
|
+
|
182
|
+
Country.all
|
183
|
+
end
|
184
|
+
|
185
|
+
it "does not re-fetch the data if the yaml file's mtime has changed" do
|
186
|
+
class Country < ActiveFile::Base
|
187
|
+
class << self
|
188
|
+
def extension
|
189
|
+
"myfile"
|
190
|
+
end
|
191
|
+
|
192
|
+
def load_file
|
193
|
+
MyClass.load_file(full_path)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
MyClass.should_receive(:load_file).once.and_return([{:foo => :bar}])
|
199
|
+
|
200
|
+
File.stub!(:mtime).and_return(1234)
|
201
|
+
Country.all
|
202
|
+
|
203
|
+
File.stub!(:mtime).and_return(3456)
|
204
|
+
Country.all
|
205
|
+
end
|
206
|
+
|
207
|
+
it "does not fetch data if data has been set to non-nil" do
|
208
|
+
class Country < ActiveFile::Base
|
209
|
+
class << self
|
210
|
+
def extension
|
211
|
+
"myfile"
|
212
|
+
end
|
213
|
+
|
214
|
+
def load_file
|
215
|
+
MyClass.load_file(full_path)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
MyClass.should_not_receive(:load_file)
|
221
|
+
Country.data = [{:foo => :bar}]
|
222
|
+
Country.all
|
223
|
+
end
|
224
|
+
|
225
|
+
it "does not fetch data if data has been set to nil" do
|
226
|
+
class Country < ActiveFile::Base
|
227
|
+
class << self
|
228
|
+
def extension
|
229
|
+
"myfile"
|
230
|
+
end
|
231
|
+
|
232
|
+
def load_file
|
233
|
+
MyClass.load_file(full_path)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
MyClass.should_not_receive(:load_file)
|
239
|
+
Country.data = nil
|
240
|
+
Country.all
|
241
|
+
end
|
242
|
+
|
243
|
+
it "does re-fetch data if force is true" do
|
244
|
+
class Country < ActiveFile::Base
|
245
|
+
class << self
|
246
|
+
def extension
|
247
|
+
"myfile"
|
248
|
+
end
|
249
|
+
|
250
|
+
def load_file
|
251
|
+
MyClass.load_file(full_path)
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
MyClass.should_receive(:load_file).once.and_return([{:foo => :bar}])
|
257
|
+
Country.data = nil
|
258
|
+
Country.reload(true)
|
259
|
+
Country.all.first.foo.should == :bar
|
260
|
+
end
|
261
|
+
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
end
|
@@ -0,0 +1,541 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe ActiveHash, "Base" do
|
4
|
+
|
5
|
+
before do
|
6
|
+
class Country < ActiveHash::Base
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
after do
|
11
|
+
Object.send :remove_const, :Country
|
12
|
+
end
|
13
|
+
|
14
|
+
describe ".fields" do
|
15
|
+
before do
|
16
|
+
Country.fields :name, :iso_name
|
17
|
+
end
|
18
|
+
|
19
|
+
it "defines a reader for each field" do
|
20
|
+
Country.new.should respond_to(:name)
|
21
|
+
Country.new.should respond_to(:iso_name)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "defines interrogator methods for each field" do
|
25
|
+
Country.new.should respond_to(:name?)
|
26
|
+
Country.new.should respond_to(:iso_name?)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "defines single finder methods for each field" do
|
30
|
+
Country.should respond_to(:find_by_name)
|
31
|
+
Country.should respond_to(:find_by_iso_name)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "defines array finder methods for each field" do
|
35
|
+
Country.should respond_to(:find_all_by_name)
|
36
|
+
Country.should respond_to(:find_all_by_iso_name)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "defines single finder methods for all combinations of fields" do
|
40
|
+
Country.should respond_to(:find_by_name_and_iso_name)
|
41
|
+
Country.should respond_to(:find_by_iso_name_and_name)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "defines array finder methods for all combinations of fields" do
|
45
|
+
Country.should respond_to(:find_all_by_name_and_iso_name)
|
46
|
+
Country.should respond_to(:find_all_by_iso_name_and_name)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe ".data=" do
|
51
|
+
before do
|
52
|
+
class Region < ActiveHash::Base
|
53
|
+
field :description
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
it "populates the object with data" do
|
58
|
+
Country.data = [{:name => "US"}, {:name => "Canada"}]
|
59
|
+
Country.data.should == [{:name => "US"}, {:name => "Canada"}]
|
60
|
+
end
|
61
|
+
|
62
|
+
it "allows each of it's subclasses to have it's own data" do
|
63
|
+
Country.data = [{:name => "US"}, {:name => "Canada"}]
|
64
|
+
Region.data = [{:description => "A big region"}, {:description => "A remote region"}]
|
65
|
+
|
66
|
+
Country.data.should == [{:name => "US"}, {:name => "Canada"}]
|
67
|
+
Region.data.should == [{:description => "A big region"}, {:description => "A remote region"}]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe ".all" do
|
72
|
+
before do
|
73
|
+
Country.field :name
|
74
|
+
Country.data = [
|
75
|
+
{:id => 1, :name => "US"},
|
76
|
+
{:id => 2, :name => "Canada"}
|
77
|
+
]
|
78
|
+
end
|
79
|
+
|
80
|
+
it "returns an empty array if data is nil" do
|
81
|
+
Country.data = nil
|
82
|
+
Country.all.should be_empty
|
83
|
+
end
|
84
|
+
|
85
|
+
it "returns all data as inflated objects" do
|
86
|
+
Country.all.all?{|country| country.should be_kind_of(Country)}
|
87
|
+
end
|
88
|
+
|
89
|
+
it "populates the data correctly" do
|
90
|
+
records = Country.all
|
91
|
+
records.first.id.should == 1
|
92
|
+
records.first.name.should == "US"
|
93
|
+
records.last.id.should == 2
|
94
|
+
records.last.name.should == "Canada"
|
95
|
+
end
|
96
|
+
|
97
|
+
it "re-populates the records after data= is called" do
|
98
|
+
Country.data = [
|
99
|
+
{:id => 45, :name => "Canada"}
|
100
|
+
]
|
101
|
+
records = Country.all
|
102
|
+
records.first.id.should == 45
|
103
|
+
records.first.name.should == "Canada"
|
104
|
+
records.length.should == 1
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe ".count" do
|
109
|
+
before do
|
110
|
+
Country.data = [
|
111
|
+
{:id => 1, :name => "US"},
|
112
|
+
{:id => 2, :name => "Canada"}
|
113
|
+
]
|
114
|
+
end
|
115
|
+
|
116
|
+
it "returns the number of elements in the array" do
|
117
|
+
Country.count.should == 2
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe ".first" do
|
122
|
+
before do
|
123
|
+
Country.data = [
|
124
|
+
{:id => 1, :name => "US"},
|
125
|
+
{:id => 2, :name => "Canada"}
|
126
|
+
]
|
127
|
+
end
|
128
|
+
|
129
|
+
it "returns the first object" do
|
130
|
+
Country.first.should == Country.new(:id => 1)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe ".last" do
|
135
|
+
before do
|
136
|
+
Country.data = [
|
137
|
+
{:id => 1, :name => "US"},
|
138
|
+
{:id => 2, :name => "Canada"}
|
139
|
+
]
|
140
|
+
end
|
141
|
+
|
142
|
+
it "returns the last object" do
|
143
|
+
Country.last.should == Country.new(:id => 2)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe ".find" do
|
148
|
+
before do
|
149
|
+
Country.data = [
|
150
|
+
{:id => 1, :name => "US"},
|
151
|
+
{:id => 2, :name => "Canada"}
|
152
|
+
]
|
153
|
+
end
|
154
|
+
|
155
|
+
context "with an id" do
|
156
|
+
it "finds the record with the specified id" do
|
157
|
+
Country.find(2).id.should == 2
|
158
|
+
end
|
159
|
+
|
160
|
+
it "finds the record with the specified id as a string" do
|
161
|
+
Country.find("2").id.should == 2
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
context "with :all" do
|
166
|
+
it "returns all records" do
|
167
|
+
Country.find(:all).should =~ [Country.new(:id => 1), Country.new(:id => 2)]
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
context "with 2 arguments" do
|
172
|
+
it "returns the record with the given id and ignores the conditions" do
|
173
|
+
Country.find(1, :conditions => "foo=bar").should == Country.new(:id => 1)
|
174
|
+
Country.find(:all, :conditions => "foo=bar").length.should == 2
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
context "with an array of ids" do
|
179
|
+
before do
|
180
|
+
Country.data = [
|
181
|
+
{:id => 1},
|
182
|
+
{:id => 2},
|
183
|
+
{:id => 3}
|
184
|
+
]
|
185
|
+
end
|
186
|
+
|
187
|
+
it "returns all matching ids" do
|
188
|
+
Country.find([1,3]).should =~ [Country.new(:id => 1), Country.new(:id => 3)]
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe ".find_by_id" do
|
194
|
+
before do
|
195
|
+
Country.data = [
|
196
|
+
{:id => 1, :name => "US"},
|
197
|
+
{:id => 2, :name => "Canada"}
|
198
|
+
]
|
199
|
+
end
|
200
|
+
|
201
|
+
context "with an id" do
|
202
|
+
it "finds the record with the specified id" do
|
203
|
+
Country.find_by_id(2).id.should == 2
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
context "with nil" do
|
208
|
+
it "returns nil" do
|
209
|
+
Country.find_by_id(nil).should be_nil
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
context "with an id not present" do
|
214
|
+
it "returns nil" do
|
215
|
+
Country.find_by_id(4567).should be_nil
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe "custom finders" do
|
221
|
+
before do
|
222
|
+
Country.fields :name, :monarch, :language
|
223
|
+
|
224
|
+
# Start ids above 4 lest we get nil and think it's an AH::Base model with id=4.
|
225
|
+
Country.data = [
|
226
|
+
{:id => 11, :name => nil, :monarch => nil, :language => "Latin"},
|
227
|
+
{:id => 12, :name => "US", :monarch => nil, :language => "English"},
|
228
|
+
{:id => 13, :name => "Canada", :monarch => "The Crown of England", :language => "English"},
|
229
|
+
{:id => 14, :name => "UK", :monarch => "The Crown of England", :language => "English"}
|
230
|
+
]
|
231
|
+
end
|
232
|
+
|
233
|
+
describe "find_by_<field_name>" do
|
234
|
+
describe "with a match" do
|
235
|
+
context "for a non-nil argument" do
|
236
|
+
it "returns the first matching record" do
|
237
|
+
Country.find_by_name("US").id.should == 12
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
context "for a nil argument" do
|
242
|
+
it "returns the first matching record" do
|
243
|
+
Country.find_by_name(nil).id.should == 11
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
describe "without a match" do
|
249
|
+
before do
|
250
|
+
Country.data = []
|
251
|
+
end
|
252
|
+
|
253
|
+
context "for a non-nil argument" do
|
254
|
+
it "returns nil" do
|
255
|
+
Country.find_by_name("Mexico").should be_nil
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
context "for a nil argument" do
|
260
|
+
it "returns nil" do
|
261
|
+
Country.find_by_name(nil).should be_nil
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
describe "find_all_by_<field_name>" do
|
268
|
+
describe "with matches" do
|
269
|
+
it "returns all matching records" do
|
270
|
+
countries = Country.find_all_by_monarch("The Crown of England")
|
271
|
+
countries.length.should == 2
|
272
|
+
countries.first.name.should == "Canada"
|
273
|
+
countries.last.name.should == "UK"
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
describe "without matches" do
|
278
|
+
it "returns an empty array" do
|
279
|
+
Country.find_all_by_name("Mexico").should be_empty
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
describe "find_by_<field_one>_and_<field_two>" do
|
285
|
+
describe "with a match" do
|
286
|
+
it "returns the first matching record" do
|
287
|
+
Country.find_by_name_and_monarch("Canada", "The Crown of England").id.should == 13
|
288
|
+
Country.find_by_monarch_and_name("The Crown of England", "Canada").id.should == 13
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
describe "without a match" do
|
293
|
+
it "returns nil" do
|
294
|
+
Country.find_by_name_and_monarch("US", "The Crown of England").should be_nil
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
describe "for fields the class doesn't have" do
|
299
|
+
it "raises a NoMethodError" do
|
300
|
+
lambda {
|
301
|
+
Country.find_by_name_and_shoe_size("US", 10)
|
302
|
+
}.should raise_error(NoMethodError, "undefined method `find_by_name_and_shoe_size' for Country:Class")
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
describe "find_all_by_<field_one>_and_<field_two>" do
|
308
|
+
describe "with matches" do
|
309
|
+
it "returns all matching records" do
|
310
|
+
countries = Country.find_all_by_monarch_and_language("The Crown of England", "English")
|
311
|
+
countries.length.should == 2
|
312
|
+
countries.first.name.should == "Canada"
|
313
|
+
countries.last.name.should == "UK"
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
describe "without matches" do
|
318
|
+
it "returns an empty array" do
|
319
|
+
Country.find_all_by_monarch_and_language("Shaka Zulu", "Zulu").should be_empty
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
|
326
|
+
describe "#attributes" do
|
327
|
+
it "returns the hash passed in the initializer" do
|
328
|
+
country = Country.new(:foo => :bar)
|
329
|
+
country.attributes.should == {:foo => :bar}
|
330
|
+
end
|
331
|
+
|
332
|
+
it "symbolizes keys" do
|
333
|
+
country = Country.new("foo" => :bar)
|
334
|
+
country.attributes.should == {:foo => :bar}
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
describe "reader methods" do
|
339
|
+
context "for regular fields" do
|
340
|
+
before do
|
341
|
+
Country.fields :name, :iso_name
|
342
|
+
end
|
343
|
+
|
344
|
+
it "returns the given attribute when present" do
|
345
|
+
country = Country.new(:name => "Spain")
|
346
|
+
country.name.should == "Spain"
|
347
|
+
end
|
348
|
+
|
349
|
+
it "returns nil when not present" do
|
350
|
+
country = Country.new
|
351
|
+
country.name.should be_nil
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
context "for fields with default values" do
|
356
|
+
before do
|
357
|
+
Country.field :name, :default => "foobar"
|
358
|
+
end
|
359
|
+
|
360
|
+
it "returns the given attribute when present" do
|
361
|
+
country = Country.new(:name => "Spain")
|
362
|
+
country.name.should == "Spain"
|
363
|
+
end
|
364
|
+
|
365
|
+
it "returns the default value when not present" do
|
366
|
+
country = Country.new
|
367
|
+
country.name.should == "foobar"
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
describe "interrogator methods" do
|
373
|
+
before do
|
374
|
+
Country.fields :name, :iso_name
|
375
|
+
end
|
376
|
+
|
377
|
+
it "returns true if the given attribute is non-blank" do
|
378
|
+
country = Country.new(:name => "Spain")
|
379
|
+
country.should be_name
|
380
|
+
end
|
381
|
+
|
382
|
+
it "returns false if the given attribute is blank" do
|
383
|
+
country = Country.new(:name => " ")
|
384
|
+
country.should_not be_name
|
385
|
+
end
|
386
|
+
|
387
|
+
it "returns false if the given attribute was not passed" do
|
388
|
+
country = Country.new
|
389
|
+
country.should_not be_name
|
390
|
+
end
|
391
|
+
end
|
392
|
+
|
393
|
+
describe "#id" do
|
394
|
+
context "when passed an id" do
|
395
|
+
it "returns the id as an integer" do
|
396
|
+
country = Country.new :id => "1"
|
397
|
+
country.id.should == 1
|
398
|
+
end
|
399
|
+
end
|
400
|
+
context "when not passed an id" do
|
401
|
+
it "returns nil" do
|
402
|
+
country = Country.new
|
403
|
+
country.id.should be_nil
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
407
|
+
|
408
|
+
describe "#new_record?" do
|
409
|
+
it "should be false" do
|
410
|
+
Country.new.should_not be_new_record
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
414
|
+
describe "#quoted_id" do
|
415
|
+
it "should return id" do
|
416
|
+
Country.new(:id => 2).quoted_id.should == 2
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
describe "#to_param" do
|
421
|
+
it "should return id as a string" do
|
422
|
+
Country.new(:id => 2).to_param.should == "2"
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
describe "#eql?" do
|
427
|
+
before do
|
428
|
+
class Region < ActiveHash::Base
|
429
|
+
end
|
430
|
+
end
|
431
|
+
|
432
|
+
it "should return true with the same class and id" do
|
433
|
+
Country.new(:id => 23).eql?(Country.new(:id => 23)).should be_true
|
434
|
+
end
|
435
|
+
|
436
|
+
it "should return false with the same class and different ids" do
|
437
|
+
Country.new(:id => 24).eql?(Country.new(:id => 23)).should be_false
|
438
|
+
end
|
439
|
+
|
440
|
+
it "should return false with the different classes and the same id" do
|
441
|
+
Country.new(:id => 23).eql?(Region.new(:id => 23)).should be_false
|
442
|
+
end
|
443
|
+
|
444
|
+
it "returns false when id is nil" do
|
445
|
+
Country.new.eql?(Country.new).should be_false
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
describe "#==" do
|
450
|
+
before do
|
451
|
+
class Region < ActiveHash::Base
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
it "should return true with the same class and id" do
|
456
|
+
Country.new(:id => 23).should == Country.new(:id => 23)
|
457
|
+
end
|
458
|
+
|
459
|
+
it "should return false with the same class and different ids" do
|
460
|
+
Country.new(:id => 24).should_not == Country.new(:id => 23)
|
461
|
+
end
|
462
|
+
|
463
|
+
it "should return false with the different classes and the same id" do
|
464
|
+
Country.new(:id => 23).should_not == Region.new(:id => 23)
|
465
|
+
end
|
466
|
+
|
467
|
+
it "returns false when id is nil" do
|
468
|
+
Country.new.should_not == Country.new
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
describe "#hash" do
|
473
|
+
it "returns id for hash" do
|
474
|
+
Country.new(:id => 45).hash.should == 45.hash
|
475
|
+
Country.new.hash.should == nil.hash
|
476
|
+
end
|
477
|
+
|
478
|
+
it "is hashable" do
|
479
|
+
{ Country.new(:id => 4) => "bar"}.should == {Country.new(:id => 4) => "bar" }
|
480
|
+
{ Country.new(:id => 3) => "bar"}.should_not == {Country.new(:id => 4) => "bar" }
|
481
|
+
end
|
482
|
+
end
|
483
|
+
|
484
|
+
describe "#readonly?" do
|
485
|
+
it "returns true" do
|
486
|
+
Country.new.should be_readonly
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
describe "auto-discovery of fields" do
|
491
|
+
it "dynamically creates fields for all keys in the hash" do
|
492
|
+
Country.data = [
|
493
|
+
{:field1 => "foo"},
|
494
|
+
{:field2 => "bar"},
|
495
|
+
{:field3 => "biz"}
|
496
|
+
]
|
497
|
+
|
498
|
+
Country.all
|
499
|
+
|
500
|
+
[:field1, :field2, :field3].each do |field|
|
501
|
+
Country.should respond_to("find_by_#{field}")
|
502
|
+
Country.should respond_to("find_all_by_#{field}")
|
503
|
+
Country.new.should respond_to(field)
|
504
|
+
Country.new.should respond_to("#{field}?")
|
505
|
+
end
|
506
|
+
end
|
507
|
+
|
508
|
+
it "doesn't override methods already defined" do
|
509
|
+
Country.class_eval do
|
510
|
+
class << self
|
511
|
+
def find_by_name(name)
|
512
|
+
"find_by_name defined manually"
|
513
|
+
end
|
514
|
+
|
515
|
+
def find_all_by_name(name)
|
516
|
+
"find_all_by_name defined manually"
|
517
|
+
end
|
518
|
+
end
|
519
|
+
|
520
|
+
def name
|
521
|
+
"name defined manually"
|
522
|
+
end
|
523
|
+
|
524
|
+
def name?
|
525
|
+
"name? defined manually"
|
526
|
+
end
|
527
|
+
end
|
528
|
+
|
529
|
+
Country.data = [
|
530
|
+
{:name => "foo"}
|
531
|
+
]
|
532
|
+
|
533
|
+
Country.all
|
534
|
+
Country.find_by_name("foo").should == "find_by_name defined manually"
|
535
|
+
Country.find_all_by_name("foo").should == "find_all_by_name defined manually"
|
536
|
+
Country.new.name.should == "name defined manually"
|
537
|
+
Country.new.name?.should == "name? defined manually"
|
538
|
+
end
|
539
|
+
end
|
540
|
+
|
541
|
+
end
|