active-fedora 9.10.0.pre1 → 9.10.0.pre2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +7 -0
- data/lib/active_fedora.rb +4 -0
- data/lib/active_fedora/associations/collection_association.rb +7 -7
- data/lib/active_fedora/attribute_assignment.rb +55 -0
- data/lib/active_fedora/attribute_methods.rb +149 -47
- data/lib/active_fedora/attribute_methods/read.rb +29 -44
- data/lib/active_fedora/attribute_methods/write.rb +16 -19
- data/lib/active_fedora/attributes.rb +5 -17
- data/lib/active_fedora/base.rb +2 -0
- data/lib/active_fedora/callbacks.rb +9 -9
- data/lib/active_fedora/common.rb +67 -0
- data/lib/active_fedora/core.rb +9 -22
- data/lib/active_fedora/errors.rb +29 -0
- data/lib/active_fedora/file.rb +5 -57
- data/lib/active_fedora/file_persistence.rb +27 -0
- data/lib/active_fedora/identifiable.rb +0 -5
- data/lib/active_fedora/indexing.rb +2 -2
- data/lib/active_fedora/inheritance.rb +34 -0
- data/lib/active_fedora/persistence.rb +22 -4
- data/lib/active_fedora/scoping.rb +80 -2
- data/lib/active_fedora/scoping/default.rb +6 -2
- data/lib/active_fedora/scoping/named.rb +141 -1
- data/lib/active_fedora/version.rb +1 -1
- data/spec/integration/collection_association_spec.rb +34 -3
- data/spec/integration/file_spec.rb +1 -1
- data/spec/integration/persistence_spec.rb +1 -1
- data/spec/unit/attributes_spec.rb +13 -7
- data/spec/unit/file_spec.rb +2 -2
- data/spec/unit/validations_spec.rb +1 -1
- metadata +6 -2
@@ -1,18 +1,24 @@
|
|
1
1
|
module ActiveFedora
|
2
2
|
module AttributeMethods
|
3
3
|
module Write
|
4
|
-
|
5
|
-
|
4
|
+
module ClassMethods
|
5
|
+
protected
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
def define_method_attribute=(name)
|
8
|
+
name = name.to_s
|
9
|
+
safe_name = name.unpack('h*'.freeze).first
|
10
|
+
ActiveFedora::AttributeMethods::AttrNames.set_name_cache safe_name, name
|
11
|
+
|
12
|
+
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
13
|
+
def __temp__#{safe_name}=(value)
|
14
|
+
name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{safe_name}
|
15
|
+
write_attribute(name, value)
|
16
|
+
end
|
17
|
+
alias_method #{(name + '=').inspect}, :__temp__#{safe_name}=
|
18
|
+
undef_method :__temp__#{safe_name}=
|
19
|
+
STR
|
12
20
|
end
|
13
|
-
|
14
|
-
end
|
15
|
-
end.new
|
21
|
+
end
|
16
22
|
|
17
23
|
extend ActiveSupport::Concern
|
18
24
|
|
@@ -33,15 +39,6 @@ module ActiveFedora
|
|
33
39
|
def attribute=(attribute_name, value)
|
34
40
|
write_attribute(attribute_name, value)
|
35
41
|
end
|
36
|
-
|
37
|
-
module ClassMethods
|
38
|
-
def define_method_attribute=(name)
|
39
|
-
method = WriterMethodCache[name.to_s]
|
40
|
-
generated_attribute_methods.module_eval do
|
41
|
-
define_method "#{name}=", method
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
42
|
end
|
46
43
|
end
|
47
44
|
end
|
@@ -19,12 +19,6 @@ module ActiveFedora
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
def attributes=(properties)
|
23
|
-
sanitize_for_mass_assignment(properties).each do |k, v|
|
24
|
-
respond_to?(:"#{k}=") ? send(:"#{k}=", v) : raise(UnknownAttributeError, "#{self.class} does not have an attribute `#{k}'")
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
22
|
def attribute_names
|
29
23
|
self.class.attribute_names
|
30
24
|
end
|
@@ -33,13 +27,6 @@ module ActiveFedora
|
|
33
27
|
attribute_names.each_with_object("id" => id) { |key, hash| hash[key] = self[key] }
|
34
28
|
end
|
35
29
|
|
36
|
-
# Calling inspect may trigger a bunch of datastream loads, but it's mainly for debugging, so no worries.
|
37
|
-
def inspect
|
38
|
-
values = ["id: #{id.inspect}"]
|
39
|
-
values << self.class.attribute_names.map { |attr| "#{attr}: #{self[attr].inspect}" }
|
40
|
-
"#<#{self.class} #{values.flatten.join(', ')}>"
|
41
|
-
end
|
42
|
-
|
43
30
|
def [](key)
|
44
31
|
if assoc = association(key.to_sym)
|
45
32
|
# This is for id attributes stored in the rdf graph.
|
@@ -93,14 +80,14 @@ module ActiveFedora
|
|
93
80
|
private
|
94
81
|
|
95
82
|
def array_reader(field, *args)
|
96
|
-
raise UnknownAttributeError,
|
83
|
+
raise UnknownAttributeError.new(self, field) unless self.class.delegated_attributes.key?(field)
|
97
84
|
|
98
85
|
val = self.class.delegated_attributes[field].reader(self, *args)
|
99
86
|
self.class.multiple?(field) ? val : val.first
|
100
87
|
end
|
101
88
|
|
102
89
|
def array_setter(field, args)
|
103
|
-
raise UnknownAttributeError,
|
90
|
+
raise UnknownAttributeError.new(self, field) unless self.class.delegated_attributes.key?(field)
|
104
91
|
if self.class.multiple?(field)
|
105
92
|
if args.present? && !args.respond_to?(:each)
|
106
93
|
raise ArgumentError, "You attempted to set the attribute `#{field}' on `#{self.class}' to a scalar value. However, this attribute is declared as being multivalued."
|
@@ -156,8 +143,8 @@ module ActiveFedora
|
|
156
143
|
options = fields.pop
|
157
144
|
delegate_target = options.delete(:datastream)
|
158
145
|
raise ArgumentError, "You must provide a datastream to has_attributes" if delegate_target.blank?
|
159
|
-
Deprecation.warn(Attributes, "has_attributes is deprecated and will be removed in ActiveFedora 10.0. Instead use:\n property #{fields.first.inspect}, delegate_to: '#{delegate_target}', ...")
|
160
146
|
|
147
|
+
Deprecation.warn Attributes, "has_attributes is deprecated and will be removed in ActiveFedora 10.0. Consider using the Form pattern to save all related models or directly delegate the properties and save the target separately"
|
161
148
|
define_delegated_accessor(fields, delegate_target, options, &block)
|
162
149
|
end
|
163
150
|
|
@@ -172,7 +159,7 @@ module ActiveFedora
|
|
172
159
|
# @param [Symbol] field the field to query
|
173
160
|
# @return [Boolean]
|
174
161
|
def multiple?(field)
|
175
|
-
raise UnknownAttributeError,
|
162
|
+
raise UnknownAttributeError.new(nil, field, self) unless delegated_attributes.key?(field)
|
176
163
|
delegated_attributes[field].multiple
|
177
164
|
end
|
178
165
|
|
@@ -180,6 +167,7 @@ module ActiveFedora
|
|
180
167
|
if properties.key?(:predicate)
|
181
168
|
define_active_triple_accessor(name, properties, &block)
|
182
169
|
elsif properties.key?(:delegate_to)
|
170
|
+
Deprecation.warn Attributes, "delegated properties are deprecated and will be removed in ActiveFedora 10.0. Consider using the Form pattern to save all related models or directly delegate the properties and save the target separately"
|
183
171
|
define_delegated_accessor([name], properties.delete(:delegate_to), properties.reverse_merge(multiple: true), &block)
|
184
172
|
else
|
185
173
|
raise "You must provide `:delegate_to' or `:predicate' options to property"
|
data/lib/active_fedora/base.rb
CHANGED
@@ -26,8 +26,10 @@ module ActiveFedora
|
|
26
26
|
extend ActiveSupport::DescendantsTracker
|
27
27
|
extend LdpCache::ClassMethods
|
28
28
|
|
29
|
+
include AttributeAssignment
|
29
30
|
include Core
|
30
31
|
include Identifiable
|
32
|
+
include Inheritance
|
31
33
|
include Persistence
|
32
34
|
include Indexing
|
33
35
|
include Scoping
|
@@ -227,21 +227,21 @@ module ActiveFedora
|
|
227
227
|
end
|
228
228
|
|
229
229
|
def destroy(*) #:nodoc:
|
230
|
-
|
230
|
+
_run_destroy_callbacks { super }
|
231
231
|
end
|
232
232
|
|
233
233
|
private
|
234
234
|
|
235
|
-
def
|
236
|
-
|
237
|
-
run_callbacks(:save) { super }
|
238
|
-
end
|
235
|
+
def create_or_update(*)
|
236
|
+
_run_save_callbacks { super }
|
239
237
|
end
|
240
238
|
|
241
|
-
def
|
242
|
-
|
243
|
-
|
244
|
-
|
239
|
+
def _create_record(*) #:nodoc:
|
240
|
+
_run_create_callbacks { super }
|
241
|
+
end
|
242
|
+
|
243
|
+
def _update_record(*) #:nodoc:
|
244
|
+
_run_update_callbacks { super }
|
245
245
|
end
|
246
246
|
end
|
247
247
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module ActiveFedora
|
2
|
+
module Common
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
def initialize_generated_modules # :nodoc:
|
7
|
+
generated_association_methods
|
8
|
+
end
|
9
|
+
|
10
|
+
def generated_association_methods
|
11
|
+
@generated_association_methods ||= begin
|
12
|
+
mod = const_set(:GeneratedAssociationMethods, Module.new)
|
13
|
+
include mod
|
14
|
+
mod
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def ldp_source
|
20
|
+
@ldp_source
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns true if +comparison_object+ is the same exact object, or +comparison_object+
|
24
|
+
# is of the same type and +self+ has an ID and it is equal to +comparison_object.id+.
|
25
|
+
#
|
26
|
+
# Note that new records are different from any other record by definition, unless the
|
27
|
+
# other record is the receiver itself.
|
28
|
+
#
|
29
|
+
# Note also that destroying a record preserves its ID in the model instance, so deleted
|
30
|
+
# models are still comparable.
|
31
|
+
def ==(other)
|
32
|
+
other.equal?(self) ||
|
33
|
+
(other.instance_of?(self.class) &&
|
34
|
+
!id.nil? &&
|
35
|
+
other.id == id)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Allows sort on objects
|
39
|
+
def <=>(other)
|
40
|
+
if other.is_a?(self.class)
|
41
|
+
to_key <=> other.to_key
|
42
|
+
else
|
43
|
+
super
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Freeze datastreams such that they can be loaded from Fedora, but can't be changed
|
48
|
+
def freeze
|
49
|
+
@frozen = true
|
50
|
+
end
|
51
|
+
|
52
|
+
def frozen?
|
53
|
+
@frozen.present?
|
54
|
+
end
|
55
|
+
|
56
|
+
# Returns +true+ if the record is read only. Records loaded through joins with piggy-back
|
57
|
+
# attributes will be marked as read only since they cannot be saved.
|
58
|
+
def readonly?
|
59
|
+
@readonly
|
60
|
+
end
|
61
|
+
|
62
|
+
# Marks this record as read only.
|
63
|
+
def readonly!
|
64
|
+
@readonly = true
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/active_fedora/core.rb
CHANGED
@@ -2,6 +2,7 @@ module ActiveFedora
|
|
2
2
|
module Core
|
3
3
|
extend ActiveSupport::Autoload
|
4
4
|
extend ActiveSupport::Concern
|
5
|
+
include ActiveFedora::Common
|
5
6
|
|
6
7
|
autoload :FedoraIdTranslator
|
7
8
|
autoload :FedoraUriTranslator
|
@@ -15,10 +16,6 @@ module ActiveFedora
|
|
15
16
|
mattr_accessor :logger, instance_writer: false
|
16
17
|
end
|
17
18
|
|
18
|
-
def ldp_source
|
19
|
-
@ldp_source
|
20
|
-
end
|
21
|
-
|
22
19
|
# Constructor. You may supply a custom +:id+, or we call the Fedora Rest API for the
|
23
20
|
# next available Fedora id, and mark as new object.
|
24
21
|
# Also, if +attrs+ does not contain +:id+ but does contain +:namespace+ it will pass the
|
@@ -31,7 +28,7 @@ module ActiveFedora
|
|
31
28
|
raise IllegalOperation, "Attempting to recreate existing ldp_source: `#{ldp_source.subject}'" unless ldp_source.new?
|
32
29
|
assert_content_model
|
33
30
|
load_attached_files
|
34
|
-
|
31
|
+
assign_attributes(attributes) if attributes
|
35
32
|
|
36
33
|
yield self if block_given?
|
37
34
|
run_callbacks :initialize
|
@@ -77,13 +74,6 @@ module ActiveFedora
|
|
77
74
|
self
|
78
75
|
end
|
79
76
|
|
80
|
-
def ==(other)
|
81
|
-
other.equal?(self) ||
|
82
|
-
(other.instance_of?(self.class) &&
|
83
|
-
other.id == id &&
|
84
|
-
!other.new_record?)
|
85
|
-
end
|
86
|
-
|
87
77
|
def freeze
|
88
78
|
@resource.freeze
|
89
79
|
# @attributes = @attributes.clone.freeze
|
@@ -93,15 +83,14 @@ module ActiveFedora
|
|
93
83
|
|
94
84
|
delegate :frozen?, to: :attached_files
|
95
85
|
|
96
|
-
# Returns
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
86
|
+
# Returns the contents of the record as a nicely formatted string.
|
87
|
+
def inspect
|
88
|
+
inspection = ["id: #{id.inspect}"]
|
89
|
+
inspection += self.class.attribute_names.collect do |name|
|
90
|
+
"#{name}: #{attribute_for_inspect(name)}" if has_attribute?(name)
|
91
|
+
end
|
101
92
|
|
102
|
-
|
103
|
-
def readonly!
|
104
|
-
@readonly = true
|
93
|
+
"#<#{self.class} #{inspection.compact.join(', ')}>"
|
105
94
|
end
|
106
95
|
|
107
96
|
protected
|
@@ -113,8 +102,6 @@ module ActiveFedora
|
|
113
102
|
end
|
114
103
|
|
115
104
|
module ClassMethods
|
116
|
-
SLASH = '/'.freeze
|
117
|
-
|
118
105
|
def generated_association_methods
|
119
106
|
@generated_association_methods ||= begin
|
120
107
|
mod = const_set(:GeneratedAssociationMethods, Module.new)
|
data/lib/active_fedora/errors.rb
CHANGED
@@ -9,6 +9,13 @@ module ActiveFedora #:nodoc:
|
|
9
9
|
|
10
10
|
# Raised when attempting to access an attribute that has not been defined
|
11
11
|
class UnknownAttributeError < NoMethodError
|
12
|
+
attr_reader :record, :attribute
|
13
|
+
|
14
|
+
def initialize(record, attribute, klass = nil)
|
15
|
+
@record = record
|
16
|
+
@attribute = attribute
|
17
|
+
super("unknown attribute '#{attribute}' for #{klass || @record.class}.")
|
18
|
+
end
|
12
19
|
end
|
13
20
|
|
14
21
|
# Raised when there is an error with the configuration files.
|
@@ -34,6 +41,9 @@ module ActiveFedora #:nodoc:
|
|
34
41
|
class AssociationTypeMismatch < ActiveFedoraError
|
35
42
|
end
|
36
43
|
|
44
|
+
class AssociationNotFoundError < ConfigurationError #:nodoc:
|
45
|
+
end
|
46
|
+
|
37
47
|
# Raised when ActiveFedora cannot find the predicate corresponding to the given property
|
38
48
|
# in the predicate registy
|
39
49
|
class UnregisteredPredicateError < ActiveFedoraError
|
@@ -44,6 +54,25 @@ module ActiveFedora #:nodoc:
|
|
44
54
|
class RecordNotSaved < ActiveFedoraError
|
45
55
|
end
|
46
56
|
|
57
|
+
# Raised by {ActiveFedora::Base#destroy!}[rdoc-ref:Persistence#destroy!]
|
58
|
+
# when a call to {#destroy}[rdoc-ref:Persistence#destroy!]
|
59
|
+
# would return false.
|
60
|
+
#
|
61
|
+
# begin
|
62
|
+
# complex_operation_that_internally_calls_destroy!
|
63
|
+
# rescue ActiveFedora::RecordNotDestroyed => invalid
|
64
|
+
# puts invalid.record.errors
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
class RecordNotDestroyed < ActiveFedoraError
|
68
|
+
attr_reader :record
|
69
|
+
|
70
|
+
def initialize(message = nil, record = nil)
|
71
|
+
@record = record
|
72
|
+
super(message)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
47
76
|
# Raised on attempt to update record that is instantiated as read only.
|
48
77
|
class ReadOnlyRecord < ActiveFedoraError
|
49
78
|
end
|
data/lib/active_fedora/file.rb
CHANGED
@@ -12,13 +12,16 @@ module ActiveFedora
|
|
12
12
|
autoload :Streaming
|
13
13
|
autoload :Attributes
|
14
14
|
|
15
|
+
include Common
|
15
16
|
include ActiveFedora::File::Attributes
|
16
17
|
include ActiveFedora::File::Streaming
|
17
|
-
include ActiveFedora::
|
18
|
+
include ActiveFedora::FilePersistence
|
18
19
|
include ActiveFedora::Versionable
|
19
20
|
include ActiveModel::Dirty
|
21
|
+
include ActiveFedora::Callbacks
|
20
22
|
include AttributeMethods # allows 'content' to be tracked
|
21
23
|
include Identifiable
|
24
|
+
include Inheritance
|
22
25
|
include Scoping
|
23
26
|
|
24
27
|
generate_method 'content'
|
@@ -55,23 +58,11 @@ module ActiveFedora
|
|
55
58
|
end
|
56
59
|
|
57
60
|
@attributes = {}.with_indifferent_access
|
61
|
+
@readonly = false
|
58
62
|
yield self if block_given?
|
59
63
|
end
|
60
64
|
end
|
61
65
|
|
62
|
-
# @return [true, false] true if the objects are equal or when the objects have uris
|
63
|
-
# and the uris are equal
|
64
|
-
def ==(other)
|
65
|
-
super ||
|
66
|
-
other.instance_of?(self.class) &&
|
67
|
-
uri.value.present? &&
|
68
|
-
other.uri == uri
|
69
|
-
end
|
70
|
-
|
71
|
-
def ldp_source
|
72
|
-
@ldp_source || raise("NO source")
|
73
|
-
end
|
74
|
-
|
75
66
|
def described_by
|
76
67
|
raise "#{self} isn't persisted yet" if new_record?
|
77
68
|
links['describedby'].first
|
@@ -160,15 +151,6 @@ module ActiveFedora
|
|
160
151
|
false
|
161
152
|
end
|
162
153
|
|
163
|
-
# Freeze datastreams such that they can be loaded from Fedora, but can't be changed
|
164
|
-
def freeze
|
165
|
-
@frozen = true
|
166
|
-
end
|
167
|
-
|
168
|
-
def frozen?
|
169
|
-
@frozen.present?
|
170
|
-
end
|
171
|
-
|
172
154
|
# serializes any changed data into the content field
|
173
155
|
def serialize!
|
174
156
|
end
|
@@ -186,14 +168,6 @@ module ActiveFedora
|
|
186
168
|
local_or_remote_content(true)
|
187
169
|
end
|
188
170
|
|
189
|
-
def readonly?
|
190
|
-
false
|
191
|
-
end
|
192
|
-
|
193
|
-
def destroy(*)
|
194
|
-
run_callbacks(:destroy) { super }
|
195
|
-
end
|
196
|
-
|
197
171
|
def self.relation
|
198
172
|
FileRelation.new(self)
|
199
173
|
end
|
@@ -224,32 +198,6 @@ module ActiveFedora
|
|
224
198
|
headers
|
225
199
|
end
|
226
200
|
|
227
|
-
def create_record(_options = {})
|
228
|
-
run_callbacks(:create) do
|
229
|
-
run_callbacks(:save) do
|
230
|
-
return false if content.nil?
|
231
|
-
ldp_source.content = content
|
232
|
-
ldp_source.create do |req|
|
233
|
-
req.headers.merge!(ldp_headers)
|
234
|
-
end
|
235
|
-
refresh
|
236
|
-
end
|
237
|
-
end
|
238
|
-
end
|
239
|
-
|
240
|
-
def update_record(_options = {})
|
241
|
-
run_callbacks(:update) do
|
242
|
-
run_callbacks(:save) do
|
243
|
-
return true unless content_changed?
|
244
|
-
ldp_source.content = content
|
245
|
-
ldp_source.update do |req|
|
246
|
-
req.headers.merge!(ldp_headers)
|
247
|
-
end
|
248
|
-
refresh
|
249
|
-
end
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
201
|
def build_ldp_resource(id)
|
254
202
|
build_ldp_resource_via_uri self.class.id_to_uri(id)
|
255
203
|
end
|