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.
@@ -1,18 +1,24 @@
1
1
  module ActiveFedora
2
2
  module AttributeMethods
3
3
  module Write
4
- WriterMethodCache = Class.new(AttributeMethodCache) do
5
- private
4
+ module ClassMethods
5
+ protected
6
6
 
7
- def method_body(method_name, const_name)
8
- <<-EOMETHOD
9
- def #{method_name}(value)
10
- name = ::ActiveFedora::AttributeMethods::AttrNames::ATTR_#{const_name}
11
- write_attribute(name, value)
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
- EOMETHOD
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, "#{self.class} does not have an attribute `#{field}'" unless self.class.delegated_attributes.key?(field)
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, "#{self.class} does not have an attribute `#{field}'" unless self.class.delegated_attributes.key?(field)
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, "#{self} does not have an attribute `#{field}'" unless delegated_attributes.key?(field)
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"
@@ -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
- run_callbacks(:destroy) { super }
230
+ _run_destroy_callbacks { super }
231
231
  end
232
232
 
233
233
  private
234
234
 
235
- def create_record(*) #:nodoc:
236
- run_callbacks(:create) do
237
- run_callbacks(:save) { super }
238
- end
235
+ def create_or_update(*)
236
+ _run_save_callbacks { super }
239
237
  end
240
238
 
241
- def update_record(*) #:nodoc:
242
- run_callbacks(:update) do
243
- run_callbacks(:save) { super }
244
- end
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
@@ -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
- self.attributes = attributes
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 +true+ if the record is read only. Records loaded through joins with piggy-back
97
- # attributes will be marked as read only since they cannot be saved.
98
- def readonly?
99
- @readonly
100
- end
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
- # Marks this record as read only.
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)
@@ -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
@@ -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::Persistence
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