activefedora-aggregation 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
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