active-fedora 6.4.5 → 6.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,3 +1,32 @@
1
+ v6.5.0 (2013-08-28)
2
+
3
+ An empty query value that is a string should not return all
4
+ [Adam Hallett]
5
+
6
+ Delegate relation methods to the array [Justin Coyne]
7
+
8
+ Use an error message that gives a thourough explanation and a
9
+ for a fix [Justin Coyne]
10
+
11
+ Include ActiveModel::Dirty on Base, call field_will_change! on
12
+ methods, and track changes on save [Chris Colvard]
13
+
14
+ Rdf terminologies should be inheritable [Justin Coyne]
15
+
16
+ Raise an error when trying to assign to a delegated attribute that
17
+ been delegated [Justin Coyne]
18
+
19
+ Added RdfNode::TermProxy.first_or_create [Justin Coyne]
20
+
21
+ replace method_missing technique in rdf_node with an accessor
22
+ [Justin Coyne]
23
+
24
+ Add ActiveFedora::Relation#last. Resolves #184 [Andrew Curley]
25
+
26
+ RdfNode::TermProxy.build should use the correct class [Justin
27
+ Coyne]
28
+
29
+
1
30
  v6.4.5 (2013-08-05)
2
31
 
3
32
  Clear rdf lists and proxies [Justin Coyne]
@@ -203,7 +203,7 @@ module ActiveFedora
203
203
  end
204
204
 
205
205
  def find_class_for_relation(klass, inverse_relation=@owner.class.to_s.underscore.to_sym)
206
- raise "Unable to find #{klass}." if inverse_relation == :'active_fedora/base'
206
+ raise "Unable to lookup the :property attribute for #{@reflection.macro} #{@reflection.name.inspect} on #{@owner.class} because #{klass} specifies \"class_name: 'ActiveFedora::Base'\". Either specify a specific class_name in #{klass} or set :property in the #{@reflection.macro} declaration on #{@owner.class}" if inverse_relation == :'active_fedora/base'
207
207
  if klass.reflections.key?(inverse_relation)
208
208
  # Try it singular
209
209
  return klass.reflections[inverse_relation].options[:property]
@@ -342,6 +342,7 @@ module ActiveFedora
342
342
  include Associations
343
343
  include NestedAttributes
344
344
  include Reflection
345
+ include ActiveModel::Dirty
345
346
  end
346
347
 
347
348
  end
@@ -2,6 +2,14 @@ module ActiveFedora
2
2
  module Delegating
3
3
  extend ActiveSupport::Concern
4
4
 
5
+ included do
6
+ after_save :clear_changed_attributes
7
+ def clear_changed_attributes
8
+ @previously_changed = changes
9
+ @changed_attributes.clear
10
+ end
11
+ end
12
+
5
13
  # Calling inspect may trigger a bunch of loads, but it's mainly for debugging, so no worries.
6
14
  def inspect
7
15
  values = self.class.delegates.keys.map {|r| "#{r}:#{send(r).inspect}"}
@@ -19,6 +27,7 @@ module ActiveFedora
19
27
 
20
28
  private
21
29
  def array_reader(field, *args)
30
+ raise UnknownAttributeError, "#{self.class} does not have an attribute `#{field}'" unless self.class.delegates.key?(field)
22
31
  if args.present?
23
32
  instance_exec(*args, &self.class.delegates[field][:reader])
24
33
  else
@@ -27,6 +36,7 @@ module ActiveFedora
27
36
  end
28
37
 
29
38
  def array_setter(field, args)
39
+ raise UnknownAttributeError, "#{self.class} does not have an attribute `#{field}'" unless self.class.delegates.key?(field)
30
40
  instance_exec(args, &self.class.delegates[field][:setter])
31
41
  end
32
42
 
@@ -68,6 +78,7 @@ module ActiveFedora
68
78
  raise ArgumentError, "Target is required"
69
79
  end
70
80
  if ds_specs.has_key? to.to_s
81
+ define_attribute_method fields.first
71
82
  create_delegate_reader(fields.first, options)
72
83
  create_delegate_setter(fields.first, options)
73
84
  else
@@ -95,6 +106,7 @@ module ActiveFedora
95
106
  # foo.field3 # => NoMethodError: undefined method `field3' for #<Foo:0x1af30c>
96
107
 
97
108
  def delegate_to(datastream,fields,args={})
109
+ define_attribute_methods fields
98
110
  fields.each do |f|
99
111
  args.merge!({:to=>datastream})
100
112
  create_delegate_reader(f, args)
@@ -139,6 +151,7 @@ module ActiveFedora
139
151
  self.delegates[field] ||= {}
140
152
  self.delegates[field][:setter] = lambda do |v|
141
153
  ds = self.send(args[:to])
154
+ self.send("#{field}_will_change!") unless v == array_reader(field)
142
155
  if ds.kind_of?(ActiveFedora::RDFDatastream)
143
156
  ds.send("#{field}=", v)
144
157
  else
@@ -1,6 +1,6 @@
1
1
  module ActiveFedora
2
2
  module Querying
3
- delegate :find, :first, :where, :limit, :order, :all, :delete_all, :destroy_all, :count, :to=>:relation
3
+ delegate :find, :first, :where, :limit, :order, :all, :delete_all, :destroy_all, :count, :last, :to=>:relation
4
4
 
5
5
  def self.extended(base)
6
6
  base.class_attribute :solr_query_handler
@@ -138,6 +138,8 @@ module ActiveFedora
138
138
  end
139
139
  if value.is_a? Array
140
140
  value.map { |val| "#{key}:#{quote_for_solr(val)}" }
141
+ elsif value.is_a? String and value.empty?
142
+ "-#{key}:['' TO *]"
141
143
  else
142
144
  key = SOLR_DOCUMENT_ID if (key === :id || key === :pid)
143
145
  escaped_value = quote_for_solr(value)
@@ -1,9 +1,10 @@
1
1
  module ActiveFedora
2
2
  module Rdf
3
3
  class NodeConfig
4
- attr_accessor :predicate, :class_name, :type, :behaviors, :multivalue
4
+ attr_accessor :predicate, :term, :class_name, :type, :behaviors, :multivalue
5
5
 
6
- def initialize(predicate, args={})
6
+ def initialize(term, predicate, args={})
7
+ self.term = term
7
8
  self.predicate = predicate
8
9
  self.class_name = args.delete(:class_name)
9
10
  self.multivalue = args.delete(:multivalue) { true }
@@ -44,16 +44,12 @@ module ActiveFedora
44
44
  # @param [Symbol] term the term to get the values for
45
45
  def get_values(subject, term)
46
46
  options = config_for_term_or_uri(term)
47
- predicate = options.predicate
48
47
  @target ||= {}
49
- @target[term.to_s] ||= TermProxy.new(self, subject, predicate, options)
48
+ @target[term.to_s] ||= TermProxy.new(self, subject, options)
50
49
  end
51
50
 
52
- def target_class(predicate)
53
- _, conf = self.class.config_for_predicate(predicate)
54
- class_name = conf.class_name
55
- return nil unless class_name
56
- ActiveFedora.class_from_string(class_name, self.class)
51
+ def target_class(conf)
52
+ ActiveFedora.class_from_string(conf.class_name, self.class) if conf.class_name
57
53
  end
58
54
 
59
55
  def mark_for_destruction
@@ -94,7 +90,7 @@ module ActiveFedora
94
90
 
95
91
  @target ||= {}
96
92
  proxy = @target[term.to_s]
97
- proxy ||= TermProxy.new(self, subject, predicate, options)
93
+ proxy ||= TermProxy.new(self, subject, options)
98
94
  proxy.reset!
99
95
  proxy
100
96
 
@@ -190,18 +186,6 @@ module ActiveFedora
190
186
  q.execute(graph, &block)
191
187
  end
192
188
 
193
- def method_missing(name, *args)
194
- if md = /^([^=]+)=$/.match(name.to_s)
195
- set_value(rdf_subject, md[1], *args)
196
- elsif find_predicate(name)
197
- get_values(rdf_subject, name)
198
- else
199
- super
200
- end
201
- rescue ActiveFedora::UnregisteredPredicateError
202
- super
203
- end
204
-
205
189
  private
206
190
 
207
191
  def remove_existing_values(subject, predicate, values)
@@ -244,6 +228,7 @@ module ActiveFedora
244
228
  class Builder
245
229
  def initialize(parent)
246
230
  @parent = parent
231
+ @parent.create_node_accessor(:type)
247
232
  end
248
233
 
249
234
  def build(&block)
@@ -252,20 +237,38 @@ module ActiveFedora
252
237
 
253
238
  def method_missing(name, *args, &block)
254
239
  args = args.first if args.respond_to? :first
255
- raise "mapping must specify RDF vocabulary as :in argument" unless args.has_key? :in
240
+ raise "mapping for '#{name}' must specify RDF vocabulary as :in argument" unless args.kind_of?(Hash) && args.has_key?(:in)
256
241
  vocab = args.delete(:in)
257
242
  field = args.delete(:to) {name}.to_sym
258
243
  raise "Vocabulary '#{vocab.inspect}' does not define property '#{field.inspect}'" unless vocab.respond_to? field
259
- @parent.config[name] = Rdf::NodeConfig.new(vocab.send(field), args).tap do |config|
244
+ @parent.config[name] = Rdf::NodeConfig.new(name, vocab.send(field), args).tap do |config|
260
245
  config.with_index(&block) if block_given?
261
246
  end
247
+
248
+ @parent.create_node_accessor(name)
262
249
  end
263
250
 
264
251
  end
265
252
 
266
253
  module ClassMethods
254
+
255
+ def create_node_accessor(name)
256
+ class_eval <<-eoruby, __FILE__, __LINE__ + 1
257
+ def #{name}=(*args)
258
+ set_value(rdf_subject, :#{name}, *args)
259
+ end
260
+ def #{name}
261
+ get_values(rdf_subject, :#{name})
262
+ end
263
+ eoruby
264
+ end
265
+
267
266
  def config
268
- @config ||= {}.with_indifferent_access
267
+ @config ||= if superclass.respond_to? :config
268
+ superclass.config.dup
269
+ else
270
+ {}.with_indifferent_access
271
+ end
269
272
  end
270
273
 
271
274
  # List of symbols representing the fields for this terminology.
@@ -289,7 +292,7 @@ module ActiveFedora
289
292
  def rdf_type(uri_or_string=nil)
290
293
  if uri_or_string
291
294
  uri = uri_or_string.kind_of?(RDF::URI) ? uri_or_string : RDF::URI.new(uri_or_string)
292
- self.config[:type] = Rdf::NodeConfig.new(RDF.type)
295
+ self.config[:type] = Rdf::NodeConfig.new(:type, RDF.type)
293
296
  @rdf_type = uri
294
297
  logger.warn "Duplicate RDF Class. Trying to register #{self} for #{uri} but it is already registered for #{ActiveFedora::RdfNode.rdf_registry[uri]}" if ActiveFedora::RdfNode.rdf_registry.key? uri
295
298
  ActiveFedora::RdfNode.rdf_registry[uri] = self
@@ -2,24 +2,23 @@ module ActiveFedora
2
2
  module RdfNode
3
3
  class TermProxy
4
4
 
5
- attr_reader :parent, :subject, :predicate, :options
5
+ attr_reader :parent, :subject, :options
6
6
  delegate *(Array.public_instance_methods - [:__send__, :__id__, :class, :object_id] + [:as_json]), :to => :target
7
7
 
8
8
 
9
9
  # @param parent RdfNode
10
10
  # @param subject RDF::URI
11
11
  # @param options Hash
12
- def initialize(parent, subject, predicate, options)
12
+ def initialize(parent, subject, options)
13
13
  @parent = parent
14
14
  @subject = subject
15
- @predicate = predicate
16
15
  @options = options
17
16
  end
18
17
 
19
18
 
20
19
  def build(attributes={})
21
20
  node = mint_node(attributes)
22
- parent.insert_child(predicate, node)
21
+ parent.insert_child(options.predicate, node)
23
22
  reset!
24
23
  new_node = target.find { |n| n.rdf_subject == node.rdf_subject}
25
24
  new_node = node unless new_node #if it's a list, the find doesn't work, just use the new node
@@ -27,9 +26,13 @@ module ActiveFedora
27
26
  new_node
28
27
  end
29
28
 
29
+ def first_or_create(attributes={})
30
+ first || build(attributes)
31
+ end
32
+
30
33
  # Remove all matching nodes from the graph
31
34
  def clear
32
- parent.query(subject, predicate).each do |solution|
35
+ parent.query(subject, options.predicate).each do |solution|
33
36
  # TODO - Recursive delete
34
37
  # Delete everythign we're pointing at.
35
38
  parent.graph.delete([solution.value, nil, nil]) if solution.value.uri?
@@ -47,20 +50,20 @@ module ActiveFedora
47
50
  # @option attributes id the rdf subject to use for the node, if omitted the new node will be a b-node
48
51
  def mint_node(attributes)
49
52
  new_subject = attributes.key?('id') ? RDF::URI.new(attributes.delete('id')) : RDF::Node.new
50
- return parent.target_class(predicate).new(parent.graph, new_subject).tap do |node|
53
+ return parent.target_class(options).new(parent.graph, new_subject).tap do |node|
51
54
  node.attributes = attributes if attributes
52
55
  end
53
56
  end
54
57
 
55
58
  def <<(*values)
56
- values.each { |value| parent.append(subject, predicate, value) }
59
+ values.each { |value| parent.append(subject, options.predicate, value) }
57
60
  reset!
58
61
  values
59
62
  end
60
63
 
61
64
  def delete(*values)
62
65
  values.each do |value|
63
- parent.delete_predicate(subject, predicate, value)
66
+ parent.delete_predicate(subject, options.predicate, value)
64
67
  end
65
68
 
66
69
  values
@@ -74,7 +77,7 @@ module ActiveFedora
74
77
  def load_values
75
78
  values = []
76
79
 
77
- parent.query(subject, predicate).each do |solution|
80
+ parent.query(subject, options.predicate).each do |solution|
78
81
  v = solution.value
79
82
  v = v.to_s if v.is_a? RDF::Literal
80
83
  if options.type == :date
@@ -100,7 +103,7 @@ module ActiveFedora
100
103
  private
101
104
 
102
105
  def target_class
103
- parent.target_class(predicate)
106
+ parent.target_class(options)
104
107
  end
105
108
 
106
109
  # Look for a RDF.type assertion on this node to see if an RDF class is specified.
@@ -108,7 +111,7 @@ module ActiveFedora
108
111
  # If no RDF.type assertion is found, fall back to using target_class
109
112
  def class_from_rdf_type(subject)
110
113
  unless subject.kind_of?(RDF::Node) || subject.kind_of?(RDF::URI)
111
- raise ArgumentError, "Expected the value of #{predicate} to be an RDF object but it is a #{subject.class} #{subject.inspect}"
114
+ raise ArgumentError, "Expected the value of #{options.predicate} to be an RDF object but it is a #{subject.class} #{subject.inspect}"
112
115
  end
113
116
  q = RDF::Query.new do
114
117
  pattern [subject, RDF.type, :value]
@@ -1,6 +1,8 @@
1
1
  module ActiveFedora
2
2
  class Relation
3
3
 
4
+ delegate :map, :each, :collect, :all?, :include?, :to => :to_a
5
+
4
6
  attr_reader :loaded
5
7
  alias :loaded? :loaded
6
8
 
@@ -33,6 +35,20 @@ module ActiveFedora
33
35
  end
34
36
  end
35
37
 
38
+ # Returns the last record sorted by id. ID was chosen because this mimics
39
+ # how ActiveRecord would achieve the same behavior.
40
+ #
41
+ # @example
42
+ # Person.where(name_t: 'Jones').last
43
+ # => #<Person @id="foo:123" @name='Jones' ... >
44
+ def last
45
+ if loaded?
46
+ @records.last
47
+ else
48
+ @last ||= order('id desc').limit(1).to_a[0]
49
+ end
50
+ end
51
+
36
52
  # Limits the number of returned records to the value specified
37
53
  #
38
54
  # @option [Integer] value the number of records to return
@@ -1,3 +1,3 @@
1
1
  module ActiveFedora
2
- VERSION = "6.4.5"
2
+ VERSION = "6.5.0"
3
3
  end
@@ -107,13 +107,34 @@ END
107
107
  ds.parts.first.label.should == ['Wheel bearing']
108
108
  end
109
109
 
110
+ it "should not create a child node when hitting the accessor" do
111
+ ds.parts
112
+ ds.parts.first.should be_nil
113
+ ds.serialize.should == ''
114
+ end
115
+
110
116
  it "should build complex objects when a parent node exists" do
111
- ds.parts #this creates a parts node, but it shouldn't
112
117
  part = ds.parts.build
113
118
  part.should be_kind_of SpecDatastream::Component
114
119
  part.label = "Wheel bearing"
115
120
  ds.parts.first.label.should == ['Wheel bearing']
116
121
  end
122
+
123
+ describe "#first_or_create" do
124
+ it "should return a result if the predicate exists" do
125
+ part1 = ds.parts.build
126
+ part2 = ds.parts.build
127
+ ds.parts.first_or_create.should == part1
128
+ end
129
+
130
+ it "should create a new result if the predicate doesn't exist" do
131
+ ds.parts.should == []
132
+ part = ds.parts.first_or_create(label: 'Front control arm bushing')
133
+ part.label.should == ['Front control arm bushing']
134
+ ds.parts.should == [part]
135
+ end
136
+
137
+ end
117
138
  end
118
139
 
119
140
 
@@ -229,6 +250,10 @@ END
229
250
  ds.series.first.type.first.to_s.should == 'http://www.ebu.ch/metadata/ontologies/ebucore#Series'
230
251
  end
231
252
 
253
+ it "should create an object of the correct type" do
254
+ ds.program.build.should be_kind_of SpecDatastream::Program
255
+ ds.series.build.should be_kind_of SpecDatastream::Series
256
+ end
232
257
  end
233
258
  end
234
259
  end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe "delegating objects" do
4
+ before :all do
5
+ class TitledObject < ActiveFedora::Base
6
+ has_metadata :type=>ActiveFedora::SimpleDatastream, :name=>"foo" do |m|
7
+ m.field "title", :string
8
+ end
9
+ delegate :title, :to=>'foo', :unique=>true
10
+ end
11
+ end
12
+ after :all do
13
+ Object.send(:remove_const, :TitledObject)
14
+ end
15
+
16
+ describe "save" do
17
+ subject do
18
+ obj = TitledObject.create
19
+ obj.title = "Hydra for Dummies"
20
+ obj.save
21
+ obj
22
+ end
23
+ it "should keep a list of changes after a successful save" do
24
+ subject.previous_changes.should_not be_empty
25
+ subject.previous_changes.keys.should include("title")
26
+ end
27
+ it "should clean out changes" do
28
+ subject.title_changed?.should be_false
29
+ subject.changes.should be_empty
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveFedora::Model do
4
+
5
+ before(:all) do
6
+ module ModelIntegrationSpec
7
+ class Basic < ActiveFedora::Base
8
+ has_metadata :name => "properties", :type => ActiveFedora::SimpleDatastream do |m|
9
+ m.field "foo", :string
10
+ m.field "bar", :string
11
+ m.field "baz", :string
12
+ end
13
+
14
+ delegate_to :properties, [:foo, :bar, :baz]
15
+
16
+ def to_solr(doc = {})
17
+ doc = super
18
+ doc[ActiveFedora::SolrService.solr_name('foo', :sortable)] = doc[ActiveFedora::SolrService.solr_name('foo', type: :string)]
19
+ doc
20
+ end
21
+
22
+ end
23
+ end
24
+
25
+ end
26
+
27
+ after(:all) do
28
+ Object.send(:remove_const, :ModelIntegrationSpec)
29
+ end
30
+
31
+
32
+ describe "with multiple objects" do
33
+ let!(:instance1){ ModelIntegrationSpec::Basic.create!(:foo=>'Beta', :bar=>'Chips')}
34
+ let!(:instance2){ ModelIntegrationSpec::Basic.create!(:foo=>'Alpha', :bar=>'Peanuts')}
35
+ let!(:instance3){ ModelIntegrationSpec::Basic.create!(:foo=>'Sigma', :bar=>'Peanuts')}
36
+
37
+ after { ModelIntegrationSpec::Basic.delete_all }
38
+
39
+ subject { ModelIntegrationSpec::Basic.where(bar: 'Peanuts') }
40
+
41
+ it "should map" do
42
+ subject.map(&:id).should == [instance2.id, instance3.id]
43
+ end
44
+
45
+ it "should collect" do
46
+ subject.collect(&:id).should == [instance2.id, instance3.id]
47
+ end
48
+
49
+ it "should have each" do
50
+ t = double
51
+ t.should_receive(:foo).twice
52
+ subject.each { t.foo }
53
+ end
54
+
55
+ it "should have all?" do
56
+ expect(subject.all? { |t| t.foo == ['Alpha']}).to be_false
57
+ expect(subject.all? { |t| t.bar == ['Peanuts']}).to be_true
58
+ end
59
+
60
+ it "should have include?" do
61
+ expect(subject.include?(instance1)).to be_false
62
+ expect(subject.include?(instance2)).to be_true
63
+ end
64
+ end
65
+ end
66
+
67
+
@@ -58,9 +58,7 @@ describe ActiveFedora::Base do
58
58
  Object.send(:remove_const, :BarHistory2)
59
59
  end
60
60
 
61
- before :each do
62
- @n = BarHistory2.new()
63
- end
61
+ subject { BarHistory2.new() }
64
62
 
65
63
  it "should reveal the unique properties" do
66
64
  BarHistory2.unique?(:fubar).should be_true
@@ -68,40 +66,54 @@ describe ActiveFedora::Base do
68
66
  end
69
67
 
70
68
  it "should save a delegated property uniquely" do
71
- @n.fubar="Quack"
72
- @n.fubar.should == "Quack"
73
- @n.withText.get_values(:fubar).first.should == 'Quack'
74
- @n.donkey="Bray"
75
- @n.donkey.should == "Bray"
76
- @n.xmlish.term_values(:donkey).first.should == 'Bray'
69
+ subject.fubar="Quack"
70
+ subject.fubar.should == "Quack"
71
+ subject.withText.get_values(:fubar).first.should == 'Quack'
72
+ subject.donkey="Bray"
73
+ subject.donkey.should == "Bray"
74
+ subject.xmlish.term_values(:donkey).first.should == 'Bray'
77
75
  end
78
76
 
79
77
  it "should allow passing parameters to the delegate accessor" do
80
- @n.cow=["one", "two"]
81
- @n.cow(1).should == ['two']
78
+ subject.cow=["one", "two"]
79
+ subject.cow(1).should == ['two']
82
80
  end
83
81
 
84
82
 
85
83
  it "should return an array if not marked as unique" do
86
84
  ### Metadata datastream does not appear to support multiple value setting
87
- @n.cow=["one", "two"]
88
- @n.cow.should == ["one", "two"]
85
+ subject.cow=["one", "two"]
86
+ subject.cow.should == ["one", "two"]
89
87
  end
90
88
 
91
89
  it "should be able to delegate deeply into the terminology" do
92
- @n.duck=["Quack", "Peep"]
93
- @n.duck.should == ["Quack", "Peep"]
90
+ subject.duck=["Quack", "Peep"]
91
+ subject.duck.should == ["Quack", "Peep"]
92
+ end
93
+
94
+ it "should be able to track change status" do
95
+ subject.fubar_changed?.should be_false
96
+ subject.fubar = "Meow"
97
+ subject.fubar_changed?.should be_true
94
98
  end
95
99
 
96
100
  describe "array getters and setters" do
97
101
  it "should accept symbol keys" do
98
- @n[:duck]= ["Cluck", "Gobble"]
99
- @n[:duck].should == ["Cluck", "Gobble"]
102
+ subject[:duck]= ["Cluck", "Gobble"]
103
+ subject[:duck].should == ["Cluck", "Gobble"]
100
104
  end
101
105
 
102
106
  it "should accept string keys" do
103
- @n['duck']= ["Cluck", "Gobble"]
104
- @n['duck'].should == ["Cluck", "Gobble"]
107
+ subject['duck']= ["Cluck", "Gobble"]
108
+ subject['duck'].should == ["Cluck", "Gobble"]
109
+ end
110
+
111
+ it "should raise an error on the reader when the field isn't delegated" do
112
+ expect {subject['goose'] }.to raise_error ActiveFedora::UnknownAttributeError, "BarHistory2 does not have an attribute `goose'"
113
+ end
114
+
115
+ it "should raise an error on the setter when the field isn't delegated" do
116
+ expect {subject['goose']="honk" }.to raise_error ActiveFedora::UnknownAttributeError, "BarHistory2 does not have an attribute `goose'"
105
117
  end
106
118
  end
107
119
 
@@ -128,7 +140,50 @@ describe ActiveFedora::Base do
128
140
  subject.donkey=["Bray", "Hee-haw"]
129
141
  subject.donkey.should == ["Bray", "Hee-haw"]
130
142
  end
143
+
144
+ it "should be able to track change status" do
145
+ subject.cow_changed?.should be_false
146
+ subject.cow = ["Moo"]
147
+ subject.cow_changed?.should be_true
148
+ end
131
149
  end
150
+
151
+ describe "with a RDF datastream" do
152
+ before :all do
153
+ class BarRdfDatastream < ActiveFedora::NtriplesRDFDatastream
154
+ map_predicates do |map|
155
+ map.title(in: RDF::DC)
156
+ map.description(in: RDF::DC, multivalue: false)
157
+ end
158
+ end
159
+ class BarHistory4 < ActiveFedora::Base
160
+ has_metadata 'rdfish', :type=>BarRdfDatastream
161
+ delegate_to 'rdfish', [:title, :description]
162
+ end
163
+ end
164
+
165
+ after :all do
166
+ Object.send(:remove_const, :BarHistory4)
167
+ Object.send(:remove_const, :BarRdfDatastream)
168
+ end
169
+
170
+ subject { BarHistory4.new }
171
+
172
+ describe "with a multivalued field" do
173
+ it "should be able to track change status" do
174
+ subject.title_changed?.should be_false
175
+ subject.title = ["Title1", "Title2"]
176
+ subject.title_changed?.should be_true
177
+ end
178
+ end
179
+ describe "with a single-valued field" do
180
+ it "should be able to track change status" do
181
+ subject.description_changed?.should be_false
182
+ subject.description = "A brief description"
183
+ subject.description_changed?.should be_true
184
+ end
185
+ end
186
+ end
132
187
  end
133
188
 
134
189
 
@@ -63,6 +63,12 @@ describe ActiveFedora::Base do
63
63
  @n.duck.should == ["Quack", "Peep"]
64
64
  end
65
65
 
66
+ it "should be able to track change status" do
67
+ @n.chicken_changed?.should be_false
68
+ @n.chicken = ["Cheep"]
69
+ @n.chicken_changed?.should be_true
70
+ end
71
+
66
72
  end
67
73
  end
68
74
 
@@ -82,6 +82,10 @@ describe ActiveFedora::Base do
82
82
  SpecModel::Basic.find({:foo=>'bar', :baz=>['quix','quack']}).should == ["Fake Object1", "Fake Object2"]
83
83
  end
84
84
 
85
+ it "should correctly query for empty strings" do
86
+ SpecModel::Basic.find( :active_fedora_model_ssi => '').count.should == 0
87
+ end
88
+
85
89
  it "should add options" do
86
90
  SpecModel::Basic.should_receive(:find_one).with("changeme:30", nil).and_return("Fake Object1")
87
91
  SpecModel::Basic.should_receive(:find_one).with("changeme:22", nil).and_return("Fake Object2")
@@ -188,6 +192,48 @@ describe ActiveFedora::Base do
188
192
  ActiveFedora::Base.count(:conditions=>'foo:bar').should == 7
189
193
  end
190
194
  end
195
+
196
+ describe '#last' do
197
+ describe 'with multiple objects' do
198
+ before(:all) do
199
+ (@a, @b, @c) = 3.times {SpecModel::Basic.create!}
200
+ end
201
+ it 'should return one object' do
202
+ SpecModel::Basic.class == SpecModel::Basic
203
+ end
204
+ it 'should return the last object sorted by pid' do
205
+ SpecModel::Basic.last == @c
206
+ SpecModel::Basic.last != @a
207
+ end
208
+ end
209
+ describe 'with one object' do
210
+ it 'should equal the first object when there is only one' do
211
+ a = SpecModel::Basic.create!
212
+ SpecModel::Basic.first == SpecModel::Basic.last
213
+ end
214
+ end
215
+ end
216
+
217
+ describe '#first' do
218
+ describe 'with multiple objects' do
219
+ before(:all) do
220
+ (@a, @b, @c) = 3.times {SpecModel::Basic.create!}
221
+ end
222
+ it 'should return one object' do
223
+ SpecModel::Basic.class == SpecModel::Basic
224
+ end
225
+ it 'should return the last object sorted by pid' do
226
+ SpecModel::Basic.first == @a
227
+ SpecModel::Basic.first != @c
228
+ end
229
+ end
230
+ describe 'with one object' do
231
+ it 'should equal the first object when there is only one' do
232
+ a = SpecModel::Basic.create!
233
+ SpecModel::Basic.first == SpecModel::Basic.last
234
+ end
235
+ end
236
+ end
191
237
 
192
238
  describe '#find_with_conditions' do
193
239
  it "should make a query to solr and return the results" do
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveFedora::RdfNode do
4
+ describe "inheritance" do
5
+ before do
6
+ class Parent
7
+ include ActiveFedora::RdfObject
8
+ map_predicates do |map|
9
+ map.title(in: RDF::DC)
10
+ end
11
+ end
12
+
13
+ class Child < Parent
14
+ map_predicates do |map|
15
+ map.description(in: RDF::DC)
16
+ end
17
+ end
18
+
19
+ end
20
+ after do
21
+ Object.send(:remove_const, :Child)
22
+ Object.send(:remove_const, :Parent)
23
+ end
24
+
25
+ describe "child class" do
26
+ it "should inherit the terms" do
27
+ Child.config.keys.should == ['title', 'description']
28
+ end
29
+ end
30
+ describe "parent class" do
31
+ it "should not be infected with the child terms" do
32
+ Parent.config.keys.should == ['title']
33
+ end
34
+ end
35
+ end
36
+ end
metadata CHANGED
@@ -1,7 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active-fedora
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.4.5
4
+ version: 6.5.0
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Matt Zumwalt
@@ -10,25 +11,28 @@ authors:
10
11
  autorequire:
11
12
  bindir: bin
12
13
  cert_chain: []
13
- date: 2013-08-05 00:00:00.000000000 Z
14
+ date: 2013-08-28 00:00:00.000000000 Z
14
15
  dependencies:
15
16
  - !ruby/object:Gem::Dependency
16
17
  name: rsolr
17
18
  requirement: !ruby/object:Gem::Requirement
19
+ none: false
18
20
  requirements:
19
- - - '>='
21
+ - - ! '>='
20
22
  - !ruby/object:Gem::Version
21
23
  version: '0'
22
24
  type: :runtime
23
25
  prerelease: false
24
26
  version_requirements: !ruby/object:Gem::Requirement
27
+ none: false
25
28
  requirements:
26
- - - '>='
29
+ - - ! '>='
27
30
  - !ruby/object:Gem::Version
28
31
  version: '0'
29
32
  - !ruby/object:Gem::Dependency
30
33
  name: om
31
34
  requirement: !ruby/object:Gem::Requirement
35
+ none: false
32
36
  requirements:
33
37
  - - ~>
34
38
  - !ruby/object:Gem::Version
@@ -36,6 +40,7 @@ dependencies:
36
40
  type: :runtime
37
41
  prerelease: false
38
42
  version_requirements: !ruby/object:Gem::Requirement
43
+ none: false
39
44
  requirements:
40
45
  - - ~>
41
46
  - !ruby/object:Gem::Version
@@ -43,82 +48,93 @@ dependencies:
43
48
  - !ruby/object:Gem::Dependency
44
49
  name: nom-xml
45
50
  requirement: !ruby/object:Gem::Requirement
51
+ none: false
46
52
  requirements:
47
- - - '>='
53
+ - - ! '>='
48
54
  - !ruby/object:Gem::Version
49
55
  version: 0.5.1
50
56
  type: :runtime
51
57
  prerelease: false
52
58
  version_requirements: !ruby/object:Gem::Requirement
59
+ none: false
53
60
  requirements:
54
- - - '>='
61
+ - - ! '>='
55
62
  - !ruby/object:Gem::Version
56
63
  version: 0.5.1
57
64
  - !ruby/object:Gem::Dependency
58
65
  name: activesupport
59
66
  requirement: !ruby/object:Gem::Requirement
67
+ none: false
60
68
  requirements:
61
- - - '>='
69
+ - - ! '>='
62
70
  - !ruby/object:Gem::Version
63
71
  version: 3.0.0
64
72
  type: :runtime
65
73
  prerelease: false
66
74
  version_requirements: !ruby/object:Gem::Requirement
75
+ none: false
67
76
  requirements:
68
- - - '>='
77
+ - - ! '>='
69
78
  - !ruby/object:Gem::Version
70
79
  version: 3.0.0
71
80
  - !ruby/object:Gem::Dependency
72
81
  name: mediashelf-loggable
73
82
  requirement: !ruby/object:Gem::Requirement
83
+ none: false
74
84
  requirements:
75
- - - '>='
85
+ - - ! '>='
76
86
  - !ruby/object:Gem::Version
77
87
  version: '0'
78
88
  type: :runtime
79
89
  prerelease: false
80
90
  version_requirements: !ruby/object:Gem::Requirement
91
+ none: false
81
92
  requirements:
82
- - - '>='
93
+ - - ! '>='
83
94
  - !ruby/object:Gem::Version
84
95
  version: '0'
85
96
  - !ruby/object:Gem::Dependency
86
97
  name: rubydora
87
98
  requirement: !ruby/object:Gem::Requirement
99
+ none: false
88
100
  requirements:
89
101
  - - ~>
90
102
  - !ruby/object:Gem::Version
91
103
  version: '1.6'
92
- - - '>='
104
+ - - ! '>='
93
105
  - !ruby/object:Gem::Version
94
106
  version: 1.6.5
95
107
  type: :runtime
96
108
  prerelease: false
97
109
  version_requirements: !ruby/object:Gem::Requirement
110
+ none: false
98
111
  requirements:
99
112
  - - ~>
100
113
  - !ruby/object:Gem::Version
101
114
  version: '1.6'
102
- - - '>='
115
+ - - ! '>='
103
116
  - !ruby/object:Gem::Version
104
117
  version: 1.6.5
105
118
  - !ruby/object:Gem::Dependency
106
119
  name: rdf
107
120
  requirement: !ruby/object:Gem::Requirement
121
+ none: false
108
122
  requirements:
109
- - - '>='
123
+ - - ! '>='
110
124
  - !ruby/object:Gem::Version
111
125
  version: '0'
112
126
  type: :runtime
113
127
  prerelease: false
114
128
  version_requirements: !ruby/object:Gem::Requirement
129
+ none: false
115
130
  requirements:
116
- - - '>='
131
+ - - ! '>='
117
132
  - !ruby/object:Gem::Version
118
133
  version: '0'
119
134
  - !ruby/object:Gem::Dependency
120
135
  name: rdf-rdfxml
121
136
  requirement: !ruby/object:Gem::Requirement
137
+ none: false
122
138
  requirements:
123
139
  - - '='
124
140
  - !ruby/object:Gem::Version
@@ -126,6 +142,7 @@ dependencies:
126
142
  type: :runtime
127
143
  prerelease: false
128
144
  version_requirements: !ruby/object:Gem::Requirement
145
+ none: false
129
146
  requirements:
130
147
  - - '='
131
148
  - !ruby/object:Gem::Version
@@ -133,141 +150,161 @@ dependencies:
133
150
  - !ruby/object:Gem::Dependency
134
151
  name: deprecation
135
152
  requirement: !ruby/object:Gem::Requirement
153
+ none: false
136
154
  requirements:
137
- - - '>='
155
+ - - ! '>='
138
156
  - !ruby/object:Gem::Version
139
157
  version: '0'
140
158
  type: :runtime
141
159
  prerelease: false
142
160
  version_requirements: !ruby/object:Gem::Requirement
161
+ none: false
143
162
  requirements:
144
- - - '>='
163
+ - - ! '>='
145
164
  - !ruby/object:Gem::Version
146
165
  version: '0'
147
166
  - !ruby/object:Gem::Dependency
148
167
  name: rdoc
149
168
  requirement: !ruby/object:Gem::Requirement
169
+ none: false
150
170
  requirements:
151
- - - '>='
171
+ - - ! '>='
152
172
  - !ruby/object:Gem::Version
153
173
  version: '0'
154
174
  type: :development
155
175
  prerelease: false
156
176
  version_requirements: !ruby/object:Gem::Requirement
177
+ none: false
157
178
  requirements:
158
- - - '>='
179
+ - - ! '>='
159
180
  - !ruby/object:Gem::Version
160
181
  version: '0'
161
182
  - !ruby/object:Gem::Dependency
162
183
  name: yard
163
184
  requirement: !ruby/object:Gem::Requirement
185
+ none: false
164
186
  requirements:
165
- - - '>='
187
+ - - ! '>='
166
188
  - !ruby/object:Gem::Version
167
189
  version: '0'
168
190
  type: :development
169
191
  prerelease: false
170
192
  version_requirements: !ruby/object:Gem::Requirement
193
+ none: false
171
194
  requirements:
172
- - - '>='
195
+ - - ! '>='
173
196
  - !ruby/object:Gem::Version
174
197
  version: '0'
175
198
  - !ruby/object:Gem::Dependency
176
199
  name: RedCloth
177
200
  requirement: !ruby/object:Gem::Requirement
201
+ none: false
178
202
  requirements:
179
- - - '>='
203
+ - - ! '>='
180
204
  - !ruby/object:Gem::Version
181
205
  version: '0'
182
206
  type: :development
183
207
  prerelease: false
184
208
  version_requirements: !ruby/object:Gem::Requirement
209
+ none: false
185
210
  requirements:
186
- - - '>='
211
+ - - ! '>='
187
212
  - !ruby/object:Gem::Version
188
213
  version: '0'
189
214
  - !ruby/object:Gem::Dependency
190
215
  name: rake
191
216
  requirement: !ruby/object:Gem::Requirement
217
+ none: false
192
218
  requirements:
193
- - - '>='
219
+ - - ! '>='
194
220
  - !ruby/object:Gem::Version
195
221
  version: '0'
196
222
  type: :development
197
223
  prerelease: false
198
224
  version_requirements: !ruby/object:Gem::Requirement
225
+ none: false
199
226
  requirements:
200
- - - '>='
227
+ - - ! '>='
201
228
  - !ruby/object:Gem::Version
202
229
  version: '0'
203
230
  - !ruby/object:Gem::Dependency
204
231
  name: jettywrapper
205
232
  requirement: !ruby/object:Gem::Requirement
233
+ none: false
206
234
  requirements:
207
- - - '>='
235
+ - - ! '>='
208
236
  - !ruby/object:Gem::Version
209
237
  version: 1.4.0
210
238
  type: :development
211
239
  prerelease: false
212
240
  version_requirements: !ruby/object:Gem::Requirement
241
+ none: false
213
242
  requirements:
214
- - - '>='
243
+ - - ! '>='
215
244
  - !ruby/object:Gem::Version
216
245
  version: 1.4.0
217
246
  - !ruby/object:Gem::Dependency
218
247
  name: rspec
219
248
  requirement: !ruby/object:Gem::Requirement
249
+ none: false
220
250
  requirements:
221
- - - '>='
251
+ - - ! '>='
222
252
  - !ruby/object:Gem::Version
223
253
  version: 2.9.0
224
254
  type: :development
225
255
  prerelease: false
226
256
  version_requirements: !ruby/object:Gem::Requirement
257
+ none: false
227
258
  requirements:
228
- - - '>='
259
+ - - ! '>='
229
260
  - !ruby/object:Gem::Version
230
261
  version: 2.9.0
231
262
  - !ruby/object:Gem::Dependency
232
263
  name: equivalent-xml
233
264
  requirement: !ruby/object:Gem::Requirement
265
+ none: false
234
266
  requirements:
235
- - - '>='
267
+ - - ! '>='
236
268
  - !ruby/object:Gem::Version
237
269
  version: '0'
238
270
  type: :development
239
271
  prerelease: false
240
272
  version_requirements: !ruby/object:Gem::Requirement
273
+ none: false
241
274
  requirements:
242
- - - '>='
275
+ - - ! '>='
243
276
  - !ruby/object:Gem::Version
244
277
  version: '0'
245
278
  - !ruby/object:Gem::Dependency
246
279
  name: rest-client
247
280
  requirement: !ruby/object:Gem::Requirement
281
+ none: false
248
282
  requirements:
249
- - - '>='
283
+ - - ! '>='
250
284
  - !ruby/object:Gem::Version
251
285
  version: '0'
252
286
  type: :development
253
287
  prerelease: false
254
288
  version_requirements: !ruby/object:Gem::Requirement
289
+ none: false
255
290
  requirements:
256
- - - '>='
291
+ - - ! '>='
257
292
  - !ruby/object:Gem::Version
258
293
  version: '0'
259
294
  - !ruby/object:Gem::Dependency
260
295
  name: webmock
261
296
  requirement: !ruby/object:Gem::Requirement
297
+ none: false
262
298
  requirements:
263
- - - '>='
299
+ - - ! '>='
264
300
  - !ruby/object:Gem::Version
265
301
  version: '0'
266
302
  type: :development
267
303
  prerelease: false
268
304
  version_requirements: !ruby/object:Gem::Requirement
305
+ none: false
269
306
  requirements:
270
- - - '>='
307
+ - - ! '>='
271
308
  - !ruby/object:Gem::Version
272
309
  version: '0'
273
310
  description: ActiveFedora provides for creating and managing objects in the Fedora
@@ -420,6 +457,7 @@ files:
420
457
  - spec/integration/datastream_collections_spec.rb
421
458
  - spec/integration/datastream_spec.rb
422
459
  - spec/integration/datastreams_spec.rb
460
+ - spec/integration/delegating_spec.rb
423
461
  - spec/integration/delete_all_spec.rb
424
462
  - spec/integration/full_featured_model_spec.rb
425
463
  - spec/integration/has_many_associations_spec.rb
@@ -429,6 +467,7 @@ files:
429
467
  - spec/integration/om_datastream_spec.rb
430
468
  - spec/integration/persistence_spec.rb
431
469
  - spec/integration/rdf_nested_attributes_spec.rb
470
+ - spec/integration/relation_delegation_spec.rb
432
471
  - spec/integration/rels_ext_datastream_spec.rb
433
472
  - spec/integration/scoped_query_spec.rb
434
473
  - spec/integration/solr_instance_loader_spec.rb
@@ -513,6 +552,7 @@ files:
513
552
  - spec/unit/rdf_datastream_spec.rb
514
553
  - spec/unit/rdf_list_nested_attributes_spec.rb
515
554
  - spec/unit/rdf_list_spec.rb
555
+ - spec/unit/rdf_node_spec.rb
516
556
  - spec/unit/rdf_xml_writer_spec.rb
517
557
  - spec/unit/rdfxml_rdf_datastream_spec.rb
518
558
  - spec/unit/relationship_graph_spec.rb
@@ -534,26 +574,30 @@ files:
534
574
  homepage: https://github.com/projecthydra/active_fedora
535
575
  licenses:
536
576
  - APACHE2
537
- metadata: {}
538
577
  post_install_message:
539
578
  rdoc_options: []
540
579
  require_paths:
541
580
  - lib
542
581
  required_ruby_version: !ruby/object:Gem::Requirement
582
+ none: false
543
583
  requirements:
544
- - - '>='
584
+ - - ! '>='
545
585
  - !ruby/object:Gem::Version
546
586
  version: 1.9.3
547
587
  required_rubygems_version: !ruby/object:Gem::Requirement
588
+ none: false
548
589
  requirements:
549
- - - '>='
590
+ - - ! '>='
550
591
  - !ruby/object:Gem::Version
551
592
  version: '0'
593
+ segments:
594
+ - 0
595
+ hash: -4121996905287829806
552
596
  requirements: []
553
597
  rubyforge_project:
554
- rubygems_version: 2.0.5
598
+ rubygems_version: 1.8.24
555
599
  signing_key:
556
- specification_version: 4
600
+ specification_version: 3
557
601
  summary: A convenience libary for manipulating documents in the Fedora Repository.
558
602
  test_files:
559
603
  - spec/config_helper.rb
@@ -581,6 +625,7 @@ test_files:
581
625
  - spec/integration/datastream_collections_spec.rb
582
626
  - spec/integration/datastream_spec.rb
583
627
  - spec/integration/datastreams_spec.rb
628
+ - spec/integration/delegating_spec.rb
584
629
  - spec/integration/delete_all_spec.rb
585
630
  - spec/integration/full_featured_model_spec.rb
586
631
  - spec/integration/has_many_associations_spec.rb
@@ -590,6 +635,7 @@ test_files:
590
635
  - spec/integration/om_datastream_spec.rb
591
636
  - spec/integration/persistence_spec.rb
592
637
  - spec/integration/rdf_nested_attributes_spec.rb
638
+ - spec/integration/relation_delegation_spec.rb
593
639
  - spec/integration/rels_ext_datastream_spec.rb
594
640
  - spec/integration/scoped_query_spec.rb
595
641
  - spec/integration/solr_instance_loader_spec.rb
@@ -674,6 +720,7 @@ test_files:
674
720
  - spec/unit/rdf_datastream_spec.rb
675
721
  - spec/unit/rdf_list_nested_attributes_spec.rb
676
722
  - spec/unit/rdf_list_spec.rb
723
+ - spec/unit/rdf_node_spec.rb
677
724
  - spec/unit/rdf_xml_writer_spec.rb
678
725
  - spec/unit/rdfxml_rdf_datastream_spec.rb
679
726
  - spec/unit/relationship_graph_spec.rb
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: 5c3b9301740101d4e6c50bd6d5ce3f8e6bdf5d48
4
- data.tar.gz: 84fed4e80fc0a7d1f5d2123836867f804427f797
5
- SHA512:
6
- metadata.gz: 70b1bcb60f130c770e54866396de53f876d3529b0befce9bcfc180fe6b2540630c7b4df492057fe7dd4e2406b3cd35ecb9cd1a675af3f3ff0591be4716d752ba
7
- data.tar.gz: d66329975f4374c0a46102235195760b1ac72ef7bddba684f9bbe6af16d2b2fc65cec3f7c526bed7870b0b38cb4a38569d480fce812b35b02e146306e5ec1543