mongomodel 0.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/LICENSE +22 -0
- data/README.md +34 -0
- data/Rakefile +47 -0
- data/bin/console +45 -0
- data/lib/mongomodel.rb +92 -0
- data/lib/mongomodel/attributes/mongo.rb +40 -0
- data/lib/mongomodel/attributes/store.rb +30 -0
- data/lib/mongomodel/attributes/typecasting.rb +51 -0
- data/lib/mongomodel/concerns/abstract_class.rb +17 -0
- data/lib/mongomodel/concerns/activemodel.rb +11 -0
- data/lib/mongomodel/concerns/associations.rb +103 -0
- data/lib/mongomodel/concerns/associations/base/association.rb +33 -0
- data/lib/mongomodel/concerns/associations/base/definition.rb +56 -0
- data/lib/mongomodel/concerns/associations/base/proxy.rb +58 -0
- data/lib/mongomodel/concerns/associations/belongs_to.rb +68 -0
- data/lib/mongomodel/concerns/associations/has_many_by_foreign_key.rb +159 -0
- data/lib/mongomodel/concerns/associations/has_many_by_ids.rb +175 -0
- data/lib/mongomodel/concerns/attribute_methods.rb +55 -0
- data/lib/mongomodel/concerns/attribute_methods/before_type_cast.rb +29 -0
- data/lib/mongomodel/concerns/attribute_methods/dirty.rb +35 -0
- data/lib/mongomodel/concerns/attribute_methods/protected.rb +127 -0
- data/lib/mongomodel/concerns/attribute_methods/query.rb +22 -0
- data/lib/mongomodel/concerns/attribute_methods/read.rb +29 -0
- data/lib/mongomodel/concerns/attribute_methods/write.rb +29 -0
- data/lib/mongomodel/concerns/attributes.rb +85 -0
- data/lib/mongomodel/concerns/callbacks.rb +294 -0
- data/lib/mongomodel/concerns/logging.rb +15 -0
- data/lib/mongomodel/concerns/pretty_inspect.rb +29 -0
- data/lib/mongomodel/concerns/properties.rb +69 -0
- data/lib/mongomodel/concerns/record_status.rb +42 -0
- data/lib/mongomodel/concerns/timestamps.rb +32 -0
- data/lib/mongomodel/concerns/validations.rb +38 -0
- data/lib/mongomodel/concerns/validations/associated.rb +46 -0
- data/lib/mongomodel/document.rb +20 -0
- data/lib/mongomodel/document/callbacks.rb +46 -0
- data/lib/mongomodel/document/dynamic_finders.rb +88 -0
- data/lib/mongomodel/document/finders.rb +82 -0
- data/lib/mongomodel/document/indexes.rb +91 -0
- data/lib/mongomodel/document/optimistic_locking.rb +48 -0
- data/lib/mongomodel/document/persistence.rb +143 -0
- data/lib/mongomodel/document/scopes.rb +161 -0
- data/lib/mongomodel/document/validations.rb +68 -0
- data/lib/mongomodel/document/validations/uniqueness.rb +78 -0
- data/lib/mongomodel/embedded_document.rb +42 -0
- data/lib/mongomodel/locale/en.yml +55 -0
- data/lib/mongomodel/support/collection.rb +109 -0
- data/lib/mongomodel/support/configuration.rb +35 -0
- data/lib/mongomodel/support/core_extensions.rb +10 -0
- data/lib/mongomodel/support/exceptions.rb +25 -0
- data/lib/mongomodel/support/mongo_options.rb +177 -0
- data/lib/mongomodel/support/types.rb +35 -0
- data/lib/mongomodel/support/types/array.rb +11 -0
- data/lib/mongomodel/support/types/boolean.rb +25 -0
- data/lib/mongomodel/support/types/custom.rb +38 -0
- data/lib/mongomodel/support/types/date.rb +20 -0
- data/lib/mongomodel/support/types/float.rb +13 -0
- data/lib/mongomodel/support/types/hash.rb +18 -0
- data/lib/mongomodel/support/types/integer.rb +13 -0
- data/lib/mongomodel/support/types/object.rb +21 -0
- data/lib/mongomodel/support/types/string.rb +9 -0
- data/lib/mongomodel/support/types/symbol.rb +9 -0
- data/lib/mongomodel/support/types/time.rb +12 -0
- data/lib/mongomodel/version.rb +3 -0
- data/spec/mongomodel/attributes/store_spec.rb +273 -0
- data/spec/mongomodel/concerns/activemodel_spec.rb +61 -0
- data/spec/mongomodel/concerns/associations/belongs_to_spec.rb +153 -0
- data/spec/mongomodel/concerns/associations/has_many_by_foreign_key_spec.rb +165 -0
- data/spec/mongomodel/concerns/associations/has_many_by_ids_spec.rb +192 -0
- data/spec/mongomodel/concerns/attribute_methods/before_type_cast_spec.rb +46 -0
- data/spec/mongomodel/concerns/attribute_methods/dirty_spec.rb +131 -0
- data/spec/mongomodel/concerns/attribute_methods/protected_spec.rb +86 -0
- data/spec/mongomodel/concerns/attribute_methods/query_spec.rb +27 -0
- data/spec/mongomodel/concerns/attribute_methods/read_spec.rb +52 -0
- data/spec/mongomodel/concerns/attribute_methods/write_spec.rb +43 -0
- data/spec/mongomodel/concerns/attributes_spec.rb +152 -0
- data/spec/mongomodel/concerns/callbacks_spec.rb +90 -0
- data/spec/mongomodel/concerns/logging_spec.rb +20 -0
- data/spec/mongomodel/concerns/pretty_inspect_spec.rb +68 -0
- data/spec/mongomodel/concerns/properties_spec.rb +29 -0
- data/spec/mongomodel/concerns/timestamps_spec.rb +170 -0
- data/spec/mongomodel/concerns/validations_spec.rb +159 -0
- data/spec/mongomodel/document/callbacks_spec.rb +80 -0
- data/spec/mongomodel/document/dynamic_finders_spec.rb +183 -0
- data/spec/mongomodel/document/finders_spec.rb +231 -0
- data/spec/mongomodel/document/indexes_spec.rb +121 -0
- data/spec/mongomodel/document/optimistic_locking_spec.rb +57 -0
- data/spec/mongomodel/document/persistence_spec.rb +319 -0
- data/spec/mongomodel/document/scopes_spec.rb +204 -0
- data/spec/mongomodel/document/validations/uniqueness_spec.rb +217 -0
- data/spec/mongomodel/document/validations_spec.rb +132 -0
- data/spec/mongomodel/document_spec.rb +74 -0
- data/spec/mongomodel/embedded_document_spec.rb +66 -0
- data/spec/mongomodel/mongomodel_spec.rb +33 -0
- data/spec/mongomodel/support/collection_spec.rb +248 -0
- data/spec/mongomodel/support/mongo_options_spec.rb +295 -0
- data/spec/mongomodel/support/property_spec.rb +83 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/specdoc.opts +6 -0
- data/spec/support/callbacks.rb +44 -0
- data/spec/support/helpers/define_class.rb +24 -0
- data/spec/support/helpers/specs_for.rb +11 -0
- data/spec/support/matchers/be_a_subclass_of.rb +5 -0
- data/spec/support/matchers/respond_to_boolean.rb +17 -0
- data/spec/support/matchers/run_callbacks.rb +20 -0
- data/spec/support/models.rb +23 -0
- data/spec/support/time.rb +6 -0
- metadata +232 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module MongoModel
|
|
4
|
+
specs_for(Document, EmbeddedDocument) do
|
|
5
|
+
define_class(:TestDocument, described_class) do
|
|
6
|
+
property :foo, Date
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
subject { TestDocument.new }
|
|
10
|
+
|
|
11
|
+
describe "#read_attribute_before_type_cast" do
|
|
12
|
+
context "with property" do
|
|
13
|
+
it "should return the attribute before type casting" do
|
|
14
|
+
subject.attributes[:foo] = 'some date'
|
|
15
|
+
subject.read_attribute_before_type_cast(:foo).should == 'some date'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should define a reader method" do
|
|
19
|
+
subject.attributes[:foo] = 'some date'
|
|
20
|
+
subject.foo_before_type_cast.should == 'some date'
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context "no property" do
|
|
25
|
+
it "should return the attribute without type casting" do
|
|
26
|
+
subject.attributes[:bar] = 'set bar'
|
|
27
|
+
subject.read_attribute_before_type_cast(:bar).should == 'set bar'
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "should not define a reader method" do
|
|
31
|
+
lambda { subject.bar_before_type_cast }.should raise_error(NoMethodError)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe "#attributes_before_type_cast" do
|
|
37
|
+
it "should return a hash of attributes before type casting" do
|
|
38
|
+
subject.attributes[:foo] = 'some date'
|
|
39
|
+
subject.attributes[:bar] = 'set bar'
|
|
40
|
+
|
|
41
|
+
subject.attributes_before_type_cast[:foo].should == 'some date'
|
|
42
|
+
subject.attributes_before_type_cast[:bar].should == 'set bar'
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module MongoModel
|
|
4
|
+
specs_for(Document, EmbeddedDocument) do
|
|
5
|
+
if specing?(Document)
|
|
6
|
+
define_class(:TestDocument, Document) do
|
|
7
|
+
property :foo, String
|
|
8
|
+
property :bar, String
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
subject { TestDocument.create!(:foo => 'original foo') }
|
|
12
|
+
else
|
|
13
|
+
define_class(:ChildDocument, EmbeddedDocument) do
|
|
14
|
+
property :foo, String
|
|
15
|
+
property :bar, String
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
define_class(:ParentDocument, Document) do
|
|
19
|
+
property :child, ChildDocument
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
let(:child) { ChildDocument.new(:foo => 'original foo') }
|
|
23
|
+
let(:parent) { ParentDocument.create!(:child => child) }
|
|
24
|
+
|
|
25
|
+
subject { parent.child }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe "#write_attribute" do
|
|
29
|
+
before(:each) do
|
|
30
|
+
subject.write_attribute(:foo, 'new foo')
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should add the old attribute name to the changed attributes" do
|
|
34
|
+
subject.changed.should include(:foo)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "should not add other attributes to the changed attributes" do
|
|
38
|
+
subject.changed.should_not include(:bar)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should add the changed attribute value to the changes hash" do
|
|
42
|
+
subject.changes[:foo].should == ['original foo', 'new foo']
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
context "when called twice" do
|
|
46
|
+
before(:each) do
|
|
47
|
+
subject.write_attribute(:foo, 'new foo #2')
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should keep the original value as the old value in the changes hash" do
|
|
51
|
+
subject.changes[:foo].should == ['original foo', 'new foo #2']
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context "with changed attributes" do
|
|
57
|
+
context "attribute set to a new value" do
|
|
58
|
+
before(:each) do
|
|
59
|
+
subject.foo = 'foo changed'
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it { should be_changed }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
context "attribute set to the original value" do
|
|
66
|
+
before(:each) do
|
|
67
|
+
subject.foo = 'original foo'
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it { should_not be_changed }
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
context "without changed attributes" do
|
|
75
|
+
it { should_not be_changed }
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
context "#original_attributes" do
|
|
79
|
+
context "with changes" do
|
|
80
|
+
before(:each) do
|
|
81
|
+
subject.foo = 'changed foo'
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "should return the attributes before changes" do
|
|
85
|
+
subject.original_attributes[:foo].should == 'original foo'
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
context "without changes" do
|
|
90
|
+
it "should return the attributes hash" do
|
|
91
|
+
subject.original_attributes.should == subject.attributes
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
specs_for(Document) do
|
|
98
|
+
define_class(:TestDocument, Document) do
|
|
99
|
+
property :foo, String
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
subject { TestDocument.create!(:foo => 'original foo') }
|
|
103
|
+
|
|
104
|
+
context "when saved" do
|
|
105
|
+
before(:each) do
|
|
106
|
+
subject.foo = 'changed foo'
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
context "with save" do
|
|
110
|
+
it "should reset the changed attributes" do
|
|
111
|
+
subject.save
|
|
112
|
+
subject.should_not be_changed
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
context "with save!" do
|
|
117
|
+
it "should reset the changed attributes" do
|
|
118
|
+
subject.save!
|
|
119
|
+
subject.should_not be_changed
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
context "when instantiated from database" do
|
|
125
|
+
it "should not be changed" do
|
|
126
|
+
instance = TestDocument.find(subject.id)
|
|
127
|
+
instance.should_not be_changed
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module MongoModel
|
|
4
|
+
specs_for(Document, EmbeddedDocument) do
|
|
5
|
+
define_class(:TestDocument, described_class) do
|
|
6
|
+
property :foo, String
|
|
7
|
+
property :bar, String
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
subject { TestDocument.new }
|
|
11
|
+
|
|
12
|
+
describe "#attr_protected" do
|
|
13
|
+
before(:each) do
|
|
14
|
+
TestDocument.attr_protected :foo
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should disallow the attribute to be mass-assigned via attributes=" do
|
|
18
|
+
subject.attributes = { :foo => 'value of foo' }
|
|
19
|
+
subject.foo.should be_nil
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "should not disallow the attribute to be assigned individually" do
|
|
23
|
+
subject.foo = 'value of foo'
|
|
24
|
+
subject.foo.should == 'value of foo'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "should not disallow other attributes to be mass-assigned via attributes=" do
|
|
28
|
+
subject.attributes = { :bar => 'value of bar' }
|
|
29
|
+
subject.bar.should == 'value of bar'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "should accept multiple attributes" do
|
|
33
|
+
TestDocument.attr_protected :foo, :bar
|
|
34
|
+
|
|
35
|
+
subject.attributes = { :foo => 'value of foo', :bar => 'value of bar' }
|
|
36
|
+
subject.foo.should be_nil
|
|
37
|
+
subject.bar.should be_nil
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe "#attr_accessible" do
|
|
42
|
+
before(:each) do
|
|
43
|
+
TestDocument.attr_accessible :foo
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "should allow the attribute to be mass-assigned via attributes=" do
|
|
47
|
+
subject.attributes = { :foo => 'value of foo' }
|
|
48
|
+
subject.foo.should == 'value of foo'
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should not disallow other attributes to be mass-assigned via attributes=" do
|
|
52
|
+
subject.attributes = { :bar => 'value of bar' }
|
|
53
|
+
subject.bar.should be_nil
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "should not disallow others attributes to be assigned individually" do
|
|
57
|
+
subject.bar = 'value of bar'
|
|
58
|
+
subject.bar.should == 'value of bar'
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "should accept multiple attributes" do
|
|
62
|
+
TestDocument.attr_accessible :foo, :bar
|
|
63
|
+
|
|
64
|
+
subject.attributes = { :foo => 'value of foo', :bar => 'value of bar' }
|
|
65
|
+
subject.foo.should == 'value of foo'
|
|
66
|
+
subject.bar.should == 'value of bar'
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
describe "#property" do
|
|
71
|
+
context "with :protected option" do
|
|
72
|
+
it "should make the attribute protected" do
|
|
73
|
+
TestDocument.should_receive(:attr_protected).with(:baz)
|
|
74
|
+
TestDocument.property :baz, String, :protected => true
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
context "with :accessible option" do
|
|
79
|
+
it "should make the attribute accessible" do
|
|
80
|
+
TestDocument.should_receive(:attr_accessible).with(:baz)
|
|
81
|
+
TestDocument.property :baz, String, :accessible => true
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module MongoModel
|
|
4
|
+
specs_for(Document, EmbeddedDocument) do
|
|
5
|
+
define_class(:TestDocument, described_class) do
|
|
6
|
+
property :foo, String
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
subject { TestDocument.new }
|
|
10
|
+
|
|
11
|
+
describe "#query_attribute" do
|
|
12
|
+
it "should return true if the attribute is not blank" do
|
|
13
|
+
subject.foo = 'set foo'
|
|
14
|
+
subject.query_attribute(:foo).should be_true
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should return false if the attribute is blank" do
|
|
18
|
+
subject.foo = ''
|
|
19
|
+
subject.query_attribute(:foo).should be_false
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "should create a query method" do
|
|
23
|
+
subject.foo?.should == subject.query_attribute(:foo)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module MongoModel
|
|
4
|
+
specs_for(Document, EmbeddedDocument) do
|
|
5
|
+
define_class(:TestDocument, described_class) do
|
|
6
|
+
property :foo, String
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
subject { TestDocument.new(:foo => 'value of foo', :bar => 'value of bar') }
|
|
10
|
+
|
|
11
|
+
describe "#read_attribute" do
|
|
12
|
+
context "valid property" do
|
|
13
|
+
it "should return the attribute value" do
|
|
14
|
+
subject.read_attribute(:foo).should == 'value of foo'
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should define a reader method" do
|
|
18
|
+
subject.foo.should == 'value of foo'
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context "no property" do
|
|
23
|
+
it "should return the attribute value" do
|
|
24
|
+
subject.read_attribute(:bar).should == 'value of bar'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "should not define a reader method" do
|
|
28
|
+
lambda { subject.bar }.should raise_error(NoMethodError)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe "#[]" do
|
|
34
|
+
it "should read the given attribute" do
|
|
35
|
+
subject.should_receive(:read_attribute).with(:foo).and_return('value of foo')
|
|
36
|
+
subject[:foo].should == 'value of foo'
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
specs_for(Document) do
|
|
42
|
+
define_class(:TestDocument, Document)
|
|
43
|
+
|
|
44
|
+
subject { TestDocument.new }
|
|
45
|
+
|
|
46
|
+
describe "#id" do
|
|
47
|
+
it "should return id from attributes" do
|
|
48
|
+
subject.id.should == subject.attributes[:id]
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module MongoModel
|
|
4
|
+
specs_for(Document, EmbeddedDocument) do
|
|
5
|
+
define_class(:TestDocument, described_class) do
|
|
6
|
+
property :foo, String
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
subject { TestDocument.new }
|
|
10
|
+
|
|
11
|
+
describe "#write_attribute" do
|
|
12
|
+
context "with property" do
|
|
13
|
+
it "should set the attribute hash" do
|
|
14
|
+
subject.write_attribute(:foo, 'set foo')
|
|
15
|
+
subject.attributes[:foo].should == 'set foo'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should define a writer method" do
|
|
19
|
+
subject.foo = 'set foo'
|
|
20
|
+
subject.attributes[:foo].should == 'set foo'
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context "no property" do
|
|
25
|
+
it "should set the attribute hash" do
|
|
26
|
+
subject.write_attribute(:bar, 'set bar')
|
|
27
|
+
subject.attributes[:bar].should == 'set bar'
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "should not define a writer method" do
|
|
31
|
+
lambda { subject.bar = 'set bar' }.should raise_error(NoMethodError)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe "#[]=" do
|
|
37
|
+
it "should write the given attribute" do
|
|
38
|
+
subject.should_receive(:write_attribute).with(:foo, 'value of foo')
|
|
39
|
+
subject[:foo] = 'value of foo'
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
|
3
|
+
|
|
4
|
+
module MongoModel
|
|
5
|
+
AttributeTypes = {
|
|
6
|
+
String => "my string",
|
|
7
|
+
Integer => 99,
|
|
8
|
+
Float => 45.123,
|
|
9
|
+
Symbol => :foobar,
|
|
10
|
+
Boolean => false,
|
|
11
|
+
Array => [ 1, 2, 3, "hello", :world, [99, 100] ],
|
|
12
|
+
Hash => { :rabbit => 'hat', 'hello' => 12345 }.with_indifferent_access,
|
|
13
|
+
Date => Date.today,
|
|
14
|
+
Time => Time.now,
|
|
15
|
+
CustomClass => CustomClass.new('hello')
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
specs_for(Document, EmbeddedDocument) do
|
|
19
|
+
define_class(:TestDocument, described_class)
|
|
20
|
+
|
|
21
|
+
it "should have an attributes store on the instance" do
|
|
22
|
+
doc = TestDocument.new
|
|
23
|
+
doc.attributes.should be_an_instance_of(MongoModel::Attributes::Store)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should convert to mongo representation" do
|
|
27
|
+
doc = TestDocument.new
|
|
28
|
+
doc.to_mongo.should == doc.attributes.to_mongo
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
AttributeTypes.each do |type, value|
|
|
32
|
+
describe "setting #{type} attributes" do
|
|
33
|
+
define_class(:TestDocument, described_class) do
|
|
34
|
+
property :test_property, type
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
if specing?(EmbeddedDocument)
|
|
38
|
+
define_class(:ParentDocument, Document) do
|
|
39
|
+
property :child, TestDocument
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
let(:parent) { ParentDocument.create!(:child => TestDocument.new(:test_property => value)) }
|
|
43
|
+
let(:child) { parent.child }
|
|
44
|
+
let(:reloaded) { ParentDocument.find(parent.id).child }
|
|
45
|
+
|
|
46
|
+
subject { child }
|
|
47
|
+
else
|
|
48
|
+
subject { TestDocument.create!(:test_property => value) }
|
|
49
|
+
|
|
50
|
+
let(:reloaded) { TestDocument.find(subject.id) }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "should read the correct value from attributes" do
|
|
54
|
+
subject.test_property.should == value
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "should read the correct value after reloading" do
|
|
58
|
+
reloaded.test_property.should == subject.test_property
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "should have an attributes store" do
|
|
64
|
+
doc = TestDocument.new
|
|
65
|
+
doc.attributes.should be_an_instance_of(MongoModel::Attributes::Store)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "should duplicate attributes when duplicating object" do
|
|
69
|
+
original = TestDocument.new
|
|
70
|
+
duplicate = original.dup
|
|
71
|
+
|
|
72
|
+
duplicate.attributes.should_not equal(original.attributes)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
describe "initializing" do
|
|
76
|
+
define_class(:Person, EmbeddedDocument) do
|
|
77
|
+
property :name, String
|
|
78
|
+
property :age, Integer, :default => 21
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "should be initializable with attributes hash" do
|
|
82
|
+
doc = Person.new(:name => 'Fred', :age => 42)
|
|
83
|
+
doc.name.should == 'Fred'
|
|
84
|
+
doc.age.should == 42
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it "should use default attributes when initializing with partial attributes hash" do
|
|
88
|
+
doc = Person.new(:name => 'Maurice')
|
|
89
|
+
doc.age.should == 21
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "should load from mongo representation" do
|
|
93
|
+
doc = Person.from_mongo({ 'name' => 'James', 'age' => 15 })
|
|
94
|
+
doc.name.should == 'James'
|
|
95
|
+
doc.age.should == 15
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
describe "setting attributes with hash" do
|
|
100
|
+
define_class(:TestDocument, described_class) do
|
|
101
|
+
property :test_property, String
|
|
102
|
+
|
|
103
|
+
def test_property=(value)
|
|
104
|
+
write_attribute(:test_property, 'set from method')
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
subject { TestDocument.new }
|
|
109
|
+
|
|
110
|
+
it "should call custom property methods" do
|
|
111
|
+
subject.attributes = { :test_property => 'property value' }
|
|
112
|
+
subject.test_property.should == 'set from method'
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it "should use write_attribute if no such property" do
|
|
116
|
+
subject.attributes = { :non_property => 'property value' }
|
|
117
|
+
subject.read_attribute(:non_property).should == 'property value'
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
describe "#new" do
|
|
122
|
+
define_class(:TestDocument, described_class)
|
|
123
|
+
|
|
124
|
+
it "should yield the instance to a block if provided" do
|
|
125
|
+
block_called = false
|
|
126
|
+
|
|
127
|
+
TestDocument.new do |doc|
|
|
128
|
+
block_called = true
|
|
129
|
+
doc.should be_an_instance_of(TestDocument)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
block_called.should be_true
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
context "a frozen instance" do
|
|
137
|
+
define_class(:TestDocument, described_class) do
|
|
138
|
+
property :test_property, String
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
subject { TestDocument.new(:test_property => 'Test') }
|
|
142
|
+
|
|
143
|
+
before(:each) { subject.freeze }
|
|
144
|
+
|
|
145
|
+
it { should be_frozen }
|
|
146
|
+
|
|
147
|
+
it "should not allow changes to the attributes hash" do
|
|
148
|
+
lambda { subject.attributes[:test_property] = 'Change' }.should raise_error
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|