active_fedora-noid 1.1.3 → 2.0.0.beta1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cb21b73450d652c999b6957aec06a64a6b93a424
4
- data.tar.gz: 92a908f1457731a303eaa3bede38fd139ba0a820
3
+ metadata.gz: b411ca036a7be29f78737f471e4299ae3e9dbe84
4
+ data.tar.gz: 11688eabbb0b224605aa9b236843cc30534c30f9
5
5
  SHA512:
6
- metadata.gz: 1a41ca01378cfab9bfeb598ebfbba2b685759058281897c6bc730b8d92cd7dc5e047676de949d05d802141cc46c448eaf052cef625154ed2a0695601e6cc88ea
7
- data.tar.gz: b844067ca1dd94891953605151997e594b0c57f4194148ed47a6ddcd9f1481b678e8bf672b73282e99a4ee4cec4e4f3dc559c9bf6f5faba7dae6daf57a39c7a8
6
+ metadata.gz: d683d23ff54c91077c0b2e3b334a5b38f894483326cda8e346fd0188efc8d81d231d0b41974ea786005edfba158a77b87ec2a76fc97b85162afab6d108d2f3f7
7
+ data.tar.gz: ab60c0951d64d425038a579f50a4727a7526e0a9b8c77b936e432b456d8c69aa3b3813feec49d0729aa3c1a5d52f91d13e7a2d121e6c8501523ec398ed7656fb
data/.gitignore CHANGED
@@ -1,6 +1,5 @@
1
1
  *.rbc
2
2
  capybara-*.html
3
- .rspec
4
3
  /log
5
4
  /tmp
6
5
  /db/*.sqlite3
@@ -10,6 +9,7 @@ capybara-*.html
10
9
  **.orig
11
10
  rerun.txt
12
11
  pickle-email-*.html
12
+ .byebug_history
13
13
 
14
14
  # TODO Comment out these rules if you are OK with secrets being uploaded to the repo
15
15
  config/initializers/secret_token.rb
@@ -32,3 +32,5 @@ pkg
32
32
  /vendor/assets/bower_components
33
33
  *.bowerrc
34
34
  bower.json
35
+
36
+ .internal_test_app
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.travis.yml CHANGED
@@ -3,12 +3,12 @@ cache: bundler
3
3
  sudo: false
4
4
  rvm:
5
5
  - 2.3.1
6
+ - 2.2
7
+ - 2.1
6
8
  env:
7
9
  global:
8
10
  - NOKOGIRI_USE_SYSTEM_LIBRARIES=true
9
- matrix:
10
- - "RAILS_VERSION=4.2.7.1"
11
- - "RAILS_VERSION=5.0.0.1"
11
+ - "RAILS_VERSION=4.2.6"
12
12
  notifications:
13
13
  irc:
14
14
  channels:
data/Gemfile CHANGED
@@ -6,4 +6,39 @@ gemspec
6
6
  group :development, :test do
7
7
  gem 'byebug' unless ENV['CI']
8
8
  gem 'coveralls', require: false
9
+ gem 'byebug' unless ENV['CI']
10
+ end
11
+ # BEGIN ENGINE_CART BLOCK
12
+ # engine_cart: 0.8.2
13
+ # engine_cart stanza: 0.8.0
14
+ # the below comes from engine_cart, a gem used to test this Rails engine gem in the context of a Rails app.
15
+ file = File.expand_path("Gemfile", ENV['ENGINE_CART_DESTINATION'] || ENV['RAILS_ROOT'] || File.expand_path(".internal_test_app", File.dirname(__FILE__)))
16
+ if File.exist?(file)
17
+ begin
18
+ eval_gemfile file
19
+ rescue Bundler::GemfileError => e
20
+ Bundler.ui.warn '[EngineCart] Skipping Rails application dependencies:'
21
+ Bundler.ui.warn e.message
22
+ end
23
+ else
24
+ Bundler.ui.warn "[EngineCart] Unable to find test application dependencies in #{file}, using placeholder dependencies"
25
+
26
+ if ENV['RAILS_VERSION']
27
+ if ENV['RAILS_VERSION'] == 'edge'
28
+ gem 'rails', github: 'rails/rails'
29
+ ENV['ENGINE_CART_RAILS_OPTIONS']= "--edge --skip-turbolinks"
30
+ else
31
+ gem 'rails', ENV['RAILS_VERSION']
32
+ end
33
+ end
34
+
35
+ if ENV['RAILS_VERSION'].nil? || ENV['RAILS_VERSION'] =~ /^4.2/
36
+ gem 'responders', "~> 2.0"
37
+ gem 'sass-rails', ">= 5.0"
38
+ elsif ENV['RAILS_VERSION'] =~ /^5.0/ || ENV['RAILS_VERSION'] == 'edge'
39
+ # nop
40
+ else
41
+ gem 'sass-rails', "< 5.0"
42
+ end
9
43
  end
44
+ # END ENGINE_CART BLOCK
data/Rakefile CHANGED
@@ -1,7 +1,12 @@
1
1
  require "bundler/gem_tasks"
2
2
  require 'rspec/core/rake_task'
3
+ require 'engine_cart/rake_task'
3
4
 
4
- task default: :spec
5
+ task default: :ci
5
6
  RSpec::Core::RakeTask.new
6
7
 
7
- import './lib/tasks/noid_tasks.rake'
8
+ Dir.glob('lib/tasks/*.rake').each { |r| import r }
9
+
10
+ desc 'Continuous Integration (generate test app and run tests)'
11
+ task ci: ['engine_cart:generate', 'spec'] do
12
+ end
@@ -18,16 +18,19 @@ Gem::Specification.new do |spec|
18
18
  spec.require_paths = ["lib"]
19
19
 
20
20
  spec.add_dependency 'active-fedora', '>= 9.7', '< 11'
21
- spec.add_dependency 'noid', '~> 0.7'
21
+ spec.add_dependency 'noid', '~> 0.9'
22
+ spec.add_dependency 'rails', '~> 4.2.6'
22
23
 
23
24
  spec.add_development_dependency "bundler", "~> 1.7"
24
25
  spec.add_development_dependency "rake", "~> 10.0"
25
26
  spec.add_development_dependency 'rspec', '~> 3.2'
27
+ spec.add_development_dependency 'sqlite3'
28
+ spec.add_development_dependency 'engine_cart', '~> 0.8'
26
29
 
27
30
  spec.post_install_message = <<-END
28
31
  NOTE: ActiveFedora::Noid 1.0.0 included a change that breaks existing minter
29
32
  statefiles. Run the `active_fedora:noid:migrate_statefile` rake task to migrate
30
- your statefile. (If you're using a custom statefile, not /tmp/minter-state,, set
33
+ your statefile. (If you're using a custom statefile, not /tmp/minter-state, set
31
34
  an environment variable called AFNOID_STATEFILE with its path.)
32
35
  END
33
36
 
@@ -0,0 +1,21 @@
1
+ class MinterState < ActiveRecord::Base
2
+ validates :namespace, presence: true, uniqueness: true
3
+ validates :template, presence: true
4
+ validates :template, format: { with: Object.const_get('Noid::Template::VALID_PATTERN'), message: 'value fails regex' }
5
+
6
+ # @return [Hash] options for Noid::Minter.new
7
+ # * template [String] setting the identifier pattern
8
+ # * seq [Integer] reflecting minter position in sequence
9
+ # * counters [Array{Hash}] "buckets" each with :current and :max values
10
+ # * rand [Object] random number generator object
11
+ def noid_options
12
+ return nil unless template
13
+ opts = {
14
+ :template => template,
15
+ :seq => seq
16
+ }
17
+ opts[:counters] = JSON.parse(counters, :symbolize_names => true) if counters
18
+ opts[:rand] = Marshal.load(random) if random
19
+ opts
20
+ end
21
+ end
@@ -0,0 +1,14 @@
1
+ class CreateMinterStates < ActiveRecord::Migration
2
+ def change
3
+ create_table :minter_states do |t|
4
+ t.string :namespace, null: false, default: 'default'
5
+ t.string :template, null: false
6
+ t.text :counters
7
+ t.bigint :seq, default: 0
8
+ t.binary :random
9
+ t.timestamps null: false
10
+ end
11
+ # Use both model and DB-level constraints for consistency while scaling horizontally
12
+ add_index :minter_states, :namespace, unique: true
13
+ end
14
+ end
@@ -1,7 +1,7 @@
1
1
  module ActiveFedora
2
2
  module Noid
3
3
  class Config
4
- attr_writer :template, :translate_uri_to_id, :translate_id_to_uri, :statefile
4
+ attr_writer :template, :translate_uri_to_id, :translate_id_to_uri, :statefile, :namespace
5
5
 
6
6
  def template
7
7
  @template ||= '.reeddeeddk'
@@ -11,6 +11,10 @@ module ActiveFedora
11
11
  @statefile ||= '/tmp/minter-state'
12
12
  end
13
13
 
14
+ def namespace
15
+ @namespace ||= 'default'
16
+ end
17
+
14
18
  def translate_uri_to_id
15
19
  lambda do |uri|
16
20
  uri.to_s.sub(baseurl, '').split('/', baseparts).last
@@ -0,0 +1,8 @@
1
+ require 'rails'
2
+
3
+ module ActiveFedora
4
+ module Noid
5
+ class Engine < ::Rails::Engine
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,32 @@
1
+ require 'noid'
2
+
3
+ module ActiveFedora
4
+ module Noid
5
+ module Minter
6
+ class Base < ::Noid::Minter
7
+ def initialize(template = default_template)
8
+ super(:template => template.to_s)
9
+ end
10
+
11
+ def mint
12
+ Mutex.new.synchronize do
13
+ while true
14
+ pid = next_id
15
+ return pid unless ActiveFedora::Base.exists?(pid) || ActiveFedora::Base.gone?(pid)
16
+ end
17
+ end
18
+ end
19
+
20
+ protected
21
+
22
+ def default_template
23
+ ActiveFedora::Noid.config.template
24
+ end
25
+
26
+ def next_id
27
+ raise NotImplementedError.new('Implement next_id in child class')
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,40 @@
1
+ require 'noid'
2
+
3
+ module ActiveFedora
4
+ module Noid
5
+ module Minter
6
+ class Db < Base
7
+ protected
8
+
9
+ # Uses pessimistic lock to ensure the record fetched is the same one updated.
10
+ # Should be fast enough to avoid terrible deadlock.
11
+ # Must lock because of multi-connection context! (transaction is per connection -- not enough)
12
+ # The DB table will only ever have at most one row per namespace.
13
+ # The 'default' namespace row is inserted by `rails generate active_fedora:noid:seed`.
14
+ # If you want another namespace, edit your config initialzer to something like:
15
+ # ActiveFedora::Noid.config.namespace = 'druid'
16
+ # ActiveFedora::Noid.config.template = '.reeedek'
17
+ # and in your app run:
18
+ # bundle exec rails generate active_fedora:noid:seed
19
+ def next_id
20
+ id = nil
21
+ MinterState.transaction do
22
+ state = MinterState.lock.where(
23
+ namespace: ActiveFedora::Noid.config.namespace,
24
+ template: ActiveFedora::Noid.config.template,
25
+ ).first!
26
+ minter = ::Noid::Minter.new(state.noid_options)
27
+ id = minter.mint
28
+ # namespace and template are the same, now update the other attributes
29
+ state.seq = minter.seq
30
+ state.counters = JSON.generate(minter.counters)
31
+ state.random = Marshal.dump(minter.instance_variable_get(:@rand))
32
+ state.save!
33
+ end # transaction
34
+ id
35
+ end
36
+
37
+ end # class Db
38
+ end
39
+ end
40
+ end
@@ -20,7 +20,7 @@ module ActiveFedora
20
20
  protected
21
21
 
22
22
  def default_minter
23
- @minter ||= ActiveFedora::Noid::SynchronizedMinter.new
23
+ ActiveFedora::Noid::SynchronizedMinter.new
24
24
  end
25
25
  end
26
26
  end
@@ -1,35 +1,19 @@
1
1
  require 'noid'
2
+
2
3
  module ActiveFedora
3
4
  module Noid
4
- class SynchronizedMinter
5
- attr_reader :template, :statefile
5
+ class SynchronizedMinter < Minter::Base
6
+ attr_reader :statefile
6
7
 
7
8
  def initialize(template = default_template, statefile = default_statefile)
8
- @template = template
9
+ super(template)
9
10
  @statefile = statefile
10
11
  end
11
12
 
12
- def mint
13
- Mutex.new.synchronize do
14
- while true
15
- pid = next_id
16
- return pid unless ActiveFedora::Base.exists?(pid) || ActiveFedora::Base.gone?(pid)
17
- end
18
- end
19
- end
20
-
21
- def valid?(identifier)
22
- ::Noid::Minter.new(template: template).valid?(identifier)
23
- end
24
-
25
13
  protected
26
14
 
27
- def default_template
28
- @template ||= ActiveFedora::Noid.config.template
29
- end
30
-
31
15
  def default_statefile
32
- @statefile ||= ActiveFedora::Noid.config.statefile
16
+ ActiveFedora::Noid.config.statefile
33
17
  end
34
18
 
35
19
  def state_for(io_object)
@@ -39,14 +23,14 @@ module ActiveFedora
39
23
  end
40
24
 
41
25
  def next_id
42
- id = ''
26
+ id = nil
43
27
  ::File.open(statefile, 'a+b', 0644) do |f|
44
28
  f.flock(::File::LOCK_EX)
45
29
  # Files opened in append mode seek to end of file
46
30
  f.rewind
47
31
  state = state_for(f)
48
- minter = ::Noid::Minter.new(state)
49
-
32
+ state[:template] &&= state[:template].to_s
33
+ minter = ::Noid::Minter.new(state) # minter w/in the minter, lives only for an instant
50
34
  id = minter.mint
51
35
 
52
36
  # Wipe prior contents so the new state can be written from the beginning of the file
@@ -1,5 +1,5 @@
1
1
  module ActiveFedora
2
2
  module Noid
3
- VERSION = '1.1.3'.freeze
3
+ VERSION = '2.0.0.beta1'.freeze
4
4
  end
5
5
  end
@@ -1,6 +1,9 @@
1
1
  require 'active_fedora/noid/version'
2
2
  require 'active_fedora/noid/config'
3
+ require 'active_fedora/noid/engine'
3
4
  require 'active_fedora/noid/service'
5
+ require 'active_fedora/noid/minter/base'
6
+ require 'active_fedora/noid/minter/db'
4
7
  require 'active_fedora/noid/synchronized_minter'
5
8
 
6
9
  module ActiveFedora
@@ -15,10 +18,7 @@ module ActiveFedora
15
18
  end
16
19
 
17
20
  def treeify(identifier)
18
- raise ArgumentError, 'Identifier must be a string of size > 0 in order to be treeified' if identifier.blank?
19
- head = identifier.split('/').first
20
- head.gsub!(/#.*/, '')
21
- (head.scan(/..?/).first(4) + [identifier]).join('/')
21
+ (identifier.scan(/..?/).first(4) + [identifier]).join('/')
22
22
  end
23
23
  end
24
24
  end
@@ -0,0 +1,24 @@
1
+ module ActiveFedora
2
+ module Noid
3
+ class InstallGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ desc <<-END_OF_DESC
7
+ Copies DB migrations
8
+ END_OF_DESC
9
+
10
+ def banner
11
+ say_status('info', 'Installing ActiveFedora::Noid', :blue)
12
+ end
13
+
14
+ def migrations
15
+ rake 'active_fedora_noid_engine:install:migrations'
16
+ rake 'db:migrate'
17
+ end
18
+
19
+ def seed
20
+ generate 'active_fedora:noid:seed'
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,29 @@
1
+ module ActiveFedora
2
+ module Noid
3
+ class SeedGenerator < Rails::Generators::Base
4
+ source_root File.expand_path('../templates', __FILE__)
5
+ argument :namespace, :type => :string, :default => ActiveFedora::Noid.config.namespace
6
+ argument :template, :type => :string, :default => ActiveFedora::Noid.config.template
7
+
8
+ desc <<-END_OF_DESC
9
+ Seeds DB from ActiveFedora::Noid.config (or command-line overrides)
10
+ END_OF_DESC
11
+
12
+ def banner
13
+ say_status('info', "Initializing database table for namespace:template of '#{namespace}:#{template}'", :blue)
14
+ end
15
+
16
+ def checks
17
+ say_status('warn', "Be sure to use an initializer to do 'ActiveFedora::Noid.config.namespace = #{namespace}'", :red) if namespace != ActiveFedora::Noid.config.namespace
18
+ say_status('warn', "Be sure to use an initializer to do 'ActiveFedora::Noid.config.template = #{template}'", :red) if template != ActiveFedora::Noid.config.template
19
+ end
20
+
21
+ def seed_row
22
+ MinterState.create!(
23
+ namespace: namespace,
24
+ template: template
25
+ )
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,58 @@
1
+ include MinterStateHelper
2
+
3
+ describe MinterState, type: :model do
4
+ before(:each) { reset_minter_state_table }
5
+ after( :all ) { reset_minter_state_table }
6
+
7
+ let(:state) { described_class.new }
8
+ let(:first) { described_class.first }
9
+
10
+ it 'db is seeded with first row' do
11
+ expect{ first }.not_to raise_error
12
+ expect(first.namespace).to eq 'default'
13
+ expect(first.template).to eq '.reeddeeddk'
14
+ expect(first.seq).to eq 0
15
+ expect(described_class.group(:namespace).count).to eq('default' => 1)
16
+ end
17
+ describe 'validation' do
18
+ it 'blocks invalid template' do
19
+ expect{ state.save! }.to raise_error(ActiveRecord::RecordInvalid) # empty
20
+ state.template = 'bad_template'
21
+ expect{ state.save! }.to raise_error(ActiveRecord::RecordInvalid)
22
+ state.template = 'reeddddk' # close, but missing '.'
23
+ expect{ state.save! }.to raise_error(ActiveRecord::RecordInvalid)
24
+ end
25
+ it 'allows valid template (edit)' do
26
+ first.template = '.reeddddk'
27
+ expect{ first.save! }.not_to raise_error # OK!
28
+ end
29
+ it 'blocks new record in same namespace' do
30
+ state.template = '.reeddddk'
31
+ expect{ state.save! }.to raise_error(ActiveRecord::RecordInvalid)
32
+ end
33
+ it 'allows new record in distinct namespace' do
34
+ state.template = '.reeddddk'
35
+ state.namespace = 'foobar'
36
+ expect{ state.save! }.not_to raise_error # OK!
37
+ expect(described_class.group(:namespace).count).to eq('default' => 1, 'foobar' => 1)
38
+ end
39
+ end
40
+
41
+ describe '#noid_options' do
42
+ it 'returns nil without template (new object not persisted)' do
43
+ expect(state.noid_options).to be_nil
44
+ end
45
+ it 'returns correct hash when populated' do
46
+ state.template = '.reeddddk'
47
+ state.seq = 1
48
+ expect(state.noid_options).to match a_hash_including(
49
+ :template => '.reeddddk',
50
+ :seq => 1
51
+ )
52
+ expect(first.noid_options).to match a_hash_including(
53
+ :template => '.reeddeeddk',
54
+ :seq => 0
55
+ )
56
+ end
57
+ end
58
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,81 +1,22 @@
1
+ ENV["RAILS_ENV"] ||= 'test'
2
+
1
3
  require 'coveralls'
2
4
  Coveralls.wear!
5
+ require 'engine_cart'
6
+ EngineCart.load_application!
3
7
 
4
8
  require 'active_fedora'
5
- require 'byebug' unless ENV['CI']
6
9
  require 'active_fedora/noid'
10
+ require 'byebug' unless ENV['CI']
11
+
12
+ Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each { |f| require f }
7
13
 
8
14
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
9
15
  RSpec.configure do |config|
10
- # rspec-expectations config goes here. You can use an alternate
11
- # assertion/expectation library such as wrong or the stdlib/minitest
12
- # assertions if you prefer.
13
16
  config.expect_with :rspec do |expectations|
14
- # This option will default to `true` in RSpec 4. It makes the `description`
15
- # and `failure_message` of custom matchers include text for helper methods
16
- # defined using `chain`, e.g.:
17
- # be_bigger_than(2).and_smaller_than(4).description
18
- # # => "be bigger than 2 and smaller than 4"
19
- # ...rather than:
20
- # # => "be bigger than 2"
21
17
  expectations.include_chain_clauses_in_custom_matcher_descriptions = true
22
18
  end
23
-
24
- # rspec-mocks config goes here. You can use an alternate test double
25
- # library (such as bogus or mocha) by changing the `mock_with` option here.
26
19
  config.mock_with :rspec do |mocks|
27
- # Prevents you from mocking or stubbing a method that does not exist on
28
- # a real object. This is generally recommended, and will default to
29
- # `true` in RSpec 4.
30
20
  mocks.verify_partial_doubles = true
31
21
  end
32
-
33
- # The settings below are suggested to provide a good initial experience
34
- # with RSpec, but feel free to customize to your heart's content.
35
- =begin
36
- # These two settings work together to allow you to limit a spec run
37
- # to individual examples or groups you care about by tagging them with
38
- # `:focus` metadata. When nothing is tagged with `:focus`, all examples
39
- # get run.
40
- config.filter_run :focus
41
- config.run_all_when_everything_filtered = true
42
-
43
- # Limits the available syntax to the non-monkey patched syntax that is
44
- # recommended. For more details, see:
45
- # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
46
- # - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
47
- # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
48
- config.disable_monkey_patching!
49
-
50
- # This setting enables warnings. It's recommended, but in some cases may
51
- # be too noisy due to issues in dependencies.
52
- config.warnings = true
53
-
54
- # Many RSpec users commonly either run the entire suite or an individual
55
- # file, and it's useful to allow more verbose output when running an
56
- # individual spec file.
57
- if config.files_to_run.one?
58
- # Use the documentation formatter for detailed output,
59
- # unless a formatter has already been configured
60
- # (e.g. via a command-line flag).
61
- config.default_formatter = 'doc'
62
- end
63
-
64
- # Print the 10 slowest examples and example groups at the
65
- # end of the spec run, to help surface which specs are running
66
- # particularly slow.
67
- config.profile_examples = 10
68
-
69
- # Run specs in random order to surface order dependencies. If you find an
70
- # order dependency and want to debug it, you can fix the order by providing
71
- # the seed, which is printed after each run.
72
- # --seed 1234
73
- config.order = :random
74
-
75
- # Seed global randomization in this process using the `--seed` CLI option.
76
- # Setting this allows you to use `--seed` to deterministically reproduce
77
- # test failures related to randomization by passing the same `--seed` value
78
- # as the one that triggered the failure.
79
- Kernel.srand config.seed
80
- =end
81
22
  end
@@ -0,0 +1,11 @@
1
+ module MinterStateHelper
2
+ # Simple truncation is not enough, since we also need seed data
3
+ def reset_minter_state_table
4
+ MinterState.destroy_all
5
+ MinterState.create!(
6
+ namespace: 'default',
7
+ template: '.reeddeeddk',
8
+ seq: 0
9
+ )
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ require 'rails/generators'
2
+
3
+ class TestAppGenerator < Rails::Generators::Base
4
+ source_root "./spec/test_app_templates"
5
+
6
+ # if you need to generate any additional configuration
7
+ # into the test app, this generator will be run immediately
8
+ # after setting up the application
9
+
10
+ def install_engine
11
+ generate 'active_fedora:noid:install'
12
+ end
13
+ end
@@ -1,8 +1,7 @@
1
- require 'spec_helper'
2
-
3
1
  describe ActiveFedora::Noid::Config do
4
2
  it { is_expected.to respond_to(:template) }
5
3
  it { is_expected.to respond_to(:statefile) }
4
+ it { is_expected.to respond_to(:namespace) }
6
5
  it { is_expected.to respond_to(:translate_id_to_uri) }
7
6
  it { is_expected.to respond_to(:translate_uri_to_id) }
8
7
 
@@ -39,77 +38,35 @@ describe ActiveFedora::Noid::Config do
39
38
 
40
39
  context "with a hash code uri" do
41
40
  let(:uri) { "http://localhost:8983/fedora/rest/test/hh/63/vz/22/hh63vz22q#g123" }
42
- it { is_expected.to eq 'hh63vz22q#g123' }
41
+ it { is_expected.to eq 'hh63vz22q#g123' }
43
42
  end
44
43
 
45
- context 'with a short custom template' do
44
+ describe 'with a short custom template' do
46
45
  let(:uri) { "http://localhost:8983/fedora/rest/test/ab/cd/abcd/members" }
47
46
  let(:custom_template) { '.reeee' }
48
47
  before { config.template = custom_template }
49
48
  subject { translator.call(uri) }
50
-
49
+
51
50
  it { is_expected.to eq 'abcd/members' }
52
51
  end
53
52
 
54
- context 'with an even shorter custom template' do
53
+ describe 'with an even shorter custom template' do
55
54
  let(:uri) { "http://localhost:8983/fedora/rest/test/ab/c/abc/members" }
56
55
  let(:custom_template) { '.reee' }
57
56
  before { config.template = custom_template }
58
57
  subject { translator.call(uri) }
59
-
58
+
60
59
  it { is_expected.to eq 'abc/members' }
61
60
  end
62
61
 
63
- context 'with a long custom template' do
62
+ describe 'with a long custom template' do
64
63
  let(:uri) { "http://localhost:8983/fedora/rest/test/ab/cd/ef/gh/abcdefghijklmnopqrstuvwxyz/members" }
65
64
  let(:custom_template) { '.reeeeeeeeeeeeeeeeeeeeeeeeee' }
66
65
  before { config.template = custom_template }
67
66
  subject { translator.call(uri) }
68
-
69
- it { is_expected.to eq 'abcdefghijklmnopqrstuvwxyz/members' }
70
- end
71
- end
72
-
73
- describe '#translate_id_to_uri' do
74
- let(:config) { described_class.new }
75
- let(:translator) { config.translate_id_to_uri }
76
- let(:id) { "hh63vz2/members" }
77
- let(:ActiveFedora) { double(ActiveFedora) }
78
- subject { translator.call(id) }
79
- before do
80
- allow(ActiveFedora).to receive_message_chain("fedora.host") { "http://localhost:8983" }
81
- allow(ActiveFedora).to receive_message_chain("fedora.base_path") { "/fedora/rest/test" }
82
- end
83
67
 
84
- it { is_expected.to eq "http://localhost:8983/fedora/rest/test/hh/63/vz/2/hh63vz2/members" }
85
-
86
- context "with a hash code id" do
87
- let(:id) { 'hh63vz2#g123' }
88
- it { is_expected.to eq "http://localhost:8983/fedora/rest/test/hh/63/vz/2/hh63vz2#g123" }
89
- end
90
-
91
- context 'with a short custom template' do
92
- let(:id) { "abcd/members" }
93
- let(:custom_template) { '.reeee' }
94
- before { config.template = custom_template }
95
- subject { translator.call(id) }
96
- it { is_expected.to eq "http://localhost:8983/fedora/rest/test/ab/cd/abcd/members" }
97
- end
98
-
99
- context 'with an even shorter custom template' do
100
- let(:id) { 'abc/members' }
101
- let(:custom_template) { '.reee' }
102
- before { config.template = custom_template }
103
- subject { translator.call(id) }
104
- it { is_expected.to eq "http://localhost:8983/fedora/rest/test/ab/c/abc/members" }
68
+ it { is_expected.to eq 'abcdefghijklmnopqrstuvwxyz/members' }
105
69
  end
106
70
 
107
- context 'with a long custom template' do
108
- let(:id) { "abcdefghijklmnopqrstuvwxyz/members" }
109
- let(:custom_template) { '.reeeeeeeeeeeeeeeeeeeeeeeeee' }
110
- before { config.template = custom_template }
111
- subject { translator.call(id) }
112
- it { is_expected.to eq "http://localhost:8983/fedora/rest/test/ab/cd/ef/gh/abcdefghijklmnopqrstuvwxyz/members" }
113
- end
114
71
  end
115
72
  end
@@ -0,0 +1,76 @@
1
+ include MinterStateHelper
2
+
3
+ describe ActiveFedora::Noid::Minter::Db do
4
+ before(:each) { reset_minter_state_table }
5
+ after( :all ) { reset_minter_state_table }
6
+
7
+ before :each do
8
+ # default novel mintings
9
+ allow(ActiveFedora::Base).to receive(:exists?).and_return(false)
10
+ allow(ActiveFedora::Base).to receive(:gone?).and_return(false)
11
+ end
12
+
13
+ let(:minter) { described_class.new }
14
+ let(:other) { described_class.new('.reedddk') }
15
+
16
+ describe '#initialize' do
17
+ it 'raises on bad templates' do
18
+ expect{ described_class.new('reeddeeddk') }.to raise_error(Noid::TemplateError)
19
+ expect{ described_class.new('') }.to raise_error(Noid::TemplateError)
20
+ end
21
+ it 'returns object w/ default template' do
22
+ expect(minter).to be_instance_of described_class
23
+ expect(minter).to be_a Noid::Minter
24
+ expect(minter.template).to be_instance_of Noid::Template
25
+ expect(minter.template.to_s).to eq ActiveFedora::Noid.config.template
26
+ end
27
+ it 'accepts valid template arg' do
28
+ expect(other).to be_instance_of described_class
29
+ expect(other).to be_a Noid::Minter
30
+ expect(other.template).to be_instance_of Noid::Template
31
+ expect(other.template.to_s).to eq '.reedddk'
32
+ end
33
+ end
34
+
35
+ describe '#mint' do
36
+ subject { minter.mint }
37
+ it { is_expected.not_to be_empty }
38
+ it 'does not mint the same ID twice in a row' do
39
+ expect(subject).not_to eq described_class.new.mint
40
+ end
41
+ it 'is valid' do
42
+ expect(minter.valid?(subject)).to be true
43
+ expect(described_class.new.valid?(subject)).to be true
44
+ end
45
+ it 'is invalid under a different template' do
46
+ expect(described_class.new('.reedddk').valid?(subject)).to be false
47
+ end
48
+ end
49
+
50
+ context 'conflicts' do
51
+ let(:existing_pid) { 'ef12ef12f' }
52
+ let(:unique_pid) { 'bb22bb22b' }
53
+ before :each do
54
+ expect(minter).to receive(:next_id).and_return(existing_pid, unique_pid)
55
+ end
56
+
57
+ context 'when the pid already exists in Fedora' do
58
+ before do
59
+ expect(ActiveFedora::Base).to receive(:exists?).with(existing_pid).and_return(true)
60
+ end
61
+ it 'skips the existing pid' do
62
+ expect(minter.mint).to eq unique_pid
63
+ end
64
+ end
65
+
66
+ context 'when the pid already existed in Fedora and now is gone' do
67
+ let(:gone_pid) { existing_pid }
68
+ before do
69
+ expect(ActiveFedora::Base).to receive(:gone?).with(gone_pid).and_return(true)
70
+ end
71
+ it 'skips the deleted pid' do
72
+ expect(minter.mint).to eq unique_pid
73
+ end
74
+ end
75
+ end
76
+ end
@@ -1,5 +1,3 @@
1
- require 'spec_helper'
2
-
3
1
  describe ActiveFedora::Noid do
4
2
  describe '#configure' do
5
3
  it { is_expected.to respond_to(:configure) }
@@ -15,21 +13,5 @@ describe ActiveFedora::Noid do
15
13
  subject { ActiveFedora::Noid.treeify(id) }
16
14
  let(:id) { 'abc123def45' }
17
15
  it { is_expected.to eq 'ab/c1/23/de/abc123def45' }
18
- context 'with a seven-digit identifier' do
19
- let(:id) { 'abc123z' }
20
- it { is_expected.to eq 'ab/c1/23/z/abc123z' }
21
- end
22
- context 'with an empty string' do
23
- let(:id) { '' }
24
- it 'raises ArgumentError' do
25
- expect { subject }.to raise_error(ArgumentError)
26
- end
27
- end
28
- context 'with a nil' do
29
- let(:id) { nil }
30
- it 'raises ArgumentError' do
31
- expect { subject }.to raise_error(ArgumentError)
32
- end
33
- end
34
16
  end
35
17
  end
@@ -1,5 +1,3 @@
1
- require 'spec_helper'
2
-
3
1
  describe ActiveFedora::Noid::Service do
4
2
  describe 'public API' do
5
3
  it { is_expected.to respond_to(:valid?) }
@@ -1,80 +1,70 @@
1
- require 'spec_helper'
2
- require 'active_fedora'
3
-
4
1
  describe ActiveFedora::Noid::SynchronizedMinter do
5
- it { is_expected.to respond_to(:mint) }
2
+ before :each do
3
+ # default novel mintings
4
+ allow(ActiveFedora::Base).to receive(:exists?).and_return(false)
5
+ allow(ActiveFedora::Base).to receive(:gone?).and_return(false)
6
+ end
6
7
 
8
+ let(:minter) { described_class.new }
9
+
10
+ it { is_expected.to respond_to(:mint) }
7
11
  it 'has a default statefile' do
8
12
  expect(subject.statefile).to eq ActiveFedora::Noid.config.statefile
9
13
  end
10
-
11
14
  it 'has a default template' do
12
- expect(subject.template).to eq ActiveFedora::Noid.config.template
15
+ expect(subject.template.to_s).to eq ActiveFedora::Noid.config.template
13
16
  end
14
17
 
15
18
  describe '#initialize' do
16
19
  let(:template) { '.rededk' }
17
20
  let(:statefile) { '/tmp/foobar' }
18
21
 
19
- subject { ActiveFedora::Noid::SynchronizedMinter.new(template, statefile) }
22
+ subject { described_class.new(template, statefile) }
20
23
 
21
24
  it 'respects the custom template' do
22
- expect(subject.template).to eq template
25
+ expect(subject.template.to_s).to eq template
23
26
  end
24
-
25
27
  it 'respects the custom statefile' do
26
28
  expect(subject.statefile).to eq statefile
27
29
  end
28
30
  end
29
31
 
30
32
  describe '#mint' do
31
- before do
32
- allow(ActiveFedora::Base).to receive(:exists?).and_return(false)
33
- allow(ActiveFedora::Base).to receive(:gone?).and_return(false)
34
- end
35
-
36
- subject { ActiveFedora::Noid::Service.new.mint }
37
-
33
+ subject { minter.mint }
38
34
  it { is_expected.not_to be_empty }
39
-
40
35
  it 'does not mint the same ID twice in a row' do
41
- expect(subject).not_to eq ActiveFedora::Noid::Service.new.mint
36
+ expect(subject).not_to eq described_class.new.mint
42
37
  end
43
-
44
38
  it 'is valid' do
45
- expect(ActiveFedora::Noid::Service.new.valid?(subject)).to be true
39
+ expect(minter.valid?(subject)).to be true
40
+ expect(described_class.new.valid?(subject)).to be true
46
41
  end
47
42
  end
48
43
 
49
- context "when the pid already exists in Fedora" do
50
- let(:existing_pid) { 'ef12ef12f' }
44
+ context 'conflicts' do
51
45
  let(:unique_pid) { 'bb22bb22b' }
52
-
53
- before do
54
- allow_any_instance_of(ActiveFedora::Noid::SynchronizedMinter).to receive(:next_id).and_return(existing_pid, unique_pid)
55
- allow(ActiveFedora::Base).to receive(:exists?).with(existing_pid).and_return(true)
56
- allow(ActiveFedora::Base).to receive(:exists?).with(unique_pid).and_return(false)
57
- allow(ActiveFedora::Base).to receive(:gone?).and_return(false)
58
- end
59
-
60
- it 'skips the existing pid' do
61
- expect(subject.mint).to eq unique_pid
46
+ let(:existing_pid) { 'ef12ef12f' }
47
+ before :each do
48
+ expect(minter).to receive(:next_id).and_return(existing_pid, unique_pid)
62
49
  end
63
- end
64
-
65
- context "when the pid already existed in Fedora and now is gone" do
66
- let(:gone_pid) { 'ef12ef12f' }
67
- let(:unique_pid) { 'bb22bb22b' }
68
50
 
69
- before do
70
- allow_any_instance_of(ActiveFedora::Noid::SynchronizedMinter).to receive(:next_id).and_return(gone_pid, unique_pid)
71
- allow(ActiveFedora::Base).to receive(:gone?).with(gone_pid).and_return(true)
72
- allow(ActiveFedora::Base).to receive(:gone?).with(unique_pid).and_return(false)
73
- allow(ActiveFedora::Base).to receive(:exists?).and_return(false)
51
+ context 'when the pid already exists in Fedora' do
52
+ before do
53
+ expect(ActiveFedora::Base).to receive(:exists?).with(existing_pid).and_return(true)
54
+ end
55
+ it 'skips the existing pid' do
56
+ expect(minter.mint).to eq unique_pid
57
+ end
74
58
  end
75
59
 
76
- it 'skips the deleted pid' do
77
- expect(subject.mint).to eq unique_pid
60
+ context 'when the pid already existed in Fedora and now is gone' do
61
+ let(:gone_pid) { existing_pid }
62
+ before do
63
+ expect(ActiveFedora::Base).to receive(:gone?).with(gone_pid).and_return(true)
64
+ end
65
+ it 'skips the deleted pid' do
66
+ expect(minter.mint).to eq unique_pid
67
+ end
78
68
  end
79
69
  end
80
70
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_fedora-noid
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 2.0.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael J. Giarlo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-26 00:00:00.000000000 Z
11
+ date: 2016-06-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active-fedora
@@ -36,14 +36,28 @@ dependencies:
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '0.7'
39
+ version: '0.9'
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '0.7'
46
+ version: '0.9'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rails
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: 4.2.6
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 4.2.6
47
61
  - !ruby/object:Gem::Dependency
48
62
  name: bundler
49
63
  requirement: !ruby/object:Gem::Requirement
@@ -86,6 +100,34 @@ dependencies:
86
100
  - - "~>"
87
101
  - !ruby/object:Gem::Version
88
102
  version: '3.2'
103
+ - !ruby/object:Gem::Dependency
104
+ name: sqlite3
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: engine_cart
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '0.8'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '0.8'
89
131
  description: Noid identifier services for ActiveFedora-based applications.
90
132
  email:
91
133
  - leftwing@alumni.rutgers.edu
@@ -94,6 +136,7 @@ extensions: []
94
136
  extra_rdoc_files: []
95
137
  files:
96
138
  - ".gitignore"
139
+ - ".rspec"
97
140
  - ".travis.yml"
98
141
  - CONTRIBUTING.md
99
142
  - Gemfile
@@ -101,14 +144,25 @@ files:
101
144
  - README.md
102
145
  - Rakefile
103
146
  - active_fedora-noid.gemspec
147
+ - app/models/minter_state.rb
148
+ - db/migrate/20160610010003_create_minter_states.rb
104
149
  - lib/active_fedora/noid.rb
105
150
  - lib/active_fedora/noid/config.rb
151
+ - lib/active_fedora/noid/engine.rb
152
+ - lib/active_fedora/noid/minter/base.rb
153
+ - lib/active_fedora/noid/minter/db.rb
106
154
  - lib/active_fedora/noid/service.rb
107
155
  - lib/active_fedora/noid/synchronized_minter.rb
108
156
  - lib/active_fedora/noid/version.rb
157
+ - lib/generators/active_fedora/noid/install_generator.rb
158
+ - lib/generators/active_fedora/noid/seed_generator.rb
109
159
  - lib/tasks/noid_tasks.rake
160
+ - spec/models/minter_state_spec.rb
110
161
  - spec/spec_helper.rb
162
+ - spec/support/minterstate_table.rb
163
+ - spec/test_app_templates/lib/generators/test_app_generator.rb
111
164
  - spec/unit/config_spec.rb
165
+ - spec/unit/db_minter_spec.rb
112
166
  - spec/unit/noid_spec.rb
113
167
  - spec/unit/service_spec.rb
114
168
  - spec/unit/synchronized_minter_spec.rb
@@ -119,7 +173,7 @@ metadata: {}
119
173
  post_install_message: |
120
174
  NOTE: ActiveFedora::Noid 1.0.0 included a change that breaks existing minter
121
175
  statefiles. Run the `active_fedora:noid:migrate_statefile` rake task to migrate
122
- your statefile. (If you're using a custom statefile, not /tmp/minter-state,, set
176
+ your statefile. (If you're using a custom statefile, not /tmp/minter-state, set
123
177
  an environment variable called AFNOID_STATEFILE with its path.)
124
178
  rdoc_options: []
125
179
  require_paths:
@@ -131,18 +185,22 @@ required_ruby_version: !ruby/object:Gem::Requirement
131
185
  version: '0'
132
186
  required_rubygems_version: !ruby/object:Gem::Requirement
133
187
  requirements:
134
- - - ">="
188
+ - - ">"
135
189
  - !ruby/object:Gem::Version
136
- version: '0'
190
+ version: 1.3.1
137
191
  requirements: []
138
192
  rubyforge_project:
139
- rubygems_version: 2.5.1
193
+ rubygems_version: 2.4.6
140
194
  signing_key:
141
195
  specification_version: 4
142
196
  summary: Noid identifier services for ActiveFedora-based applications
143
197
  test_files:
198
+ - spec/models/minter_state_spec.rb
144
199
  - spec/spec_helper.rb
200
+ - spec/support/minterstate_table.rb
201
+ - spec/test_app_templates/lib/generators/test_app_generator.rb
145
202
  - spec/unit/config_spec.rb
203
+ - spec/unit/db_minter_spec.rb
146
204
  - spec/unit/noid_spec.rb
147
205
  - spec/unit/service_spec.rb
148
206
  - spec/unit/synchronized_minter_spec.rb