active_triples-local_name 0.1.0
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 +15 -0
- data/.gitignore +7 -0
- data/.travis.yml +12 -0
- data/AUTHORS +2 -0
- data/Gemfile +8 -0
- data/Guardfile +9 -0
- data/LICENSE +12 -0
- data/README.md +137 -0
- data/active_triples-local_name.gemspec +34 -0
- data/lib/active_triples/local_name.rb +28 -0
- data/lib/active_triples/local_name/minter.rb +75 -0
- data/lib/active_triples/local_name/version.rb +5 -0
- data/spec/active_triples/local_name/minter_spec.rb +336 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/support/active_model_lint.rb +81 -0
- metadata +130 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MTcyOTBhODdmODAzNWQ5OWJiYjFlOWY3YTA4ZDRmZTBlNDIwYzI3MA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MTRjNzcwNWQ3NjhkMjQzOWRlZTcyMDVkNTE3ZDFmZDA0NjUzNjM1Nw==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ZTRmYzc4NmEyMjgyYzg2MDE5MWNkMWVlZWJjZjExMzFmMWY4YzBkYTEyZWQ0
|
10
|
+
NTg4MTYyZGNlYmMzZGQyYzJmYjI1MDQ5YWNiZjMzMThiNTU5MmRiMGFmMGIx
|
11
|
+
NTI5YTVhNWQ5NDgwMzgyY2ViZGU2YmVjMWExOGVlOTIwOGVmNTA=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NjBkNDc3NTM4MjMwODlmYTk1M2RlNDJkMmVkMTVkNmJkNjllY2M2YzYzY2Jk
|
14
|
+
ZTUxMWIwMTc2MzkwNmIyYTdhMTVmMTIxODJjMDhlM2I3ZDEwMmViOGVlMGJm
|
15
|
+
MjhiNWI2NjBmYjYwZjU2MGEwZjc1OTM5NWUxMDk2ZTFmNGNjMzQ=
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/AUTHORS
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
# GETTING FROM GEMFILE UNTIL ActiveTriples master CODE IS RELEASED (>0.4.0), THEN MOVE THIS BACK TO *.gemspec FILE
|
6
|
+
# Use active-triple for handling of triple persistence
|
7
|
+
gem 'active-triples', :git => 'git@github.com:no-reply/ActiveTriples.git', :branch => 'master'
|
8
|
+
|
data/Guardfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
##########################################################################
|
2
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
3
|
+
# you may not use this file except in compliance with the License.
|
4
|
+
# You may obtain a copy of the License at
|
5
|
+
#
|
6
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
7
|
+
#
|
8
|
+
# Unless required by applicable law or agreed to in writing, software
|
9
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
10
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
11
|
+
# See the License for the specific language governing permissions and
|
12
|
+
# limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
# ActiveTriples::LocalName
|
2
|
+
|
3
|
+
|
4
|
+
Provides utilities for working with local names under the [ActiveTriples](https://github.com/ActiveTriples/ActiveTriples)
|
5
|
+
framework. Includes a default implementation of a local name minter.
|
6
|
+
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
gem 'active_triples-local_name'
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle install
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install active_triples-local_name
|
21
|
+
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
**Utilities**
|
26
|
+
|
27
|
+
* Local Name Minter
|
28
|
+
* Others may be added in the future.
|
29
|
+
|
30
|
+
|
31
|
+
### Local Name Minter
|
32
|
+
|
33
|
+
Common prep code for all examples:
|
34
|
+
```ruby
|
35
|
+
require 'active_triples'
|
36
|
+
require 'active_triples/local_name'
|
37
|
+
|
38
|
+
# create an in-memory repository for ad-hoc testing
|
39
|
+
ActiveTriples::Repositories.add_repository :default, RDF::Repository.new
|
40
|
+
|
41
|
+
# create a DummyResource for ad-hoc testing
|
42
|
+
# NOTE: local name minter requires resource class to have base_uri configured
|
43
|
+
class DummyResourceWithBaseURI < ActiveTriples::Resource
|
44
|
+
configure :base_uri => "http://example.org",
|
45
|
+
:type => RDF::URI("http://example.org/SomeClass"),
|
46
|
+
:repository => :default
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
#### Example: Using default minter
|
51
|
+
```ruby
|
52
|
+
# create a new resource with a minted local name using default minter
|
53
|
+
localname = ActiveTriples::LocalName::Minter.generate_local_name(
|
54
|
+
DummyResourceWithBaseURI, 10, {:prefix=>'d'})
|
55
|
+
# => something like -- "http://example.org/d59beebc5-5238-4aad-bf92-f63fbbd8faaa"
|
56
|
+
```
|
57
|
+
|
58
|
+
Parameter NOTES:
|
59
|
+
* for_class = DummyResourceWithBaseURI - resource class must have base_uri configured
|
60
|
+
* max_tries = 10 - If using default minter, it should easily find an available local name in 10 tries.
|
61
|
+
If your minter algorithm gets lots of clashes with existing URIs and max_tries is set high, you may
|
62
|
+
run into performance issues.
|
63
|
+
* minter_args (optional) = {:prefix=>'d'} - The default minter takes a single hash argument. You can
|
64
|
+
define minters that take no arguments, multiple arguments, or a multiple item hash argument.
|
65
|
+
* minter_block = nil - When minter_block is not passed in, the default minter algorithm, which produces
|
66
|
+
a UUID, will be used. Best practice is to start local names with an alpha character. UUIDs generate
|
67
|
+
with either an alpha or numeric as the first character. Passing in a prefix of 'd' forces the local
|
68
|
+
name to start with the character 'd'.
|
69
|
+
|
70
|
+
|
71
|
+
#### Example: Passing in a block as minter
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
# create a new resource with a minted local name using passed in block
|
75
|
+
localname = ActiveTriples::LocalName::Minter.generate_local_name(
|
76
|
+
DummyResourceWithBaseURI,10,'d') do |prefix|
|
77
|
+
prefix ||= ""
|
78
|
+
local_name = SecureRandom.uuid
|
79
|
+
local_name = prefix + "_blockproc_" + local_name if prefix && prefix.is_a?(String)
|
80
|
+
local_name
|
81
|
+
end
|
82
|
+
# => something like -- "http://example.org/d_blockproc_59beebc5-5238-4aad-bf92-f63fbbd8faaa"
|
83
|
+
```
|
84
|
+
|
85
|
+
|
86
|
+
#### Example: Passing in a method as minter
|
87
|
+
```ruby
|
88
|
+
# minter method
|
89
|
+
def uuid_minter( *options )
|
90
|
+
prefix = options[0][:prefix] if ! options.empty? && options[0].is_a?(Hash) && options[0].key?(:prefix)
|
91
|
+
local_name = SecureRandom.uuid
|
92
|
+
local_name = prefix + "_method_" + local_name if prefix && prefix.is_a?(String)
|
93
|
+
local_name
|
94
|
+
end
|
95
|
+
|
96
|
+
# create a new resource with a minted local name using a minter method
|
97
|
+
localname = ActiveTriples::LocalName::Minter.generate_local_name(
|
98
|
+
DummyResourceWithBaseURI,10,{:prefix=>"d"}) {|args| uuid_minter(args)}
|
99
|
+
# => something like -- "http://example.org/d_method_59beebc5-5238-4aad-bf92-f63fbbd8faaa"
|
100
|
+
```
|
101
|
+
|
102
|
+
#### Example: Override default minter.
|
103
|
+
```ruby
|
104
|
+
# minter method
|
105
|
+
module ActiveTriples
|
106
|
+
module LocalName
|
107
|
+
class Minter
|
108
|
+
def self.default_minter( *options )
|
109
|
+
prefix = options[0][:prefix] if ! options.empty? && options[0].is_a?(Hash) && options[0].key?(:prefix)
|
110
|
+
local_name = SecureRandom.uuid
|
111
|
+
local_name = prefix + "_default_" + local_name if prefix && prefix.is_a?(String)
|
112
|
+
local_name
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# create a new resource with a minted local name using override of default minter
|
119
|
+
localname = ActiveTriples::LocalName::Minter.generate_local_name(
|
120
|
+
DummyResourceWithBaseURI,10,{:prefix=>"d"})
|
121
|
+
# => something like -- "http://example.org/d_default_59beebc5-5238-4aad-bf92-f63fbbd8faaa"
|
122
|
+
```
|
123
|
+
|
124
|
+
See more examples in spec/active_triples/local_name/minter_spec.rb.
|
125
|
+
|
126
|
+
|
127
|
+
## Contributing
|
128
|
+
|
129
|
+
Please observe the following guidelines:
|
130
|
+
|
131
|
+
- Do your work in a feature branch based on ```master``` and rebase before submitting a pull request.
|
132
|
+
- Write tests for your contributions.
|
133
|
+
- Document every method you add using YARD annotations. (_Note: Annotations are sparse in the existing codebase, help us fix that!_)
|
134
|
+
- Organize your commits into logical units.
|
135
|
+
- Don't leave trailing whitespace (i.e. run ```git diff --check``` before committing).
|
136
|
+
- Use [well formed](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) commit messages.
|
137
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "active_triples/local_name/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "active_triples-local_name"
|
7
|
+
s.version = ActiveTriples::LocalName::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["E. Lynette Rayle"]
|
10
|
+
s.homepage = 'https://github.com/no-reply/active_triples-local_name'
|
11
|
+
s.email = 'elr37@cornell.edu'
|
12
|
+
s.summary = %q{Local name minter for ActiveTriples based resources.}
|
13
|
+
s.description = %q{active_triples-local_name provides a standard interface and default implementation for a minter of the local name portion of a URI.}
|
14
|
+
s.license = "APACHE2"
|
15
|
+
s.required_ruby_version = '>= 1.9.3'
|
16
|
+
|
17
|
+
# GETTING FROM GEMFILE UNTIL persistent check CODE IS RELEASED
|
18
|
+
# s.add_dependency('active-triples', '~> 0.4')
|
19
|
+
|
20
|
+
s.add_dependency('deprecation', '~> 0.1')
|
21
|
+
s.add_dependency('activesupport', '>= 3.0.0')
|
22
|
+
|
23
|
+
s.add_development_dependency('rdoc')
|
24
|
+
s.add_development_dependency('rspec')
|
25
|
+
s.add_development_dependency('guard-rspec')
|
26
|
+
|
27
|
+
s.files = `git ls-files`.split("\n")
|
28
|
+
s.test_files = `git ls-files -- {spec}/*`.split("\n")
|
29
|
+
|
30
|
+
s.extra_rdoc_files = [
|
31
|
+
"LICENSE",
|
32
|
+
"README.md"
|
33
|
+
]
|
34
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# require 'rdf'
|
2
|
+
require 'active_triples/local_name/version'
|
3
|
+
require 'active_support'
|
4
|
+
|
5
|
+
module ActiveTriples
|
6
|
+
module LocalName
|
7
|
+
extend ActiveSupport::Autoload
|
8
|
+
eager_autoload do
|
9
|
+
autoload :Minter
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.class_from_string(class_name, container_class=Kernel)
|
13
|
+
container_class = container_class.name if container_class.is_a? Module
|
14
|
+
container_parts = container_class.split('::')
|
15
|
+
(container_parts + class_name.split('::')).flatten.inject(Kernel) do |mod, class_name|
|
16
|
+
if mod == Kernel
|
17
|
+
Object.const_get(class_name)
|
18
|
+
elsif mod.const_defined? class_name.to_sym
|
19
|
+
mod.const_get(class_name)
|
20
|
+
else
|
21
|
+
container_parts.pop
|
22
|
+
class_from_string(class_name, container_parts.join('::'))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module ActiveTriples
|
2
|
+
module LocalName
|
3
|
+
|
4
|
+
##
|
5
|
+
# Provide a standard interface for minting new IDs and validating
|
6
|
+
# the ID is not in use in any known (i.e., registered) repository.
|
7
|
+
class Minter
|
8
|
+
|
9
|
+
##
|
10
|
+
# Generate a random localname that combined with a class' base_uri does not already exist in
|
11
|
+
# registered triplestores.
|
12
|
+
#
|
13
|
+
# @param [Class] the class inheriting from <tt>ActiveTriples::Reource</tt> whose configuration
|
14
|
+
# is used to generate the full URI for testing for uniqueness of the generated local name
|
15
|
+
# @param [Integer] the maximum number of attempts to make a unique local name
|
16
|
+
# @yieldparam the arguments to pass to the minter block (optional)
|
17
|
+
# @yield the function to use to mint the local name. If not specified, the
|
18
|
+
# +default_minter+ function will be used to generate an UUID.
|
19
|
+
# @yieldreturn [String] the generated local name to be tested for uniqueness
|
20
|
+
#
|
21
|
+
# @return [String] the generated local name
|
22
|
+
#
|
23
|
+
# @raise [ArgumentError] if maximum allowed tries is less than 0
|
24
|
+
# @raise [ArgumentError] if for_class does not inherit from ActiveTriples::Resources
|
25
|
+
# @raise [ArgumentError] if minter_block is not a block (does not respond to call)
|
26
|
+
# @raise [Exception] if for_class does not have base_uri configured
|
27
|
+
# @raise [Exception] if an available local name is not found in the maximum allowed tries.
|
28
|
+
#
|
29
|
+
# @TODO This is inefficient if max_tries is large. Could try
|
30
|
+
# multi-threading. When using the default_minter included
|
31
|
+
# in this class, it is unlikely to be a problem and should
|
32
|
+
# find an ID within the first few attempts.
|
33
|
+
def self.generate_local_name(for_class, max_tries=10, *minter_args, &minter_block)
|
34
|
+
raise ArgumentError, 'Argument max_tries must be >= 1 if passed in' if max_tries <= 0
|
35
|
+
|
36
|
+
raise ArgumentError, 'Argument for_class must inherit from ActiveTriples::Resource' unless for_class < ActiveTriples::Resource
|
37
|
+
raise 'Requires base_uri to be defined in for_class.' unless for_class.base_uri
|
38
|
+
|
39
|
+
raise ArgumentError, 'Invalid minter_block.' if minter_block && !minter_block.respond_to?(:call)
|
40
|
+
minter_block = proc { |args| default_minter(args) } unless minter_block
|
41
|
+
|
42
|
+
found = true
|
43
|
+
test_id = nil
|
44
|
+
(1).upto(max_tries) do
|
45
|
+
test_id = minter_block.call( *minter_args )
|
46
|
+
found = for_class.id_persisted?(test_id)
|
47
|
+
break unless found
|
48
|
+
end
|
49
|
+
raise 'Available ID not found. Exceeded maximum tries.' if found
|
50
|
+
test_id
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# Default minter used by generate_id.
|
55
|
+
#
|
56
|
+
# @param [Hash] options the options to use while generating the local name
|
57
|
+
# @option options [String] :prefix the prefix to put before the generated local name (optional)
|
58
|
+
#
|
59
|
+
# @note Because <tt>:prefix</tt> is optional, errors in type for <tt>:prefix</tt> are ignored. Any additional
|
60
|
+
# parameters beyond <tt>:prefix</tt> are also ignored.
|
61
|
+
#
|
62
|
+
# @note Best practice is to begin localnames with an alpha character. UUIDs can generate with an alpha or
|
63
|
+
# numeric as the first character. Pass in an alpha character as <tt>:prefix</tt> to enforce this best
|
64
|
+
# practice.
|
65
|
+
#
|
66
|
+
# @return [String] a uuid
|
67
|
+
def self.default_minter( *options )
|
68
|
+
prefix = options[0][:prefix] if ! options.empty? && options[0].is_a?(Hash) && options[0].key?(:prefix)
|
69
|
+
local_name = SecureRandom.uuid
|
70
|
+
local_name = prefix + local_name if prefix && prefix.is_a?(String)
|
71
|
+
local_name
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,336 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveTriples::LocalName::Minter do
|
4
|
+
|
5
|
+
describe "#generate_local_name" do
|
6
|
+
before (:all) do
|
7
|
+
@timeHashMinter_lambda = lambda do |digit_count|
|
8
|
+
rnd_id = 0
|
9
|
+
rnd_id = Time.now.hash until rnd_id != 0
|
10
|
+
rnd_id *= -1 if rnd_id < 0
|
11
|
+
rnd_id /= 10 until rnd_id < (10**digit_count)
|
12
|
+
"lambda_#{rnd_id}"
|
13
|
+
end
|
14
|
+
|
15
|
+
@timeHashMinter_proc = proc do |digit_count|
|
16
|
+
rnd_id = 0
|
17
|
+
rnd_id = Time.now.hash until rnd_id != 0
|
18
|
+
rnd_id *= -1 if rnd_id < 0
|
19
|
+
rnd_id /= 10 until rnd_id < (10**digit_count)
|
20
|
+
"proc_#{rnd_id}"
|
21
|
+
end
|
22
|
+
|
23
|
+
@timeHashMinter2_proc = proc do |digit_count,prefix|
|
24
|
+
rnd_id = 0
|
25
|
+
rnd_id = Time.now.hash until rnd_id != 0
|
26
|
+
rnd_id *= -1 if rnd_id < 0
|
27
|
+
rnd_id /= 10 until rnd_id < (10**digit_count)
|
28
|
+
"#{prefix}_#{rnd_id}"
|
29
|
+
end
|
30
|
+
|
31
|
+
# See also timeHashMinter_method defined in DummyResourceWithBaseURI class below.
|
32
|
+
end
|
33
|
+
|
34
|
+
subject {DummyResourceWithBaseURI.new('1')}
|
35
|
+
|
36
|
+
before do
|
37
|
+
class DummyResource < ActiveTriples::Resource
|
38
|
+
configure :type => RDF::URI('http://example.org/SomeClass')
|
39
|
+
property :title, :predicate => RDF::DC.title
|
40
|
+
end
|
41
|
+
class DummyResourceWithBaseURI < ActiveTriples::Resource
|
42
|
+
configure :base_uri => "http://example.org",
|
43
|
+
:type => RDF::URI("http://example.org/SomeClass"),
|
44
|
+
:repository => :default
|
45
|
+
|
46
|
+
def self.timeHashMinter_method( *args )
|
47
|
+
digit_count = args.size > 0 ? args[0] : 10
|
48
|
+
rnd_id = 0
|
49
|
+
rnd_id = Time.now.hash until rnd_id != 0
|
50
|
+
rnd_id *= -1 if rnd_id < 0
|
51
|
+
rnd_id /= 10 until rnd_id < (10**digit_count)
|
52
|
+
"method_#{rnd_id}"
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.timeHashMinter2_method( *args )
|
56
|
+
digit_count = args && args.size > 0 ? args[0] : 10
|
57
|
+
prefix = args && args.size > 1 ? args[1] : ""
|
58
|
+
rnd_id = 0
|
59
|
+
rnd_id = Time.now.hash until rnd_id != 0
|
60
|
+
rnd_id *= -1 if rnd_id < 0
|
61
|
+
rnd_id /= 10 until rnd_id < (10**digit_count)
|
62
|
+
"#{prefix}_#{rnd_id}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.timeHashMinter3_method( *args )
|
66
|
+
digit_count = (args && args.size > 0 && args[0]) ? args[0][:digit_count] : 10
|
67
|
+
prefix = args && args.size > 0 && args[0] ? args[0][:prefix] : ""
|
68
|
+
rnd_id = 0
|
69
|
+
rnd_id = Time.now.hash until rnd_id != 0
|
70
|
+
rnd_id *= -1 if rnd_id < 0
|
71
|
+
rnd_id /= 10 until rnd_id < (10**digit_count)
|
72
|
+
localname = "#{prefix}_#{rnd_id}"
|
73
|
+
localname
|
74
|
+
end
|
75
|
+
end
|
76
|
+
ActiveTriples::Repositories.add_repository :default, RDF::Repository.new
|
77
|
+
end
|
78
|
+
after do
|
79
|
+
Object.send(:remove_const, "DummyResourceWithBaseURI") if Object
|
80
|
+
Object.send(:remove_const, "DummyResource") if Object
|
81
|
+
ActiveTriples::Repositories.clear_repositories!
|
82
|
+
end
|
83
|
+
|
84
|
+
context "when class doesn't have base_uri defined" do
|
85
|
+
it "should raise an Exception" do
|
86
|
+
expect{ ActiveTriples::LocalName::Minter.generate_local_name(DummyResource) }.to raise_error(RuntimeError, 'Requires base_uri to be defined in for_class.')
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "when all IDs available" do
|
91
|
+
context "and no minter function is passed in" do
|
92
|
+
it "should generate an ID using default minter function" do
|
93
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI)
|
94
|
+
expect(id).to be_kind_of String
|
95
|
+
expect(id.length).to be 36
|
96
|
+
id.should match /[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}/
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "and minter function is passed as ad-hoc proc" do
|
101
|
+
it "should generate an ID with passed in minter function block" do
|
102
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI,10,1) do |digit_count|
|
103
|
+
rnd_id = 0
|
104
|
+
rnd_id = Time.now.hash until rnd_id != 0
|
105
|
+
rnd_id *= -1 if rnd_id < 0
|
106
|
+
rnd_id /= 10 until rnd_id < (10**digit_count)
|
107
|
+
rnd_id
|
108
|
+
end
|
109
|
+
expect(id).to be_between(1,9)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context "and minter function is pre-defined proc that takes 1 parameter" do
|
114
|
+
context "and minter function is passed as proc in block with hardcoded parameter" do
|
115
|
+
it "should generate an ID with passed in proc in block" do
|
116
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI) {
|
117
|
+
@timeHashMinter_proc.call(1) }
|
118
|
+
expect(id[0..4]).to eq "proc_"
|
119
|
+
expect(id[5..id.length].to_i).to be_between(1,9)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context "and minter function is passed as proc in block with parameter passed in minterargs" do
|
124
|
+
it "should generate an ID with passed in proc in block" do
|
125
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI,10,1) {
|
126
|
+
|digit_count| @timeHashMinter_proc.call(digit_count) }
|
127
|
+
expect(id[0..4]).to eq "proc_"
|
128
|
+
expect(id[5..id.length].to_i).to be_between(1,9)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context "and minter function is passed address to proc with parameter passed in minterargs" do
|
133
|
+
it "should generate an ID with passed in proc" do
|
134
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI,10,1,
|
135
|
+
&@timeHashMinter_proc)
|
136
|
+
expect(id[0..4]).to eq "proc_"
|
137
|
+
expect(id[5..id.length].to_i).to be_between(1,9)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context "and minter function is pre-defined proc that takes 2 parameter" do
|
143
|
+
context "and minter function is passed as proc in block with hardcoded parameter" do
|
144
|
+
it "should generate an ID with passed in proc in block" do
|
145
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI) {
|
146
|
+
@timeHashMinter2_proc.call(1,'foo') }
|
147
|
+
expect(id[0..3]).to eq "foo_"
|
148
|
+
expect(id[4..id.length].to_i).to be_between(1,9)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context "and minter function is passed as proc in block with parameter passed in minterargs" do
|
153
|
+
it "should generate an ID with passed in proc in block" do
|
154
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI,10,1,'foo') {
|
155
|
+
|digit_count,prefix| @timeHashMinter2_proc.call(digit_count,prefix) }
|
156
|
+
expect(id[0..3]).to eq "foo_"
|
157
|
+
expect(id[4..id.length].to_i).to be_between(1,9)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
context "and minter function is passed address to proc with parameters passed in minterargs" do
|
162
|
+
it "should generate an ID with passed in proc" do
|
163
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI,10,1,"foo",
|
164
|
+
&@timeHashMinter2_proc)
|
165
|
+
expect(id[0..3]).to eq "foo_"
|
166
|
+
expect(id[4..id.length].to_i).to be_between(1,9)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
context "and minter function is method that takes 1 parameter" do
|
173
|
+
context "and parameter is hardcoded in block" do
|
174
|
+
it "should generate an ID with passed in method" do
|
175
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI) {
|
176
|
+
DummyResourceWithBaseURI.timeHashMinter_method (1) }
|
177
|
+
expect(id[0..6]).to eq "method_"
|
178
|
+
expect(id[7..id.length].to_i).to be_between(1,9)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
context "and parameter is passed as minterargs" do
|
183
|
+
it "should generate an ID with passed in method" do
|
184
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI,10,1) {
|
185
|
+
|digit_count| DummyResourceWithBaseURI.timeHashMinter_method(digit_count) }
|
186
|
+
expect(id[0..6]).to eq "method_"
|
187
|
+
expect(id[7..id.length].to_i).to be_between(1,9)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
|
193
|
+
context "and minter function is method that takes 2 parameters" do
|
194
|
+
context "and parameters are hardcoded in block" do
|
195
|
+
it "should generate an ID with passed in method" do
|
196
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI) {
|
197
|
+
DummyResourceWithBaseURI.timeHashMinter2_method(1,"foo") }
|
198
|
+
expect(id[0..3]).to eq "foo_"
|
199
|
+
expect(id[4..id.length].to_i).to be_between(1,9)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
context "and parameters are passed as minterargs" do
|
204
|
+
it "should generate an ID with passed in method" do
|
205
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI,10,1,"foo") {
|
206
|
+
|digit_count,prefix| DummyResourceWithBaseURI.timeHashMinter2_method(digit_count,prefix) }
|
207
|
+
expect(id[0..3]).to eq "foo_"
|
208
|
+
expect(id[4..id.length].to_i).to be_between(1,9)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
|
214
|
+
context "and minter function is method that takes 1 hash parameter" do
|
215
|
+
context "and parameter is hardcoded in block" do
|
216
|
+
it "should generate an ID with passed in method" do
|
217
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI) {
|
218
|
+
DummyResourceWithBaseURI.timeHashMinter3_method({:digit_count=>1,:prefix=>"foo"}) }
|
219
|
+
expect(id[0..3]).to eq "foo_"
|
220
|
+
expect(id[4..id.length].to_i).to be_between(1,9)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
context "and parameter is passed as minterargs" do
|
226
|
+
it "should generate an ID with passed in method" do
|
227
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI,10,{:digit_count=>1,:prefix=>"foo"}) {
|
228
|
+
|hash_args| DummyResourceWithBaseURI.timeHashMinter3_method(hash_args) }
|
229
|
+
expect(id[0..3]).to eq "foo_"
|
230
|
+
expect(id[4..id.length].to_i).to be_between(1,9)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
context "and no parameters are passed in" do
|
235
|
+
it "should generate an ID with passed in method using defaults when no params passed" do
|
236
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI,10) {
|
237
|
+
|hash_args| DummyResourceWithBaseURI.timeHashMinter3_method(hash_args) }
|
238
|
+
expect(id[0]).to eq "_"
|
239
|
+
expect(id[1..id.length].to_i).to be_between(1000000000,9999999999)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
context "but block defines method with no parameters" do
|
244
|
+
it "should generate an ID with passed in method using defaults when no params passed" do
|
245
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI,10) {
|
246
|
+
DummyResourceWithBaseURI.timeHashMinter3_method }
|
247
|
+
expect(id[0]).to eq "_"
|
248
|
+
expect(id[1..id.length].to_i).to be_between(1000000000,9999999999)
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
context "when some IDs available" do
|
253
|
+
before do
|
254
|
+
DummyResourceWithBaseURI.new('proc_3').persist!
|
255
|
+
DummyResourceWithBaseURI.new('proc_4').persist!
|
256
|
+
DummyResourceWithBaseURI.new('proc_8').persist!
|
257
|
+
end
|
258
|
+
after do
|
259
|
+
DummyResourceWithBaseURI.new('proc_3').destroy!
|
260
|
+
DummyResourceWithBaseURI.new('proc_4').destroy!
|
261
|
+
DummyResourceWithBaseURI.new('proc_8').destroy!
|
262
|
+
end
|
263
|
+
|
264
|
+
it "should generate an ID not already in use" do
|
265
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI) { @timeHashMinter_proc.call(1) }
|
266
|
+
expect(id[0..4]).to eq "proc_"
|
267
|
+
expect(id[5..id.length].to_i).to be_between(1,9)
|
268
|
+
expect(id).not_to eq 'proc_3'
|
269
|
+
expect(id).not_to eq 'proc_4'
|
270
|
+
expect(id).not_to eq 'proc_8'
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
context "when no IDs available" do
|
275
|
+
before do
|
276
|
+
1.upto(9) { |id| DummyResourceWithBaseURI.new("proc_#{id}").persist! }
|
277
|
+
end
|
278
|
+
after do
|
279
|
+
1.upto(9) { |id| DummyResourceWithBaseURI.new("proc_#{id}").destroy! }
|
280
|
+
end
|
281
|
+
|
282
|
+
it "should raise an Exception" do
|
283
|
+
expect{ ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI) { @timeHashMinter_proc.call(1) } }.
|
284
|
+
to raise_error(RuntimeError, "Available ID not found. Exceeded maximum tries.")
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
context "when passing prefix to default minter function" do
|
289
|
+
context "and prefix is string" do
|
290
|
+
it "should generate a prefixed ID" do
|
291
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI,10,{:prefix=>"s"})
|
292
|
+
expect(id).to be_kind_of String
|
293
|
+
expect(id.length).to be 37
|
294
|
+
id.should match /s[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}/
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
context "and prefix is integer" do
|
299
|
+
it "should generate ID ignoring prefix" do
|
300
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI,10,1)
|
301
|
+
expect(id).to be_kind_of String
|
302
|
+
expect(id.length).to be 36
|
303
|
+
id.should match /[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}/
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
context "and prefix is float" do
|
308
|
+
it "should generate ID ignoring prefix" do
|
309
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI,10,{:prefix=>1.5})
|
310
|
+
expect(id).to be_kind_of String
|
311
|
+
expect(id.length).to be 36
|
312
|
+
id.should match /[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}/
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
context "and prefix is hash" do
|
317
|
+
it "should generate ID ignoring prefix" do
|
318
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI,10,{:prefix=>{"a"=>"b"}})
|
319
|
+
expect(id).to be_kind_of String
|
320
|
+
expect(id.length).to be 36
|
321
|
+
id.should match /[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}/
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
context "and prefix is array" do
|
326
|
+
it "should generate ID ignoring prefix" do
|
327
|
+
id = ActiveTriples::LocalName::Minter.generate_local_name(DummyResourceWithBaseURI,10,{:prefix=>[1,2,3]})
|
328
|
+
expect(id).to be_kind_of String
|
329
|
+
expect(id.length).to be 36
|
330
|
+
id.should match /[a-zA-Z0-9]{8}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{4}-[a-zA-Z0-9]{12}/
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
end
|
336
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
Bundler.setup
|
3
|
+
|
4
|
+
require 'active_triples/local_name'
|
5
|
+
require 'active_triples'
|
6
|
+
|
7
|
+
|
8
|
+
Dir['./spec/support/**/*.rb'].each { |f| require f }
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.color = true
|
12
|
+
config.tty = true
|
13
|
+
|
14
|
+
# Uncomment the following line to get errors and backtrace for deprecation warnings
|
15
|
+
# config.raise_errors_for_deprecations!
|
16
|
+
|
17
|
+
# Use the specified formatter
|
18
|
+
config.formatter = :progress
|
19
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
shared_examples_for "an ActiveModel" do
|
2
|
+
subject { described_class.new }
|
3
|
+
|
4
|
+
describe '#to_key' do
|
5
|
+
it 'should respond' do
|
6
|
+
expect(subject).to respond_to :to_key
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should return nil when #persisted? is false ' do
|
10
|
+
def subject.persisted?() false end
|
11
|
+
expect(subject.to_key).to eq nil
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#to_param' do
|
16
|
+
it 'should respond' do
|
17
|
+
expect(subject).to respond_to :to_param
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should return nil when #persisted? is false ' do
|
21
|
+
def subject.persisted?() false end
|
22
|
+
expect(subject.to_param).to eq nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#model_name' do
|
27
|
+
let(:model_name) { subject.class.model_name }
|
28
|
+
|
29
|
+
it 'should have a model name' do
|
30
|
+
expect(model_name).to respond_to :to_str
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should have a human name' do
|
34
|
+
expect(model_name.human).to respond_to :to_str
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should have a singular name' do
|
38
|
+
expect(model_name.singular).to respond_to :to_str
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'should have a plural name' do
|
42
|
+
expect(model_name.plural).to respond_to :to_str
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#to_partial_path' do
|
47
|
+
it 'should return a string' do
|
48
|
+
expect(subject.to_partial_path).to be_a String
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#persisted?' do
|
53
|
+
it 'should return a boolean' do
|
54
|
+
expect(match_boolean(subject.persisted?)).to be true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe '#valid?' do
|
59
|
+
it 'should return a boolean' do
|
60
|
+
expect(match_boolean(subject.valid?)).to be true
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#new_record' do
|
65
|
+
it 'should return a boolean' do
|
66
|
+
expect(match_boolean(subject.new_record?)).to be true
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '#destroyed?' do
|
71
|
+
it 'should return a boolean' do
|
72
|
+
expect(match_boolean(subject.destroyed?)).to be true
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def match_boolean(result)
|
79
|
+
result == true || result == false
|
80
|
+
end
|
81
|
+
end
|
metadata
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: active_triples-local_name
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- E. Lynette Rayle
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-11-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: deprecation
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ! '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.0.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rdoc
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ! '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
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: guard-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: active_triples-local_name provides a standard interface and default implementation
|
84
|
+
for a minter of the local name portion of a URI.
|
85
|
+
email: elr37@cornell.edu
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files:
|
89
|
+
- LICENSE
|
90
|
+
- README.md
|
91
|
+
files:
|
92
|
+
- .gitignore
|
93
|
+
- .travis.yml
|
94
|
+
- AUTHORS
|
95
|
+
- Gemfile
|
96
|
+
- Guardfile
|
97
|
+
- LICENSE
|
98
|
+
- README.md
|
99
|
+
- active_triples-local_name.gemspec
|
100
|
+
- lib/active_triples/local_name.rb
|
101
|
+
- lib/active_triples/local_name/minter.rb
|
102
|
+
- lib/active_triples/local_name/version.rb
|
103
|
+
- spec/active_triples/local_name/minter_spec.rb
|
104
|
+
- spec/spec_helper.rb
|
105
|
+
- spec/support/active_model_lint.rb
|
106
|
+
homepage: https://github.com/no-reply/active_triples-local_name
|
107
|
+
licenses:
|
108
|
+
- APACHE2
|
109
|
+
metadata: {}
|
110
|
+
post_install_message:
|
111
|
+
rdoc_options: []
|
112
|
+
require_paths:
|
113
|
+
- lib
|
114
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ! '>='
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: 1.9.3
|
119
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ! '>='
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
requirements: []
|
125
|
+
rubyforge_project:
|
126
|
+
rubygems_version: 2.2.2
|
127
|
+
signing_key:
|
128
|
+
specification_version: 4
|
129
|
+
summary: Local name minter for ActiveTriples based resources.
|
130
|
+
test_files: []
|