active_fedora-registered_attributes 0.0.1
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 +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +12 -0
- data/Gemfile +10 -0
- data/Guardfile +9 -0
- data/LICENSE.txt +17 -0
- data/README.md +63 -0
- data/Rakefile +7 -0
- data/active_fedora-registered_attributes.gemspec +27 -0
- data/lib/active_fedora/registered_attributes.rb +69 -0
- data/lib/active_fedora/registered_attributes/attribute.rb +124 -0
- data/lib/active_fedora/registered_attributes/attribute_registry.rb +57 -0
- data/lib/active_fedora/registered_attributes/version.rb +5 -0
- data/spec/active_fedora/registered_attributes/attribute_registry_spec.rb +81 -0
- data/spec/active_fedora/registered_attributes/attribute_spec.rb +160 -0
- data/spec/active_fedora/registered_attributes_spec.rb +158 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/book.rb +5 -0
- metadata +137 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8dac8cbef5f9c4b50b43a392200ac5ad508c946a
|
4
|
+
data.tar.gz: 24c9889b73ad5b4cd584323c7a654d72877ab4ca
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5c056a733cd092784c5b730fe233c1988c3cb65e2cc116a7ab36e1cfff5c595fd2337492e78cf6b07c5eeba5ecb064fc6a1d602508283abbb9f75ae4857b18fd
|
7
|
+
data.tar.gz: 2bf802fc4d7178567339b552a84a51e12f8befe12cfdff0163371b5012d55c729ee19360f700fb3e0daa2184af66f0b278185e5698f92d5254da56617709c805
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# A sample Guardfile
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
guard 'rspec' do
|
5
|
+
watch(%r{^spec/.+_spec\.rb$})
|
6
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
|
7
|
+
watch('spec/spec_helper.rb') { "spec" }
|
8
|
+
watch('spec/support/*') { "spec" }
|
9
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
##########################################################################
|
2
|
+
# active_fedora-registered_attributes
|
3
|
+
#
|
4
|
+
# Copyright © 2013 University of Notre Dame
|
5
|
+
# Additional copyright may be held by others, as reflected in the commit history.
|
6
|
+
#
|
7
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
8
|
+
# you may not use this file except in compliance with the License.
|
9
|
+
# You may obtain a copy of the License at
|
10
|
+
#
|
11
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
12
|
+
#
|
13
|
+
# Unless required by applicable law or agreed to in writing, software
|
14
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
15
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16
|
+
# See the License for the specific language governing permissions and
|
17
|
+
# limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# ActiveFedora::RegisteredAttributes
|
2
|
+
|
3
|
+
[](https://travis-ci.org/jeremyf/active_fedora-registered_attributes)
|
4
|
+
|
5
|
+
An ActiveFedora extension for consolidating the attribute definitions for an object.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'active_fedora-registered_attributes'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install active_fedora-registered_attributes
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
class Foo < ActiveRecord::Base
|
24
|
+
include ActiveFedora::RegisteredAttributes
|
25
|
+
|
26
|
+
has_metadata name: "descMetadata", type: FooMetadataDatastream
|
27
|
+
|
28
|
+
attribute :title,
|
29
|
+
datastream: :descMetadata, multiple: false,
|
30
|
+
label: "Title of your Senior Thesis",
|
31
|
+
validates: { presence: { message: 'Your must have a title.' } }
|
32
|
+
|
33
|
+
attribute :creator,
|
34
|
+
datastream: :descMetadata, multiple: true,
|
35
|
+
label: "Author",
|
36
|
+
hint: "Enter your preferred name",
|
37
|
+
writer: :parse_person_names,
|
38
|
+
reader: :parse_person_names,
|
39
|
+
validates: { presence: { message: "You must have an author."} }
|
40
|
+
end
|
41
|
+
|
42
|
+
## Internationalization
|
43
|
+
|
44
|
+
If you utilize internationalization, such as below, then regardless of what
|
45
|
+
your model indicates as the label, it will use the internationalization.
|
46
|
+
|
47
|
+
en:
|
48
|
+
activemodel:
|
49
|
+
attributes:
|
50
|
+
foo:
|
51
|
+
internationalized_field: Welcome
|
52
|
+
|
53
|
+
## TODO
|
54
|
+
|
55
|
+
* Add internationalization support for hints and validation messages.
|
56
|
+
|
57
|
+
## Contributing
|
58
|
+
|
59
|
+
1. Fork it
|
60
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
61
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
62
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
63
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'active_fedora/registered_attributes/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "active_fedora-registered_attributes"
|
8
|
+
spec.version = ActiveFedora::RegisteredAttributes::VERSION
|
9
|
+
spec.authors = ["Jeremy Friesen"]
|
10
|
+
spec.email = ["jeremy.n.friesen@gmail.com"]
|
11
|
+
spec.description = %q{An ActiveFedora extension for registring attributes}
|
12
|
+
spec.summary = %q{An ActiveFedora extension for registring attributes}
|
13
|
+
spec.homepage = "http://github.com/jeremyf/active_fedora-registered_attributes"
|
14
|
+
spec.license = "APACHE2"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "active-fedora", ">= 6.4"
|
22
|
+
spec.add_dependency "active_attr", "~> 0.8.2"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
spec.add_development_dependency "rspec"
|
27
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require "active_fedora/registered_attributes/version"
|
2
|
+
require 'active_attr'
|
3
|
+
require "active_fedora/registered_attributes/attribute"
|
4
|
+
require "active_fedora/registered_attributes/attribute_registry"
|
5
|
+
|
6
|
+
module ActiveFedora
|
7
|
+
module RegisteredAttributes
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
included do
|
10
|
+
class_attribute :attribute_registry, instance_writer: false, instance_reader: false
|
11
|
+
end
|
12
|
+
|
13
|
+
delegate :attribute_defaults, to: :attribute_registry
|
14
|
+
delegate :input_options_for, to: :attribute_registry
|
15
|
+
delegate :label_for, to: :attribute_registry
|
16
|
+
delegate :editable_attributes, to: :attribute_registry
|
17
|
+
delegate :displayable_attributes, to: :attribute_registry
|
18
|
+
|
19
|
+
def attribute_registry
|
20
|
+
self.class.attribute_registry
|
21
|
+
end
|
22
|
+
private :attribute_registry
|
23
|
+
|
24
|
+
module ClassMethods
|
25
|
+
def attribute(attribute_name, options ={})
|
26
|
+
self.attribute_registry ||= AttributeRegistry.new(self)
|
27
|
+
self.attribute_registry.register(attribute_name, options) do |attribute|
|
28
|
+
|
29
|
+
attribute.with_validation_options do |name, opts|
|
30
|
+
validates(name, opts)
|
31
|
+
end
|
32
|
+
|
33
|
+
attribute.with_accession_options do |name, opts|
|
34
|
+
attr_accessor name
|
35
|
+
end
|
36
|
+
|
37
|
+
attribute.with_delegation_options do |name, opts|
|
38
|
+
delegate(name, opts)
|
39
|
+
end
|
40
|
+
|
41
|
+
attribute.wrap_writer_method(self)
|
42
|
+
attribute.wrap_reader_method(self)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
# Applies the attribute defaults
|
49
|
+
#
|
50
|
+
# Applies all the default values to any attributes not yet set, avoiding
|
51
|
+
# any attribute setter logic, such as dirty tracking.
|
52
|
+
#
|
53
|
+
# @param [Hash{String => Object}, #each] defaults The defaults to apply
|
54
|
+
def apply_defaults(defaults=attribute_defaults)
|
55
|
+
defaults.each do |name, value|
|
56
|
+
unless value.nil?
|
57
|
+
send("#{name}=", value) unless send("#{name}").present?
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Applies attribute default values
|
63
|
+
def initialize(*)
|
64
|
+
super
|
65
|
+
apply_defaults
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module ActiveFedora
|
2
|
+
module RegisteredAttributes
|
3
|
+
class Attribute
|
4
|
+
|
5
|
+
attr_reader :context_class, :name, :datastream
|
6
|
+
private :context_class
|
7
|
+
|
8
|
+
def initialize(context_class, name, options = {})
|
9
|
+
@context_class = context_class
|
10
|
+
@options = options.symbolize_keys
|
11
|
+
@options.assert_valid_keys(:default, :displayable, :editable, :form, :datastream, :validates, :at, :as, :multiple, :writer, :reader, :label, :hint)
|
12
|
+
@datastream = @options.fetch(:datastream, false)
|
13
|
+
@name = name
|
14
|
+
@options[:multiple] = false unless @options.key?(:multiple)
|
15
|
+
@options[:form] ||= {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def displayable?
|
19
|
+
@options.fetch(:displayable, true)
|
20
|
+
end
|
21
|
+
|
22
|
+
def editable?
|
23
|
+
@options.fetch(:editable, true)
|
24
|
+
end
|
25
|
+
|
26
|
+
def label
|
27
|
+
default = options[:label] || name.to_s.humanize
|
28
|
+
context_class.human_attribute_name(name, default: default)
|
29
|
+
end
|
30
|
+
|
31
|
+
def with_delegation_options
|
32
|
+
yield(name, options_for_delegation) if datastream
|
33
|
+
end
|
34
|
+
|
35
|
+
def with_validation_options
|
36
|
+
yield(name, options[:validates]) if options[:validates]
|
37
|
+
end
|
38
|
+
|
39
|
+
def with_accession_options
|
40
|
+
yield(name, {}) if !datastream
|
41
|
+
end
|
42
|
+
|
43
|
+
def options_for_input(overrides = {})
|
44
|
+
options[:form].tap {|hash|
|
45
|
+
hash[:hint] ||= options[:hint] if options[:hint]
|
46
|
+
hash[:label] ||= options[:label] if options[:label]
|
47
|
+
hash[:as] ||= options[:as] if options[:as]
|
48
|
+
if options[:multiple]
|
49
|
+
hash[:as] = 'multi_value'
|
50
|
+
hash[:input_html] ||= {}
|
51
|
+
hash[:input_html][:multiple] = 'multiple'
|
52
|
+
end
|
53
|
+
}.deep_merge(overrides)
|
54
|
+
end
|
55
|
+
|
56
|
+
def default(context)
|
57
|
+
this_default = options[:default]
|
58
|
+
case
|
59
|
+
when this_default.respond_to?(:call) then context.instance_exec(&this_default)
|
60
|
+
when this_default.duplicable? then this_default.dup
|
61
|
+
else this_default
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def wrap_writer_method(context)
|
66
|
+
with_writer_method_wrap do |method_name, block|
|
67
|
+
context.instance_exec do
|
68
|
+
original_method = instance_method(method_name)
|
69
|
+
define_method(method_name) do |*args|
|
70
|
+
original_method.bind(self).call(instance_exec(*args, &block))
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def wrap_reader_method(context)
|
77
|
+
with_reader_method_wrapper do |method_name, block|
|
78
|
+
context.instance_exec do
|
79
|
+
original_method = instance_method(method_name)
|
80
|
+
define_method(method_name) do |*args|
|
81
|
+
instance_exec(original_method.bind(self).call(*args), &block)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def options_for_delegation
|
90
|
+
{
|
91
|
+
to: datastream,
|
92
|
+
unique: !options[:multiple]
|
93
|
+
}.tap {|hash|
|
94
|
+
hash[:at] = options[:at] if options.key?(:at)
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
def with_writer_method_wrap
|
99
|
+
if writer = options[:writer]
|
100
|
+
method_name = "#{name}=".to_sym
|
101
|
+
proc = writer.respond_to?(:call) ?
|
102
|
+
writer :
|
103
|
+
lambda { |value| send(writer, value) }
|
104
|
+
yield(method_name, proc)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def with_reader_method_wrapper
|
109
|
+
if reader = options[:reader]
|
110
|
+
method_name = "#{name}".to_sym
|
111
|
+
proc = reader.respond_to?(:call) ?
|
112
|
+
reader :
|
113
|
+
lambda { |value| send(reader, value) }
|
114
|
+
yield(method_name, proc)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def options
|
119
|
+
@options
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
require 'active_support/hash_with_indifferent_access'
|
3
|
+
require 'active_fedora/registered_attributes/attribute'
|
4
|
+
|
5
|
+
|
6
|
+
module ActiveFedora
|
7
|
+
module RegisteredAttributes
|
8
|
+
class AttributeRegistry < DelegateClass(HashWithIndifferentAccess)
|
9
|
+
attr_accessor :context_class
|
10
|
+
def initialize(context_class)
|
11
|
+
@context_class = context_class
|
12
|
+
super(HashWithIndifferentAccess.new)
|
13
|
+
end
|
14
|
+
|
15
|
+
def register(attribute_name, options)
|
16
|
+
attribute = Attribute.new(context_class, attribute_name, options)
|
17
|
+
self[attribute.name] = attribute
|
18
|
+
yield(attribute) if block_given?
|
19
|
+
attribute
|
20
|
+
end
|
21
|
+
|
22
|
+
def editable_attributes
|
23
|
+
@editable_attributes ||= each_with_object([]) {|(name, attribute), m|
|
24
|
+
m << attribute if attribute.editable?
|
25
|
+
m
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
def displayable_attributes
|
30
|
+
@displayable_attributes ||= each_with_object([]) {|(name, attribute),m|
|
31
|
+
m << attribute if attribute.displayable?
|
32
|
+
m
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
# Calculates the attribute defaults from the attribute definitions
|
37
|
+
#
|
38
|
+
# @return [Hash{String => Object}] the attribute defaults
|
39
|
+
def attribute_defaults
|
40
|
+
collect { |name, attribute| [name, attribute.default(context_class)] }
|
41
|
+
end
|
42
|
+
|
43
|
+
def input_options_for(attribute_name, override_options = {})
|
44
|
+
fetch(attribute_name).options_for_input(override_options)
|
45
|
+
rescue KeyError
|
46
|
+
override_options
|
47
|
+
end
|
48
|
+
|
49
|
+
def label_for(name)
|
50
|
+
fetch(name).label
|
51
|
+
rescue KeyError
|
52
|
+
name.to_s.titleize
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require "active_fedora/registered_attributes/attribute_registry"
|
3
|
+
|
4
|
+
describe ActiveFedora::RegisteredAttributes::AttributeRegistry do
|
5
|
+
let(:context) { Book }
|
6
|
+
let(:name) { "My Name" }
|
7
|
+
let(:options) { {} }
|
8
|
+
subject { ActiveFedora::RegisteredAttributes::AttributeRegistry.new(context) }
|
9
|
+
|
10
|
+
describe '#register' do
|
11
|
+
it 'yields an attribute' do
|
12
|
+
@name = nil
|
13
|
+
subject.register(name, options) do |attribute|
|
14
|
+
@name = attribute.name
|
15
|
+
end
|
16
|
+
expect(@name).to eq(name)
|
17
|
+
end
|
18
|
+
it 'stores the attribute' do
|
19
|
+
subject.register(name, options)
|
20
|
+
expect(subject.fetch(name)).to be_kind_of(ActiveFedora::RegisteredAttributes::Attribute)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
describe 'editable and displayable attributes' do
|
24
|
+
let(:editable_options) { { editable: true, displayable: false } }
|
25
|
+
let(:displayable_options) { { editable: false, displayable: true } }
|
26
|
+
let(:default_options) { {} }
|
27
|
+
|
28
|
+
before(:each) do
|
29
|
+
@editable_attribute = subject.register('editable', editable_options)
|
30
|
+
@displayable_attribute = subject.register('displayable', displayable_options)
|
31
|
+
@default_attribute = subject.register('default', default_options)
|
32
|
+
end
|
33
|
+
it 'has #editable_attributes derived from registered inputs' do
|
34
|
+
expect(subject.editable_attributes).to eq([@editable_attribute, @default_attribute])
|
35
|
+
end
|
36
|
+
it 'has #displayable_attributes derived from registered inputs' do
|
37
|
+
expect(subject.displayable_attributes).to eq([@displayable_attribute, @default_attribute])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
describe '#attribute_defaults' do
|
41
|
+
let(:context) { double }
|
42
|
+
let(:default_options) { { default: '1234' } }
|
43
|
+
let(:default_field_name) { 'something' }
|
44
|
+
it "assigns default on registry's context context" do
|
45
|
+
subject.register(default_field_name, default_options)
|
46
|
+
expect(subject.attribute_defaults).to eq([[default_field_name, default_options.fetch(:default)]])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
describe '#input_options_for' do
|
50
|
+
let(:editable_options) { { editable: true, displayable: false, multiple: true } }
|
51
|
+
|
52
|
+
before(:each) do
|
53
|
+
@editable_attribute = subject.register('editable', editable_options)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "returns input options for existing attribute" do
|
57
|
+
expect(subject.input_options_for('editable')).to eq({as: "multi_value",input_html: {multiple:"multiple"}})
|
58
|
+
end
|
59
|
+
|
60
|
+
it "returns default options for existing attribute" do
|
61
|
+
options = {hello: :world}
|
62
|
+
expect(subject.input_options_for('hello', options)).to eq(options)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
describe '#label_for' do
|
66
|
+
let(:label_options) { { label: "Hello World" } }
|
67
|
+
let(:field_name) { 'thing' }
|
68
|
+
|
69
|
+
before(:each) do
|
70
|
+
subject.register(field_name, label_options)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "handles label for existing field" do
|
74
|
+
expect(subject.label_for(field_name)).to eq(label_options.fetch(:label))
|
75
|
+
end
|
76
|
+
|
77
|
+
it "handles missing field's label" do
|
78
|
+
expect(subject.label_for("hydra_field")).to eq("Hydra Field")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require "active_fedora/registered_attributes/attribute"
|
3
|
+
|
4
|
+
describe ActiveFedora::RegisteredAttributes::Attribute do
|
5
|
+
let(:context) { Book }
|
6
|
+
let(:field_name) { :title }
|
7
|
+
let(:datastream) { 'properties' }
|
8
|
+
let(:validation_options) {{ presence: true }}
|
9
|
+
let(:options) {
|
10
|
+
{
|
11
|
+
datastream: datastream, hint: 'Your title',
|
12
|
+
form: { input_html: {style: 'title-picker'}},
|
13
|
+
multiple: true,
|
14
|
+
displayable: displayable,
|
15
|
+
editable: editable,
|
16
|
+
default: default_value,
|
17
|
+
validates: validation_options
|
18
|
+
}
|
19
|
+
}
|
20
|
+
let(:displayable) { true }
|
21
|
+
let(:editable) { true }
|
22
|
+
let(:default_value) { nil }
|
23
|
+
subject { ActiveFedora::RegisteredAttributes::Attribute.new(context, field_name, options) }
|
24
|
+
|
25
|
+
describe '#displayable?' do
|
26
|
+
its (:displayable?) { should == displayable }
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#editable?' do
|
30
|
+
its (:editable?) { should == editable }
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#label' do
|
34
|
+
describe 'with explicit model level label' do
|
35
|
+
it 'uses the explicit label' do
|
36
|
+
expect(subject.label).to eq(field_name.to_s.titleize)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'with inferred field' do
|
41
|
+
let(:field_name) { 'internationalized_field' }
|
42
|
+
it 'uses the explicit label' do
|
43
|
+
expect(subject.label).to eq('Internationalized field')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#with_delegation_options' do
|
49
|
+
describe 'with a datastream' do
|
50
|
+
it 'yields name and options' do
|
51
|
+
@yielded = false
|
52
|
+
subject.with_delegation_options {|name,opts|
|
53
|
+
@yielded = true
|
54
|
+
expect(name).to eq(field_name)
|
55
|
+
expect(opts).to eq(subject.send(:options_for_delegation))
|
56
|
+
}
|
57
|
+
expect(@yielded).to eq(true)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
describe 'without datastream' do
|
61
|
+
let(:datastream) { nil }
|
62
|
+
it 'does not yield name and options for #delegation' do
|
63
|
+
@yielded = false
|
64
|
+
subject.with_delegation_options {|name,opts|
|
65
|
+
@yielded = true
|
66
|
+
}
|
67
|
+
expect(@yielded).to eq(false)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#with_validation_options' do
|
73
|
+
describe 'with validation options' do
|
74
|
+
it 'yields name and options for #validations' do
|
75
|
+
@yielded = false
|
76
|
+
subject.with_validation_options do |name, opts|
|
77
|
+
expect(name).to eq(field_name)
|
78
|
+
expect(opts).to eq(validation_options)
|
79
|
+
@yielded = true
|
80
|
+
end
|
81
|
+
expect(@yielded).to eq(true)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
describe 'without validation options' do
|
85
|
+
let(:validation_options) { nil }
|
86
|
+
it 'does not yield validation options' do
|
87
|
+
@yielded = false
|
88
|
+
subject.with_validation_options do |name, opts|
|
89
|
+
@yielded = true
|
90
|
+
end
|
91
|
+
expect(@yielded).to eq(false)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '#with_accession_options' do
|
97
|
+
describe 'with a datastream' do
|
98
|
+
it 'does not yield name nor options' do
|
99
|
+
@yielded = false
|
100
|
+
subject.with_accession_options {|name,opts|
|
101
|
+
@yielded = true
|
102
|
+
}
|
103
|
+
expect(@yielded).to eq(false)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
describe 'without datastream' do
|
108
|
+
let(:datastream) { nil }
|
109
|
+
it 'yields name and options for #accession' do
|
110
|
+
@yielded = false
|
111
|
+
subject.with_accession_options {|name,opts|
|
112
|
+
@yielded = true
|
113
|
+
expect(name).to eq(field_name)
|
114
|
+
expect(opts).to eq({})
|
115
|
+
}
|
116
|
+
expect(@yielded).to eq(true)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe '#options_for_input' do
|
122
|
+
it 'is roughly what simple_form expects' do
|
123
|
+
expect(subject.options_for_input(input_html: {size: 10})).to eq(
|
124
|
+
{
|
125
|
+
hint: 'Your title', as: 'multi_value', input_html:
|
126
|
+
{
|
127
|
+
style: 'title-picker', multiple: 'multiple', size: 10
|
128
|
+
}
|
129
|
+
}
|
130
|
+
)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe '#default' do
|
135
|
+
let(:instance) { Book.new }
|
136
|
+
describe 'with string as default value' do
|
137
|
+
let(:default_value) { '1234' }
|
138
|
+
it 'defaults to the string' do
|
139
|
+
expect(subject.default(instance)).to eq(default_value)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe 'with a lambda as the option' do
|
144
|
+
let(:default_value) { lambda { object_id } }
|
145
|
+
it "evaluates the lambda in the context of the default method's input" do
|
146
|
+
expect(subject.default(instance)).to eq(instance.object_id)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe '#wrap_writer_method(context)' do
|
152
|
+
xit 'with a symbol referencing an instance method'
|
153
|
+
xit 'with a lambda'
|
154
|
+
end
|
155
|
+
|
156
|
+
describe '#wrap_reader_method(context)' do
|
157
|
+
xit 'with a symbol referencing an instance method'
|
158
|
+
xit 'with a lambda'
|
159
|
+
end
|
160
|
+
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'active_fedora/registered_attributes'
|
3
|
+
|
4
|
+
describe 'ActiveFedora::RegisteredAttributes' do
|
5
|
+
class MockDelegateAttribute < ActiveFedora::Base
|
6
|
+
include ActiveFedora::RegisteredAttributes
|
7
|
+
|
8
|
+
has_metadata :name => "properties", :type => ActiveFedora::SimpleDatastream do |m|
|
9
|
+
m.field "title", :string
|
10
|
+
m.field "description", :string
|
11
|
+
m.field "creator", :string
|
12
|
+
m.field "file_names", :string
|
13
|
+
m.field "locations", :string
|
14
|
+
m.field "created_on", :date
|
15
|
+
m.field "modified_on", :date
|
16
|
+
end
|
17
|
+
|
18
|
+
attribute :title, {
|
19
|
+
datastream: 'properties',
|
20
|
+
label: 'Title of your Work',
|
21
|
+
hint: "How would you name this?",
|
22
|
+
validates: { presence: true }
|
23
|
+
}
|
24
|
+
|
25
|
+
attribute :description, {
|
26
|
+
datastream: 'properties',
|
27
|
+
default: ['One two'],
|
28
|
+
multiple: true
|
29
|
+
}
|
30
|
+
|
31
|
+
attribute :creator, {
|
32
|
+
datastream: 'properties',
|
33
|
+
multiple: false,
|
34
|
+
writer: lambda{|value| value.reverse }
|
35
|
+
}
|
36
|
+
|
37
|
+
attribute :file_names, {
|
38
|
+
datastream: 'properties',
|
39
|
+
multiple: true,
|
40
|
+
writer: lambda{|value| value.reverse }
|
41
|
+
}
|
42
|
+
|
43
|
+
def set_locations(value)
|
44
|
+
value.dup << '127.0.0.1'
|
45
|
+
end
|
46
|
+
protected :set_locations
|
47
|
+
|
48
|
+
attribute :locations, {
|
49
|
+
datastream: 'properties',
|
50
|
+
displayable: false,
|
51
|
+
multiple: true,
|
52
|
+
writer: :set_locations
|
53
|
+
}
|
54
|
+
|
55
|
+
attribute :created_on, {
|
56
|
+
datastream: 'properties',
|
57
|
+
multiple: false,
|
58
|
+
reader: lambda {|value|
|
59
|
+
"DATE: #{value}"
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
attribute :not_in_the_datastream, {
|
64
|
+
multiple: false,
|
65
|
+
editable: false,
|
66
|
+
displayable: false
|
67
|
+
}
|
68
|
+
|
69
|
+
attribute :modified_on, {
|
70
|
+
datastream: 'properties',
|
71
|
+
multiple: true,
|
72
|
+
editable: false,
|
73
|
+
reader: lambda {|value|
|
74
|
+
"DATE: #{value}"
|
75
|
+
}
|
76
|
+
}
|
77
|
+
end
|
78
|
+
subject { MockDelegateAttribute.new() }
|
79
|
+
|
80
|
+
describe '#editable_attributes' do
|
81
|
+
let(:expected_attribute_names) {
|
82
|
+
[ :title, :description, :creator, :file_names, :locations, :created_on ]
|
83
|
+
}
|
84
|
+
it 'is all of the attributes that are editable' do
|
85
|
+
actual_editable_attributes = subject.editable_attributes.collect {|a| a.name }
|
86
|
+
expect(actual_editable_attributes).to eq(expected_attribute_names)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe '#displayable_attributes' do
|
91
|
+
let(:expected_attribute_names) {
|
92
|
+
[ :title, :description, :creator, :file_names, :created_on, :modified_on ]
|
93
|
+
}
|
94
|
+
it 'is all of the attributes that are displayable' do
|
95
|
+
actual_displayable_attributes = subject.displayable_attributes.collect {|a| a.name }
|
96
|
+
expect(actual_displayable_attributes).to eq(expected_attribute_names)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '.attribute' do
|
101
|
+
it 'handles attributes not delegated to a datastream' do
|
102
|
+
subject.not_in_the_datastream = 'World?'
|
103
|
+
expect(subject.not_in_the_datastream).to eq('World?')
|
104
|
+
end
|
105
|
+
it "has creates a setter/getter" do
|
106
|
+
subject.title = 'Hello'
|
107
|
+
expect(subject.properties.title).to eq([subject.title])
|
108
|
+
end
|
109
|
+
|
110
|
+
it "enforces validation when passed" do
|
111
|
+
subject.title = nil
|
112
|
+
subject.valid?
|
113
|
+
expect(subject.errors[:title].size).to eq(1)
|
114
|
+
end
|
115
|
+
|
116
|
+
it "allows for default" do
|
117
|
+
expect(subject.description).to eq(['One two'])
|
118
|
+
end
|
119
|
+
|
120
|
+
it "allows for a reader to intercept the returning of values" do
|
121
|
+
date = Date.today
|
122
|
+
subject.created_on = date
|
123
|
+
expect(subject.properties.created_on).to eq([date])
|
124
|
+
expect(subject.created_on).to eq("DATE: #{date}")
|
125
|
+
end
|
126
|
+
|
127
|
+
it "allows for a reader to intercept the returning of values" do
|
128
|
+
date = Date.today
|
129
|
+
subject.created_on = date
|
130
|
+
expect(subject.properties.created_on).to eq([date])
|
131
|
+
expect(subject.created_on).to eq("DATE: #{date}")
|
132
|
+
end
|
133
|
+
|
134
|
+
it "allows for a writer to intercept the setting of values" do
|
135
|
+
text = 'hello world'
|
136
|
+
subject.creator = 'hello world'
|
137
|
+
expect(subject.properties.creator).to eq([text.reverse])
|
138
|
+
expect(subject.creator).to eq(text.reverse)
|
139
|
+
end
|
140
|
+
|
141
|
+
it "allows for a writer to intercept the setting of values" do
|
142
|
+
values = ['foo.rb', 'bar.rb']
|
143
|
+
subject.file_names = values
|
144
|
+
expect(subject.properties.file_names).to eq(values.reverse)
|
145
|
+
expect(subject.file_names).to eq(values.reverse)
|
146
|
+
end
|
147
|
+
|
148
|
+
it "allows for a writer that is a symbol" do
|
149
|
+
values = ['South Bend', 'State College', 'Minneapolis']
|
150
|
+
expected_values = values.dup
|
151
|
+
expected_values << '127.0.0.1'
|
152
|
+
subject.locations = values
|
153
|
+
expect(subject.properties.locations).to eq(expected_values)
|
154
|
+
expect(subject.locations).to eq(expected_values)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start do
|
3
|
+
add_filter "/spec"
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'active_fedora'
|
7
|
+
|
8
|
+
Dir[File.join(File.dirname(__FILE__), "support/**/*.rb")].each {|f| require f}
|
9
|
+
|
10
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
11
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
12
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
13
|
+
# loaded once.
|
14
|
+
#
|
15
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
16
|
+
RSpec.configure do |config|
|
17
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
18
|
+
config.run_all_when_everything_filtered = true
|
19
|
+
config.filter_run :focus
|
20
|
+
|
21
|
+
# Run specs in random order to surface order dependencies. If you find an
|
22
|
+
# order dependency and want to debug it, you can fix the order by providing
|
23
|
+
# the seed, which is printed after each run.
|
24
|
+
# --seed 1234
|
25
|
+
config.order = 'random'
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: active_fedora-registered_attributes
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jeremy Friesen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-07-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: active-fedora
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '6.4'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '6.4'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: active_attr
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.8.2
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.8.2
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.3'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: An ActiveFedora extension for registring attributes
|
84
|
+
email:
|
85
|
+
- jeremy.n.friesen@gmail.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- .gitignore
|
91
|
+
- .rspec
|
92
|
+
- .travis.yml
|
93
|
+
- Gemfile
|
94
|
+
- Guardfile
|
95
|
+
- LICENSE.txt
|
96
|
+
- README.md
|
97
|
+
- Rakefile
|
98
|
+
- active_fedora-registered_attributes.gemspec
|
99
|
+
- lib/active_fedora/registered_attributes.rb
|
100
|
+
- lib/active_fedora/registered_attributes/attribute.rb
|
101
|
+
- lib/active_fedora/registered_attributes/attribute_registry.rb
|
102
|
+
- lib/active_fedora/registered_attributes/version.rb
|
103
|
+
- spec/active_fedora/registered_attributes/attribute_registry_spec.rb
|
104
|
+
- spec/active_fedora/registered_attributes/attribute_spec.rb
|
105
|
+
- spec/active_fedora/registered_attributes_spec.rb
|
106
|
+
- spec/spec_helper.rb
|
107
|
+
- spec/support/book.rb
|
108
|
+
homepage: http://github.com/jeremyf/active_fedora-registered_attributes
|
109
|
+
licenses:
|
110
|
+
- APACHE2
|
111
|
+
metadata: {}
|
112
|
+
post_install_message:
|
113
|
+
rdoc_options: []
|
114
|
+
require_paths:
|
115
|
+
- lib
|
116
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
117
|
+
requirements:
|
118
|
+
- - '>='
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
121
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
requirements: []
|
127
|
+
rubyforge_project:
|
128
|
+
rubygems_version: 2.0.3
|
129
|
+
signing_key:
|
130
|
+
specification_version: 4
|
131
|
+
summary: An ActiveFedora extension for registring attributes
|
132
|
+
test_files:
|
133
|
+
- spec/active_fedora/registered_attributes/attribute_registry_spec.rb
|
134
|
+
- spec/active_fedora/registered_attributes/attribute_spec.rb
|
135
|
+
- spec/active_fedora/registered_attributes_spec.rb
|
136
|
+
- spec/spec_helper.rb
|
137
|
+
- spec/support/book.rb
|