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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
# File 'lib/couchdb_adapter/attachments.rb', line 12
def self.included(mod)
mod.class_eval do
def add_attachment(file, options = {})
assert_attachments_property
filename = File.basename(file.path)
content_type = options[:content_type] || begin
mime_types = MIME::Types.of(filename)
mime_types.empty? ? 'application/octet-stream' : mime_types.first.content_type
end
name = options[:name] || filename
data = file.read
if new_record? || !model.properties.has_property?(:rev)
self.attachments ||= {}
self.attachments[name] = {
'content_type' => content_type,
'data' => Base64.encode64(data).chomp,
}
else
adapter = repository.adapter
http = Net::HTTP.new(adapter.uri.host, adapter.uri.port)
uri = Addressable::URI.encode_component("#{attachment_path(name)}?rev=#{self.rev}")
= {
'Content-Length' => data.size.to_s,
'Content-Type' => content_type,
}
http.put(uri, data, )
self.reload
end
end
def delete_attachment(name)
assert_attachments_property
attachment = self.attachments[name] if self.attachments
unless attachment
return false
end
response = unless new_record?
adapter = repository.adapter
http = Net::HTTP.new(adapter.uri.host, adapter.uri.port)
uri = Addressable::URI.encode_component("#{attachment_path(name)}?rev=#{self.rev}")
http.delete(uri, 'Content-Type' => attachment['content_type'])
end
if response && !response.kind_of?(Net::HTTPSuccess)
false
else
self.attachments.delete(name)
self.attachments = nil if self.attachments.empty?
true
end
end
def get_attachment(name)
assert_attachments_property
attachment = self.attachments[name] if self.attachments
unless self.id && attachment
nil
else
adapter = repository.adapter
http = Net::HTTP.new(adapter.uri.host, adapter.uri.port)
uri = Addressable::URI.encode_component(attachment_path(name))
response, data = http.get(uri, 'Content-Type' => attachment['content_type'])
unless response.kind_of?(Net::HTTPSuccess)
nil
else
data
end
end
end
private
def attachment_path(name)
if new_record?
nil
else
"/#{repository.adapter.escaped_db_name}/#{self.id}/#{name}"
end
end
def assert_attachments_property
property = model.properties[:attachments]
unless property &&
property.type == DataMapper::Types::JsonObject &&
property.field == '_attachments'
raise ArgumentError, "Attachments require property :attachments, JsonObject, :field => '_attachments'"
end
end
end
end
|