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 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
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.travis.yml ADDED
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ - "2.0.0"
5
+
6
+ script: "rspec"
7
+
8
+ notifications:
9
+ irc: "irc.freenode.org#ndlib"
10
+
11
+ before_install:
12
+ - gem install bundler
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in active_fedora-registered_attributes.gemspec
4
+ gemspec
5
+
6
+ group :test do
7
+ gem 'simplecov', require: false
8
+ gem "guard"
9
+ gem "guard-rspec"
10
+ end
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,7 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
@@ -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,5 @@
1
+ module ActiveFedora
2
+ module RegisteredAttributes
3
+ VERSION = "0.0.1"
4
+ end
5
+ 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
@@ -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
@@ -0,0 +1,5 @@
1
+ class Book < ActiveFedora::Base
2
+ has_metadata name: "properties", type: ActiveFedora::SimpleDatastream do |m|
3
+ m.field('title')
4
+ end
5
+ 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