mongodoc 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +42 -12
- data/Rakefile +4 -4
- data/TODO +26 -0
- data/VERSION +1 -1
- data/examples/simple_document.rb +1 -1
- data/examples/simple_object.rb +0 -2
- data/features/mongodb.yml +6 -5
- data/features/removing_documents.feature +68 -0
- data/features/step_definitions/collection_steps.rb +3 -3
- data/features/step_definitions/document_steps.rb +2 -2
- data/features/step_definitions/removing_documents_steps.rb +14 -0
- data/features/support/support.rb +2 -2
- data/lib/mongodoc.rb +4 -7
- data/lib/mongodoc/associations/collection_proxy.rb +103 -0
- data/lib/mongodoc/associations/document_proxy.rb +53 -0
- data/lib/mongodoc/associations/hash_proxy.rb +96 -0
- data/lib/mongodoc/associations/proxy_base.rb +51 -0
- data/lib/mongodoc/attributes.rb +49 -17
- data/lib/mongodoc/collection.rb +15 -5
- data/lib/mongodoc/connection.rb +83 -20
- data/lib/mongodoc/criteria.rb +9 -4
- data/lib/mongodoc/cursor.rb +9 -3
- data/lib/mongodoc/document.rb +37 -24
- data/lib/mongodoc/validations/macros.rb +11 -0
- data/lib/mongodoc/validations/validates_embedded.rb +13 -0
- data/mongodb.example.yml +13 -5
- data/mongodoc.gemspec +33 -23
- data/spec/associations/collection_proxy_spec.rb +200 -0
- data/spec/associations/document_proxy_spec.rb +42 -0
- data/spec/associations/hash_proxy_spec.rb +163 -0
- data/spec/attributes_spec.rb +113 -47
- data/spec/bson_spec.rb +24 -24
- data/spec/collection_spec.rb +67 -86
- data/spec/connection_spec.rb +98 -150
- data/spec/criteria_spec.rb +4 -3
- data/spec/cursor_spec.rb +33 -27
- data/spec/document_spec.rb +173 -156
- data/spec/embedded_save_spec.rb +8 -3
- data/spec/new_record_spec.rb +33 -121
- metadata +80 -39
- data/lib/mongodoc/parent_proxy.rb +0 -44
- data/lib/mongodoc/proxy.rb +0 -83
- data/spec/parent_proxy_spec.rb +0 -44
- data/spec/proxy_spec.rb +0 -80
@@ -1,44 +0,0 @@
|
|
1
|
-
module MongoDoc
|
2
|
-
class ParentProxy
|
3
|
-
attr_reader :assoc_name, :_parent
|
4
|
-
|
5
|
-
def initialize(parent, assoc_name)
|
6
|
-
raise ArgumentError.new('ParentProxy requires a parent') if parent.nil?
|
7
|
-
raise ArgumentError.new('ParentProxy require an association name') if assoc_name.blank?
|
8
|
-
@_parent = parent
|
9
|
-
@assoc_name = assoc_name
|
10
|
-
end
|
11
|
-
|
12
|
-
def _path_to_root(src, attrs)
|
13
|
-
_parent._path_to_root(src, _annotated_keys(attrs))
|
14
|
-
end
|
15
|
-
|
16
|
-
def _selector_path_to_root(selector)
|
17
|
-
_parent._selector_path_to_root(_annotated_keys(selector))
|
18
|
-
end
|
19
|
-
|
20
|
-
protected
|
21
|
-
|
22
|
-
def _annotated_keys(hash)
|
23
|
-
hash.inject({}) do |annotated, (key, value)|
|
24
|
-
annotated["#{assoc_name}.#{key}"] = value
|
25
|
-
annotated
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def method_missing(method, *args)
|
32
|
-
unless @_parent.respond_to?(method)
|
33
|
-
message = "undefined method `#{method.to_s}' for proxied \"#{@_parent}\":#{@_parent.class.to_s}"
|
34
|
-
raise NoMethodError, message
|
35
|
-
end
|
36
|
-
|
37
|
-
if block_given?
|
38
|
-
@_parent.send(method, *args) { |*block_args| yield(*block_args) }
|
39
|
-
else
|
40
|
-
@_parent.send(method, *args)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
data/lib/mongodoc/proxy.rb
DELETED
@@ -1,83 +0,0 @@
|
|
1
|
-
# Thanks Sandro!
|
2
|
-
# http://github.com/sandro
|
3
|
-
module MongoDoc
|
4
|
-
class Proxy
|
5
|
-
# List of array methods (that are not in +Object+) that need to be
|
6
|
-
# delegated to +collection+.
|
7
|
-
ARRAY_METHODS = (Array.instance_methods - Object.instance_methods).map { |n| n.to_s }
|
8
|
-
|
9
|
-
# List of additional methods that must be delegated to +collection+.
|
10
|
-
MUST_DEFINE = %w[to_a to_ary inspect to_bson ==]
|
11
|
-
|
12
|
-
(ARRAY_METHODS + MUST_DEFINE).uniq.each do |method|
|
13
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
14
|
-
def #{method}(*args, &block) # def each(*args, &block)
|
15
|
-
collection.send(:#{method}, *args, &block) # collection.send(:each, *args, &block)
|
16
|
-
end # end
|
17
|
-
RUBY
|
18
|
-
end
|
19
|
-
|
20
|
-
attr_reader :assoc_name, :collection, :collection_class, :_parent, :_root
|
21
|
-
|
22
|
-
def _parent=(parent)
|
23
|
-
@_parent = parent
|
24
|
-
end
|
25
|
-
|
26
|
-
def _root=(root)
|
27
|
-
@_root = root
|
28
|
-
collection.each do |item|
|
29
|
-
item._root = root
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def initialize(options)
|
34
|
-
@assoc_name = options[:assoc_name]
|
35
|
-
@collection = []
|
36
|
-
@collection_class = options[:collection_class]
|
37
|
-
@_root = options[:root]
|
38
|
-
@_parent = options[:parent]
|
39
|
-
end
|
40
|
-
|
41
|
-
alias_method :append, :<<
|
42
|
-
def <<(item)
|
43
|
-
item = build(item) if Hash === item
|
44
|
-
if Document === item
|
45
|
-
item._parent = self
|
46
|
-
item._root = _root
|
47
|
-
_root.send(:register_save_observer, item)
|
48
|
-
end
|
49
|
-
append item
|
50
|
-
self
|
51
|
-
end
|
52
|
-
alias_method :push, :<<
|
53
|
-
alias_method :concat, :<<
|
54
|
-
|
55
|
-
# Lie about our class. Borrowed from Rake::FileList
|
56
|
-
# Note: Does not work for case equality (<tt>===</tt>)
|
57
|
-
def is_a?(klass)
|
58
|
-
klass == Array || super(klass)
|
59
|
-
end
|
60
|
-
alias kind_of? is_a?
|
61
|
-
|
62
|
-
def _path_to_root(src, attrs)
|
63
|
-
assoc_path = "#{assoc_name}.#{index(src)}"
|
64
|
-
assoc_attrs = attrs.inject({}) do |assoc_attrs, (key, value)|
|
65
|
-
assoc_attrs["#{assoc_path}.#{key}"] = value
|
66
|
-
assoc_attrs
|
67
|
-
end
|
68
|
-
_parent._path_to_root(src, assoc_attrs)
|
69
|
-
end
|
70
|
-
|
71
|
-
def _selector_path_to_root(selector)
|
72
|
-
annotated_selector = selector.inject({}) do |annotated, (key, value)|
|
73
|
-
annotated["#{assoc_name}.#{key}"] = value
|
74
|
-
annotated
|
75
|
-
end
|
76
|
-
_parent._selector_path_to_root(annotated_selector)
|
77
|
-
end
|
78
|
-
|
79
|
-
def build(attrs)
|
80
|
-
collection_class.new(attrs)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
data/spec/parent_proxy_spec.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
|
3
|
-
describe "MongoDoc::ParentProxy" do
|
4
|
-
class Parent
|
5
|
-
include MongoDoc::Document
|
6
|
-
end
|
7
|
-
|
8
|
-
class Child
|
9
|
-
include MongoDoc::Document
|
10
|
-
end
|
11
|
-
|
12
|
-
before do
|
13
|
-
@parent = Parent.new
|
14
|
-
@assoc_name = 'association'
|
15
|
-
end
|
16
|
-
|
17
|
-
subject do
|
18
|
-
MongoDoc::ParentProxy.new(@parent, @assoc_name)
|
19
|
-
end
|
20
|
-
|
21
|
-
it "has the association name" do
|
22
|
-
should respond_to(:assoc_name)
|
23
|
-
end
|
24
|
-
|
25
|
-
it "has a parent" do
|
26
|
-
should respond_to(:_parent)
|
27
|
-
end
|
28
|
-
|
29
|
-
it "requires a parent" do
|
30
|
-
expect do
|
31
|
-
MongoDoc::ParentProxy.new(nil, @assoc_name)
|
32
|
-
end.should raise_error
|
33
|
-
end
|
34
|
-
|
35
|
-
it "requires an association name" do
|
36
|
-
expect do
|
37
|
-
MongoDoc::ParentProxy.new(@parent, nil)
|
38
|
-
end.should raise_error
|
39
|
-
end
|
40
|
-
|
41
|
-
it "inserts the association name the _path_to_root" do
|
42
|
-
subject._path_to_root(Child.new, :name1 => 'value1', :name2 => 'value2').should == {"#{@assoc_name}.name1" => 'value1', "#{@assoc_name}.name2" => "value2"}
|
43
|
-
end
|
44
|
-
end
|
data/spec/proxy_spec.rb
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
|
3
|
-
describe MongoDoc::Proxy do
|
4
|
-
class ProxyTest
|
5
|
-
include MongoDoc::Document
|
6
|
-
|
7
|
-
key :name
|
8
|
-
end
|
9
|
-
|
10
|
-
let(:root) { stub('root', :register_save_observer => nil) }
|
11
|
-
let(:proxy) { MongoDoc::Proxy.new(:assoc_name => 'has_many_name', :collection_class => ProxyTest, :root => root, :parent => root) }
|
12
|
-
|
13
|
-
context "#<<" do
|
14
|
-
let(:item) { ProxyTest.new }
|
15
|
-
|
16
|
-
it "appends the item to the collection" do
|
17
|
-
(proxy << item).should include(item)
|
18
|
-
end
|
19
|
-
|
20
|
-
context "when the item is a Hash" do
|
21
|
-
let(:hash) {{:name => 'hash'}}
|
22
|
-
|
23
|
-
it "calls build when the item is a hash" do
|
24
|
-
proxy.should_receive(:build).with(hash).and_return(item)
|
25
|
-
proxy << hash
|
26
|
-
end
|
27
|
-
|
28
|
-
it "registers a save observer" do
|
29
|
-
proxy.stub(:build).and_return(item)
|
30
|
-
root.should_receive(:register_save_observer)
|
31
|
-
proxy << hash
|
32
|
-
end
|
33
|
-
|
34
|
-
it "sets the root" do
|
35
|
-
proxy.stub(:build).and_return(item)
|
36
|
-
proxy << hash
|
37
|
-
item._root.should == root
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
context "when the item is not a MongoDoc::Document" do
|
42
|
-
it "does not register a save observer" do
|
43
|
-
root.should_not_receive(:register_save_observer)
|
44
|
-
proxy << 'not_doc'
|
45
|
-
end
|
46
|
-
|
47
|
-
it "does not set the root" do
|
48
|
-
item.should_not_receive(:_root=)
|
49
|
-
proxy << 'not_doc'
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
context "when the item is a MongoDoc::Document" do
|
54
|
-
it "registers a save observer" do
|
55
|
-
root.should_receive(:register_save_observer)
|
56
|
-
proxy << item
|
57
|
-
end
|
58
|
-
|
59
|
-
it "sets the root" do
|
60
|
-
proxy << item
|
61
|
-
item._root.should == root
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
context "when the item is an array" do
|
66
|
-
it "adds the array" do
|
67
|
-
array = ['something else']
|
68
|
-
proxy << array
|
69
|
-
proxy.should include(array)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
context "#build" do
|
75
|
-
it "builds an object of the collection class from the hash attrs" do
|
76
|
-
name = 'built'
|
77
|
-
proxy.build({:name => name}).name.should == name
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|