active_nomad 0.2.2 → 0.2.3
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/CHANGELOG +7 -0
- data/lib/active_nomad/version.rb +1 -1
- data/lib/active_nomad.rb +20 -15
- data/spec/unit/active_nomad_spec.rb +86 -41
- metadata +4 -4
data/CHANGELOG
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
== 0.2.3 2010-10-12
|
2
|
+
|
3
|
+
* #inspect no longer requires a database connection.
|
4
|
+
* ActiveRecord::Base.default_timezone support.
|
5
|
+
* Dirty attribute tracking works.
|
6
|
+
* Undeclared attributes are preserved when roundtripped through ActiveNomad.
|
7
|
+
|
1
8
|
== 0.2.2 2010-10-07
|
2
9
|
|
3
10
|
* Support custom destruction strategies.
|
data/lib/active_nomad/version.rb
CHANGED
data/lib/active_nomad.rb
CHANGED
@@ -26,25 +26,23 @@ module ActiveNomad
|
|
26
26
|
def to_serialized_attributes
|
27
27
|
attributes = ActiveSupport::OrderedHash.new
|
28
28
|
columns = self.class.columns_hash
|
29
|
-
|
30
|
-
column = columns[name]
|
31
|
-
|
32
|
-
attributes[name] = serialize_value(send(name), column.type)
|
29
|
+
@attributes.sort.each do |name, value|
|
30
|
+
column = columns[name]
|
31
|
+
attributes[name] = serialize_value(send(name), column ? column.type : :string)
|
33
32
|
end
|
34
33
|
attributes
|
35
34
|
end
|
36
35
|
|
37
36
|
#
|
38
|
-
# Recreate an object from
|
37
|
+
# Recreate an object from the serialized attributes returned by
|
38
|
+
# #to_serialized_attributes.
|
39
39
|
#
|
40
|
-
def self.from_serialized_attributes(
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
next
|
45
|
-
instance.send "#{column.name}=", deserialize_value(serialized_value, column.type)
|
40
|
+
def self.from_serialized_attributes(serialized_attributes)
|
41
|
+
serialized_attributes = serialized_attributes.dup
|
42
|
+
columns_hash.each do |name, column|
|
43
|
+
serialized_attributes[name] ||= column.default
|
46
44
|
end
|
47
|
-
|
45
|
+
instantiate(serialized_attributes)
|
48
46
|
end
|
49
47
|
|
50
48
|
#
|
@@ -65,9 +63,10 @@ module ActiveNomad
|
|
65
63
|
#
|
66
64
|
def self.from_query_string(string)
|
67
65
|
return new if string.blank?
|
68
|
-
serialized_attributes =
|
66
|
+
serialized_attributes = {}
|
67
|
+
string.strip.split(/&/).map do |pair|
|
69
68
|
name, value = pair.split(/=/, 2)
|
70
|
-
[CGI.unescape(name)
|
69
|
+
serialized_attributes[CGI.unescape(name)] = CGI.unescape(value)
|
71
70
|
end
|
72
71
|
from_serialized_attributes(serialized_attributes)
|
73
72
|
end
|
@@ -170,6 +169,10 @@ module ActiveNomad
|
|
170
169
|
def transaction
|
171
170
|
yield
|
172
171
|
end
|
172
|
+
|
173
|
+
def inspect
|
174
|
+
(n = name).blank? ? '(anonymous)' : n
|
175
|
+
end
|
173
176
|
end
|
174
177
|
|
175
178
|
@columns = []
|
@@ -185,6 +188,7 @@ module ActiveNomad
|
|
185
188
|
case type
|
186
189
|
when :datetime, :timestamp, :time
|
187
190
|
# The day in RFC 2822 is optional - chop it.
|
191
|
+
value = ActiveRecord::Base.default_timezone == :utc ? value.utc : value.in_time_zone(Time.zone)
|
188
192
|
value.rfc2822.sub(/\A[A-Za-z]{3}, /, '')
|
189
193
|
when :date
|
190
194
|
value.to_date.strftime(DATE_FORMAT)
|
@@ -197,7 +201,8 @@ module ActiveNomad
|
|
197
201
|
return nil if string.nil?
|
198
202
|
case type
|
199
203
|
when :datetime, :timestamp, :time
|
200
|
-
Time.parse(string)
|
204
|
+
value = Time.parse(string).in_time_zone
|
205
|
+
ActiveRecord::Base.default_timezone == :utc ? value.utc : value.in_time_zone(Time.zone)
|
201
206
|
when :date
|
202
207
|
Date.parse(string)
|
203
208
|
else
|
@@ -1,6 +1,12 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe ActiveNomad::Base do
|
4
|
+
before do
|
5
|
+
Time.zone = -5
|
6
|
+
ActiveRecord::Base.default_timezone = :utc
|
7
|
+
ActiveRecord::Base.time_zone_aware_attributes = true
|
8
|
+
end
|
9
|
+
|
4
10
|
describe ".attribute" do
|
5
11
|
it "should create a column with the given name and type" do
|
6
12
|
klass = Class.new(ActiveNomad::Base) do
|
@@ -148,7 +154,7 @@ describe ActiveNomad::Base do
|
|
148
154
|
end
|
149
155
|
|
150
156
|
describe "#to_serialized_attributes" do
|
151
|
-
it "should return
|
157
|
+
it "should return an ordered hash of attribute names with serialized attributes, sorted by name" do
|
152
158
|
klass = Class.new(ActiveNomad::Base) do
|
153
159
|
attribute :integer_attribute, :integer
|
154
160
|
attribute :string_attribute, :string
|
@@ -169,15 +175,15 @@ describe ActiveNomad::Base do
|
|
169
175
|
:text_attribute => 'text',
|
170
176
|
:float_attribute => 1.23,
|
171
177
|
:decimal_attribute => BigDecimal.new('123.45'),
|
172
|
-
:datetime_attribute => Time.parse('03 Feb 2001
|
173
|
-
:timestamp_attribute => Time.parse('03 Feb 2001
|
174
|
-
:time_attribute => Time.parse('03 Feb 2001
|
178
|
+
:datetime_attribute => Time.parse('03 Feb 2001 7:34:56 -500'),
|
179
|
+
:timestamp_attribute => Time.parse('03 Feb 2001 7:34:56 -500'),
|
180
|
+
:time_attribute => Time.parse('03 Feb 2001 7:34:56 -500'),
|
175
181
|
:date_attribute => Date.parse('03 Feb 2001'),
|
176
182
|
:binary_attribute => "\0\1",
|
177
183
|
:boolean_attribute => true,
|
178
184
|
:nil_attribute => nil
|
179
185
|
)
|
180
|
-
instance.to_serialized_attributes.
|
186
|
+
instance.to_serialized_attributes.should == ActiveSupport::OrderedHash[[
|
181
187
|
['binary_attribute', "\0\1"],
|
182
188
|
['boolean_attribute', 'true'],
|
183
189
|
['date_attribute', '03 Feb 2001'],
|
@@ -190,7 +196,7 @@ describe ActiveNomad::Base do
|
|
190
196
|
['text_attribute', 'text'],
|
191
197
|
['time_attribute', '03 Feb 2001 12:34:56 -0000'],
|
192
198
|
['timestamp_attribute', '03 Feb 2001 12:34:56 -0000'],
|
193
|
-
]
|
199
|
+
]]
|
194
200
|
end
|
195
201
|
end
|
196
202
|
|
@@ -210,49 +216,34 @@ describe ActiveNomad::Base do
|
|
210
216
|
attribute :boolean_attribute, :boolean
|
211
217
|
attribute :nil_attribute, :boolean
|
212
218
|
end
|
213
|
-
instance = klass.from_serialized_attributes([
|
214
|
-
[
|
215
|
-
[
|
216
|
-
[
|
217
|
-
[
|
218
|
-
[
|
219
|
-
[
|
220
|
-
[
|
221
|
-
[
|
222
|
-
[
|
223
|
-
[
|
224
|
-
[
|
225
|
-
[
|
226
|
-
])
|
219
|
+
instance = klass.from_serialized_attributes(ActiveSupport::OrderedHash[[
|
220
|
+
['integer_attribute', '5'],
|
221
|
+
['string_attribute', 'string'],
|
222
|
+
['text_attribute', 'text'],
|
223
|
+
['float_attribute', '1.23'],
|
224
|
+
['decimal_attribute', '123.45'],
|
225
|
+
['datetime_attribute', '03 Feb 2001 12:34:56 -0000'],
|
226
|
+
['timestamp_attribute', '03 Feb 2001 12:34:56 -0000'],
|
227
|
+
['time_attribute', '03 Feb 2001 12:34:56 -0000'],
|
228
|
+
['date_attribute', '03 Feb 2001'],
|
229
|
+
['binary_attribute', "\0\1"],
|
230
|
+
['boolean_attribute', 'true'],
|
231
|
+
['nil_attribute', nil],
|
232
|
+
]])
|
227
233
|
instance.integer_attribute.should == 5
|
228
234
|
instance.string_attribute.should == 'string'
|
229
235
|
instance.text_attribute.should == 'text'
|
230
236
|
instance.float_attribute.should == 1.23
|
231
237
|
instance.decimal_attribute.should == BigDecimal.new('123.45')
|
232
|
-
instance.datetime_attribute.should == Time.parse('03 Feb 2001
|
233
|
-
instance.timestamp_attribute.should == Time.parse('03 Feb 2001
|
234
|
-
instance.time_attribute.should == Time.parse('03 Feb 2001 12:34:56 -0000')
|
238
|
+
instance.datetime_attribute.should == Time.parse('03 Feb 2001 7:34:56 -500').in_time_zone
|
239
|
+
instance.timestamp_attribute.should == Time.parse('03 Feb 2001 7:34:56 -500').in_time_zone
|
240
|
+
instance.time_attribute.should == Time.parse('03 Feb 2001 12:34:56 -0000').in_time_zone
|
235
241
|
instance.date_attribute.should == Date.parse('03 Feb 2001')
|
236
242
|
instance.binary_attribute.should == "\0\1"
|
237
243
|
instance.boolean_attribute.should be_true
|
238
244
|
instance.nil_attribute.should be_nil
|
239
245
|
end
|
240
246
|
|
241
|
-
it "should work with any enumerable" do
|
242
|
-
klass = Class.new(ActiveNomad::Base) do
|
243
|
-
attribute :name, :string
|
244
|
-
end
|
245
|
-
params = Object.new
|
246
|
-
class << params
|
247
|
-
def each
|
248
|
-
yield :name, 'joe'
|
249
|
-
end
|
250
|
-
end
|
251
|
-
params.extend Enumerable
|
252
|
-
instance = klass.from_serialized_attributes(params)
|
253
|
-
instance.name.should == 'joe'
|
254
|
-
end
|
255
|
-
|
256
247
|
it "should leave defaults alone for attributes which are not set" do
|
257
248
|
klass = Class.new(ActiveNomad::Base) do
|
258
249
|
attribute :name, :string, :default => 'Joe'
|
@@ -317,6 +308,22 @@ describe ActiveNomad::Base do
|
|
317
308
|
end
|
318
309
|
end
|
319
310
|
|
311
|
+
it "should roundtrip undeclared attributes from the store through ActiveNomad" do
|
312
|
+
klass = Class.new(ActiveNomad::Base) do
|
313
|
+
attribute :declared, :string
|
314
|
+
end
|
315
|
+
stored_attributes = ActiveSupport::OrderedHash[[
|
316
|
+
['declared', 'a'],
|
317
|
+
['undeclared', 'b'],
|
318
|
+
]]
|
319
|
+
instance = klass.from_serialized_attributes(stored_attributes)
|
320
|
+
roundtripped_attributes = instance.to_serialized_attributes
|
321
|
+
roundtripped_attributes.to_a.should == [
|
322
|
+
['declared', 'a'],
|
323
|
+
['undeclared', 'b'],
|
324
|
+
]
|
325
|
+
end
|
326
|
+
|
320
327
|
def self.it_should_roundtrip_through(serializer, deserializer, &block)
|
321
328
|
describe "roundtripping through ##{serializer} and .#{deserializer}" do
|
322
329
|
class_eval(&block) if block
|
@@ -356,15 +363,18 @@ describe ActiveNomad::Base do
|
|
356
363
|
it_should_roundtrip :decimal, BigDecimal.new('123.45')
|
357
364
|
|
358
365
|
it_should_roundtrip :datetime, nil
|
359
|
-
it_should_roundtrip :datetime, Time.
|
366
|
+
it_should_roundtrip :datetime, Time.parse('2000-01-01 01:23:34 UTC')
|
367
|
+
it_should_roundtrip :datetime, Time.parse('2000-01-01 01:23:34 EST')
|
360
368
|
# TODO: Support DateTime here, which is used when the value is
|
361
369
|
# outside the range of a Time.
|
362
370
|
|
363
371
|
it_should_roundtrip :timestamp, nil
|
364
|
-
it_should_roundtrip :timestamp, Time.
|
372
|
+
it_should_roundtrip :timestamp, Time.parse('2000-01-01 01:23:34 UTC')
|
373
|
+
it_should_roundtrip :timestamp, Time.parse('2000-01-01 01:23:34 EST')
|
365
374
|
|
366
375
|
it_should_roundtrip :time, nil
|
367
|
-
it_should_roundtrip :time, Time.parse('2000-01-01 01:23:34')
|
376
|
+
it_should_roundtrip :time, Time.parse('2000-01-01 01:23:34 UTC')
|
377
|
+
it_should_roundtrip :time, Time.parse('2000-01-01 01:23:34 EST')
|
368
378
|
|
369
379
|
it_should_roundtrip :date, nil
|
370
380
|
it_should_roundtrip :date, Date.today
|
@@ -449,4 +459,39 @@ describe ActiveNomad::Base do
|
|
449
459
|
instance.transaction_called.should be_true
|
450
460
|
end
|
451
461
|
end
|
462
|
+
|
463
|
+
describe "#ATTRIBUTE_changed?" do
|
464
|
+
describe "on a new record with no attributes" do
|
465
|
+
before do
|
466
|
+
@klass = Class.new(ActiveNomad::Base) do
|
467
|
+
attribute :i, :integer
|
468
|
+
end
|
469
|
+
@instance = @klass.new
|
470
|
+
end
|
471
|
+
|
472
|
+
it "should be false" do
|
473
|
+
@instance.i_changed?.should be_false
|
474
|
+
end
|
475
|
+
|
476
|
+
describe "when the attribute has been assigned" do
|
477
|
+
before do
|
478
|
+
@instance.i = 2
|
479
|
+
end
|
480
|
+
|
481
|
+
it "should be true" do
|
482
|
+
@instance.i_changed?.should be_true
|
483
|
+
end
|
484
|
+
|
485
|
+
describe "when the record is roundtripped" do
|
486
|
+
before do
|
487
|
+
@instance = @klass.from_serialized_attributes(@instance.to_serialized_attributes)
|
488
|
+
end
|
489
|
+
|
490
|
+
it "should be false" do
|
491
|
+
@instance.i_changed?.should be_false
|
492
|
+
end
|
493
|
+
end
|
494
|
+
end
|
495
|
+
end
|
496
|
+
end
|
452
497
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_nomad
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 17
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 3
|
10
|
+
version: 0.2.3
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- George Ogata
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-10-
|
18
|
+
date: 2010-10-12 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|