activefedora-aggregation 0.9.0 → 0.10.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1bb8da4f1630029337549d9975113e80a7882d7a
4
- data.tar.gz: da0dc596fba4be563217e0eba4b066c9230bfdae
3
+ metadata.gz: f69090697f543089afbc0a5a0e83fd2deddb0b3a
4
+ data.tar.gz: 0d8775ae201b1ae026fca4d2ee0018079b0eb59d
5
5
  SHA512:
6
- metadata.gz: a1760935368d3699da0320d8e768f653ca31434f59df34d7e5a6377d0994b38adfc02d101839e31219f21fc83263164a705b63acc24efc8a9d6e4286e999f280
7
- data.tar.gz: 8a6e54cb29ba1821be04b8d4c9f63684a8133bcce86fd3182a81b0c3e89691e40e16888a85b934b257f38f12d74e65b50d75d717708271b8f86280a473c4b21b
6
+ metadata.gz: be36c19a9bd67b2c73ebf9398ae1a0b9dc324db7ca664b957c41d4496e743a21e55ea747f4a06f59ea2c0bdc6458dd1e732380252b589741837a9433b736a567
7
+ data.tar.gz: 80e91cdac629e9b372f5c8938cd50580d52c80a8c5b40e917ef1f88633f148d633837877fc50fc4bf951a337239a161ae6a22d92a6bf768d6c56e2a3cf7122aa
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
17
17
  spec.require_paths = ["lib"]
18
18
 
19
19
  spec.add_dependency 'activesupport'
20
- spec.add_dependency 'active-fedora', '~> 9.9.0'
20
+ spec.add_dependency 'active-fedora', '~> 9.10.1'
21
21
  spec.add_dependency 'rdf-vocab', '~> 0.8.1'
22
22
  # Avoid RDF 1.1.17 because of a bug from ruby 2.2
23
23
  # https://github.com/ruby-rdf/rdf/pull/213
@@ -9,23 +9,9 @@ module ActiveFedora
9
9
  module Aggregation
10
10
  extend ActiveSupport::Autoload
11
11
  eager_autoload do
12
- autoload :Association
13
- autoload :AggregationExtension
14
12
  autoload :Proxy
15
- autoload :Builder
16
- autoload :Reflection
17
13
  autoload :BaseExtension
18
- autoload :LinkInserter
19
14
  autoload :OrderedReader
20
- autoload :PersistLinks
21
- autoload :OrderedProxy
22
- autoload :AppendsToAggregation
23
- autoload :ProxyOwner
24
- autoload :NullProxy
25
- autoload :DecoratingRepository
26
- autoload :DecoratorWithArguments
27
- autoload :DecoratorList
28
- autoload :ProxyRepository
29
15
  autoload :ListSource
30
16
  end
31
17
 
@@ -2,20 +2,6 @@ module ActiveFedora::Aggregation
2
2
  module BaseExtension
3
3
  extend ActiveSupport::Concern
4
4
 
5
- # Queries the RDF graph to find all records that include this object in their aggregations
6
- # Since any class may be the target of an aggregation, this must be on every class extending
7
- # from ActiveFedora::Base
8
- # @return [Array] records that include this object in their aggregations
9
- def aggregated_by
10
- # In theory you should be able to find the aggregation predicate (ie ore:aggregates)
11
- # but Fedora does not return that predicate due to this bug in FCREPO:
12
- # https://jira.duraspace.org/browse/FCREPO-1497
13
- # so we have to look up the proxies asserting RDF::Vocab::ORE.proxyFor
14
- # and return their containers.
15
- return [] unless id
16
- proxy_class.where(proxyFor_ssim: id).map(&:container)
17
- end
18
-
19
5
  def ordered_by
20
6
  ordered_by_ids.lazy.map{ |x| ActiveFedora::Base.find(x) }
21
7
  end
@@ -31,21 +17,7 @@ module ActiveFedora::Aggregation
31
17
  end
32
18
  end
33
19
 
34
- def proxy_class
35
- ActiveFedora::Aggregation::Proxy
36
- end
37
-
38
20
  module ClassMethods
39
- ##
40
- # Create an aggregation association on the class
41
- # @example
42
- # class Image < ActiveFedora::Base
43
- # aggregates :generic_files
44
- # end
45
- def aggregates(name, options={})
46
- Builder.build(self, name, options)
47
- end
48
-
49
21
  ##
50
22
  # Allows ordering of an association
51
23
  # @example
@@ -79,25 +51,6 @@ module ActiveFedora::Aggregation
79
51
  name = options.delete(:as)
80
52
  ActiveFedora::Filter::Builder.build(self, name, options.merge(extending_from: extending_from))
81
53
  end
82
-
83
- def create_reflection(macro, name, options, active_fedora)
84
- case macro
85
- when :aggregation
86
- Reflection.new(macro, name, options, active_fedora).tap do |reflection|
87
- add_reflection name, reflection
88
- end
89
- when :filter
90
- ActiveFedora::Filter::Reflection.new(macro, name, options, active_fedora).tap do |reflection|
91
- add_reflection name, reflection
92
- end
93
- when :orders
94
- ActiveFedora::Orders::Reflection.new(macro, name, options, active_fedora).tap do |reflection|
95
- add_reflection name, reflection
96
- end
97
- else
98
- super
99
- end
100
- end
101
54
  end
102
55
  end
103
56
  end
@@ -1,5 +1,5 @@
1
1
  module ActiveFedora
2
2
  module Aggregation
3
- VERSION = "0.9.0"
3
+ VERSION = "0.10.0"
4
4
  end
5
5
  end
@@ -1,7 +1,12 @@
1
1
  module ActiveFedora::Filter
2
2
  class Builder < ActiveFedora::Associations::Builder::CollectionAssociation
3
- self.macro = :filter
4
- self.valid_options = [:extending_from, :condition]
3
+ def self.valid_options(options)
4
+ super + [:extending_from, :condition]
5
+ end
6
+
7
+ def self.macro
8
+ :filter
9
+ end
5
10
 
6
11
  def self.define_readers(mixin, name)
7
12
  super
@@ -9,6 +14,20 @@ module ActiveFedora::Filter
9
14
  association(name).ids_reader
10
15
  end
11
16
  end
17
+
18
+ def self.create_reflection(model, name, scope, options, extension = nil)
19
+ unless name.is_a?(Symbol)
20
+ name = name.to_sym
21
+ Deprecation.warn(ActiveFedora::Base, "association names must be a Symbol")
22
+ end
23
+ validate_options(options)
24
+ translate_property_to_predicate(options)
25
+
26
+ scope = build_scope(scope, extension)
27
+ name = better_name(name)
28
+
29
+ ActiveFedora::Orders::Reflection.create(macro, name, scope, options, model)
30
+ end
12
31
  end
13
32
  end
14
33
 
@@ -10,7 +10,7 @@ module ActiveFedora::Filter
10
10
  end
11
11
 
12
12
  def extending_from
13
- @extending_from ||= active_fedora.reflect_on_association(options.fetch(:extending_from))
13
+ @extending_from ||= active_fedora._reflect_on_association(options.fetch(:extending_from))
14
14
  end
15
15
 
16
16
  def collection?
@@ -1,47 +1,45 @@
1
1
  module ActiveFedora::Orders
2
2
  class AggregationBuilder < ActiveFedora::Associations::Builder::Association
3
- self.valid_options = [:through, :class_name, :has_member_relation, :type_validator]
4
-
5
- def self.build(model, name, options)
6
- new(model, name, options).build
3
+ def self.valid_options(options)
4
+ [:through, :class_name, :has_member_relation, :type_validator]
7
5
  end
8
6
 
9
- def build
10
- model.indirectly_contains name, {has_member_relation: has_member_relation, through: proxy_class, foreign_key: proxy_foreign_key, inserted_content_relation: inserted_content_relation}.merge(indirect_options)
11
- model.contains contains_key, class_name: list_source_class
12
- model.orders name, through: contains_key
7
+ def self.build(model, name, options)
8
+ model.indirectly_contains name, { has_member_relation: has_member_relation(options), through: proxy_class, foreign_key: proxy_foreign_key, inserted_content_relation: inserted_content_relation}.merge(indirect_options(options))
9
+ model.contains contains_key(options), class_name: list_source_class
10
+ model.orders name, through: contains_key(options)
13
11
  end
14
12
 
15
13
  private
16
14
 
17
- def indirect_options
15
+ def self.indirect_options(options)
18
16
  {
19
17
  class_name: options[:class_name],
20
18
  type_validator: options[:type_validator]
21
- }.select{ |k, v| v.present? }
19
+ }.select { |k, v| v.present? }
22
20
  end
23
21
 
24
- def has_member_relation
22
+ def self.has_member_relation(options)
25
23
  options[:has_member_relation] || ::RDF::DC.hasPart
26
24
  end
27
25
 
28
- def inserted_content_relation
26
+ def self.inserted_content_relation
29
27
  ::RDF::Vocab::ORE::proxyFor
30
28
  end
31
29
 
32
- def proxy_class
30
+ def self.proxy_class
33
31
  "ActiveFedora::Aggregation::Proxy"
34
32
  end
35
33
 
36
- def proxy_foreign_key
34
+ def self.proxy_foreign_key
37
35
  :target
38
36
  end
39
37
 
40
- def contains_key
38
+ def self.contains_key(options)
41
39
  options[:through]
42
40
  end
43
41
 
44
- def list_source_class
42
+ def self.list_source_class
45
43
  "ActiveFedora::Aggregation::ListSource"
46
44
  end
47
45
  end
@@ -12,6 +12,7 @@ module ActiveFedora::Orders
12
12
 
13
13
  def reader(*args)
14
14
  @proxy ||= ActiveFedora::Orders::CollectionProxy.new(self)
15
+ @null_proxy ||= ActiveFedora::Orders::CollectionProxy.new(self)
15
16
  super
16
17
  end
17
18
 
@@ -144,11 +145,11 @@ module ActiveFedora::Orders
144
145
  end
145
146
 
146
147
  def unordered_association
147
- owner.association(ordered_reflection_name)
148
+ owner.association(unordered_reflection_name)
148
149
  end
149
150
 
150
- def ordered_reflection_name
151
- reflection.ordered_reflection.name
151
+ def unordered_reflection_name
152
+ reflection.unordered_reflection.name
152
153
  end
153
154
  end
154
155
  end
@@ -1,8 +1,13 @@
1
1
  module ActiveFedora::Orders
2
2
  class Builder < ActiveFedora::Associations::Builder::CollectionAssociation
3
3
  include ActiveFedora::AutosaveAssociation::AssociationBuilderExtension
4
- self.macro = :orders
5
- self.valid_options += [:through, :ordered_reflection]
4
+ def self.macro
5
+ :orders
6
+ end
7
+
8
+ def self.valid_options(options)
9
+ super + [:through, :unordered_reflection]
10
+ end
6
11
 
7
12
  def self.define_readers(mixin, name)
8
13
  super
@@ -14,14 +19,37 @@ module ActiveFedora::Orders
14
19
  end
15
20
  end
16
21
 
17
- def initialize(model, name, options)
18
- @original_name = name
19
- @model = model
22
+ def self.build(model, name, options)
23
+ options = { unordered_reflection: unordered_reflection(model, name)}.merge(options)
20
24
  name = :"ordered_#{name.to_s.singularize}_proxies"
21
- options = {ordered_reflection: ordered_reflection}.merge(options)
25
+ model.property :head, predicate: ::RDF::Vocab::IANA['first']
26
+ model.property :tail, predicate: ::RDF::Vocab::IANA.last
27
+ model.send(:define_method, :apply_first_and_last) do
28
+ source = send(options[:through])
29
+ source.save
30
+ return if head.map(&:rdf_subject) == source.head_id && tail.map(&:rdf_subject) == source.tail_id
31
+ self.head = source.head_id
32
+ self.tail = source.tail_id
33
+ save! if changed?
34
+ end
35
+ model.include ActiveFedora::Orders::Builder::FixFirstLast
22
36
  super
23
37
  end
24
38
 
39
+ def self.create_reflection(model, name, scope, options, extension = nil)
40
+ unless name.is_a?(Symbol)
41
+ name = name.to_sym
42
+ Deprecation.warn(ActiveFedora::Base, "association names must be a Symbol")
43
+ end
44
+ validate_options(options)
45
+ translate_property_to_predicate(options)
46
+
47
+ scope = build_scope(scope, extension)
48
+ name = better_name(name)
49
+
50
+ ActiveFedora::Orders::Reflection.create(macro, name, scope, options, model)
51
+ end
52
+
25
53
  module FixFirstLast
26
54
  def save(*args)
27
55
  super.tap do |result|
@@ -39,29 +67,14 @@ module ActiveFedora::Orders
39
67
  end
40
68
  end
41
69
 
42
- def build
43
- super.tap do |result|
44
- model.property :head, predicate: ::RDF::Vocab::IANA['first']
45
- model.property :tail, predicate: ::RDF::Vocab::IANA.last
46
- model.send(:define_method, :apply_first_and_last) do
47
- source = send(result.options[:through])
48
- return if head.map(&:rdf_subject) == source.head_id && tail.map(&:rdf_subject) == source.tail_id
49
- self.head = source.head_id
50
- self.tail = source.tail_id
51
- save! if changed?
52
- end
53
- model.include ActiveFedora::Orders::Builder::FixFirstLast
54
- end
55
- end
56
-
57
70
  private
58
71
 
59
72
  def self.target_accessor(name)
60
73
  name.to_s.gsub("_proxies","").pluralize
61
74
  end
62
75
 
63
- def ordered_reflection
64
- model.reflect_on_association(@original_name)
76
+ def self.unordered_reflection(model, original_name)
77
+ model._reflect_on_association(original_name)
65
78
  end
66
79
  end
67
80
  end
@@ -1,5 +1,20 @@
1
1
  module ActiveFedora::Orders
2
2
  class Reflection < ActiveFedora::Reflection::AssociationReflection
3
+ class << self
4
+ def create(macro, name, scope, options, active_fedora)
5
+ klass = case macro
6
+ when :aggregation
7
+ Reflection
8
+ when :filter
9
+ ActiveFedora::Filter::Reflection
10
+ when :orders
11
+ ActiveFedora::Orders::Reflection
12
+ end
13
+ reflection = klass.new(macro, name, scope, options, active_fedora)
14
+ ActiveFedora::Reflection.add_reflection(active_fedora, name, reflection)
15
+ reflection
16
+ end
17
+ end
3
18
  def association_class
4
19
  Association
5
20
  end
@@ -12,8 +27,8 @@ module ActiveFedora::Orders
12
27
  klass.to_s
13
28
  end
14
29
 
15
- def ordered_reflection
16
- options[:ordered_reflection]
30
+ def unordered_reflection
31
+ options[:unordered_reflection]
17
32
  end
18
33
 
19
34
  def klass
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activefedora-aggregation
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Coyne
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-24 00:00:00.000000000 Z
11
+ date: 2016-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 9.9.0
33
+ version: 9.10.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 9.9.0
40
+ version: 9.10.1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rdf-vocab
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -177,24 +177,10 @@ files:
177
177
  - bin/setup
178
178
  - circle.yml
179
179
  - lib/active_fedora/aggregation.rb
180
- - lib/active_fedora/aggregation/aggregation_extension.rb
181
- - lib/active_fedora/aggregation/appends_to_aggregation.rb
182
- - lib/active_fedora/aggregation/association.rb
183
180
  - lib/active_fedora/aggregation/base_extension.rb
184
- - lib/active_fedora/aggregation/builder.rb
185
- - lib/active_fedora/aggregation/decorating_repository.rb
186
- - lib/active_fedora/aggregation/decorator_list.rb
187
- - lib/active_fedora/aggregation/decorator_with_arguments.rb
188
- - lib/active_fedora/aggregation/link_inserter.rb
189
181
  - lib/active_fedora/aggregation/list_source.rb
190
- - lib/active_fedora/aggregation/null_proxy.rb
191
- - lib/active_fedora/aggregation/ordered_proxy.rb
192
182
  - lib/active_fedora/aggregation/ordered_reader.rb
193
- - lib/active_fedora/aggregation/persist_links.rb
194
183
  - lib/active_fedora/aggregation/proxy.rb
195
- - lib/active_fedora/aggregation/proxy_owner.rb
196
- - lib/active_fedora/aggregation/proxy_repository.rb
197
- - lib/active_fedora/aggregation/reflection.rb
198
184
  - lib/active_fedora/aggregation/version.rb
199
185
  - lib/active_fedora/filter.rb
200
186
  - lib/active_fedora/filter/association.rb
@@ -246,9 +232,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
246
232
  version: '0'
247
233
  requirements: []
248
234
  rubyforge_project:
249
- rubygems_version: 2.5.1
235
+ rubygems_version: 2.4.5.1
250
236
  signing_key:
251
237
  specification_version: 4
252
238
  summary: Aggregations for active-fedora
253
239
  test_files: []
254
- has_rdoc:
@@ -1,26 +0,0 @@
1
- # This module is mixed into classes that declare 'aggregates ...'
2
- #
3
- module ActiveFedora::Aggregation
4
- module AggregationExtension
5
- extend ActiveSupport::Concern
6
- include PersistLinks
7
-
8
- included do
9
- after_destroy :remove_aggregation_proxies_from_solr
10
-
11
- # Doesn't use after_save because we need this callback to come after the autosave callback
12
- after_create :persist_aggregation_links
13
- after_update :persist_aggregation_links
14
- end
15
-
16
- private
17
-
18
- # The proxies, being nested under the object, are automatically destroyed
19
- # this cleans up their records from solr.
20
- def remove_aggregation_proxies_from_solr
21
- query = ActiveFedora::SolrQueryBuilder.construct_query_for_rel(proxyIn: id, has_model: Proxy.to_class_uri)
22
- ActiveFedora::SolrService.instance.conn.delete_by_query(query, params: {'softCommit' => true})
23
- end
24
-
25
- end
26
- end
@@ -1,31 +0,0 @@
1
- module ActiveFedora::Aggregation
2
- class AppendsToAggregation < SimpleDelegator
3
- attr_reader :parent_node
4
- # @param [#next, #prev] proxy The proxy to add behavior to.
5
- # @param [#head, #tail] parent_node The aggregation to append proxies to.
6
- def initialize(proxy, parent_node)
7
- @parent_node = parent_node
8
- super(proxy)
9
- end
10
-
11
- def is_a?(klass)
12
- __getobj__.is_a?(klass)
13
- end
14
-
15
- def save(*args)
16
- insert_link do
17
- super
18
- end
19
- end
20
-
21
- private
22
-
23
- def insert_link
24
- result = yield
25
- if result
26
- LinkInserter.new(parent_node, self).call
27
- end
28
- result
29
- end
30
- end
31
- end
@@ -1,81 +0,0 @@
1
- module ActiveFedora::Aggregation
2
- class Association < ::ActiveFedora::Associations::IndirectlyContainsAssociation
3
- delegate :first, to: :ordered_reader
4
-
5
- def ordered_reader
6
- OrderedReader.new(owner).to_a.map(&:target)
7
- end
8
-
9
- def proxy_class
10
- @proxy_class ||= ProxyRepository.new(owner, super)
11
- end
12
-
13
- def options
14
- @all_options ||= default_options.merge(super)
15
- end
16
-
17
- # Implements the ids reader method, e.g. foo.item_ids for Foo.has_many :items
18
- def ids_reader
19
- return [] if @owner.new_record?
20
- if loaded?
21
- load_target.map do |record|
22
- record.id
23
- end
24
- else
25
- proxies = load_proxies_from_solr(fl: 'id, next_ssim, proxyFor_ssim')
26
- create_linked_list(@owner.head_id, proxies)
27
- end
28
- end
29
-
30
- private
31
-
32
- # Write a query to find the proxies
33
- def construct_proxy_query
34
- raise "Owner must have an identifier" unless @owner.id
35
- @proxy_query ||= begin
36
- clauses = { 'proxyIn' => @owner.id }
37
- clauses[:has_model] = ActiveFedora::Aggregation::Proxy.to_class_uri
38
- ActiveFedora::SolrQueryBuilder.construct_query_for_rel(clauses)
39
- end
40
- end
41
-
42
- # Finds the proxies
43
- # @param opts [Hash] Options that will be passed through to ActiveFedora::SolrService.query.
44
- def load_proxies_from_solr(opts = Hash.new)
45
- finder_query = construct_proxy_query
46
- rows = 1000
47
- ActiveFedora::SolrService.query(finder_query, { rows: rows }.merge(opts))
48
- end
49
-
50
- # @param [String, NilClass] first_id
51
- # @param [Array<Hash>] remainder
52
- # @param [Array] list
53
- def create_linked_list(first_id, remainder, list=[])
54
- return list if remainder.empty?
55
-
56
- index = remainder.find_index { |n| n.fetch('id') == first_id }
57
- first = remainder.delete_at(index)
58
- next_id = first['next_ssim'].try(:first)
59
- proxy_for = first.fetch('proxyFor_ssim', []).first
60
- if proxy_for
61
- create_linked_list(next_id, remainder, list + [proxy_for])
62
- else
63
- ActiveFedora::Base.logger.error("Found a proxy (id: #{first['id']}) that has no proxyFor_ssim") if ActiveFedora::Base.logger
64
- create_linked_list(next_id, remainder, list)
65
- end
66
- end
67
-
68
- def default_options
69
- { through: default_proxy_class, foreign_key: :target, has_member_relation: reflection.predicate, inserted_content_relation: content_relation }
70
- end
71
-
72
- def content_relation
73
- default_proxy_class.constantize.reflect_on_association(:target).predicate
74
- end
75
-
76
- def default_proxy_class
77
- 'ActiveFedora::Aggregation::Proxy'
78
- end
79
-
80
- end
81
- end
@@ -1,33 +0,0 @@
1
- module ActiveFedora::Aggregation
2
- class Builder < ActiveFedora::Associations::Builder::CollectionAssociation
3
- include ActiveFedora::AutosaveAssociation::AssociationBuilderExtension
4
- self.macro = :aggregation
5
-
6
- def build
7
- reflection = super
8
- model.belongs_to :head, predicate: ::RDF::Vocab::IANA['first'], class_name: 'ActiveFedora::Aggregation::Proxy'
9
- model.belongs_to :tail, predicate: ::RDF::Vocab::IANA.last, class_name: 'ActiveFedora::Aggregation::Proxy'
10
-
11
- model.include AggregationExtension
12
- reflection
13
- end
14
-
15
- def self.define_readers(mixin, name)
16
- super
17
- mixin.redefine_method("#{name.to_s.singularize}_ids") do
18
- association(name).ids_reader
19
- end
20
- mixin.redefine_method("ordered_#{name.to_s.pluralize}") do
21
- association(name).ordered_reader
22
- end
23
- end
24
-
25
- def self.define_writers(mixin, name)
26
- super
27
- mixin.redefine_method("#{name.to_s.singularize}_ids=") do |ids|
28
- association(name).ids_writer(ids)
29
- end
30
- end
31
-
32
- end
33
- end
@@ -1,29 +0,0 @@
1
- module ActiveFedora::Aggregation
2
- ##
3
- # Decorates the results of a repository with the given decorator.
4
- class DecoratingRepository < SimpleDelegator
5
- attr_reader :decorator
6
- # @param [#new] decorator A decorator.
7
- # @param [#find, #new] base_repository A repository to decorate.
8
- def initialize(decorator, base_repository)
9
- @decorator = decorator
10
- super(base_repository)
11
- end
12
-
13
- def find(id)
14
- decorate(super(id))
15
- end
16
-
17
- def new(*args)
18
- result = decorate(super(*args))
19
- yield result if block_given?
20
- result
21
- end
22
-
23
- private
24
-
25
- def decorate(obj)
26
- decorator.new(obj)
27
- end
28
- end
29
- end
@@ -1,15 +0,0 @@
1
- module ActiveFedora::Aggregation
2
- # A composite object to allow for a list of decorators to be treated like one.
3
- class DecoratorList
4
- attr_reader :decorators
5
- def initialize(*decorators)
6
- @decorators = decorators
7
- end
8
-
9
- def new(undecorated_object)
10
- decorators.inject(undecorated_object) do |obj, decorator|
11
- decorator.new(obj)
12
- end
13
- end
14
- end
15
- end
@@ -1,15 +0,0 @@
1
- module ActiveFedora::Aggregation
2
- # This is an Adapter to allow a Decorator to respond to the interface #new()
3
- # but still require other arguments to instantiate.
4
- class DecoratorWithArguments
5
- attr_reader :decorator, :args
6
- def initialize(decorator, *args)
7
- @decorator = decorator
8
- @args = args
9
- end
10
-
11
- def new(obj)
12
- decorator.new(obj, *args)
13
- end
14
- end
15
- end
@@ -1,56 +0,0 @@
1
- module ActiveFedora::Aggregation
2
- class LinkInserter
3
- attr_reader :root, :proxy
4
- # @param [ProxyOwner] root the node representing the aggregation
5
- # @param [Proxy] proxy the proxy to add to the aggregation
6
- def initialize(root, proxy)
7
- @root = root
8
- @proxy = proxy
9
- end
10
-
11
- def call
12
- if root.head
13
- append
14
- else
15
- set
16
- end
17
- proxy.container = root
18
- persist_nodes!
19
- end
20
-
21
- private
22
-
23
- def append
24
- Appender.new(root, proxy).call
25
- end
26
-
27
- def set
28
- root.head = proxy
29
- root.tail = proxy
30
- end
31
-
32
- def persist_nodes!
33
- [proxy, proxy.prev].uniq.compact.each(&:save!)
34
- end
35
-
36
- class Appender
37
- attr_reader :root, :proxy
38
- def initialize(root, proxy)
39
- @root = root
40
- @proxy = proxy
41
- end
42
-
43
- def call
44
- last_proxy.next = proxy
45
- proxy.prev = last_proxy
46
- root.tail = proxy
47
- end
48
-
49
- private
50
-
51
- def last_proxy
52
- @last_proxy ||= root.tail
53
- end
54
- end
55
- end
56
- end
@@ -1,23 +0,0 @@
1
- module ActiveFedora::Aggregation
2
- # A null proxy to simplify logic.
3
- class NullProxy
4
- include Singleton
5
-
6
- attr_writer :prev, :next
7
- def prev
8
- self
9
- end
10
-
11
- def next
12
- self
13
- end
14
-
15
- def reload
16
- self
17
- end
18
-
19
- def changed?
20
- false
21
- end
22
- end
23
- end
@@ -1,57 +0,0 @@
1
- module ActiveFedora::Aggregation
2
- # A proxy which knows how to delete itself from an aggregation.
3
- class OrderedProxy < SimpleDelegator
4
- attr_reader :parent_node
5
- # @param [#next, #prev, #delete] proxy The proxy to add behavior to.
6
- # @param [#delete_proxy!] parent_node The aggregation to delete proxies
7
- # from.
8
- def initialize(proxy, parent_node)
9
- @parent_node = parent_node
10
- super(proxy)
11
- end
12
-
13
- def is_a?(klass)
14
- __getobj__.is_a?(klass)
15
- end
16
-
17
- def delete(*args)
18
- link_node_if_true do
19
- super
20
- end
21
- end
22
-
23
- protected
24
-
25
- def link_node_if_true
26
- # Have to precache these or AF tries to access this node?
27
- next_or_null
28
- prev_or_null
29
- yield.tap do |result|
30
- if result
31
- # Have to reload proxies because otherwise you persist them with bad
32
- # referencing triples.
33
- [next_or_null, prev_or_null, parent_node].each(&:reload)
34
- prev_or_null.next = self.next
35
- next_or_null.prev = prev
36
- changed_nodes.each(&:save!)
37
- parent_node.delete_proxy!(self)
38
- end
39
- end
40
- end
41
-
42
- def next_or_null
43
- self.next || NullProxy.instance
44
- end
45
-
46
- def prev_or_null
47
- self.prev || NullProxy.instance
48
- end
49
-
50
- private
51
-
52
- def changed_nodes
53
- [self.prev, self.next].uniq.compact.select(&:changed?)
54
- end
55
-
56
- end
57
- end
@@ -1,9 +0,0 @@
1
- module ActiveFedora::Aggregation
2
- module PersistLinks
3
- # If the head or tail pointer was updated (in an autosave callback), then persist them
4
- def persist_aggregation_links
5
- return true unless @new_record_before_save
6
- save if changes.key?("head_id") or changes.key?("tail_id")
7
- end
8
- end
9
- end
@@ -1,24 +0,0 @@
1
- module ActiveFedora::Aggregation
2
- ##
3
- # Decorates a proxy owner such that it knows how to delete a proxy from its
4
- # ordered list.
5
- class ProxyOwner < SimpleDelegator
6
- def is_a?(klass)
7
- __getobj__.is_a?(klass)
8
- end
9
-
10
- # @param [#next, #prev] proxy A Proxy link to delete.
11
- def delete_proxy!(proxy)
12
- if proxy == head || head.nil? # Head is nil if proxy is now deleted.
13
- self.head = proxy.next
14
- end
15
- if proxy == tail || tail.nil? # Head is nil if proxy is now deleted.
16
- self.tail = proxy.prev
17
- end
18
- [head, tail].uniq.compact.each(&:reload)
19
- if changed?
20
- save!
21
- end
22
- end
23
- end
24
- end
@@ -1,38 +0,0 @@
1
- module ActiveFedora::Aggregation
2
- ##
3
- # Repository for Proxies. This repository is responsible for decorating a
4
- # proxy such that it's useful for aggregation and is an attempt at
5
- # centralizing hard-coded dependencies without a dependency injection
6
- # container.
7
- class ProxyRepository < SimpleDelegator
8
- attr_reader :owner, :base_proxy_factory
9
- # @param [ActiveFedora::Base] owner The node which proxy will assert order
10
- # on.
11
- # @param [#find, #new] base_proxy_factory The base factory which returns proxies
12
- # that will be decorated.
13
- # @return [#find, #new] A repository which can return proxies useful for
14
- # aggregation.
15
- def initialize(owner, base_proxy_factory)
16
- @owner = owner
17
- @base_proxy_factory = base_proxy_factory
18
- super(repository)
19
- end
20
-
21
- private
22
-
23
- def repository
24
- DecoratingRepository.new(proxy_decorator, base_proxy_factory)
25
- end
26
-
27
- def proxy_decorator
28
- DecoratorList.new(
29
- DecoratorWithArguments.new(OrderedProxy, proxy_owner),
30
- DecoratorWithArguments.new(AppendsToAggregation, proxy_owner)
31
- )
32
- end
33
-
34
- def proxy_owner
35
- @proxy_owner ||= ProxyOwner.new(owner)
36
- end
37
- end
38
- end
@@ -1,28 +0,0 @@
1
- module ActiveFedora::Aggregation
2
- class Reflection < ActiveFedora::Reflection::AssociationReflection
3
- def association_class
4
- Association
5
- end
6
-
7
- def klass
8
- @klass ||= begin
9
- klass = class_name.constantize
10
- klass.respond_to?(:uri_to_id) ? klass : ActiveFedora::Base
11
- rescue NameError => e
12
- # If the NameError is a result of the class having a
13
- # NameError (e.g. NoMethodError) within it then raise the error.
14
- raise e if Object.const_defined? class_name
15
- # Otherwise the NameError was a result of not being able to find the class
16
- ActiveFedora::Base
17
- end
18
- end
19
-
20
- def predicate
21
- @options[:predicate] || ::RDF::Vocab::ORE.aggregates
22
- end
23
-
24
- def collection?
25
- true
26
- end
27
- end
28
- end