active-fedora 6.6.1 → 6.7.0.rc1
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.
- checksums.yaml +4 -4
- data/lib/active_fedora/attributes.rb +158 -0
- data/lib/active_fedora/base.rb +1 -1
- data/lib/active_fedora/delegating.rb +11 -153
- data/lib/active_fedora/querying.rb +1 -1
- data/lib/active_fedora/version.rb +1 -1
- data/spec/integration/attributes_spec.rb +33 -0
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73293480bda74204d6fd5e1424101a3fb167b77e
|
4
|
+
data.tar.gz: ee53d98f31f3221263e3bfb4d97b09b5b53bfc1c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9cc9cf2c01d35ae188f39f646da5c9459d3986a68d078ba2c5cda24e0a75a937c6c22e0fb19ad87ab2fe6c0c1c58536d7721346c1d7cf4b0ec949fa05c08e13f
|
7
|
+
data.tar.gz: a7edd16e6d84e76f25e31b8bfae4c2326fd87ad717e9d5e2af5b43f775ad7f741de63999484837739ba4c08d0a823228147bda9a65ab42154ddae5411b3dafdd
|
@@ -10,6 +10,11 @@ module ActiveFedora
|
|
10
10
|
|
11
11
|
included do
|
12
12
|
include Serializers
|
13
|
+
after_save :clear_changed_attributes
|
14
|
+
def clear_changed_attributes
|
15
|
+
@previously_changed = changes
|
16
|
+
@changed_attributes.clear
|
17
|
+
end
|
13
18
|
end
|
14
19
|
|
15
20
|
def attributes=(properties)
|
@@ -17,8 +22,161 @@ module ActiveFedora
|
|
17
22
|
respond_to?(:"#{k}=") ? send(:"#{k}=", v) : raise(UnknownAttributeError, "unknown attribute: #{k}")
|
18
23
|
end
|
19
24
|
end
|
25
|
+
|
26
|
+
# Calling inspect may trigger a bunch of loads, but it's mainly for debugging, so no worries.
|
27
|
+
def inspect
|
28
|
+
values = self.class.defined_attributes.keys.map {|r| "#{r}:#{send(r).inspect}"}
|
29
|
+
"#<#{self.class} pid:\"#{pretty_pid}\", #{values.join(', ')}>"
|
30
|
+
end
|
31
|
+
|
32
|
+
def [](key)
|
33
|
+
array_reader(key)
|
34
|
+
end
|
35
|
+
|
36
|
+
def []=(key, value)
|
37
|
+
array_setter(key, value)
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
private
|
42
|
+
def array_reader(field, *args)
|
43
|
+
raise UnknownAttributeError, "#{self.class} does not have an attribute `#{field}'" unless self.class.defined_attributes.key?(field)
|
44
|
+
if args.present?
|
45
|
+
instance_exec(*args, &self.class.defined_attributes[field][:reader])
|
46
|
+
else
|
47
|
+
instance_exec &self.class.defined_attributes[field][:reader]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def array_setter(field, args)
|
52
|
+
raise UnknownAttributeError, "#{self.class} does not have an attribute `#{field}'" unless self.class.defined_attributes.key?(field)
|
53
|
+
instance_exec(args, &self.class.defined_attributes[field][:setter])
|
54
|
+
end
|
55
|
+
|
56
|
+
# @return [Boolean] true if there is an reader method and it returns a
|
57
|
+
# value different from the new_value.
|
58
|
+
def value_has_changed?(field, new_value)
|
59
|
+
begin
|
60
|
+
new_value != array_reader(field)
|
61
|
+
rescue NoMethodError
|
62
|
+
false
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def mark_as_changed(field)
|
67
|
+
self.send("#{field}_will_change!")
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
module ClassMethods
|
73
|
+
def defined_attributes
|
74
|
+
@defined_attributes ||= {}.with_indifferent_access
|
75
|
+
return @defined_attributes unless superclass.respond_to?(:defined_attributes) and value = superclass.defined_attributes
|
76
|
+
@defined_attributes = value.dup if @defined_attributes.empty?
|
77
|
+
@defined_attributes
|
78
|
+
end
|
79
|
+
|
80
|
+
def defined_attributes= val
|
81
|
+
@defined_attributes = val
|
82
|
+
end
|
83
|
+
|
84
|
+
def has_attributes(*fields)
|
85
|
+
options = fields.pop
|
86
|
+
datastream = options.delete(:datastream)
|
87
|
+
define_attribute_methods fields
|
88
|
+
fields.each do |f|
|
89
|
+
create_attribute_reader(f, datastream, options)
|
90
|
+
create_attribute_setter(f, datastream, options)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Reveal if the attribute has been declared unique
|
95
|
+
# @param [Symbol] field the field to query
|
96
|
+
# @return [Boolean]
|
97
|
+
def unique?(field)
|
98
|
+
!multiple?(field)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Reveal if the attribute is multivalued
|
102
|
+
# @param [Symbol] field the field to query
|
103
|
+
# @return [Boolean]
|
104
|
+
def multiple?(field)
|
105
|
+
defined_attributes[field][:multiple]
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
|
110
|
+
private
|
111
|
+
def create_attribute_reader(field, dsid, args)
|
112
|
+
self.defined_attributes[field] ||= {}
|
113
|
+
self.defined_attributes[field][:reader] = lambda do |*opts|
|
114
|
+
ds = self.send(dsid)
|
115
|
+
if ds.kind_of?(ActiveFedora::RDFDatastream)
|
116
|
+
ds.send(field)
|
117
|
+
else
|
118
|
+
terminology = args[:at] || [field]
|
119
|
+
if terminology.length == 1 && opts.present?
|
120
|
+
ds.send(terminology.first, *opts)
|
121
|
+
else
|
122
|
+
ds.send(:term_values, *terminology)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
if !args[:multiple].nil?
|
128
|
+
self.defined_attributes[field][:multiple] = args[:multiple]
|
129
|
+
elsif !args[:unique].nil?
|
130
|
+
i = 0
|
131
|
+
begin
|
132
|
+
match = /in `(delegate.*)'/.match(caller[i])
|
133
|
+
i+=1
|
134
|
+
end while match.nil?
|
135
|
+
|
136
|
+
prev_method = match.captures.first
|
137
|
+
Deprecation.warn Attributes, "The :unique option for `#{prev_method}' is deprecated. Use :multiple instead. :unique will be removed in ActiveFedora 7", caller(i+1)
|
138
|
+
self.defined_attributes[field][:multiple] = !args[:unique]
|
139
|
+
else
|
140
|
+
i = 0
|
141
|
+
begin
|
142
|
+
match = /in `(delegate.*)'/.match(caller[i])
|
143
|
+
i+=1
|
144
|
+
end while match.nil?
|
145
|
+
|
146
|
+
prev_method = match.captures.first
|
147
|
+
Deprecation.warn Attributes, "You have not explicitly set the :multiple option on `#{prev_method}'. The default value will switch from true to false in ActiveFedora 7, so if you want to future-proof this application set `multiple: true'", caller(i+ 1)
|
148
|
+
self.defined_attributes[field][:multiple] = true # this should be false for ActiveFedora 7
|
149
|
+
end
|
150
|
+
|
151
|
+
define_method field do |*opts|
|
152
|
+
val = array_reader(field, *opts)
|
153
|
+
self.class.multiple?(field) ? val : val.first
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
def create_attribute_setter(field, dsid, args)
|
159
|
+
self.defined_attributes[field] ||= {}
|
160
|
+
self.defined_attributes[field][:setter] = lambda do |v|
|
161
|
+
ds = self.send(dsid)
|
162
|
+
mark_as_changed(field) if value_has_changed?(field, v)
|
163
|
+
if ds.kind_of?(ActiveFedora::RDFDatastream)
|
164
|
+
ds.send("#{field}=", v)
|
165
|
+
else
|
166
|
+
terminology = args[:at] || [field]
|
167
|
+
ds.send(:update_indexed_attributes, {terminology => v})
|
168
|
+
end
|
169
|
+
end
|
170
|
+
define_method "#{field}=".to_sym do |v|
|
171
|
+
self[field]=v
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
end
|
20
176
|
|
21
177
|
|
178
|
+
public
|
179
|
+
|
22
180
|
# A convenience method for updating indexed attributes. The passed in hash
|
23
181
|
# must look like this :
|
24
182
|
# {{:name=>{"0"=>"a","1"=>"b"}}
|
data/lib/active_fedora/base.rb
CHANGED
@@ -345,7 +345,6 @@ module ActiveFedora
|
|
345
345
|
end
|
346
346
|
|
347
347
|
Base.class_eval do
|
348
|
-
include Attributes
|
349
348
|
include ActiveFedora::Persistence
|
350
349
|
extend ActiveSupport::DescendantsTracker
|
351
350
|
extend Model
|
@@ -354,6 +353,7 @@ module ActiveFedora
|
|
354
353
|
include ActiveModel::Conversion
|
355
354
|
include Validations
|
356
355
|
include Callbacks
|
356
|
+
include Attributes
|
357
357
|
include Datastreams
|
358
358
|
extend ActiveModel::Naming
|
359
359
|
include Delegating
|
@@ -2,71 +2,7 @@ module ActiveFedora
|
|
2
2
|
module Delegating
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
extend Deprecation
|
5
|
-
|
6
|
-
included do
|
7
|
-
after_save :clear_changed_attributes
|
8
|
-
def clear_changed_attributes
|
9
|
-
@previously_changed = changes
|
10
|
-
@changed_attributes.clear
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
# Calling inspect may trigger a bunch of loads, but it's mainly for debugging, so no worries.
|
15
|
-
def inspect
|
16
|
-
values = self.class.delegates.keys.map {|r| "#{r}:#{send(r).inspect}"}
|
17
|
-
"#<#{self.class} pid:\"#{pretty_pid}\", #{values.join(', ')}>"
|
18
|
-
end
|
19
|
-
|
20
|
-
def [](key)
|
21
|
-
array_reader(key)
|
22
|
-
end
|
23
|
-
|
24
|
-
def []=(key, value)
|
25
|
-
array_setter(key, value)
|
26
|
-
end
|
27
|
-
|
28
|
-
|
29
|
-
private
|
30
|
-
def array_reader(field, *args)
|
31
|
-
raise UnknownAttributeError, "#{self.class} does not have an attribute `#{field}'" unless self.class.delegates.key?(field)
|
32
|
-
if args.present?
|
33
|
-
instance_exec(*args, &self.class.delegates[field][:reader])
|
34
|
-
else
|
35
|
-
instance_exec &self.class.delegates[field][:reader]
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
def array_setter(field, args)
|
40
|
-
raise UnknownAttributeError, "#{self.class} does not have an attribute `#{field}'" unless self.class.delegates.key?(field)
|
41
|
-
instance_exec(args, &self.class.delegates[field][:setter])
|
42
|
-
end
|
43
|
-
|
44
|
-
# @return [Boolean] true if there is an reader method and it returns a
|
45
|
-
# value different from the new_value.
|
46
|
-
def value_has_changed?(field, new_value)
|
47
|
-
begin
|
48
|
-
new_value != array_reader(field)
|
49
|
-
rescue NoMethodError
|
50
|
-
false
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def mark_as_changed(field)
|
55
|
-
self.send("#{field}_will_change!")
|
56
|
-
end
|
57
|
-
|
58
|
-
|
59
5
|
module ClassMethods
|
60
|
-
def delegates
|
61
|
-
@local_delegates ||= {}.with_indifferent_access
|
62
|
-
return @local_delegates unless superclass.respond_to?(:delegates) and value = superclass.delegates
|
63
|
-
@local_delegates = value.dup if @local_delegates.empty?
|
64
|
-
@local_delegates
|
65
|
-
end
|
66
|
-
|
67
|
-
def delegates= val
|
68
|
-
@local_delegates = val
|
69
|
-
end
|
70
6
|
# Provides a delegate class method to expose methods in metadata streams
|
71
7
|
# as member of the base object. Pass the target datastream via the
|
72
8
|
# <tt>:to</tt> argument. If you want to return a multivalue result, (e.g. array
|
@@ -86,6 +22,11 @@ module ActiveFedora
|
|
86
22
|
# foo.field1 # => "My Value"
|
87
23
|
# foo.field2 # => [""]
|
88
24
|
# foo.field3 # => NoMethodError: undefined method `field3' for #<Foo:0x1af30c>
|
25
|
+
#
|
26
|
+
# The optional <tt>:default</tt> forces this method to have the behavior defined by ActiveSupport
|
27
|
+
# until this method has a chance to be removed
|
28
|
+
#
|
29
|
+
# delegate :method1, to: 'descMetadata', default: true
|
89
30
|
|
90
31
|
def delegate(*methods)
|
91
32
|
fields = methods.dup
|
@@ -93,10 +34,10 @@ module ActiveFedora
|
|
93
34
|
unless options.is_a?(Hash) && to = options[:to]
|
94
35
|
raise ArgumentError, "Target is required"
|
95
36
|
end
|
96
|
-
if ds_specs.has_key?
|
97
|
-
|
98
|
-
|
99
|
-
|
37
|
+
if ds_specs.has_key?(to.to_s) && !options[:default]
|
38
|
+
Deprecation.warn(Delegating, "delegate is deprecated and will be removed in ActiveFedora 7.0. use has_attributes instead", caller(1))
|
39
|
+
datastream = options.delete(:to)
|
40
|
+
has_attributes fields.first, options.merge!({:datastream=>datastream})
|
100
41
|
else
|
101
42
|
super(*methods)
|
102
43
|
end
|
@@ -122,91 +63,8 @@ module ActiveFedora
|
|
122
63
|
# foo.field3 # => NoMethodError: undefined method `field3' for #<Foo:0x1af30c>
|
123
64
|
|
124
65
|
def delegate_to(datastream,fields,args={})
|
125
|
-
|
126
|
-
fields.
|
127
|
-
args.merge!({:to=>datastream})
|
128
|
-
create_delegate_reader(f, args)
|
129
|
-
create_delegate_setter(f, args)
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
# Reveal if the delegated field is unique or not
|
134
|
-
# @param [Symbol] field the field to query
|
135
|
-
# @return [Boolean]
|
136
|
-
def unique?(field)
|
137
|
-
!multiple?(field)
|
138
|
-
end
|
139
|
-
|
140
|
-
# Reveal if the delegated field is multivalued or not
|
141
|
-
# @param [Symbol] field the field to query
|
142
|
-
# @return [Boolean]
|
143
|
-
def multiple?(field)
|
144
|
-
delegates[field][:multiple]
|
145
|
-
end
|
146
|
-
|
147
|
-
private
|
148
|
-
def create_delegate_reader(field, args)
|
149
|
-
self.delegates[field] ||= {}
|
150
|
-
self.delegates[field][:reader] = lambda do |*opts|
|
151
|
-
ds = self.send(args[:to])
|
152
|
-
if ds.kind_of?(ActiveFedora::RDFDatastream)
|
153
|
-
ds.send(field)
|
154
|
-
else
|
155
|
-
terminology = args[:at] || [field]
|
156
|
-
if terminology.length == 1 && opts.present?
|
157
|
-
ds.send(terminology.first, *opts)
|
158
|
-
else
|
159
|
-
ds.send(:term_values, *terminology)
|
160
|
-
end
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
if !args[:multiple].nil?
|
165
|
-
self.delegates[field][:multiple] = args[:multiple]
|
166
|
-
elsif !args[:unique].nil?
|
167
|
-
i = 0
|
168
|
-
begin
|
169
|
-
match = /in `(delegate.*)'/.match(caller[i])
|
170
|
-
i+=1
|
171
|
-
end while match.nil?
|
172
|
-
|
173
|
-
prev_method = match.captures.first
|
174
|
-
Deprecation.warn Delegating, "The :unique option for `#{prev_method}' is deprecated. Use :multiple instead. :unique will be removed in ActiveFedora 7", caller(i+1)
|
175
|
-
self.delegates[field][:multiple] = !args[:unique]
|
176
|
-
else
|
177
|
-
i = 0
|
178
|
-
begin
|
179
|
-
match = /in `(delegate.*)'/.match(caller[i])
|
180
|
-
i+=1
|
181
|
-
end while match.nil?
|
182
|
-
|
183
|
-
prev_method = match.captures.first
|
184
|
-
Deprecation.warn Delegating, "You have not explicitly set the :multiple option on `#{prev_method}'. The default value will switch from true to false in ActiveFedora 7, so if you want to future-proof this application set `multiple: true'", caller(i+ 1)
|
185
|
-
self.delegates[field][:multiple] = true # this should be false for ActiveFedora 7
|
186
|
-
end
|
187
|
-
|
188
|
-
define_method field do |*opts|
|
189
|
-
val = array_reader(field, *opts)
|
190
|
-
self.class.multiple?(field) ? val : val.first
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
|
195
|
-
def create_delegate_setter(field, args)
|
196
|
-
self.delegates[field] ||= {}
|
197
|
-
self.delegates[field][:setter] = lambda do |v|
|
198
|
-
ds = self.send(args[:to])
|
199
|
-
mark_as_changed(field) if value_has_changed?(field, v)
|
200
|
-
if ds.kind_of?(ActiveFedora::RDFDatastream)
|
201
|
-
ds.send("#{field}=", v)
|
202
|
-
else
|
203
|
-
terminology = args[:at] || [field]
|
204
|
-
ds.send(:update_indexed_attributes, {terminology => v})
|
205
|
-
end
|
206
|
-
end
|
207
|
-
define_method "#{field}=".to_sym do |v|
|
208
|
-
self[field]=v
|
209
|
-
end
|
66
|
+
Deprecation.warn(Delegating, "delegate_to is deprecated and will be removed in ActiveFedora 7.0. use has_attributes instead", caller(1))
|
67
|
+
has_attributes *fields, args.merge!({:datastream=>datastream})
|
210
68
|
end
|
211
69
|
|
212
70
|
end
|
@@ -145,7 +145,7 @@ module ActiveFedora
|
|
145
145
|
def condition_to_clauses(key, value)
|
146
146
|
unless value.nil?
|
147
147
|
# if the key is a property name, turn it into a solr field
|
148
|
-
if self.
|
148
|
+
if self.defined_attributes.key?(key)
|
149
149
|
# TODO Check to see if `key' is a possible solr field for this class, if it isn't try :searchable instead
|
150
150
|
key = ActiveFedora::SolrService.solr_name(key, :stored_searchable, type: :string)
|
151
151
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "delegating attributes" do
|
4
|
+
before :all do
|
5
|
+
class TitledObject < ActiveFedora::Base
|
6
|
+
has_metadata 'foo', type: ActiveFedora::SimpleDatastream do |m|
|
7
|
+
m.field "title", :string
|
8
|
+
end
|
9
|
+
has_attributes :title, datastream: 'foo', multiple: false
|
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
|
33
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active-fedora
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.7.0.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Zumwalt
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-10-
|
13
|
+
date: 2013-10-25 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rsolr
|
@@ -413,6 +413,7 @@ files:
|
|
413
413
|
- spec/fixtures/sharded_fedora.yml
|
414
414
|
- spec/fixtures/solr_rdf_descMetadata.nt
|
415
415
|
- spec/integration/associations_spec.rb
|
416
|
+
- spec/integration/attributes_spec.rb
|
416
417
|
- spec/integration/auditable_spec.rb
|
417
418
|
- spec/integration/base_spec.rb
|
418
419
|
- spec/integration/bug_spec.rb
|
@@ -550,9 +551,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
550
551
|
version: 1.9.3
|
551
552
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
552
553
|
requirements:
|
553
|
-
- - '
|
554
|
+
- - '>'
|
554
555
|
- !ruby/object:Gem::Version
|
555
|
-
version:
|
556
|
+
version: 1.3.1
|
556
557
|
requirements: []
|
557
558
|
rubyforge_project:
|
558
559
|
rubygems_version: 2.0.3
|
@@ -578,6 +579,7 @@ test_files:
|
|
578
579
|
- spec/fixtures/sharded_fedora.yml
|
579
580
|
- spec/fixtures/solr_rdf_descMetadata.nt
|
580
581
|
- spec/integration/associations_spec.rb
|
582
|
+
- spec/integration/attributes_spec.rb
|
581
583
|
- spec/integration/auditable_spec.rb
|
582
584
|
- spec/integration/base_spec.rb
|
583
585
|
- spec/integration/bug_spec.rb
|