active-fedora 6.6.1 → 6.7.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|