active-fedora 9.10.0.pre2 → 9.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/History.txt +141 -0
  4. data/lib/active_fedora/associations/association.rb +38 -12
  5. data/lib/active_fedora/associations/association_scope.rb +6 -2
  6. data/lib/active_fedora/associations/basic_contains_association.rb +2 -3
  7. data/lib/active_fedora/associations/belongs_to_association.rb +23 -4
  8. data/lib/active_fedora/associations/builder/association.rb +37 -56
  9. data/lib/active_fedora/associations/builder/belongs_to.rb +27 -1
  10. data/lib/active_fedora/associations/builder/collection_association.rb +33 -2
  11. data/lib/active_fedora/associations/builder/contains.rb +3 -3
  12. data/lib/active_fedora/associations/builder/directly_contains.rb +1 -7
  13. data/lib/active_fedora/associations/builder/directly_contains_one.rb +20 -17
  14. data/lib/active_fedora/associations/builder/has_and_belongs_to_many.rb +1 -1
  15. data/lib/active_fedora/associations/builder/has_many.rb +2 -43
  16. data/lib/active_fedora/associations/builder/indirectly_contains.rb +1 -7
  17. data/lib/active_fedora/associations/builder/property.rb +2 -13
  18. data/lib/active_fedora/associations/builder/singular_association.rb +2 -6
  19. data/lib/active_fedora/associations/builder/singular_property.rb +2 -3
  20. data/lib/active_fedora/associations/collection_association.rb +6 -14
  21. data/lib/active_fedora/associations/directly_contains_one_association.rb +1 -2
  22. data/lib/active_fedora/associations/has_and_belongs_to_many_association.rb +1 -1
  23. data/lib/active_fedora/associations/has_many_association.rb +23 -0
  24. data/lib/active_fedora/attached_files.rb +1 -1
  25. data/lib/active_fedora/core.rb +2 -1
  26. data/lib/active_fedora/errors.rb +13 -0
  27. data/lib/active_fedora/file.rb +16 -1
  28. data/lib/active_fedora/file/attributes.rb +6 -6
  29. data/lib/active_fedora/reflection.rb +200 -76
  30. data/lib/active_fedora/version.rb +1 -1
  31. data/lib/active_fedora/with_metadata/metadata_node.rb +2 -1
  32. data/lib/generators/active_fedora/config/fedora/fedora_generator.rb +4 -0
  33. data/lib/generators/active_fedora/config/fedora/templates/.fcrepo_wrapper +3 -0
  34. data/lib/generators/active_fedora/config/solr/solr_generator.rb +4 -0
  35. data/lib/generators/active_fedora/config/solr/templates/.solr_wrapper +5 -0
  36. data/spec/integration/attached_files_spec.rb +4 -4
  37. data/spec/integration/file_spec.rb +1 -1
  38. data/spec/integration/om_datastream_spec.rb +6 -6
  39. data/spec/unit/collection_proxy_spec.rb +1 -1
  40. data/spec/unit/file_spec.rb +19 -0
  41. data/spec/unit/has_and_belongs_to_many_association_spec.rb +4 -4
  42. data/spec/unit/has_many_association_spec.rb +2 -2
  43. data/spec/unit/reflection_spec.rb +2 -2
  44. metadata +6 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b9fa729bb22950bf6f1a5a8910eef83e17d699b6
4
- data.tar.gz: 2230ceaf9cf100c0737997c5235c0a87364ec2df
3
+ metadata.gz: 8497f7de37069e9bfe075f4b7f9ac67a0e3c7d68
4
+ data.tar.gz: cb858eb8a45c08fec2dea7578b854cc51b4b5401
5
5
  SHA512:
6
- metadata.gz: df06b4f7448346189c3ca49029200205eaf671a84854035fba131dc60d84f0954aaf79df54e29746118cac1074ca2241e7b5bc7e291f89b120e44340b034d250
7
- data.tar.gz: 60a819b84ffd5f68bdb80436648621738e2b77b68e629265be3d3257efa566969d33c040660a561445c39a60d38742865afd0dd6b6681ef0aeb7bfc8cd08d961
6
+ metadata.gz: 6307a89a0b6417ef313efda00a37466cd0ef1f8a9bbb18dafb5f7fbbedc7dd87598f3213619604e6dac06f55eb985dc87c0b99b3f3e33369d213e038bbf56f02
7
+ data.tar.gz: d084f99333f8059f504b6735fde1bab7ace4868de441b2f48ced69d876a7271570007c9452acb4f10f22f05e39efa513130eb09562d1a8ad8d2151fbe7d60a0d
@@ -86,6 +86,7 @@ Metrics/ClassLength:
86
86
  - 'lib/active_fedora/associations/builder/association.rb'
87
87
  - 'lib/active_fedora/associations/collection_proxy.rb'
88
88
  - 'lib/active_fedora/associations/collection_association.rb'
89
+ - 'lib/active_fedora/reflection.rb'
89
90
 
90
91
  Metrics/MethodLength:
91
92
  Enabled: false
@@ -1,3 +1,144 @@
1
+ v9.10.0
2
+ 2016-03-24: Continued alignment of associations with upstream changes [Chris
3
+ Beer]
4
+
5
+ 2016-03-24: ActiveFedora::File.mime_type should be updatable [Chris Colvard]
6
+
7
+ 2016-03-23: Update reflections and associations to reflect upstream changes
8
+ [Chris Beer]
9
+
10
+ 2016-03-23: Generate default configs for fcrepo_wrapper [Justin Coyne]
11
+
12
+ 2016-03-23: Generate solr_wrapper config file [Justin Coyne]
13
+
14
+ 2016-03-22: Bump version to 9.10.0.pre2 [Justin Coyne]
15
+
16
+ 2016-03-19: Update scoping with latest upstream changes [Chris Beer]
17
+
18
+ 2016-03-22: Deprecate delegating attributes to associated objects [Justin Coyne]
19
+
20
+ 2016-03-22: Add AttributeAssignment module from upstream [Chris Beer]
21
+
22
+ 2016-03-21: Update AF::AttributeMethods with upstream changes [Chris Beer]
23
+
24
+ 2016-03-21: Extract ActiveFedora::Common to share methods between AF::Base and
25
+ AF::File [Chris Beer]
26
+
27
+ 2016-03-18: Update AF::File update callbacks to align with Rails [Chris Beer]
28
+
29
+ 2016-03-18: Extract ActiveFedora::FilePersistence, so ActiveFedora::File can
30
+ work with AF::Callbacks [Chris Beer]
31
+
32
+ 2016-03-18: Prefix internal create_ and update_record callbacks with an
33
+ underscore [Chris Beer]
34
+
35
+ 2016-03-18: Add create_or_update to provide save callbacks [Chris Beer]
36
+
37
+ 2016-03-18: Add ActiveFedora::Persistence#destroy! [Chris Beer]
38
+
39
+ 2016-03-20: Correctly find the size of a collection in memory [Justin Coyne]
40
+
41
+ 2016-03-18: Bump version to 9.10.0.pre1 [Justin Coyne]
42
+
43
+ 2016-03-18: Update Validations with latest upstream changes [Chris Beer]
44
+
45
+ 2016-03-18: Delegate count to the scope [Justin Coyne]
46
+
47
+ 2016-03-18: Update nested attributes with upstream improvements [Chris Beer]
48
+
49
+ 2016-03-18: Update reflection methods to match new upstream names [Chris Beer]
50
+
51
+ 2016-03-18: Add explicit ActiveModel dependency [Chris Beer]
52
+
53
+ 2016-03-18: Update minimum versions of ruby and activesupport [Chris Beer]
54
+
55
+ 2016-03-17: Extract Builder::Association.create_reflection [Chris Beer]
56
+
57
+ 2016-03-17: Delegate responsibility for cleaning up dependencies to association
58
+ instances [Chris Beer]
59
+
60
+ 2016-03-17: validate dependent options [Chris Beer]
61
+
62
+ 2016-03-17: Port .dangerous_attribute_method? from Rails [Chris Beer]
63
+
64
+ 2016-03-17: Migrate valid_options from a class attribute to a method [Chris
65
+ Beer]
66
+
67
+ 2016-03-17: Convert Assocations::Builder.macro from a class variable to a class
68
+ method [Chris Beer]
69
+
70
+ 2016-03-15: Add default scopes [Justin Coyne]
71
+
72
+ 2016-03-16: Unconditionally run coverage reports when running tests [Chris Beer]
73
+
74
+ 2016-03-16: Remove or deprecate unused code [Chris Beer]
75
+
76
+ 2016-03-16: Silence SolrQueryBuilder deprecation warnings when running tests
77
+ [Chris Beer]
78
+
79
+ 2016-03-16: Update relation calculations to use SolrService.count [Chris Beer]
80
+
81
+ 2016-03-16: Extract SolrService.get to send requests to Solr and get the
82
+ original response [Chris Beer]
83
+
84
+ 2016-03-16: Use field queries instead of raw queries [Chris Beer]
85
+
86
+ 2016-03-16: Deprecate ActiveFedora::SolrQueryBuilder.raw_query in favor of
87
+ .construct_query [Chris Beer]
88
+
89
+ 2016-03-16: Deprecate ActiveFedora::SolrQueryBuilder.solr_name in favor of using
90
+ ActiveFedora.index_field_mapper directly [Chris Beer]
91
+
92
+ 2016-03-15: Extract SolrHit class to wrap Solr response documents [Chris Beer]
93
+
94
+ 2016-03-15: Deprecate unused methods [Justin Coyne]
95
+
96
+ 2016-03-15: ActiveFedora depends on Solrizer [Justin Coyne]
97
+
98
+ 2016-03-15: Don't rely on exceptions for flow control [Justin Coyne]
99
+
100
+ 2016-03-15: Update testing versions of Ruby and Rails [Justin Coyne]
101
+
102
+ 2016-03-15: Push .search_by_id into ActiveFedora::FinderMethod [Chris Beer]
103
+
104
+ 2016-03-15: Rename find_with_conditions and find_in_batches to
105
+ search_with_conditions and search_in_batches [Chris Beer]
106
+
107
+ 2016-03-11: Provide class-level accessors in place of global constants for
108
+ configuration [Chris Beer]
109
+
110
+ 2016-03-11: Use ActiveFedora.index_field_mapper instead of accessing Solrizer
111
+ directly [Chris Beer]
112
+
113
+ 2016-03-11: Use the same logic for lazy_reify_solr_results and
114
+ reify_solr_results [Chris Beer]
115
+
116
+ 2016-03-10: Move indexer to a class attribute [Justin Coyne]
117
+
118
+ 2016-03-09: Decompose ActiveFedora::Model into a generic model mapper and a
119
+ classifier [Chris Beer]
120
+
121
+ 2016-03-09: Add DefaultModelMapper class to encapsulate model selection logic
122
+ [Chris Beer]
123
+
124
+ 2016-03-09: Use ActiveFedora.model_mapper accessor to get the type to class
125
+ mapper [Chris Beer]
126
+
127
+ 2016-03-09: Unify class lookup for Fedora types to ActiveFedora models [Chris
128
+ Beer]
129
+
130
+ 2016-03-09: Move ActiveFedora.class_from_string into ActiveFedora::Model [Chris
131
+ Beer]
132
+
133
+ 2016-03-09: Remove require of rubocop-rspec [Justin Coyne]
134
+
135
+ 2016-03-09: Pin rake to ~> 10.0 [Justin Coyne]
136
+
137
+ 2016-03-09: Update test to support ActiveModel 4.2.6 [Justin Coyne]
138
+
139
+ 2016-03-08: Update to use ldp 0.5 [Chris Beer]
140
+
141
+
1
142
  v9.9.1
2
143
  2016-03-05: Restore autocommit in the update handler [Justin Coyne]
3
144
 
@@ -76,7 +76,7 @@ module ActiveFedora
76
76
  # by scope.scoping { ... } or with_scope { ... } etc, which affects the scope which
77
77
  # actually gets built.
78
78
  def association_scope
79
- @association_scope ||= AssociationScope.new(self).scope if klass
79
+ @association_scope ||= AssociationScope.scope(self) if klass
80
80
  end
81
81
 
82
82
  def reset_scope
@@ -115,12 +115,17 @@ module ActiveFedora
115
115
  @target = find_target if (@stale_state && stale_target?) || find_target?
116
116
  loaded! unless loaded?
117
117
  target
118
+ rescue ActiveFedora::ObjectNotFoundError
119
+ reset
118
120
  end
119
121
 
120
- def initialize_attributes(record) #:nodoc:
122
+ def initialize_attributes(record, except_from_scope_attributes = nil) #:nodoc:
123
+ except_from_scope_attributes ||= {}
121
124
  skip_assign = [reflection.foreign_key].compact
122
- attributes = create_scope.except(*(record.changed - skip_assign))
123
- record.attributes = attributes
125
+ assigned_keys = record.changed
126
+ assigned_keys += except_from_scope_attributes.keys.map(&:to_s)
127
+ attributes = create_scope.except(*(assigned_keys - skip_assign))
128
+ record.assign_attributes(attributes)
124
129
  set_inverse_instance(record)
125
130
  end
126
131
 
@@ -130,6 +135,25 @@ module ActiveFedora
130
135
  !loaded? && (!owner.new_record? || foreign_key_present?) && klass
131
136
  end
132
137
 
138
+ def creation_attributes
139
+ attributes = {}
140
+
141
+ if (reflection.has_one? || reflection.collection?) && !options[:through]
142
+ attributes[reflection.foreign_key] = owner[reflection.active_record_primary_key]
143
+
144
+ if reflection.options[:as]
145
+ attributes[reflection.type] = owner.class.base_class.name
146
+ end
147
+ end
148
+
149
+ attributes
150
+ end
151
+
152
+ # Sets the owner attributes on the given record
153
+ def set_owner_attributes(record)
154
+ creation_attributes.each { |key, value| record[key] = value }
155
+ end
156
+
133
157
  # Returns true if there is a foreign key present on the owner which
134
158
  # references the target. This is used to determine whether we can load
135
159
  # the target if the owner is currently a new record (and therefore
@@ -144,10 +168,16 @@ module ActiveFedora
144
168
  # Raises ActiveFedora::AssociationTypeMismatch unless +record+ is of
145
169
  # the kind of the class of the associated objects. Meant to be used as
146
170
  # a sanity check when you are about to assign an associated record.
147
- def raise_on_type_mismatch(record)
148
- return if record.is_a?(@reflection.klass) || record.is_a?(@reflection.class_name.constantize)
149
- message = "#{@reflection.class_name}(##{@reflection.klass.object_id}) expected, got #{record.class}(##{record.class.object_id})"
150
- raise ActiveFedora::AssociationTypeMismatch, message
171
+ def raise_on_type_mismatch!(record)
172
+ unless record.is_a?(reflection.klass)
173
+ fresh_class = reflection.class_name.safe_constantize
174
+ unless fresh_class && record.is_a?(fresh_class)
175
+ message = "#{reflection.class_name}(##{reflection.klass.object_id}) expected, got #{record.class}(##{record.class.object_id})"
176
+ raise ActiveFedora::AssociationTypeMismatch, message
177
+ end
178
+ end
179
+
180
+ type_validator.validate!(self, record)
151
181
  end
152
182
 
153
183
  def type_validator
@@ -180,10 +210,6 @@ module ActiveFedora
180
210
  initialize_attributes(record)
181
211
  end
182
212
  end
183
-
184
- def run_type_validator(record)
185
- type_validator.validate!(self, record)
186
- end
187
213
  end
188
214
  end
189
215
  end
@@ -1,6 +1,10 @@
1
1
  module ActiveFedora
2
2
  module Associations
3
3
  class AssociationScope #:nodoc:
4
+ def self.scope(association)
5
+ new(association).scope
6
+ end
7
+
4
8
  attr_reader :association
5
9
 
6
10
  delegate :klass, :owner, :reflection, :interpolate, to: :association
@@ -19,10 +23,10 @@ module ActiveFedora
19
23
 
20
24
  def add_constraints(scope)
21
25
  chain.each_with_index do |reflection, i|
22
- if reflection.source_macro == :belongs_to
26
+ if reflection.macro == :belongs_to
23
27
  # Create a partial solr query using the ids. We may add additional filters such as class_name later
24
28
  scope = scope.where(ActiveFedora::SolrQueryBuilder.construct_query_for_ids([owner[reflection.foreign_key]]))
25
- elsif reflection.source_macro == :has_and_belongs_to_many
29
+ elsif reflection.macro == :has_and_belongs_to_many
26
30
  else
27
31
  scope = scope.where(ActiveFedora::SolrQueryBuilder.construct_query_for_rel(association.send(:find_reflection) => owner.id))
28
32
  end
@@ -18,7 +18,7 @@ module ActiveFedora
18
18
 
19
19
  private
20
20
 
21
- def raise_on_type_mismatch(record)
21
+ def raise_on_type_mismatch!(record)
22
22
  return if record.is_a? LoadableFromJson::SolrBackedMetadataFile
23
23
  super
24
24
  end
@@ -35,8 +35,7 @@ module ActiveFedora
35
35
 
36
36
  def replace(record)
37
37
  if record
38
- raise_on_type_mismatch(record)
39
- run_type_validator(record)
38
+ raise_on_type_mismatch!(record)
40
39
  @updated = true
41
40
  end
42
41
 
@@ -1,16 +1,19 @@
1
1
  module ActiveFedora
2
2
  module Associations
3
3
  class BelongsToAssociation < SingularAssociation #:nodoc:
4
+ def handle_dependency
5
+ target.send(options[:dependent]) if load_target
6
+ end
7
+
4
8
  def replace(record)
5
9
  if record
6
- raise_on_type_mismatch(record)
7
- run_type_validator(record)
8
- # update_counters(record)
10
+ raise_on_type_mismatch!(record)
11
+ update_counters_on_replace(record)
9
12
  replace_keys(record)
10
13
  set_inverse_instance(record)
11
14
  @updated = true
12
15
  else
13
- # decrement_counters
16
+ decrement_counters
14
17
  remove_keys
15
18
  end
16
19
 
@@ -26,8 +29,24 @@ module ActiveFedora
26
29
  @updated
27
30
  end
28
31
 
32
+ def decrement_counters # :nodoc:
33
+ # noop
34
+ end
35
+
36
+ def increment_counters # :nodoc:
37
+ # noop
38
+ end
39
+
29
40
  private
30
41
 
42
+ def find_target?
43
+ !loaded? && foreign_key_present? && klass
44
+ end
45
+
46
+ def update_counters_on_replace(_record)
47
+ # noop
48
+ end
49
+
31
50
  def replace_keys(record)
32
51
  owner[reflection.foreign_key] = record.id
33
52
  end
@@ -7,20 +7,6 @@ module ActiveFedora::Associations::Builder
7
7
 
8
8
  VALID_OPTIONS = [:class_name, :predicate, :type_validator].freeze
9
9
 
10
- def self.macro
11
- raise NotImplementedError
12
- end
13
-
14
- def self.valid_options(_options)
15
- VALID_OPTIONS + Association.extensions.flat_map(&:valid_options)
16
- end
17
-
18
- def self.validate_options(options)
19
- options.assert_valid_keys(valid_options(options))
20
- end
21
-
22
- attr_reader :model, :name, :options, :mixin
23
-
24
10
  # configure_dependency
25
11
  def self.build(model, name, options, &block)
26
12
  if model.dangerous_attribute_method?(name)
@@ -37,42 +23,58 @@ module ActiveFedora::Associations::Builder
37
23
  reflection
38
24
  end
39
25
 
40
- def self.create_reflection(model, name, _scope, options, _extension = nil)
26
+ def self.create_reflection(model, name, scope, options, extension = nil)
41
27
  unless name.is_a?(Symbol)
42
28
  name = name.to_sym
43
29
  Deprecation.warn(ActiveFedora::Base, "association names must be a Symbol")
44
30
  end
45
-
46
31
  validate_options(options)
32
+ translate_property_to_predicate(options)
33
+
34
+ scope = build_scope(scope, extension)
35
+ name = better_name(name)
47
36
 
48
- new(model, name, options).build
37
+ ActiveFedora::Reflection.create(macro, name, scope, options, model)
49
38
  end
50
39
 
51
- def initialize(model, name, options)
52
- @model = model
53
- @name = name
54
- @options = options
55
- translate_property_to_predicate
56
- validate_options
40
+ def self.build_scope(scope, extension)
41
+ new_scope = scope
42
+
43
+ new_scope = proc { instance_exec(&scope) } if scope && scope.arity == 0
44
+
45
+ new_scope = wrap_scope new_scope, extension if extension
46
+
47
+ new_scope
57
48
  end
58
49
 
59
- def build
60
- configure_dependency if options[:dependent] # see https://github.com/rails/rails/commit/9da52a5e55cc665a539afb45783f84d9f3607282
61
- model.create_reflection(self.class.macro, name, options, model)
50
+ def self.wrap_scope(scope, _extension)
51
+ scope
62
52
  end
63
53
 
64
- def translate_property_to_predicate
54
+ def self.macro
55
+ raise NotImplementedError
56
+ end
57
+
58
+ def self.valid_options(_options)
59
+ VALID_OPTIONS + Association.extensions.flat_map(&:valid_options)
60
+ end
61
+
62
+ def self.validate_options(options)
63
+ options.assert_valid_keys(valid_options(options))
64
+ end
65
+
66
+ def self.better_name(name)
67
+ name
68
+ end
69
+
70
+ def self.translate_property_to_predicate(options)
65
71
  return unless options[:property]
66
72
  Deprecation.warn Association, "the :property option to `#{model}.#{macro} :#{name}' is deprecated and will be removed in active-fedora 10.0. Use :predicate instead", caller(5)
67
73
  options[:predicate] = predicate(options.delete(:property))
68
74
  end
69
75
 
70
- def validate_options
71
- self.class.validate_options(options)
72
- end
73
-
74
76
  # Returns the RDF predicate as defined by the :property attribute
75
- def predicate(property)
77
+ def self.predicate(property)
76
78
  return property if property.is_a? RDF::URI
77
79
  ActiveFedora::Predicates.find_graph_predicate(property)
78
80
  end
@@ -124,14 +126,6 @@ module ActiveFedora::Associations::Builder
124
126
  # noop
125
127
  end
126
128
 
127
- def self.add_destroy_callbacks(model, reflection)
128
- name = reflection.name
129
- model.before_destroy lambda do |o|
130
- a = o.association(name)
131
- a.handle_dependency if a.respond_to? :handle_dependency
132
- end
133
- end
134
-
135
129
  def self.valid_dependent_options
136
130
  raise NotImplementedError
137
131
  end
@@ -142,22 +136,9 @@ module ActiveFedora::Associations::Builder
142
136
  end
143
137
  end
144
138
 
145
- def configure_dependency
146
- return unless options[:dependent]
147
- return if model.association(name).respond_to? :handle_dependency
148
-
149
- unless [:destroy, :delete].include?(options[:dependent])
150
- raise ArgumentError, "The :dependent option expects either :destroy or :delete (#{options[:dependent].inspect})"
151
- end
152
-
153
- method_name = "belongs_to_dependent_#{options[:dependent]}_for_#{name}"
154
- model.send(:class_eval, <<-eoruby, __FILE__, __LINE__ + 1)
155
- def #{method_name}
156
- association = #{name}
157
- association.#{options[:dependent]} if association
158
- end
159
- eoruby
160
- model.after_destroy method_name
139
+ def self.add_destroy_callbacks(model, reflection)
140
+ name = reflection.name
141
+ model.before_destroy ->(o) { o.association(name).handle_dependency }
161
142
  end
162
143
  end
163
144
  end