active_fedora-registered_attributes 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/jeremyf/active_fedora-registered_attributes.png?branch=master)](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
|