diff --git a/lib/active_fedora/attributes/property_builder.rb b/lib/active_fedora/attributes/property_builder.rb index 6ca928f71..97e17766d 100644 --- a/lib/active_fedora/attributes/property_builder.rb +++ b/lib/active_fedora/attributes/property_builder.rb @@ -27,7 +27,9 @@ def #{name}=(value) def self.define_singular_readers(mixin, name) mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1 def #{name}(*args) - get_values(:#{name}).first + vals = get_values(:#{name}) + raise ActiveFedora::ConstraintError, "Expected \\"#{name}\\" to have 0-1 statements, but there are \#{vals.size}" if vals.size > 1 + vals.first end CODE end diff --git a/lib/active_fedora/errors.rb b/lib/active_fedora/errors.rb index 3ad4b21d1..373859ea1 100644 --- a/lib/active_fedora/errors.rb +++ b/lib/active_fedora/errors.rb @@ -54,6 +54,20 @@ class ReadOnlyRecord < ActiveFedoraError class IllegalOperation < ActiveFedoraError end + # Raised when the data has more than one statement for a predicate, but our constraints say it's singular + # This helps to prevent overwriting multiple values with a single value when round tripping: + # class Book < ActiveFedora::Base + # predicate :title, predicate: RDF::DC.title, multiple: false + # end + # + # b = Book.new + # b.resource.title = ['foo', 'bar'] + # b.title # Raises ConstraintError + # # which prevents us from doing: + # b.title = b.title + class ConstraintError < ActiveFedoraError + end + # Used to rollback a transaction in a deliberate way without raising an exception. # Transactions are currently incomplete class Rollback < ActiveFedoraError diff --git a/spec/unit/attributes_spec.rb b/spec/unit/attributes_spec.rb index ae29e55d3..7b8f35b96 100644 --- a/spec/unit/attributes_spec.rb +++ b/spec/unit/attributes_spec.rb @@ -418,6 +418,17 @@ class BarHistory4 < ActiveFedora::Base expect(subject[:abstract]).to be_nil end + context "when there are two assertions for the predicate" do + before do + subject.resource[:abstract] = ['foo', 'bar'] + end + it "should raise an error if just returning the first value would cause data loss" do + expect { subject[:abstract] }.to raise_error ActiveFedora::ConstraintError, "Expected \"abstract\" to have 0-1 statements, but there are 2" + end + end + end + + context "multiple values" do it "should return values" do expect(subject[:title]).to eq ['test1'] end