-
Notifications
You must be signed in to change notification settings - Fork 63
/
persistence.rb
192 lines (165 loc) · 5.94 KB
/
persistence.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
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
module ActiveFedora
# = Active Fedora Persistence
module Persistence
extend ActiveSupport::Concern
def new_record?
@ldp_source.new?
end
def persisted?
!(destroyed? || new_record?)
end
# Returns true if this object has been destroyed, otherwise returns false.
def destroyed?
@destroyed
end
# Saves a Base object, and any dirty attached files, then updates
# the Solr index for this object, unless option :update_index=>false is present.
# Indexing is also controlled by the `create_needs_index?' and `update_needs_index?' methods.
#
# @param [Hash] options
# @option options [Boolean] :update_index (true) set false to skip indexing
# @return [Boolean] true if save was successful, otherwise false
def save(options={})
raise ReadOnlyRecord if readonly?
new_record? ? create_record(options) : update_record(options)
end
def save!(options={})
save(options)
end
# Pushes the object and all of its new or dirty attached files into Fedora
def update(attributes)
self.attributes=attributes
save
end
alias update_attributes update
#Deletes a Base object, also deletes the info indexed in Solr, and
#the underlying inner_object. If this object is held in any relationships (ie inbound relationships
#outside of this object it will remove it from those items rels-ext as well
def delete
return self if new_record?
@destroyed = true
reflections.each_pair do |name, reflection|
if reflection.macro == :has_many
association(name.to_sym).delete_all
end
end
id = self.id ## cache so it's still available after delete
# Clear out the ETag
@ldp_source = build_ldp_resource(id)
begin
@ldp_source.delete
rescue Ldp::NotFound
raise ObjectNotFoundError, "Unable to find #{id} in the repository"
end
ActiveFedora::SolrService.delete(id) if ENABLE_SOLR_UPDATES
freeze
end
def destroy
raise ReadOnlyRecord if readonly?
delete
end
def eradicate
self.class.eradicate(self.id)
end
module ClassMethods
# Creates an object (or multiple objects) and saves it to the repository, if validations pass.
# The resulting object is returned whether the object was saved successfully to the repository or not.
#
# The +attributes+ parameter can be either be a Hash or an Array of Hashes. These Hashes describe the
# attributes on the objects that are to be created.
#
# ==== Examples
# # Create a single new object
# User.create(:first_name => 'Jamie')
#
# # Create an Array of new objects
# User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }])
#
# # Create a single object and pass it into a block to set other attributes.
# User.create(:first_name => 'Jamie') do |u|
# u.is_admin = false
# end
#
# # Creating an Array of new objects using a block, where the block is executed for each object:
# User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }]) do |u|
# u.is_admin = false
# end
def create(attributes = nil, &block)
if attributes.is_a?(Array)
attributes.collect { |attr| create(attr, &block) }
else
object = new(attributes, &block)
object.save
object
end
end
# Removes an object's tombstone so another object with the same uri may be created.
# NOTE: this is in violation of the linked data platform and is only here as a convience
# method. It shouldn't be used in the general course of repository operations.
def eradicate(uri)
gone?(uri) ? delete_tombstone(uri) : false
end
private
def gone? uri
ActiveFedora::Base.find(uri)
false
rescue Ldp::Gone
true
end
def delete_tombstone uri
tombstone = ActiveFedora::Base.id_to_uri(uri) + "/fcr:tombstone"
ActiveFedora.fedora.connection.delete(tombstone)
true
end
end
private
# Deals with preparing new object to be saved to Fedora, then pushes it and its attached files into Fedora.
def create_record(options = {})
assign_rdf_subject
serialize_attached_files
@ldp_source = @ldp_source.create
@resource = nil
assign_uri_to_attached_files
save_attached_files
refresh
end
def update_record(options = {})
serialize_attached_files
execute_sparql_update
save_attached_files
refresh
end
def refresh
@ldp_source = build_ldp_resource(id)
@resource = nil
end
def execute_sparql_update
change_set = ChangeSet.new(self, self.resource, self.changed_attributes.keys)
return true if change_set.empty?
ActiveFedora.fedora.ldp_resource_service.update(change_set, self.class, id)
end
# Override to tie in an ID minting service
def assign_id
end
# This is only used when creating a new record. If the object doesn't have an id
# and assign_id can mint an id for the object, then assign it to the resource.
# Otherwise the resource will have the id assigned by the LDP server
def assign_rdf_subject
@ldp_source = if !id && new_id = assign_id
LdpResource.new(ActiveFedora.fedora.connection, self.class.id_to_uri(new_id), @resource)
else
LdpResource.new(ActiveFedora.fedora.connection, @ldp_source.subject, @resource, ActiveFedora.fedora.host + ActiveFedora.fedora.base_path)
end
end
def assign_uri_to_attached_files
attached_files.each do |name, ds|
ds.uri= "#{uri}/#{name}"
end
end
def save_attached_files
attached_files.select { |_, file| file.changed? }.each do |_, file|
file.save # Don't call save! because if the content_changed? returns false, it'll raise an error.
end
end
end
end