-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This writes the properties to ./fcr:metadata relative to the files URI Fixes #499
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
module ActiveFedora | ||
module WithMetadata | ||
extend ActiveSupport::Concern | ||
|
||
def metadata_node | ||
@metadata_node ||= self.class.metadata_schema.new(self) | ||
end | ||
|
||
def save(*) | ||
if super | ||
metadata_node.metadata_uri = described_by # TODO only necessary if the URI was < > before | ||
metadata_node.save # TODO if changed? | ||
end | ||
end | ||
|
||
module ClassMethods | ||
def metadata(&block) | ||
metadata_schema.exec_block(&block) | ||
end | ||
|
||
def metadata_schema | ||
@metadata_schema ||= MetadataNode(self) | ||
end | ||
|
||
def MetadataNode(parent_klass) | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
jcoyne
Author
Member
|
||
klass = self.const_set(:GeneratedMetadataSchema, Class.new(MetadataNode)) | ||
klass.parent_class = parent_klass | ||
klass | ||
end | ||
end | ||
|
||
class MetadataNode < ActiveTriples::Resource | ||
include ActiveModel::Dirty | ||
attr_reader :file | ||
|
||
def initialize(file) | ||
@file = file | ||
super(file.uri, ldp_source.graph) | ||
end | ||
|
||
def metadata_uri= uri | ||
@metadata_uri = uri | ||
end | ||
|
||
def metadata_uri | ||
@metadata_uri ||= if file.new_record? | ||
RDF::URI.new nil | ||
else | ||
raise "#{file} must respond_to described_by" unless file.respond_to? :described_by | ||
file.described_by | ||
end | ||
end | ||
|
||
def set_value(*args) | ||
super | ||
attribute_will_change! args.first | ||
end | ||
|
||
def self.parent_class= parent | ||
@parent_class = parent | ||
end | ||
|
||
def self.parent_class | ||
@parent_class | ||
end | ||
|
||
def self.property(name, options) | ||
parent_class.delegate name, :"#{name}=", :"#{name}_changed?", to: :metadata_node | ||
super | ||
end | ||
|
||
def self.create_delegating_setter(name) | ||
file.class.delegate(name, to: :metadata_node) | ||
end | ||
|
||
def ldp_source | ||
@ldp_source ||= LdpResource.new(ldp_connection, metadata_uri) | ||
end | ||
|
||
def ldp_connection | ||
ActiveFedora.fedora.connection | ||
end | ||
|
||
def save | ||
raise "Save the file first" if file.new_record? | ||
change_set = ChangeSet.new(self, self, changed_attributes.keys) | ||
SparqlInsert.new(change_set.changes, RDF::URI.new(file.uri)).execute(metadata_uri) | ||
@ldp_source = nil | ||
true | ||
end | ||
|
||
def self.exec_block(&block) | ||
class_eval &block | ||
end | ||
|
||
end | ||
|
||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
require 'spec_helper' | ||
|
||
describe ActiveFedora::WithMetadata do | ||
before do | ||
class Sample < ActiveFedora::Base | ||
contains :file, class_name: 'SampleFile' | ||
end | ||
|
||
class SampleFile < ActiveFedora::File | ||
include ActiveFedora::WithMetadata | ||
|
||
metadata do | ||
property :title, predicate: RDF::DC.title | ||
This comment has been minimized.
Sorry, something went wrong.
awead
Contributor
|
||
end | ||
end | ||
end | ||
|
||
after do | ||
Object.send(:remove_const, :SampleFile) | ||
Object.send(:remove_const, :Sample) | ||
end | ||
|
||
let(:base) { Sample.new } | ||
let(:file) { base.file } | ||
|
||
describe "properties" do | ||
before do | ||
file.title = ['one', 'two'] | ||
end | ||
it "should set and retrieve properties" do | ||
expect(file.title).to eq ['one', 'two'] | ||
end | ||
|
||
it "should track changes" do | ||
expect(file.title_changed?).to be true | ||
end | ||
end | ||
|
||
describe "#save" do | ||
before do | ||
file.content = "Hey" | ||
file.title = ["foo"] | ||
base.save | ||
base.reload | ||
end | ||
|
||
it "should save the metadata too" do | ||
expect(base.file.title).to eq ['foo'] | ||
end | ||
end | ||
|
||
end |
There's apparently something very clever going on here, however, I'm not clever enough to understand it. A method name that's the same name as the class defined below? MetadataNode really looks like a different thing and ought to be in its own file for clarity. Then at least some comments about what's going on in that method.