wayne-friendly 0.5.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 +2 -0
- data/.gitignore +26 -0
- data/APACHE-LICENSE +202 -0
- data/CHANGELOG.md +28 -0
- data/CONTRIBUTORS.md +7 -0
- data/LICENSE +20 -0
- data/README.md +288 -0
- data/Rakefile +68 -0
- data/TODO.md +5 -0
- data/VERSION +1 -0
- data/examples/friendly.yml +7 -0
- data/friendly.gemspec +240 -0
- data/lib/friendly.rb +58 -0
- data/lib/friendly/associations.rb +7 -0
- data/lib/friendly/associations/association.rb +34 -0
- data/lib/friendly/associations/set.rb +37 -0
- data/lib/friendly/attribute.rb +98 -0
- data/lib/friendly/boolean.rb +10 -0
- data/lib/friendly/cache.rb +24 -0
- data/lib/friendly/cache/by_id.rb +33 -0
- data/lib/friendly/data_store.rb +73 -0
- data/lib/friendly/document.rb +70 -0
- data/lib/friendly/document/associations.rb +50 -0
- data/lib/friendly/document/attributes.rb +114 -0
- data/lib/friendly/document/convenience.rb +41 -0
- data/lib/friendly/document/mixin.rb +15 -0
- data/lib/friendly/document/scoping.rb +66 -0
- data/lib/friendly/document/storage.rb +63 -0
- data/lib/friendly/document_table.rb +56 -0
- data/lib/friendly/index.rb +73 -0
- data/lib/friendly/indexer.rb +50 -0
- data/lib/friendly/memcached.rb +48 -0
- data/lib/friendly/newrelic.rb +6 -0
- data/lib/friendly/query.rb +42 -0
- data/lib/friendly/scope.rb +100 -0
- data/lib/friendly/scope_proxy.rb +43 -0
- data/lib/friendly/sequel_monkey_patches.rb +34 -0
- data/lib/friendly/storage.rb +31 -0
- data/lib/friendly/storage_factory.rb +24 -0
- data/lib/friendly/storage_proxy.rb +111 -0
- data/lib/friendly/table.rb +15 -0
- data/lib/friendly/table_creator.rb +50 -0
- data/lib/friendly/time.rb +14 -0
- data/lib/friendly/translator.rb +33 -0
- data/lib/friendly/uuid.rb +148 -0
- data/lib/tasks/friendly.rake +7 -0
- data/rails/init.rb +3 -0
- data/spec/config.yml.example +7 -0
- data/spec/fakes/data_store_fake.rb +29 -0
- data/spec/fakes/database_fake.rb +12 -0
- data/spec/fakes/dataset_fake.rb +28 -0
- data/spec/fakes/document.rb +18 -0
- data/spec/fakes/serializer_fake.rb +12 -0
- data/spec/fakes/time_fake.rb +12 -0
- data/spec/integration/ad_hoc_scopes_spec.rb +42 -0
- data/spec/integration/basic_object_lifecycle_spec.rb +114 -0
- data/spec/integration/batch_insertion_spec.rb +29 -0
- data/spec/integration/convenience_api_spec.rb +25 -0
- data/spec/integration/count_spec.rb +12 -0
- data/spec/integration/default_value_spec.rb +30 -0
- data/spec/integration/dirty_tracking_spec.rb +43 -0
- data/spec/integration/find_via_cache_spec.rb +101 -0
- data/spec/integration/finder_spec.rb +71 -0
- data/spec/integration/has_many_spec.rb +18 -0
- data/spec/integration/index_spec.rb +57 -0
- data/spec/integration/named_scope_spec.rb +34 -0
- data/spec/integration/offline_indexing_spec.rb +53 -0
- data/spec/integration/pagination_spec.rb +63 -0
- data/spec/integration/scope_chaining_spec.rb +22 -0
- data/spec/integration/table_creator_spec.rb +69 -0
- data/spec/integration/write_through_cache_spec.rb +53 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +105 -0
- data/spec/unit/associations/association_spec.rb +57 -0
- data/spec/unit/associations/set_spec.rb +43 -0
- data/spec/unit/attribute_spec.rb +125 -0
- data/spec/unit/cache_by_id_spec.rb +102 -0
- data/spec/unit/cache_spec.rb +21 -0
- data/spec/unit/data_store_spec.rb +201 -0
- data/spec/unit/document/attributes_spec.rb +130 -0
- data/spec/unit/document_spec.rb +318 -0
- data/spec/unit/document_table_spec.rb +126 -0
- data/spec/unit/friendly_spec.rb +25 -0
- data/spec/unit/index_spec.rb +196 -0
- data/spec/unit/memcached_spec.rb +114 -0
- data/spec/unit/query_spec.rb +104 -0
- data/spec/unit/scope_proxy_spec.rb +44 -0
- data/spec/unit/scope_spec.rb +113 -0
- data/spec/unit/storage_factory_spec.rb +59 -0
- data/spec/unit/storage_proxy_spec.rb +244 -0
- data/spec/unit/translator_spec.rb +91 -0
- data/website/index.html +210 -0
- data/website/scripts/clipboard.swf +0 -0
- data/website/scripts/shBrushAS3.js +61 -0
- data/website/scripts/shBrushBash.js +66 -0
- data/website/scripts/shBrushCSharp.js +67 -0
- data/website/scripts/shBrushColdFusion.js +102 -0
- data/website/scripts/shBrushCpp.js +99 -0
- data/website/scripts/shBrushCss.js +93 -0
- data/website/scripts/shBrushDelphi.js +57 -0
- data/website/scripts/shBrushDiff.js +43 -0
- data/website/scripts/shBrushErlang.js +54 -0
- data/website/scripts/shBrushGroovy.js +69 -0
- data/website/scripts/shBrushJScript.js +52 -0
- data/website/scripts/shBrushJava.js +59 -0
- data/website/scripts/shBrushJavaFX.js +60 -0
- data/website/scripts/shBrushPerl.js +74 -0
- data/website/scripts/shBrushPhp.js +91 -0
- data/website/scripts/shBrushPlain.js +35 -0
- data/website/scripts/shBrushPowerShell.js +76 -0
- data/website/scripts/shBrushPython.js +66 -0
- data/website/scripts/shBrushRuby.js +57 -0
- data/website/scripts/shBrushScala.js +53 -0
- data/website/scripts/shBrushSql.js +68 -0
- data/website/scripts/shBrushVb.js +58 -0
- data/website/scripts/shBrushXml.js +71 -0
- data/website/scripts/shCore.js +30 -0
- data/website/scripts/shLegacy.js +30 -0
- data/website/styles/friendly.css +103 -0
- data/website/styles/help.png +0 -0
- data/website/styles/ie.css +35 -0
- data/website/styles/magnifier.png +0 -0
- data/website/styles/page_white_code.png +0 -0
- data/website/styles/page_white_copy.png +0 -0
- data/website/styles/print.css +29 -0
- data/website/styles/printer.png +0 -0
- data/website/styles/screen.css +257 -0
- data/website/styles/shCore.css +330 -0
- data/website/styles/shThemeDefault.css +173 -0
- data/website/styles/shThemeDjango.css +176 -0
- data/website/styles/shThemeEclipse.css +190 -0
- data/website/styles/shThemeEmacs.css +175 -0
- data/website/styles/shThemeFadeToGrey.css +177 -0
- data/website/styles/shThemeMidnight.css +175 -0
- data/website/styles/shThemeRDark.css +175 -0
- metadata +337 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
require 'friendly/time'
|
|
2
|
+
require 'friendly/attribute'
|
|
3
|
+
|
|
4
|
+
# This class was extracted from the cassandra gem by Evan Weaver
|
|
5
|
+
# As such, it is distributed under the terms of the apache license.
|
|
6
|
+
# See the APACHE-LICENSE file in the root of this project for more information.
|
|
7
|
+
#
|
|
8
|
+
module Friendly
|
|
9
|
+
# UUID format version 1, as specified in RFC 4122, with jitter in place of the mac address and sequence counter.
|
|
10
|
+
class UUID
|
|
11
|
+
|
|
12
|
+
class InvalidVersion < StandardError; end
|
|
13
|
+
class TypeError < ::TypeError; end
|
|
14
|
+
|
|
15
|
+
GREGORIAN_EPOCH_OFFSET = 0x01B2_1DD2_1381_4000 # Oct 15, 1582
|
|
16
|
+
|
|
17
|
+
VARIANT = 0b1000_0000_0000_0000
|
|
18
|
+
|
|
19
|
+
def initialize(bytes = nil)
|
|
20
|
+
case bytes
|
|
21
|
+
when self.class # UUID
|
|
22
|
+
@bytes = bytes.to_s
|
|
23
|
+
when String
|
|
24
|
+
case bytes.size
|
|
25
|
+
when 16 # Raw byte array
|
|
26
|
+
@bytes = bytes
|
|
27
|
+
when 36 # Human-readable UUID representation; inverse of #to_guid
|
|
28
|
+
elements = bytes.split("-")
|
|
29
|
+
raise TypeError, "Expected #{bytes.inspect} to cast to a #{self.class} (malformed UUID representation)" if elements.size != 5
|
|
30
|
+
@bytes = Array(elements.join).pack('H32')
|
|
31
|
+
else
|
|
32
|
+
raise TypeError, "Expected #{bytes.inspect} to cast to a #{self.class} (invalid bytecount)"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
when Integer
|
|
36
|
+
raise TypeError, "Expected #{bytes.inspect} to cast to a #{self.class} (integer out of range)" if bytes < 0 or bytes > 2**128
|
|
37
|
+
@bytes = [
|
|
38
|
+
(bytes >> 96) & 0xFFFF_FFFF,
|
|
39
|
+
(bytes >> 64) & 0xFFFF_FFFF,
|
|
40
|
+
(bytes >> 32) & 0xFFFF_FFFF,
|
|
41
|
+
bytes & 0xFFFF_FFFF
|
|
42
|
+
].pack("NNNN")
|
|
43
|
+
|
|
44
|
+
when NilClass, Time
|
|
45
|
+
time = (bytes || Time).stamp * 10 + GREGORIAN_EPOCH_OFFSET
|
|
46
|
+
# See http://github.com/spectra/ruby-uuid/
|
|
47
|
+
@bytes = [
|
|
48
|
+
time & 0xFFFF_FFFF,
|
|
49
|
+
time >> 32,
|
|
50
|
+
((time >> 48) & 0x0FFF) | 0x1000,
|
|
51
|
+
# Top 3 bytes reserved
|
|
52
|
+
rand(2**13) | VARIANT,
|
|
53
|
+
rand(2**16),
|
|
54
|
+
rand(2**32)
|
|
55
|
+
].pack("NnnnnN")
|
|
56
|
+
|
|
57
|
+
else
|
|
58
|
+
raise TypeError, "Expected #{bytes.inspect} to cast to a #{self.class} (unknown source class)"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def to_i
|
|
63
|
+
ints = @bytes.unpack("NNNN")
|
|
64
|
+
(ints[0] << 96) +
|
|
65
|
+
(ints[1] << 64) +
|
|
66
|
+
(ints[2] << 32) +
|
|
67
|
+
ints[3]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def version
|
|
71
|
+
time_high = @bytes.unpack("NnnQ")[2]
|
|
72
|
+
version = (time_high & 0xF000).to_s(16)[0].chr.to_i
|
|
73
|
+
version > 0 and version < 6 ? version : -1
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def variant
|
|
77
|
+
@bytes.unpack('QnnN')[1] >> 13
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def to_guid
|
|
81
|
+
elements = @bytes.unpack("NnnCCa6")
|
|
82
|
+
node = elements[-1].unpack('C*')
|
|
83
|
+
elements[-1] = '%02x%02x%02x%02x%02x%02x' % node
|
|
84
|
+
"%08x-%04x-%04x-%02x%02x-%s" % elements
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def to_json(*args)
|
|
88
|
+
to_guid.to_json(*args)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def seconds
|
|
92
|
+
total_usecs / 1_000_000
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def usecs
|
|
96
|
+
total_usecs % 1_000_000
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def <=>(other)
|
|
100
|
+
total_usecs <=> other.send(:total_usecs)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def inspect(long = false)
|
|
104
|
+
"<Friendly::UUID##{object_id} time: #{
|
|
105
|
+
Time.at(seconds).inspect
|
|
106
|
+
}, usecs: #{
|
|
107
|
+
usecs
|
|
108
|
+
} jitter: #{
|
|
109
|
+
@bytes.unpack('QQ')[1]
|
|
110
|
+
}" + (long ? ", version: #{version}, variant: #{variant}, guid: #{to_guid}>" : ">")
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def <=>(other)
|
|
114
|
+
self.to_i <=> other.to_i
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def hash
|
|
118
|
+
@bytes.hash
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def eql?(other)
|
|
122
|
+
other.is_a?(Comparable) and @bytes == other.to_s
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def ==(other)
|
|
126
|
+
self.to_s == other.to_s
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def to_s
|
|
130
|
+
@bytes
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def sql_literal(dataset)
|
|
134
|
+
dataset.literal(to_s.to_sequel_blob)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
private
|
|
138
|
+
|
|
139
|
+
def total_usecs
|
|
140
|
+
elements = @bytes.unpack("NnnQ")
|
|
141
|
+
(elements[0] + (elements[1] << 32) + ((elements[2] & 0x0FFF) << 48) - GREGORIAN_EPOCH_OFFSET) / 10
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
Friendly::Attribute.register_type(Friendly::UUID, 'binary(16)') do |s|
|
|
147
|
+
Friendly::UUID.new(s)
|
|
148
|
+
end
|
data/rails/init.rb
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
class DataStoreFake
|
|
2
|
+
attr_writer :insert, :all, :first
|
|
3
|
+
attr_reader :inserts, :updates
|
|
4
|
+
|
|
5
|
+
def initialize(opts = {})
|
|
6
|
+
opts.each { |k,v| send("#{k}=", v) }
|
|
7
|
+
@inserts = []
|
|
8
|
+
@updates = []
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def insert(*args)
|
|
12
|
+
@inserts << args
|
|
13
|
+
@insert
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def update(*args)
|
|
17
|
+
@updates << args
|
|
18
|
+
@update
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def all(*args)
|
|
22
|
+
@all[args]
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def first(*args)
|
|
26
|
+
@first[args]
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
class DatasetFake
|
|
2
|
+
attr_accessor :where, :insert, :inserts, :update, :updates, :first
|
|
3
|
+
|
|
4
|
+
def initialize(opts = {})
|
|
5
|
+
opts.each { |k,v| send("#{k}=", v) }
|
|
6
|
+
@inserts ||= []
|
|
7
|
+
@updates ||= []
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def where(conditions)
|
|
11
|
+
@where.detect { |k,v| k == conditions }.last
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def insert(attributes)
|
|
15
|
+
inserts << attributes
|
|
16
|
+
@insert
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def update(attributes)
|
|
20
|
+
updates << attributes
|
|
21
|
+
@update
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def first(conditions)
|
|
25
|
+
@first.detect { |k,v| k == conditions }.last
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
class FakeDocument
|
|
2
|
+
attr_accessor :id, :created_at, :to_hash, :new_record, :table_name,
|
|
3
|
+
:indexes, :name, :updated_at, :where_clause
|
|
4
|
+
|
|
5
|
+
def initialize(opts = {})
|
|
6
|
+
opts.each { |k,v| send("#{k}=", v) }
|
|
7
|
+
new_record = true if new_record.nil?
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def new_record?
|
|
11
|
+
new_record
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def attributes=(attrs)
|
|
15
|
+
attrs.each { |k,v| send("#{k}=", v) }
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require File.expand_path("../../spec_helper", __FILE__)
|
|
2
|
+
|
|
3
|
+
describe "Querying with an ad-hoc scope" do
|
|
4
|
+
before do
|
|
5
|
+
User.all(:name => "Fred").each { |u| u.destroy }
|
|
6
|
+
@users = (1..10).map { User.create(:name => "Fred") }
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "can return all the objects matching the scope" do
|
|
10
|
+
User.scope(:name => "Fred").all.should == @users
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "can return the first object matching the scope" do
|
|
14
|
+
User.scope(:name => "Fred").first.should == User.first(:name => "Fred")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "can paginate over the matching objects" do
|
|
18
|
+
found = User.scope(:name => "Fred").paginate(:per_page! => 5)
|
|
19
|
+
found.should == User.paginate(:name => "Fred", :per_page! => 5)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "can build an object at scope" do
|
|
23
|
+
User.scope(:name => "Fred", :limit! => 5).build.name.should == "Fred"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "supports overriding parameters when building" do
|
|
27
|
+
scope = User.scope(:name => "Fred", :limit! => 5)
|
|
28
|
+
scope.build(:name => "Joe").name.should == "Joe"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "can create an object at scope" do
|
|
32
|
+
user = User.scope(:name => "Joe").create
|
|
33
|
+
user.should_not be_new_record
|
|
34
|
+
user.name.should == "Joe"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "supports overriding parameters when creating" do
|
|
38
|
+
user = User.scope(:name => "Joe").create(:name => "Fred")
|
|
39
|
+
user.should_not be_new_record
|
|
40
|
+
user.name.should == "Fred"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
require File.expand_path("../../spec_helper", __FILE__)
|
|
2
|
+
|
|
3
|
+
describe "Creating and retrieving an object" do
|
|
4
|
+
before do
|
|
5
|
+
@user = User.new :name => "Stewie Griffin",
|
|
6
|
+
:age => 3
|
|
7
|
+
@user.save
|
|
8
|
+
@found_user = User.find(@user.id)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "finds the user in the database" do
|
|
12
|
+
@found_user.name.should == @user.name
|
|
13
|
+
@found_user.age.should == @user.age
|
|
14
|
+
@found_user.id.should == @user.id
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "locates an object that is == to the created object" do
|
|
18
|
+
@found_user.should == @user
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "sets the created_at timestamp for the record" do
|
|
22
|
+
@user.created_at.should_not be_nil
|
|
23
|
+
@user.created_at.should be_instance_of(Time)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "sets the created_at on the way out of the database" do
|
|
27
|
+
@found_user.created_at.should_not be_nil
|
|
28
|
+
@found_user.created_at.to_i.should == @user.created_at.to_i
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "sets the updated_at on the way out of the database" do
|
|
32
|
+
@found_user.updated_at.should_not be_nil
|
|
33
|
+
@found_user.updated_at.to_i.should == @user.updated_at.to_i
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "sets the updated_at" do
|
|
37
|
+
@user.updated_at.to_i.should == @user.created_at.to_i
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "doesn't serialize id, created_at, or updated_at in the attributes column" do
|
|
41
|
+
result = $db.from("users").first(:id => @user.id)
|
|
42
|
+
attrs = JSON.parse(result[:attributes])
|
|
43
|
+
attrs.keys.should_not include("id")
|
|
44
|
+
attrs.keys.should_not include("created_at")
|
|
45
|
+
attrs.keys.should_not include("updated_at")
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "has an id of type Friendly::UUID" do
|
|
49
|
+
@user.id.should be_kind_of(Friendly::UUID)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
describe "Updating an object" do
|
|
54
|
+
before do
|
|
55
|
+
@user = User.new :name => "Stewie Griffin",
|
|
56
|
+
:age => 3
|
|
57
|
+
@user.save
|
|
58
|
+
@created_id = @user.id
|
|
59
|
+
@created_at = @user.created_at
|
|
60
|
+
|
|
61
|
+
sleep(0.1)
|
|
62
|
+
@user.name = "Brian Griffin"
|
|
63
|
+
@user.age = 8
|
|
64
|
+
@user.save
|
|
65
|
+
|
|
66
|
+
@found_user = User.find(@created_id)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "sets the updated_at column" do
|
|
70
|
+
@user.updated_at.should_not be_nil
|
|
71
|
+
@user.updated_at.should_not == @user.created_at
|
|
72
|
+
@user.updated_at.should > @user.created_at
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "doesn't change the created_at" do
|
|
76
|
+
@user.created_at.should == @created_at
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "doesn't change the id" do
|
|
80
|
+
@user.id.should == @created_id
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "saves the new attrs to the db" do
|
|
84
|
+
@found_user.name.should == "Brian Griffin"
|
|
85
|
+
@found_user.age.should == 8
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
describe "destroying a document" do
|
|
90
|
+
before do
|
|
91
|
+
@user = User.new :name => "Stewie Griffin"
|
|
92
|
+
@user.save
|
|
93
|
+
@user.destroy
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it "removes it from the database" do
|
|
97
|
+
User.first(:id => @user.id).should be_nil
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
describe "Finding an object by id" do
|
|
102
|
+
it "raises Friendly::RecordNotFound if it doesn't exist" do
|
|
103
|
+
lambda { User.find(12345) }.should raise_error(Friendly::RecordNotFound)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
describe "An object that has a foreign key" do
|
|
108
|
+
it "is saveable in the database" do
|
|
109
|
+
lambda {
|
|
110
|
+
Address.create :user_id => Friendly::UUID.new
|
|
111
|
+
}.should_not raise_error
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|