Skip to content

Commit

Permalink
Merge pull request #566 from projecthydra/properties_are_multiple
Browse files Browse the repository at this point in the history
ActiveTriples properties should know that they are multiple. Fixes #547
  • Loading branch information
mjgiarlo committed Nov 4, 2014
2 parents 4dc4dfe + ced8455 commit a420766
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 14 deletions.
26 changes: 21 additions & 5 deletions lib/active_fedora/attributes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,22 @@ def array_setter(field, args)

module ClassMethods
def attribute_names
@attribute_names ||= delegated_attributes.keys + local_attributes
@attribute_names ||= delegated_attributes.keys + association_attributes - system_attributes
end

# Attributes that are asserted about this RdfSource (not on a datastream)
def local_attributes
outgoing_reflections.values.map { |reflection| reflection.foreign_key.to_s } + properties.keys - ['has_model', 'create_date', 'modified_date']
association_attributes + properties.keys - system_attributes
end

# Attributes that are required by ActiveFedora and Fedora
def system_attributes
['has_model', 'create_date', 'modified_date']
end

# Attributes that represent associations to other repository objects
def association_attributes
outgoing_reflections.values.map { |reflection| reflection.foreign_key.to_s }
end

def defined_attributes
Expand Down Expand Up @@ -153,16 +163,22 @@ def unique?(field)
# @param [Symbol] field the field to query
# @return [Boolean]
def multiple?(field)
raise UnknownAttributeError, "#{self} does not have an attribute `#{field}'" unless self.delegated_attributes.key?(field)
raise UnknownAttributeError, "#{self} does not have an attribute `#{field}'" unless delegated_attributes.key?(field)
delegated_attributes[field].multiple
end

def find_or_create_defined_attribute(field, dsid, args)
delegated_attributes[field] ||= DelegatedAttribute.new(field, dsid, datastream_class_for_name(dsid), args)

def property name, properties
find_or_create_defined_attribute(name, nil, {multiple: true}.merge(properties))
super
end

private

def find_or_create_defined_attribute(field, dsid, args)
delegated_attributes[field] ||= DelegatedAttribute.new(field, dsid, datastream_class_for_name(dsid), args)
end

def create_attribute_reader(field, dsid, args)
find_or_create_defined_attribute(field, dsid, args)

Expand Down
25 changes: 16 additions & 9 deletions spec/unit/attributes_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ class BarHistory2 < ActiveFedora::Base
has_attributes :horse, datastream: 'xmlish', multiple: true
has_attributes :duck, datastream: 'xmlish', :at=>[:waterfowl, :ducks, :duck], multiple: true
has_attributes :animal_id, datastream: 'someData', multiple: false

property :goose, predicate: RDF::URI.new('http://example.com#hasGoose')

end
end

Expand All @@ -68,27 +71,27 @@ class BarHistory2 < ActiveFedora::Base
describe "#attribute_names" do
context "on an instance" do
it "should list the attributes" do
expect(subject.attribute_names).to eq ["cow", "fubar", "pig", "horse", "duck", "animal_id"]
expect(subject.attribute_names).to eq ["cow", "fubar", "pig", "horse", "duck", "animal_id", "goose"]
end
end

context "on a class" do
it "should list the attributes" do
expect(BarHistory2.attribute_names).to eq ["cow", "fubar", "pig", "horse", "duck", "animal_id"]
expect(BarHistory2.attribute_names).to eq ["cow", "fubar", "pig", "horse", "duck", "animal_id", "goose"]
end
end
end

describe "inspect" do
it "should show the attributes" do
expect(subject.inspect).to eq "#<BarHistory2 id: nil, cow: \"\", fubar: [], pig: nil, horse: [], duck: [\"\"], animal_id: nil>"
expect(subject.inspect).to eq "#<BarHistory2 id: nil, cow: \"\", fubar: [], pig: nil, horse: [], duck: [\"\"], animal_id: nil, goose: []>"
end

describe "with a id" do
before { allow(subject).to receive(:id).and_return('test:123') }

it "should show a id" do
expect(subject.inspect).to eq "#<BarHistory2 id: \"test:123\", cow: \"\", fubar: [], pig: nil, horse: [], duck: [\"\"], animal_id: nil>"
expect(subject.inspect).to eq "#<BarHistory2 id: \"test:123\", cow: \"\", fubar: [], pig: nil, horse: [], duck: [\"\"], animal_id: nil, goose: []>"
end
end

Expand All @@ -115,7 +118,7 @@ class BarHistory3 < BarHistory2
end

it "should show the library_id" do
expect(subject.inspect).to eq "#<BarHistory3 id: nil, cow: \"\", fubar: [], pig: nil, horse: [], duck: [\"\"], animal_id: nil, library_id: \"#{library.id}\">"
expect(subject.inspect).to eq "#<BarHistory3 id: nil, cow: \"\", fubar: [], pig: nil, horse: [], duck: [\"\"], animal_id: nil, goose: [], library_id: \"#{library.id}\">"
end
end
end
Expand Down Expand Up @@ -191,22 +194,22 @@ class BarHistory3 < BarHistory2
end

it "should raise an error on the reader when the field isn't delegated" do
expect {subject['goose'] }.to raise_error ActiveFedora::UnknownAttributeError, "BarHistory2 does not have an attribute `goose'"
expect {subject['donkey'] }.to raise_error ActiveFedora::UnknownAttributeError, "BarHistory2 does not have an attribute `donkey'"
end

it "should raise an error on the setter when the field isn't delegated" do
expect {subject['goose']="honk" }.to raise_error ActiveFedora::UnknownAttributeError, "BarHistory2 does not have an attribute `goose'"
expect {subject['donkey']="bray" }.to raise_error ActiveFedora::UnknownAttributeError, "BarHistory2 does not have an attribute `donkey'"
end
end

describe "attributes=" do
it "should raise an error on an invalid attribute" do
expect {subject.attributes = {'goose'=>"honk" }}.to raise_error ActiveFedora::UnknownAttributeError, "BarHistory2 does not have an attribute `goose'"
expect {subject.attributes = {'donkey'=>"bray" }}.to raise_error ActiveFedora::UnknownAttributeError, "BarHistory2 does not have an attribute `donkey'"
end
end

describe "attributes" do
let(:vals) { {'cow'=>"moo", 'pig' => 'oink', 'horse' =>['neigh'], "fubar"=>[], 'duck'=>['quack'], 'animal_id'=>'' } }
let(:vals) { {'cow'=>"moo", 'pig' => 'oink', 'horse' =>['neigh'], "fubar"=>[], 'duck'=>['quack'], 'animal_id'=>'', 'goose' => [] } }
before { subject.attributes = vals }
it "should return a hash" do
expect(subject.attributes).to eq(vals.merge('id' => nil))
Expand All @@ -218,6 +221,10 @@ class BarHistory3 < BarHistory2
expect(BarHistory2.multiple?(:pig)).to be false
end

it 'returns true if attribute is a ActiveTriples property' do
expect(BarHistory2.multiple?(:goose)).to be true
end

it 'returns true if attribute has been defined as multi-valued' do
expect(BarHistory2.multiple?(:horse)).to be true
end
Expand Down

0 comments on commit a420766

Please sign in to comment.