/
many_to_one.rb
87 lines (68 loc) · 2.78 KB
/
many_to_one.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
require __DIR__.parent + 'associations'
require __DIR__ + 'relationship'
module DataMapper
module Associations
module ManyToOne
def many_to_one(name, options = {})
raise ArgumentError, "+name+ should be a Symbol, but was #{name.class}", caller unless Symbol === name
raise ArgumentError, "+options+ should be a Hash, but was #{options.class}", caller unless Hash === options
child_model_name = DataMapper::Inflection.demodulize(self.name)
parent_model_name = options[:class_name] || DataMapper::Inflection.classify(name)
relationships[name] = Relationship.new(
name,
repository.name,
child_model_name,
nil,
parent_model_name,
nil
)
class_eval <<-EOS, __FILE__, __LINE__
def #{name}
#{name}_association.parent
end
def #{name}=(value)
#{name}_association.parent = value
end
private
def #{name}_association
@#{name}_association ||= begin
relationship = self.class.relationships[:#{name}]
association = relationship.with_child(self, Instance) do |repository, child_key, parent_key, parent_model, child_resource|
repository.all(parent_model, parent_key.to_query(child_key.get(child_resource))).first
end
child_associations << association
association
end
end
EOS
relationships[name]
end
class Instance
def parent
@parent_resource ||= @parent_loader.call
end
def parent=(parent_resource)
@parent_resource = parent_resource
@relationship.attach_parent(@child_resource, @parent_resource) if @parent_resource.nil? || !@parent_resource.new_record?
end
def loaded?
!defined?(@parent_resource)
end
def save
if parent.new_record?
repository(@relationship.repository_name).save(parent)
@relationship.attach_parent(@child_resource, parent)
end
end
private
def initialize(relationship, child_resource, &parent_loader)
# raise ArgumentError, "+relationship+ should be a DataMapper::Association::Relationship, but was #{relationship.class}", caller unless Relationship === relationship
# raise ArgumentError, "+child_resource+ should be a DataMapper::Resource, but was #{child_resource.class}", caller unless Resource === child_resource
@relationship = relationship
@child_resource = child_resource
@parent_loader = parent_loader
end
end # class Instance
end # module ManyToOne
end # module Associations
end # module DataMapper