dm-mongo-adapter 0.2.0.pre1
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/.gitignore +9 -0
- data/LICENSE +20 -0
- data/README.rdoc +130 -0
- data/Rakefile +36 -0
- data/TODO +33 -0
- data/VERSION.yml +5 -0
- data/bin/console +31 -0
- data/dm-mongo-adapter.gemspec +154 -0
- data/lib/mongo_adapter.rb +71 -0
- data/lib/mongo_adapter/adapter.rb +255 -0
- data/lib/mongo_adapter/aggregates.rb +21 -0
- data/lib/mongo_adapter/conditions.rb +100 -0
- data/lib/mongo_adapter/embedded_model.rb +187 -0
- data/lib/mongo_adapter/embedded_resource.rb +134 -0
- data/lib/mongo_adapter/embedments/one_to_many.rb +139 -0
- data/lib/mongo_adapter/embedments/one_to_one.rb +53 -0
- data/lib/mongo_adapter/embedments/relationship.rb +258 -0
- data/lib/mongo_adapter/migrations.rb +45 -0
- data/lib/mongo_adapter/model.rb +89 -0
- data/lib/mongo_adapter/model/embedment.rb +215 -0
- data/lib/mongo_adapter/modifier.rb +85 -0
- data/lib/mongo_adapter/query.rb +252 -0
- data/lib/mongo_adapter/query/java_script.rb +145 -0
- data/lib/mongo_adapter/resource.rb +147 -0
- data/lib/mongo_adapter/types/date.rb +28 -0
- data/lib/mongo_adapter/types/date_time.rb +28 -0
- data/lib/mongo_adapter/types/db_ref.rb +65 -0
- data/lib/mongo_adapter/types/discriminator.rb +32 -0
- data/lib/mongo_adapter/types/object_id.rb +72 -0
- data/lib/mongo_adapter/types/objects.rb +31 -0
- data/script/performance.rb +260 -0
- data/spec/legacy/README +6 -0
- data/spec/legacy/adapter_shared_spec.rb +299 -0
- data/spec/legacy/adapter_spec.rb +174 -0
- data/spec/legacy/associations_spec.rb +140 -0
- data/spec/legacy/embedded_resource_spec.rb +157 -0
- data/spec/legacy/embedments_spec.rb +177 -0
- data/spec/legacy/modifier_spec.rb +81 -0
- data/spec/legacy/property_spec.rb +51 -0
- data/spec/legacy/spec_helper.rb +3 -0
- data/spec/legacy/sti_spec.rb +53 -0
- data/spec/lib/cleanup_models.rb +32 -0
- data/spec/lib/raw_connections.rb +11 -0
- data/spec/public/embedded_collection_spec.rb +61 -0
- data/spec/public/embedded_resource_spec.rb +220 -0
- data/spec/public/model/embedment_spec.rb +186 -0
- data/spec/public/model_spec.rb +37 -0
- data/spec/public/resource_spec.rb +564 -0
- data/spec/public/shared/model_embedments_spec.rb +338 -0
- data/spec/public/shared/object_id_shared_spec.rb +56 -0
- data/spec/public/types/df_ref_spec.rb +6 -0
- data/spec/public/types/discriminator_spec.rb +118 -0
- data/spec/public/types/embedded_array_spec.rb +55 -0
- data/spec/public/types/embedded_hash_spec.rb +83 -0
- data/spec/public/types/object_id_spec.rb +6 -0
- data/spec/rcov.opts +6 -0
- data/spec/semipublic/embedded_model_spec.rb +43 -0
- data/spec/semipublic/model/embedment_spec.rb +42 -0
- data/spec/semipublic/resource_spec.rb +70 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +45 -0
- data/tasks/spec.rake +37 -0
- data/tasks/yard.rake +9 -0
- data/tasks/yardstick.rake +21 -0
- metadata +215 -0
@@ -0,0 +1,134 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Mongo
|
3
|
+
module EmbeddedResource
|
4
|
+
# Raised when trying to save an EmbeddedResource which doesn't have a
|
5
|
+
# parent set.
|
6
|
+
class MissingParentError < StandardError; end
|
7
|
+
|
8
|
+
include Types
|
9
|
+
include DataMapper::Resource
|
10
|
+
|
11
|
+
def self.included(base)
|
12
|
+
base.extend(DataMapper::Mongo::EmbeddedModel)
|
13
|
+
end
|
14
|
+
|
15
|
+
# @api public
|
16
|
+
alias_method :model, :class
|
17
|
+
|
18
|
+
# Returns the resource to which this EmbeddedResource belongs.
|
19
|
+
#
|
20
|
+
# @return [DataMapper::Mongo::Resource]
|
21
|
+
# The parent
|
22
|
+
#
|
23
|
+
# @api public
|
24
|
+
attr_reader :parent
|
25
|
+
|
26
|
+
# Gets all the attributes of the EmbeddedResource instance
|
27
|
+
#
|
28
|
+
# @param [Symbol] key_on
|
29
|
+
# Use this attribute of the Property as keys.
|
30
|
+
# defaults to :name. :field is useful for adapters
|
31
|
+
# :property or nil use the actual Property object.
|
32
|
+
#
|
33
|
+
# @return [Hash]
|
34
|
+
# All the attributes
|
35
|
+
#
|
36
|
+
# @overrides DataMapper::Resource#attributes
|
37
|
+
#
|
38
|
+
# @api public
|
39
|
+
def attributes(key_on=:name)
|
40
|
+
attributes = {}
|
41
|
+
|
42
|
+
fields.each do |property|
|
43
|
+
if model.public_method_defined?(name = property.name)
|
44
|
+
key = case key_on
|
45
|
+
when :name then name
|
46
|
+
when :field then property.field
|
47
|
+
else property
|
48
|
+
end
|
49
|
+
|
50
|
+
attributes[key] = __send__(name)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
attributes
|
55
|
+
end
|
56
|
+
|
57
|
+
# Sets the resource to which this EmbeddedResource belongs
|
58
|
+
#
|
59
|
+
# @param [DataMapper::Mongo::Resource] resource
|
60
|
+
# The new parent resource
|
61
|
+
#
|
62
|
+
# @api public
|
63
|
+
def parent=(resource)
|
64
|
+
@parent = resource
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns whether this resource (or rather, it's parent) has been saved
|
68
|
+
#
|
69
|
+
# @return [Boolean]
|
70
|
+
#
|
71
|
+
# @api public
|
72
|
+
def saved?
|
73
|
+
parent && parent.saved?
|
74
|
+
end
|
75
|
+
|
76
|
+
# Returns whether this resource (or rather, it's parent) is unsaved
|
77
|
+
#
|
78
|
+
# @return [Boolean]
|
79
|
+
#
|
80
|
+
# @api public
|
81
|
+
def new?
|
82
|
+
!parent? || parent.new?
|
83
|
+
end
|
84
|
+
|
85
|
+
# Returns if the EmbeddedResource has a parent set
|
86
|
+
#
|
87
|
+
# @return [Boolean]
|
88
|
+
#
|
89
|
+
# @api public
|
90
|
+
def parent?
|
91
|
+
!parent.nil?
|
92
|
+
end
|
93
|
+
|
94
|
+
# Saves the EmbeddedResource by saving the parent
|
95
|
+
#
|
96
|
+
# @return [Boolean]
|
97
|
+
# Returns true if the resource was successfully saved, false
|
98
|
+
# otherwise
|
99
|
+
#
|
100
|
+
# @raise [MissingParentError]
|
101
|
+
# Raises a MissingParentError if a parent has not been set
|
102
|
+
#
|
103
|
+
# @api public
|
104
|
+
def save
|
105
|
+
if parent?
|
106
|
+
if parent.save
|
107
|
+
original_attributes.clear
|
108
|
+
true
|
109
|
+
end
|
110
|
+
else
|
111
|
+
raise MissingParentError, 'EmbeddedResource needs a parent to be ' \
|
112
|
+
'set before it can be saved'
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# Checks if the resource has unsaved changes
|
117
|
+
#
|
118
|
+
# @return [Boolean]
|
119
|
+
# True if resource may be persisted
|
120
|
+
#
|
121
|
+
# @api public
|
122
|
+
def dirty_self?
|
123
|
+
if original_attributes.any?
|
124
|
+
true
|
125
|
+
elsif new?
|
126
|
+
properties.any? { |property| property.default? }
|
127
|
+
else
|
128
|
+
false
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
end # EmbeddedResource
|
133
|
+
end # Mongo
|
134
|
+
end # DataMapper
|
@@ -0,0 +1,139 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Mongo
|
3
|
+
module Embedments
|
4
|
+
module OneToMany
|
5
|
+
class Relationship < Embedments::Relationship
|
6
|
+
# Loads and returns embedment target for given source
|
7
|
+
#
|
8
|
+
# @param [DataMapper::Mongo::Resource] source
|
9
|
+
# The resource whose relationship value is to be retrieved.
|
10
|
+
#
|
11
|
+
# @return [DataMapper::Collection]
|
12
|
+
#
|
13
|
+
# @api semipublic
|
14
|
+
def get(source, other_query = nil)
|
15
|
+
assert_kind_of 'source', source, source_model
|
16
|
+
|
17
|
+
unless loaded?(source)
|
18
|
+
set!(source, collection_for(source, other_query))
|
19
|
+
end
|
20
|
+
|
21
|
+
get!(source)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Sets and returns association target for given source
|
25
|
+
#
|
26
|
+
# @param [DataMapper::Mongo::Resource] source
|
27
|
+
# The parent resource whose target is to be set.
|
28
|
+
# @param [DataMapper::Mongo::EmbeddedResource] targets
|
29
|
+
# The embedded resources to be set to the relationship
|
30
|
+
# @param [Boolean] loading
|
31
|
+
# Do the attributes have to be loaded before being set? Setting
|
32
|
+
# this to true will typecase the attributes, and set the
|
33
|
+
# original_values on the resource.
|
34
|
+
#
|
35
|
+
# @api semipublic
|
36
|
+
def set(source, targets, loading=false)
|
37
|
+
assert_kind_of 'source', source, source_model
|
38
|
+
assert_kind_of 'targets', targets, Array
|
39
|
+
|
40
|
+
targets = targets.map do |target|
|
41
|
+
case target
|
42
|
+
when Hash
|
43
|
+
load_target(source, target)
|
44
|
+
when DataMapper::Mongo::EmbeddedResource
|
45
|
+
target.parent = source
|
46
|
+
target
|
47
|
+
else
|
48
|
+
raise ArgumentError, 'one-to-many embedment requires an ' \
|
49
|
+
'EmbeddedResource or a hash'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
set_original_attributes(source, targets) unless loading
|
54
|
+
|
55
|
+
unless loaded?(source)
|
56
|
+
set!(source, collection_for(source))
|
57
|
+
end
|
58
|
+
|
59
|
+
get!(source).replace(targets)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
# Creates a new collection instance for the source resources.
|
65
|
+
#
|
66
|
+
# @param [DataMapper::Mongo::Resource] source
|
67
|
+
# The resources to be wrapped in a Collection.
|
68
|
+
#
|
69
|
+
# @return [DataMapper::Collection]
|
70
|
+
#
|
71
|
+
# @api private
|
72
|
+
def collection_for(source, other_query=nil)
|
73
|
+
Collection.new(source, target_model)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Extends Array to ensure that each EmbeddedResource has it's +parent+
|
78
|
+
# attribute set.
|
79
|
+
class Collection < Array
|
80
|
+
# Returns the resource to which this collection belongs
|
81
|
+
#
|
82
|
+
# @return [DataMapper::Mongo::Resource]
|
83
|
+
# The resource to which the contained EmbeddedResource instances
|
84
|
+
# belong.
|
85
|
+
#
|
86
|
+
# @api semipublic
|
87
|
+
attr_reader :source
|
88
|
+
|
89
|
+
# @api semipublic
|
90
|
+
attr_reader :target_model
|
91
|
+
|
92
|
+
# Creates a new Collection instance
|
93
|
+
#
|
94
|
+
# @param [DataMapper::Mongo::Resource] source
|
95
|
+
# The resource to which the contained EmbeddedResource instances
|
96
|
+
# belong.
|
97
|
+
#
|
98
|
+
# @api semipublic
|
99
|
+
def initialize(source, target_model)
|
100
|
+
@source = source
|
101
|
+
@target_model = target_model
|
102
|
+
end
|
103
|
+
|
104
|
+
# Adds a new embedded resource to the collection
|
105
|
+
#
|
106
|
+
# @param [DataMapper::Mongo::EmbeddedResource] resource
|
107
|
+
# The embedded resource to be added.
|
108
|
+
#
|
109
|
+
# @api public
|
110
|
+
def <<(resource)
|
111
|
+
resource.parent = source
|
112
|
+
super(resource)
|
113
|
+
end
|
114
|
+
|
115
|
+
# TODO: document
|
116
|
+
# @api public
|
117
|
+
def dirty?
|
118
|
+
any? { |resource| resource.dirty? }
|
119
|
+
end
|
120
|
+
|
121
|
+
# TODO: document
|
122
|
+
# @api public
|
123
|
+
def save
|
124
|
+
source.save
|
125
|
+
end
|
126
|
+
|
127
|
+
# TODO: document
|
128
|
+
# @api public
|
129
|
+
def new(attributes={})
|
130
|
+
resource = target_model.new(attributes)
|
131
|
+
self. << resource
|
132
|
+
resource
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
end # OneToMany
|
137
|
+
end # Embedments
|
138
|
+
end # Mongo
|
139
|
+
end # DataMapper
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Mongo
|
3
|
+
module Embedments
|
4
|
+
module OneToOne
|
5
|
+
class Relationship < Embedments::Relationship
|
6
|
+
# Loads and returns embedment target for given source
|
7
|
+
#
|
8
|
+
# Returns a new instance of the target model if there isn't one set.
|
9
|
+
#
|
10
|
+
# @param [DataMapper::Mongo::Resource] source
|
11
|
+
# The resource whose relationship value is to be retrieved.
|
12
|
+
#
|
13
|
+
# @return [DataMapper::Mongo::Resource]
|
14
|
+
#
|
15
|
+
# @api semipublic
|
16
|
+
def get(source, other_query = nil)
|
17
|
+
get!(source)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Sets and returns association target for given source
|
21
|
+
#
|
22
|
+
# @param [DataMapper::Mongo::Resource] source
|
23
|
+
# The resource whose target is to be set.
|
24
|
+
# @param [DataMapper::Mongo::EmbeddedResource] target
|
25
|
+
# The value to be set to the target
|
26
|
+
# @param [Boolean] loading
|
27
|
+
# Do the attributes have to be loaded before being set? Setting
|
28
|
+
# this to true will typecase the attributes, and set the
|
29
|
+
# original_values on the resource.
|
30
|
+
#
|
31
|
+
# @api semipublic
|
32
|
+
def set(source, target, loading=false)
|
33
|
+
assert_kind_of 'source', source, source_model
|
34
|
+
assert_kind_of 'target', target, target_model, Hash, NilClass
|
35
|
+
|
36
|
+
unless target.nil?
|
37
|
+
if target.kind_of?(Hash)
|
38
|
+
target = load_target(source, target, loading)
|
39
|
+
else
|
40
|
+
target.parent = source
|
41
|
+
end
|
42
|
+
|
43
|
+
set_original_attributes(source, target) unless loading
|
44
|
+
end
|
45
|
+
|
46
|
+
set!(source, target)
|
47
|
+
end
|
48
|
+
|
49
|
+
end # Relationship
|
50
|
+
end # OneToOne
|
51
|
+
end # Embedments
|
52
|
+
end # Mongo
|
53
|
+
end # DataMapper
|
@@ -0,0 +1,258 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module Mongo
|
3
|
+
module Embedments
|
4
|
+
# Base class for embedment relationships. Each type of relationship
|
5
|
+
# (1 to 1, 1 to n) implements a subclass of this class with methods like
|
6
|
+
# get and set overridden.
|
7
|
+
class Relationship
|
8
|
+
include Extlib::Assertions
|
9
|
+
|
10
|
+
# Relationship name
|
11
|
+
#
|
12
|
+
# @example for :parent relationship in
|
13
|
+
#
|
14
|
+
# class VersionControl::Commit
|
15
|
+
# # ...
|
16
|
+
# belongs_to :parent
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# name is :parent
|
20
|
+
#
|
21
|
+
# @api semipublic
|
22
|
+
attr_reader :name
|
23
|
+
|
24
|
+
# Returns the model class used by the parent side of the relationship
|
25
|
+
#
|
26
|
+
# @return [Resource]
|
27
|
+
# Model for relationship parent
|
28
|
+
#
|
29
|
+
# @api semipublic
|
30
|
+
attr_reader :source_model
|
31
|
+
|
32
|
+
# Options used to set up this relationship
|
33
|
+
#
|
34
|
+
# @example for :author relationship in
|
35
|
+
#
|
36
|
+
# class VersionControl::Commit
|
37
|
+
# # ...
|
38
|
+
#
|
39
|
+
# belongs_to :author, :model => 'Person'
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# options is a hash with a single key, :model
|
43
|
+
#
|
44
|
+
# @api semipublic
|
45
|
+
attr_reader :options
|
46
|
+
|
47
|
+
# The name of the variable used to store the relationship
|
48
|
+
#
|
49
|
+
# @example for :commits relationship in
|
50
|
+
#
|
51
|
+
# class VersionControl::Branch
|
52
|
+
# # ...
|
53
|
+
#
|
54
|
+
# has n, :commits
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# instance variable name for source will be @commits
|
58
|
+
#
|
59
|
+
# @api semipublic
|
60
|
+
attr_reader :instance_variable_name
|
61
|
+
|
62
|
+
# Returns query options for relationship.
|
63
|
+
#
|
64
|
+
# For this base class, always returns query options has been
|
65
|
+
# initialized with. Overridden in subclasses.
|
66
|
+
#
|
67
|
+
# @api private
|
68
|
+
attr_reader :query
|
69
|
+
|
70
|
+
# Returns the visibility for the source accessor
|
71
|
+
#
|
72
|
+
# @return [Symbol]
|
73
|
+
# the visibility for the accessor added to the source
|
74
|
+
#
|
75
|
+
# @api semipublic
|
76
|
+
attr_reader :reader_visibility
|
77
|
+
|
78
|
+
# Returns the visibility for the source accessor
|
79
|
+
#
|
80
|
+
# @return [Symbol]
|
81
|
+
# the visibility for the accessor added to the source
|
82
|
+
#
|
83
|
+
# @api semipublic
|
84
|
+
attr_reader :writer_visibility
|
85
|
+
|
86
|
+
# Loads and returns "other end" of the embedment
|
87
|
+
#
|
88
|
+
# Must be implemented in subclasses.
|
89
|
+
#
|
90
|
+
# @api semipublic
|
91
|
+
def get(resource, other_query = nil)
|
92
|
+
raise NotImplementedError, "#{self.class}#get not implemented"
|
93
|
+
end
|
94
|
+
|
95
|
+
# Gets "other end" of the embedment directly
|
96
|
+
#
|
97
|
+
# @api semipublic
|
98
|
+
def get!(resource)
|
99
|
+
resource.instance_variable_get(instance_variable_name)
|
100
|
+
end
|
101
|
+
|
102
|
+
# Sets value of the "other end" of the embedment on given resource
|
103
|
+
#
|
104
|
+
# Must be implemented in subclasses.
|
105
|
+
#
|
106
|
+
# @api semipublic
|
107
|
+
def set(resource, association)
|
108
|
+
raise NotImplementedError, "#{self.class}#set not implemented"
|
109
|
+
end
|
110
|
+
|
111
|
+
# Sets "other end" of the embedment directly.
|
112
|
+
#
|
113
|
+
# @api semipublic
|
114
|
+
def set!(resource, association)
|
115
|
+
resource.instance_variable_set(instance_variable_name, association)
|
116
|
+
end
|
117
|
+
|
118
|
+
# Returns the model class used by the child side of the relationship
|
119
|
+
#
|
120
|
+
# @return [Resource]
|
121
|
+
# Model for relationship child
|
122
|
+
#
|
123
|
+
# @api semipublic
|
124
|
+
def target_model
|
125
|
+
if defined?(@target_model)
|
126
|
+
@target_model
|
127
|
+
elsif @target_model_name
|
128
|
+
@target_model = (@source_model || Object).find_const(@target_model_name)
|
129
|
+
else
|
130
|
+
raise "No model type defined for relationship #{@name}"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# @api semipublic
|
135
|
+
def set_original_attributes(resource, association)
|
136
|
+
Array(association).each do |association|
|
137
|
+
resource.original_attributes[self] = association.original_attributes if association.dirty?
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Checks if "other end" of the embedment is loaded on given resource
|
142
|
+
#
|
143
|
+
# @api semipublic
|
144
|
+
def loaded?(resource)
|
145
|
+
assert_kind_of 'resource', resource, source_model
|
146
|
+
|
147
|
+
resource.instance_variable_defined?(instance_variable_name)
|
148
|
+
end
|
149
|
+
|
150
|
+
# Creates an instance of the target model with its attributes
|
151
|
+
#
|
152
|
+
# @param [DataMapper::Mongo::Resource] source
|
153
|
+
# The source model to which the target belongs.
|
154
|
+
# @param [Hash, #to_mash] attributes
|
155
|
+
# The attributes to be set on the embedded resource.
|
156
|
+
# @param [Boolean] loading
|
157
|
+
# Do the attributes have to be loaded before being set? Setting
|
158
|
+
# this to true will typecase the attributes, and set the
|
159
|
+
# original_values on the resource.
|
160
|
+
#
|
161
|
+
# @return [DataMapper::Mongo::EmbeddedResource]
|
162
|
+
# The initialized embedded resource instance.
|
163
|
+
#
|
164
|
+
# @api semipublic
|
165
|
+
def load_target(source, attributes, loading=false)
|
166
|
+
target = target_model.allocate
|
167
|
+
target.parent = source
|
168
|
+
|
169
|
+
attributes = attributes.to_mash
|
170
|
+
|
171
|
+
target_model.properties.each do |property|
|
172
|
+
property.send(loading ? :set! : :set, target, attributes[property.field])
|
173
|
+
end
|
174
|
+
|
175
|
+
target
|
176
|
+
end
|
177
|
+
|
178
|
+
# Creates and returns Query instance that represents the embedment
|
179
|
+
#
|
180
|
+
# The returned query can be used to fetch target resource(s)
|
181
|
+
# (ex.: articles) for given target resource (ex.: author).
|
182
|
+
#
|
183
|
+
# @return [DataMapper::Mongo::Query]
|
184
|
+
#
|
185
|
+
# @api semipublic
|
186
|
+
def query_for(source, other_query = nil)
|
187
|
+
Query.new
|
188
|
+
end
|
189
|
+
|
190
|
+
# Creates a hash of attributes for the relationship.
|
191
|
+
#
|
192
|
+
# @api semipublic
|
193
|
+
def value(relationship)
|
194
|
+
relationship.model.properties.map { |property| [property, property.get(relationship)] }.to_hash
|
195
|
+
end
|
196
|
+
|
197
|
+
# Test the resource to see if it is a valid target
|
198
|
+
#
|
199
|
+
# @param [Object] relationship
|
200
|
+
# The resource or collection to be tested
|
201
|
+
#
|
202
|
+
# @return [Boolean]
|
203
|
+
# True if the resource is valid
|
204
|
+
#
|
205
|
+
# @api semipublic
|
206
|
+
def valid?(relationship)
|
207
|
+
relationship.kind_of?(target_model)
|
208
|
+
end
|
209
|
+
|
210
|
+
# @api public
|
211
|
+
def method_missing(method, *args, &block)
|
212
|
+
target_model.send(method, args, &block)
|
213
|
+
end
|
214
|
+
|
215
|
+
private
|
216
|
+
|
217
|
+
# Creates a new Relationship instance
|
218
|
+
#
|
219
|
+
# @param [DataMapper::Mongo::EmbeddedModel, String] target_model
|
220
|
+
# The child side of the relationship.
|
221
|
+
# @param [DataMapper::Mongo::Model] source_model
|
222
|
+
# The parent side of the relationship.
|
223
|
+
# @param [Hash] options
|
224
|
+
# Options for customising the relationship.
|
225
|
+
#
|
226
|
+
# @option options [Symbol] :reader_visibility
|
227
|
+
# The visibility of the reader method created on the source model;
|
228
|
+
# one of public, protected or private.
|
229
|
+
# @option options [Symbol] :writer_visibility
|
230
|
+
# The visibility of the writer method created on the source model;
|
231
|
+
# one of public, protected or private.
|
232
|
+
#
|
233
|
+
def initialize(name, target_model, source_model, options={})
|
234
|
+
if target_model.kind_of?(EmbeddedModel)
|
235
|
+
@target_model = target_model
|
236
|
+
elsif target_model.nil?
|
237
|
+
# No model given, infer it from the name.
|
238
|
+
@target_model_name =
|
239
|
+
Extlib::Inflection.camelize(name.to_s.singular).freeze
|
240
|
+
else
|
241
|
+
# We were likely given a string as the target model -- perhaps
|
242
|
+
# because the user's app hasn't loaded yet; get the constant
|
243
|
+
# later in Relationship#target_model.
|
244
|
+
@target_model_name = target_model.to_str.dup.freeze
|
245
|
+
end
|
246
|
+
|
247
|
+
@name = name
|
248
|
+
@source_model = source_model
|
249
|
+
@instance_variable_name = "@#{@name}".freeze
|
250
|
+
@options = options.dup.freeze
|
251
|
+
@reader_visibility = @options.fetch(:reader_visibility, :public)
|
252
|
+
@writer_visibility = @options.fetch(:writer_visibility, :public)
|
253
|
+
end
|
254
|
+
|
255
|
+
end # Relationship
|
256
|
+
end # Embedments
|
257
|
+
end # Mongo
|
258
|
+
end # DataMapper
|