active-fedora 6.4.5 → 6.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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