abbey 0.1.0.beta3 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/abbey.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "abbey"
8
- s.version = "0.1.0.beta3"
8
+ s.version = "0.1.1"
9
9
 
10
- s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Pavel Kalvoda"]
12
- s.date = "2011-11-13"
12
+ s.date = "2011-11-17"
13
13
  s.description = "Primitive JSON data store. Key-value structure with namespaces."
14
14
  s.email = "me@pavelkalvoda.com"
15
15
  s.extra_rdoc_files = [
@@ -4,6 +4,8 @@ module Abbey
4
4
  # JSON serialization under the hood.
5
5
  class EntityStorage
6
6
 
7
+ ForbiddenChars = '/'
8
+
7
9
  # @return [Settings]
8
10
  attr_accessor :settings
9
11
 
@@ -29,6 +31,7 @@ module Abbey
29
31
  # Set up the directory structure
30
32
  # @return void
31
33
  def set_up!
34
+ return if set_up?
32
35
  settings.namespaces.each do |ns|
33
36
  path = make_path(ns)
34
37
  if !Dir.exists?(path) then
@@ -45,7 +48,7 @@ module Abbey
45
48
  # @return void
46
49
  def save(namespace, key, data)
47
50
  path = make_path(namespace, key)
48
- raise ItemAlreadyPresentError.new if File.exist?(path)
51
+ raise ItemAlreadyPresentError, "Item '#{make_key(namespace,key)}' already present" if File.exist?(path)
49
52
  f = File.new(path, File::CREAT | File::RDWR)
50
53
  size = f.write(MultiJson.encode(data))
51
54
  f.close
@@ -58,7 +61,7 @@ module Abbey
58
61
  # @return [Object]
59
62
  def get(namespace, key)
60
63
  path = make_path(namespace, key)
61
- raise ItemNotFoundError.new unless exists?(namespace, key)
64
+ raise ItemNotFoundError, "Item '#{make_key(namespace,key)}' not found" unless exists?(namespace, key)
62
65
  settings.logger.info("Read #{make_key(namespace, key)}")
63
66
  MultiJson.decode(File.read(path))
64
67
  end
@@ -89,7 +92,7 @@ module Abbey
89
92
  # @return void
90
93
  def delete(namespace, key)
91
94
  path = make_path(namespace, key)
92
- raise ItemNotFoundError.new unless exists?(namespace, key)
95
+ raise ItemNotFoundError, "Item '#{make_key(namespace,key)}' already exists" unless exists?(namespace, key)
93
96
  File.delete(path)
94
97
  settings.logger.info("Deleted #{make_key(namespace,key)}")
95
98
  end
@@ -118,13 +121,35 @@ module Abbey
118
121
  list(namespace).each {|item| delete(namespace, item)}
119
122
  end
120
123
 
124
+ # Check whether the key is formally valid
125
+ # @param key [String, Fixnum, Symbol or any other object whose #to_s method returns string]
126
+ # @return [Boolean]
127
+ def identifier_valid?(key)
128
+ key = key.to_s
129
+ ForbiddenChars.each_char do |char|
130
+ return false if key.include?(char)
131
+ end
132
+ end
133
+
121
134
  private
122
135
 
136
+ def validate_namespace(namespace)
137
+ raise InvalidNameError, "The namespace contains illegal characters" unless identifier_valid?(namespace)
138
+ end
139
+
140
+ def validate_key(key)
141
+ raise InvalidNameError, "The key contains illegal characters" unless identifier_valid?(key)
142
+ end
143
+
144
+ # Compose path to a namespace or an item
123
145
  def make_path(namespace, key = nil)
146
+ validate_namespace(namespace)
147
+ validate_key(key) if key
124
148
  dir = File.join(settings.path, namespace.to_s)
125
149
  key ? File.join(dir, key.to_s) : dir
126
150
  end
127
151
 
152
+ # Unify IDs format
128
153
  def make_key(namespace, key)
129
154
  namespace.to_s + ':' + key.to_s
130
155
  end
data/lib/errors.rb CHANGED
@@ -1,9 +1,17 @@
1
1
  module Abbey
2
2
 
3
- # Thrown when trying to overwrite an item
3
+ # Raised when trying to overwrite an item
4
4
  class ItemAlreadyPresentError < RuntimeError
5
5
  end
6
6
 
7
7
  class ItemNotFoundError < RuntimeError
8
8
  end
9
+
10
+ # Raised when the data can't be serialized
11
+ class NotSerializableError < ArgumentError
12
+ end
13
+
14
+ # Raised when a key or a namespace containing a FS separator is passed
15
+ class InvalidNameError < ArgumentError
16
+ end
9
17
  end
data/lib/version.rb CHANGED
@@ -2,8 +2,8 @@ module Abbey
2
2
  module Version
3
3
  MAJOR = 0
4
4
  MINOR = 1
5
- PATCH = 0
6
- BUILD = 'beta3'
5
+ PATCH = 1
6
+ BUILD = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
9
9
  end
@@ -8,7 +8,7 @@ class AbbeyTest < Test::Unit::TestCase
8
8
  end
9
9
 
10
10
  def teardown
11
- FileUtils.rm_r('/tmp/abbey')
11
+ FileUtils.rm_r('/tmp/abbey') if Dir.exist?('/tmp/abbey')
12
12
  end
13
13
 
14
14
  def test_it_will_check_for_readiness
@@ -87,4 +87,24 @@ class AbbeyTest < Test::Unit::TestCase
87
87
  assert_equal(Set.new, @abbey.list(:ns1))
88
88
  assert_equal Set.new([:key]), @abbey.list(:ns2)
89
89
  end
90
+
91
+ def test_special_chars_in_keys
92
+ @abbey.set_up!
93
+ @abbey.save(:ns1, "with:colon", {"a" => 1})
94
+ assert_equal ({"a" => 1}), @abbey.get(:ns1, "with:colon")
95
+ assert_raise Abbey::InvalidNameError do
96
+ @abbey.save(:ns1, "with/slash", {"a" => 5})
97
+ end
98
+ end
99
+
100
+ def test_special_chars_in_namespaces
101
+ abbey = Abbey::EntityStorage.new(Abbey::Settings.new('/tmp/abbey', [:ns1, :"with:colon"], Logger.new(STDOUT)))
102
+ abbey.set_up!
103
+ abbey.save("with:colon", :key, ["datadata"])
104
+ assert_equal ["datadata"], abbey.get("with:colon", :key)
105
+ assert_raise Abbey::InvalidNameError do
106
+ Abbey::EntityStorage.new(Abbey::Settings.new('/tmp/abbey', [:ns1, :"with/slash"], Logger.new(STDOUT))).set_up!
107
+ end
108
+ end
109
+
90
110
  end
metadata CHANGED
@@ -1,19 +1,19 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: abbey
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.beta3
5
- prerelease: 6
4
+ version: 0.1.1
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Pavel Kalvoda
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-13 00:00:00.000000000 Z
12
+ date: 2011-11-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: multi_json
16
- requirement: &13335600 !ruby/object:Gem::Requirement
16
+ requirement: &6562960 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *13335600
24
+ version_requirements: *6562960
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rake
27
- requirement: &13334660 !ruby/object:Gem::Requirement
27
+ requirement: &6560780 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *13334660
35
+ version_requirements: *6560780
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: bundler
38
- requirement: &13333200 !ruby/object:Gem::Requirement
38
+ requirement: &6559960 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *13333200
46
+ version_requirements: *6559960
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: jeweler
49
- requirement: &13332360 !ruby/object:Gem::Requirement
49
+ requirement: &6610240 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 1.6.4
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *13332360
57
+ version_requirements: *6610240
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rcov
60
- requirement: &13331340 !ruby/object:Gem::Requirement
60
+ requirement: &6608820 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *13331340
68
+ version_requirements: *6608820
69
69
  description: Primitive JSON data store. Key-value structure with namespaces.
70
70
  email: me@pavelkalvoda.com
71
71
  executables: []
@@ -104,13 +104,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
104
104
  version: '0'
105
105
  segments:
106
106
  - 0
107
- hash: -2996718355299514668
107
+ hash: -1187583575974686402
108
108
  required_rubygems_version: !ruby/object:Gem::Requirement
109
109
  none: false
110
110
  requirements:
111
- - - ! '>'
111
+ - - ! '>='
112
112
  - !ruby/object:Gem::Version
113
- version: 1.3.1
113
+ version: '0'
114
114
  requirements: []
115
115
  rubyforge_project:
116
116
  rubygems_version: 1.8.10