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 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