active-fedora 9.1.2 → 9.2.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/Gemfile +1 -0
- data/History.txt +90 -0
- data/active-fedora.gemspec +2 -2
- data/lib/active_fedora.rb +17 -3
- data/lib/active_fedora/associations.rb +77 -0
- data/lib/active_fedora/associations/association.rb +2 -2
- data/lib/active_fedora/associations/basic_contains_association.rb +52 -0
- data/lib/active_fedora/associations/builder/directly_contains.rb +23 -0
- data/lib/active_fedora/associations/builder/directly_contains_one.rb +44 -0
- data/lib/active_fedora/associations/builder/has_and_belongs_to_many.rb +2 -23
- data/lib/active_fedora/associations/builder/indirectly_contains.rb +26 -0
- data/lib/active_fedora/associations/builder/property.rb +10 -0
- data/lib/active_fedora/associations/collection_association.rb +42 -45
- data/lib/active_fedora/associations/collection_proxy.rb +6 -0
- data/lib/active_fedora/associations/contained_finder.rb +41 -0
- data/lib/active_fedora/associations/container_proxy.rb +9 -0
- data/lib/active_fedora/associations/contains_association.rb +20 -38
- data/lib/active_fedora/associations/delete_proxy.rb +28 -0
- data/lib/active_fedora/associations/directly_contains_association.rb +56 -0
- data/lib/active_fedora/associations/directly_contains_one_association.rb +113 -0
- data/lib/active_fedora/associations/has_and_belongs_to_many_association.rb +6 -14
- data/lib/active_fedora/associations/has_many_association.rb +0 -3
- data/lib/active_fedora/associations/id_composite.rb +30 -0
- data/lib/active_fedora/associations/indirectly_contains_association.rb +90 -0
- data/lib/active_fedora/associations/rdf.rb +8 -4
- data/lib/active_fedora/associations/record_composite.rb +39 -0
- data/lib/active_fedora/attached_files.rb +1 -1
- data/lib/active_fedora/attributes.rb +28 -10
- data/lib/active_fedora/attributes/active_triple_attribute.rb +17 -0
- data/lib/active_fedora/attributes/om_attribute.rb +29 -0
- data/lib/active_fedora/attributes/rdf_datastream_attribute.rb +47 -0
- data/lib/active_fedora/attributes/stream_attribute.rb +46 -0
- data/lib/active_fedora/autosave_association.rb +2 -2
- data/lib/active_fedora/base.rb +3 -0
- data/lib/active_fedora/containers/container.rb +38 -0
- data/lib/active_fedora/containers/direct_container.rb +5 -0
- data/lib/active_fedora/containers/indirect_container.rb +7 -0
- data/lib/active_fedora/core.rb +4 -48
- data/lib/active_fedora/delegated_attribute.rb +5 -98
- data/lib/active_fedora/fedora.rb +1 -1
- data/lib/active_fedora/fedora_attributes.rb +4 -26
- data/lib/active_fedora/file.rb +87 -159
- data/lib/active_fedora/file/attributes.rb +63 -0
- data/lib/active_fedora/file/streaming.rb +46 -0
- data/lib/active_fedora/file_relation.rb +7 -0
- data/lib/active_fedora/identifiable.rb +87 -0
- data/lib/active_fedora/inbound_relation_connection.rb +21 -0
- data/lib/active_fedora/indexers.rb +10 -0
- data/lib/active_fedora/indexers/global_indexer.rb +30 -0
- data/lib/active_fedora/indexers/null_indexer.rb +12 -0
- data/lib/active_fedora/indexing/map.rb +4 -5
- data/lib/active_fedora/indexing_service.rb +3 -22
- data/lib/active_fedora/loadable_from_json.rb +8 -0
- data/lib/active_fedora/pathing.rb +24 -0
- data/lib/active_fedora/persistence.rb +15 -8
- data/lib/active_fedora/rdf.rb +2 -0
- data/lib/active_fedora/rdf/fcrepo4.rb +1 -0
- data/lib/active_fedora/rdf/field_map.rb +90 -0
- data/lib/active_fedora/rdf/field_map_entry.rb +28 -0
- data/lib/active_fedora/rdf/indexing_service.rb +9 -23
- data/lib/active_fedora/rdf/rdf_datastream.rb +1 -2
- data/lib/active_fedora/reflection.rb +16 -15
- data/lib/active_fedora/relation/delegation.rb +15 -4
- data/lib/active_fedora/relation/finder_methods.rb +4 -4
- data/lib/active_fedora/schema.rb +26 -0
- data/lib/active_fedora/schema_indexing_strategy.rb +25 -0
- data/lib/active_fedora/simple_datastream.rb +2 -2
- data/lib/active_fedora/solr_query_builder.rb +3 -2
- data/lib/active_fedora/version.rb +1 -1
- data/lib/active_fedora/with_metadata.rb +1 -1
- data/spec/integration/associations/rdf_spec.rb +49 -0
- data/spec/integration/base_spec.rb +19 -0
- data/spec/integration/belongs_to_association_spec.rb +6 -6
- data/spec/integration/collection_association_spec.rb +4 -4
- data/spec/integration/complex_rdf_datastream_spec.rb +12 -12
- data/spec/integration/datastream_rdf_nested_attributes_spec.rb +1 -1
- data/spec/integration/direct_container_spec.rb +254 -0
- data/spec/integration/directly_contains_one_association_spec.rb +102 -0
- data/spec/integration/file_spec.rb +16 -5
- data/spec/integration/has_many_associations_spec.rb +93 -58
- data/spec/integration/indirect_container_spec.rb +251 -0
- data/spec/integration/rdf_nested_attributes_spec.rb +1 -1
- data/spec/integration/relation_spec.rb +43 -27
- data/spec/spec_helper.rb +1 -1
- data/spec/unit/attributes_spec.rb +6 -6
- data/spec/unit/collection_proxy_spec.rb +28 -0
- data/spec/unit/file_spec.rb +1 -1
- data/spec/unit/files_hash_spec.rb +4 -4
- data/spec/unit/has_and_belongs_to_many_association_spec.rb +11 -9
- data/spec/unit/indexers/global_indexer_spec.rb +41 -0
- data/spec/unit/indexing_service_spec.rb +0 -21
- data/spec/unit/loadable_from_json_spec.rb +31 -0
- data/spec/unit/pathing_spec.rb +37 -0
- data/spec/unit/rdf/indexing_service_spec.rb +3 -3
- data/spec/unit/rdf_resource_datastream_spec.rb +26 -7
- data/spec/unit/schema_indexing_strategy_spec.rb +68 -0
- data/spec/unit/solr_query_builder_spec.rb +1 -1
- data/spec/unit/solr_service_spec.rb +1 -1
- metadata +49 -8
@@ -0,0 +1,113 @@
|
|
1
|
+
module ActiveFedora
|
2
|
+
module Associations
|
3
|
+
# Filters a DirectContainer relationship, returning the first item that matches the given :type
|
4
|
+
class DirectlyContainsOneAssociation < SingularAssociation #:nodoc:
|
5
|
+
|
6
|
+
# Finds objects contained by the container predicate (either the configured has_member_relation or ldp:contains)
|
7
|
+
# TODO: Refactor this to use solr (for efficiency) instead of parsing the RDF graph. Requires indexing ActiveFedora::File objects into solr, including their RDF.type and, if possible, the id of their container
|
8
|
+
def find_target
|
9
|
+
# filtered_objects = container_association_proxy.to_a.select { |o| o.metadata_node.type.include?(options[:type]) }
|
10
|
+
query_node = if container_predicate = options[:has_member_relation]
|
11
|
+
owner
|
12
|
+
else
|
13
|
+
container_predicate = ::RDF::Vocab::LDP.contains
|
14
|
+
container_association.container # Use the :through association's container
|
15
|
+
end
|
16
|
+
|
17
|
+
contained_uris = query_node.resource.query(predicate: container_predicate).map { |r| r.object.to_s }
|
18
|
+
contained_uris.each do |object_uri|
|
19
|
+
contained_object = klass.find(klass.uri_to_id(object_uri))
|
20
|
+
return contained_object if get_type_from_record(contained_object).include?(options[:type])
|
21
|
+
end
|
22
|
+
return nil # if nothing was found & returned while iterating on contained_uris, return nil
|
23
|
+
end
|
24
|
+
|
25
|
+
# Adds record to the DirectContainer identified by the container_association
|
26
|
+
# Relies on container_association.initialize_attributes to appropriately set things like record.uri
|
27
|
+
def add_to_container(record)
|
28
|
+
container_association.add_to_target(record) # adds record to corresponding Container
|
29
|
+
# TODO is send necessary?
|
30
|
+
container_association.send(:initialize_attributes, record) # Uses the :through association initialize the record with things like the correct URI for a direclty contained object
|
31
|
+
end
|
32
|
+
|
33
|
+
# Replaces association +target+ with +record+
|
34
|
+
# Ensures that this association's +type+ is set on the record and adds the record to the association's DirectContainer
|
35
|
+
def replace(record, *)
|
36
|
+
if record
|
37
|
+
raise_on_type_mismatch(record)
|
38
|
+
remove_existing_target
|
39
|
+
add_type_to_record(record, options[:type])
|
40
|
+
add_to_container(record)
|
41
|
+
else
|
42
|
+
remove_existing_target
|
43
|
+
end
|
44
|
+
|
45
|
+
self.target = record
|
46
|
+
end
|
47
|
+
|
48
|
+
def updated?
|
49
|
+
@updated
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def remove_existing_target
|
55
|
+
@target ||= find_target
|
56
|
+
if @target
|
57
|
+
container_association_proxy.delete @target
|
58
|
+
@updated = true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Overrides initialize_attributes to ensure that record is initialized with attributes from the corresponding container
|
63
|
+
def initialize_attributes(record)
|
64
|
+
super
|
65
|
+
container_association.initialize_attributes(record)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Returns the Reflection corresponding to the direct container association that's being filtered
|
69
|
+
def container_reflection
|
70
|
+
@container_reflection ||= @owner.class.reflect_on_association(@reflection.options[:through])
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns the DirectContainerAssociation corresponding to the direct container that's being filtered
|
74
|
+
def container_association
|
75
|
+
container_association_proxy.proxy_association
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns the ContainerAssociationProxy corresponding to the direct container that's being filtered
|
79
|
+
def container_association_proxy
|
80
|
+
@owner.send(@reflection.options[:through])
|
81
|
+
end
|
82
|
+
|
83
|
+
# Adds type_uri to the RDF.type assertions on record
|
84
|
+
def add_type_to_record(record, type_uri)
|
85
|
+
metadata_node = metadata_node_for_record(record)
|
86
|
+
types = metadata_node.type
|
87
|
+
unless types.include?(type_uri)
|
88
|
+
types << type_uri
|
89
|
+
metadata_node.set_value(:type, types)
|
90
|
+
end
|
91
|
+
return record
|
92
|
+
end
|
93
|
+
|
94
|
+
# Returns the RDF.type assertions for the record
|
95
|
+
def get_type_from_record(record)
|
96
|
+
metadata_node_for_record(record).type
|
97
|
+
end
|
98
|
+
|
99
|
+
# Returns the RDF node that contains metadata like RDF.type assertions for the record
|
100
|
+
# Sometimes this is the record, other times it's record.metadata_node
|
101
|
+
def metadata_node_for_record(record)
|
102
|
+
if record.respond_to?(:type) && record.respond_to?(:set_value)
|
103
|
+
return record
|
104
|
+
elsif record.respond_to?(:metadata_node)
|
105
|
+
return record.metadata_node
|
106
|
+
else
|
107
|
+
raise ArgumentError, "record must either have a metadata node or must respond to .type"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -46,20 +46,6 @@ module ActiveFedora
|
|
46
46
|
result && records
|
47
47
|
end
|
48
48
|
|
49
|
-
|
50
|
-
def find_target
|
51
|
-
page_size = @reflection.options[:solr_page_size]
|
52
|
-
page_size ||= 200
|
53
|
-
ids = owner[reflection.foreign_key]
|
54
|
-
return [] if ids.blank?
|
55
|
-
solr_result = []
|
56
|
-
0.step(ids.size,page_size) do |startIdx|
|
57
|
-
query = ActiveFedora::SolrQueryBuilder.construct_query_for_ids(ids.slice(startIdx,page_size))
|
58
|
-
solr_result += ActiveFedora::SolrService.query(query, rows: page_size)
|
59
|
-
end
|
60
|
-
return ActiveFedora::QueryResultBuilder.reify_solr_results(solr_result)
|
61
|
-
end
|
62
|
-
|
63
49
|
# In a HABTM, just look in the RDF, no need to run a count query from solr.
|
64
50
|
def count(options = {})
|
65
51
|
owner[reflection.foreign_key].size
|
@@ -96,6 +82,12 @@ module ActiveFedora
|
|
96
82
|
owner[reflection.foreign_key]
|
97
83
|
end
|
98
84
|
|
85
|
+
def find_target
|
86
|
+
ids = owner[reflection.foreign_key]
|
87
|
+
return [] if ids.blank?
|
88
|
+
ActiveFedora::Base.find(ids)
|
89
|
+
end
|
90
|
+
|
99
91
|
end
|
100
92
|
end
|
101
93
|
end
|
@@ -35,19 +35,16 @@ module ActiveFedora
|
|
35
35
|
record[inverse.foreign_key] = owner.id
|
36
36
|
else # HABTM
|
37
37
|
record[inverse.foreign_key] ||= []
|
38
|
-
#TODO use primary_key instead of `owner.id`
|
39
38
|
record[inverse.foreign_key] += [owner.id]
|
40
39
|
end
|
41
40
|
elsif owner.persisted?
|
42
41
|
inverse = reflection.inverse_of
|
43
42
|
if inverse && inverse.collection?
|
44
43
|
record[inverse.foreign_key] ||= []
|
45
|
-
#TODO use primary_key instead of `owner.id`
|
46
44
|
record[inverse.foreign_key] += [owner.id]
|
47
45
|
elsif inverse && inverse.klass == ActiveFedora::Base
|
48
46
|
record[inverse.foreign_key] = owner.id
|
49
47
|
else
|
50
|
-
#TODO use primary_key instead of `owner.id`
|
51
48
|
record[reflection.foreign_key] = owner.id
|
52
49
|
end
|
53
50
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module ActiveFedora::Associations
|
2
|
+
##
|
3
|
+
# A composite object for an array of IDs. This abstracts away the fact that an
|
4
|
+
# ID might be either a relative ID or a URI to a resource.
|
5
|
+
class IDComposite
|
6
|
+
attr_reader :ids, :id_translator
|
7
|
+
include Enumerable
|
8
|
+
def initialize(ids, id_translator)
|
9
|
+
@ids = ids
|
10
|
+
@id_translator = id_translator
|
11
|
+
end
|
12
|
+
|
13
|
+
# @return [Array<relative_id>]
|
14
|
+
def each
|
15
|
+
ids.each do |id|
|
16
|
+
yield convert(id)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def convert(id)
|
23
|
+
if id.start_with?("http")
|
24
|
+
id_translator.call(id)
|
25
|
+
else
|
26
|
+
id
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module ActiveFedora
|
2
|
+
module Associations
|
3
|
+
class IndirectlyContainsAssociation < ContainsAssociation #:nodoc:
|
4
|
+
|
5
|
+
# TODO we may want to split this into two subclasses, one for has_member_relation
|
6
|
+
# and the other for is_member_of_relation
|
7
|
+
|
8
|
+
def insert_record(record, force = true, validate = true)
|
9
|
+
container.save!
|
10
|
+
if force
|
11
|
+
record.save!
|
12
|
+
else
|
13
|
+
return false unless record.save(validate: validate)
|
14
|
+
end
|
15
|
+
|
16
|
+
save_through_record(record)
|
17
|
+
|
18
|
+
return true
|
19
|
+
end
|
20
|
+
|
21
|
+
def find_target
|
22
|
+
if container_predicate = options[:has_member_relation]
|
23
|
+
uris = owner.resource.query(predicate: container_predicate).map { |r| r.object.to_s }
|
24
|
+
uris.map { |object_uri| klass.find(klass.uri_to_id(object_uri)) }
|
25
|
+
else # is_member_of_relation
|
26
|
+
# TODO this is a lot of reads. Avoid this path
|
27
|
+
container_predicate = ::RDF::Vocab::LDP.contains
|
28
|
+
proxy_uris = container.resource.query(predicate: container_predicate).map { |r| r.object.to_s }
|
29
|
+
proxy_uris.map { |uri| proxy_class.find(proxy_class.uri_to_id(uri))[options[:foreign_key]] }
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
def container
|
36
|
+
@container ||= begin
|
37
|
+
IndirectContainer.find_or_initialize(ActiveFedora::Base.uri_to_id(uri)).tap do |container|
|
38
|
+
container.parent = @owner
|
39
|
+
container.has_member_relation = Array(options[:has_member_relation])
|
40
|
+
container.is_member_of_relation = Array(options[:is_member_of_relation])
|
41
|
+
container.inserted_content_relation = Array(options[:inserted_content_relation])
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
|
48
|
+
def initialize_attributes(record) #:nodoc:
|
49
|
+
#record.uri = ActiveFedora::Base.id_to_uri(container.mint_id)
|
50
|
+
# set_inverse_instance(record)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def delete_records(records, method)
|
56
|
+
container.reload # Reload container to get updated LDP.contains
|
57
|
+
records.each do |record|
|
58
|
+
delete_record(record)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def delete_record(record)
|
63
|
+
record_proxy_finder.find(record).delete
|
64
|
+
end
|
65
|
+
|
66
|
+
def record_proxy_finder
|
67
|
+
ContainedFinder.new(container: container, repository: composite_proxy_repository)
|
68
|
+
end
|
69
|
+
|
70
|
+
def composite_proxy_repository
|
71
|
+
RecordComposite::Repository.new(base_repository: proxy_class)
|
72
|
+
end
|
73
|
+
|
74
|
+
def save_through_record(record)
|
75
|
+
build_proxy_node({}) do |node|
|
76
|
+
node[options[:foreign_key]] = record
|
77
|
+
node.save
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def build_proxy_node(attributes, &block)
|
82
|
+
proxy_class.new({ id: container.mint_id }.merge(attributes), &block)
|
83
|
+
end
|
84
|
+
|
85
|
+
def proxy_class
|
86
|
+
@proxy_class ||= options[:through].constantize
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -33,9 +33,15 @@ module ActiveFedora
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
# TODO Detect when this is the only relationship for this predicate, then skip the filtering.
|
37
36
|
def filtering_required?
|
38
|
-
reflection.klass
|
37
|
+
return false if reflection.klass == ActiveFedora::Base
|
38
|
+
reflections_with_same_predicate.count > 1
|
39
|
+
end
|
40
|
+
|
41
|
+
# Count the number of reflections that have the same predicate as the reflection
|
42
|
+
# for this association.
|
43
|
+
def reflections_with_same_predicate
|
44
|
+
owner.class.outgoing_reflections.select { |k, v| v.options[:predicate] == reflection.predicate }
|
39
45
|
end
|
40
46
|
|
41
47
|
# @return [Array<RDF::URI>]
|
@@ -48,8 +54,6 @@ module ActiveFedora
|
|
48
54
|
owner.resource.query(subject: owner.rdf_subject, predicate: reflection.predicate).enum_statement
|
49
55
|
end
|
50
56
|
|
51
|
-
|
52
|
-
# TODO this is a huge waste of time that can be completely avoided if the attributes aren't sharing predicates.
|
53
57
|
# @return [Array<RDF::URI>]
|
54
58
|
def filter_by_class(candidate_uris)
|
55
59
|
return [] if candidate_uris.empty?
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module ActiveFedora::Associations
|
2
|
+
##
|
3
|
+
# A Composite for records - currently only supports delete interface.
|
4
|
+
# The goal is to push commands down to the containing records.
|
5
|
+
class RecordComposite
|
6
|
+
attr_reader :records
|
7
|
+
include Enumerable
|
8
|
+
def initialize(records:)
|
9
|
+
@records = records
|
10
|
+
end
|
11
|
+
|
12
|
+
def each
|
13
|
+
records.each do |record|
|
14
|
+
yield record
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def delete
|
19
|
+
self.each(&:delete)
|
20
|
+
end
|
21
|
+
##
|
22
|
+
# A Repository which returns a composite from #find instead of a single
|
23
|
+
# record. Delegates find to a base repository.
|
24
|
+
class Repository
|
25
|
+
attr_reader :base_repository
|
26
|
+
delegate :translate_uri_to_id, to: :base_repository
|
27
|
+
def initialize(base_repository:)
|
28
|
+
@base_repository = base_repository
|
29
|
+
end
|
30
|
+
|
31
|
+
def find(ids)
|
32
|
+
records = ids.map do |id|
|
33
|
+
base_repository.find(id)
|
34
|
+
end
|
35
|
+
RecordComposite.new(records: records)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -124,7 +124,7 @@ module ActiveFedora
|
|
124
124
|
private
|
125
125
|
def create_singleton_association(file_path)
|
126
126
|
self.undeclared_files << file_path.to_sym
|
127
|
-
association = Associations::
|
127
|
+
association = Associations::BasicContainsAssociation.new(self, Reflection::AssociationReflection.new(:contains, file_path, {class_name: 'ActiveFedora::File'}, self.class))
|
128
128
|
@association_cache[file_path.to_sym] = association
|
129
129
|
|
130
130
|
self.singleton_class.send :define_method, accessor_name(file_path) do
|
@@ -177,7 +177,7 @@ module ActiveFedora
|
|
177
177
|
elsif properties.key?(:delegate_to)
|
178
178
|
define_delegated_accessor([name], properties.delete(:delegate_to), properties.reverse_merge(multiple: true), &block)
|
179
179
|
else
|
180
|
-
raise "You must provide `:
|
180
|
+
raise "You must provide `:delegate_to' or `:predicate' options to property"
|
181
181
|
end
|
182
182
|
end
|
183
183
|
|
@@ -186,7 +186,7 @@ module ActiveFedora
|
|
186
186
|
def define_active_triple_accessor(name, properties, &block)
|
187
187
|
warn_duplicate_predicates name, properties
|
188
188
|
properties = { multiple: true }.merge(properties)
|
189
|
-
find_or_create_defined_attribute(name,
|
189
|
+
find_or_create_defined_attribute(name, ActiveTripleAttribute, properties)
|
190
190
|
raise ArgumentError, "#{name} is a keyword and not an acceptable property name." if protected_property_name? name
|
191
191
|
reflection = ActiveFedora::Attributes::PropertyBuilder.build(self, name, properties, &block)
|
192
192
|
ActiveTriples::Reflection.add_reflection self, name, reflection
|
@@ -197,6 +197,10 @@ module ActiveFedora
|
|
197
197
|
def define_delegated_accessor(fields, delegate_target, options, &block)
|
198
198
|
define_attribute_methods fields
|
199
199
|
fields.each do |f|
|
200
|
+
klass = datastream_class_for_name(delegate_target)
|
201
|
+
attribute_properties = options.merge(delegate_target: delegate_target, klass: klass)
|
202
|
+
find_or_create_defined_attribute f, attribute_class(klass), attribute_properties
|
203
|
+
|
200
204
|
create_attribute_reader(f, delegate_target, options)
|
201
205
|
create_attribute_setter(f, delegate_target, options)
|
202
206
|
add_attribute_indexing_config(f, &block) if block_given?
|
@@ -204,8 +208,7 @@ module ActiveFedora
|
|
204
208
|
end
|
205
209
|
|
206
210
|
def add_attribute_indexing_config(name, &block)
|
207
|
-
|
208
|
-
index_config[name] ||= ActiveFedora::Indexing::Map::IndexObject.new &block
|
211
|
+
index_config[name] ||= ActiveFedora::Indexing::Map::IndexObject.new(name, &block)
|
209
212
|
end
|
210
213
|
|
211
214
|
def warn_duplicate_predicates new_name, new_properties
|
@@ -215,31 +218,46 @@ module ActiveFedora
|
|
215
218
|
end
|
216
219
|
end
|
217
220
|
|
218
|
-
|
219
|
-
|
221
|
+
# @param [Symbol] field the field to find or create
|
222
|
+
# @param [Class] klass the class to use to delegate the attribute (e.g.
|
223
|
+
# ActiveTripleAttribute, OmAttribute, or RdfDatastreamAttribute)
|
224
|
+
# @param [Hash] args
|
225
|
+
# @option args [String] :delegate_target the path to the delegate
|
226
|
+
# @option args [Class] :klass the class to create
|
227
|
+
# @option args [true,false] :multiple (false) true for multi-value fields
|
228
|
+
# @option args [Array<Symbol>] :at path to a deep node
|
229
|
+
# @return [DelegatedAttribute] the found or created attribute
|
230
|
+
def find_or_create_defined_attribute(field, klass, args)
|
231
|
+
delegated_attributes[field] ||= klass.new(field, args)
|
220
232
|
end
|
221
233
|
|
222
234
|
# @param [String] dsid the datastream id
|
223
235
|
# @return [Class] the class of the datastream
|
224
236
|
def datastream_class_for_name(dsid)
|
225
|
-
reflection = reflect_on_association(dsid)
|
237
|
+
reflection = reflect_on_association(dsid.to_sym)
|
226
238
|
reflection ? reflection.klass : ActiveFedora::File
|
227
239
|
end
|
228
240
|
|
229
241
|
def create_attribute_reader(field, dsid, args)
|
230
|
-
find_or_create_defined_attribute(field, dsid, args)
|
231
|
-
|
232
242
|
define_method field do |*opts|
|
233
243
|
array_reader(field, *opts)
|
234
244
|
end
|
235
245
|
end
|
236
246
|
|
237
247
|
def create_attribute_setter(field, dsid, args)
|
238
|
-
find_or_create_defined_attribute(field, dsid, args)
|
239
248
|
define_method "#{field}=".to_sym do |v|
|
240
249
|
self[field]=v
|
241
250
|
end
|
242
251
|
end
|
252
|
+
|
253
|
+
def attribute_class(klass)
|
254
|
+
if klass < ActiveFedora::RDFDatastream
|
255
|
+
RdfDatastreamAttribute
|
256
|
+
else
|
257
|
+
OmAttribute
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
243
261
|
end
|
244
262
|
end
|
245
263
|
end
|