symboltable 0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README ADDED
@@ -0,0 +1,81 @@
1
+ +++ SymbolTable +++
2
+
3
+ SymbolTable is a handy little Ruby class that was conceived from the union of
4
+ Hash and Symbol. SymbolTable directly extends Hash, but it stores all keys
5
+ internally as symbols. Any key that cannot be converted to a Symbol is not
6
+ valid.
7
+
8
+ While this may seem restrictive, it does have the nice side effect of making
9
+ all keys slightly more memorable and usable. For example, values may be set
10
+ and retrieved using any key that resolves to the same symbol.
11
+
12
+ h = Hash.new
13
+ h[:a] = 1
14
+ h[:a] # => 1
15
+ h['a'] # => nil
16
+ h.a # => NoMethodError: undefined method `a' for {}:Hash
17
+
18
+ require 'symboltable'
19
+
20
+ t = SymbolTable.new
21
+ t[:a] = 1
22
+ t[:a] # => 1
23
+ t['a'] # => 1
24
+ t.a # => 1
25
+ t.b = 2 # => 2
26
+
27
+ Also, because SymbolTable subclasses Hash, you get all the nice methods of Hash
28
+ for free.
29
+
30
+ t.keys # => [:a, :b]
31
+ t.values # => [1, 2]
32
+
33
+ t.merge!('c' => 3, :d => 4)
34
+ t.keys # => [:a, :b, :c, :d]
35
+ t.values # => [1, 2, 3, 4]
36
+
37
+ t.each do |k, v|
38
+ puts "#{k} = #{v}"
39
+ end
40
+
41
+ You get the idea. This kind of data structure is mainly useful for large
42
+ configuration objects and the like, where you want to store a bunch of data and
43
+ you don't want to have to remember later how you stored it.
44
+
45
+ == Why?
46
+
47
+ Mainly just for fun, and because I sometimes miss the automatic and ubiquitous
48
+ type conversion you get in PHP.
49
+
50
+ == Installation
51
+
52
+ Using RubyGems:
53
+
54
+ $ sudo gem install symboltable
55
+
56
+ From a local copy:
57
+
58
+ $ git clone git://github.com/mjijackson/symboltable.git
59
+ $ rake package && sudo rake install
60
+
61
+ == License
62
+
63
+ Copyright 2010 Michael J. I. Jackson
64
+
65
+ Permission is hereby granted, free of charge, to any person obtaining a copy
66
+ of this software and associated documentation files (the "Software"), to deal
67
+ in the Software without restriction, including without limitation the rights
68
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
69
+ copies of the Software, and to permit persons to whom the Software is
70
+ furnished to do so, subject to the following conditions:
71
+
72
+ The above copyright notice and this permission notice shall be included in
73
+ all copies or substantial portions of the Software.
74
+
75
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
76
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
77
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
78
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
79
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
80
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
81
+ THE SOFTWARE.
@@ -0,0 +1,67 @@
1
+ require 'rake/clean'
2
+ require 'rake/testtask'
3
+
4
+ task :default => :test
5
+
6
+ CLEAN.include %w< doc >
7
+ CLOBBER.include %w< dist >
8
+
9
+ # TESTS #######################################################################
10
+
11
+ Rake::TestTask.new(:test) do |t|
12
+ t.test_files = FileList['test/symboltable.rb']
13
+ end
14
+
15
+ # DOCS ########################################################################
16
+
17
+ desc "Generate API documentation (in doc)"
18
+ task :doc => FileList['lib/**/*.rb'] do |t|
19
+ rm_rf 'doc'
20
+ sh((<<-SH).gsub(/[\s\n]+/, ' ').strip)
21
+ hanna
22
+ --op doc
23
+ --promiscuous
24
+ --charset utf8
25
+ --fmt html
26
+ --inline-source
27
+ --line-numbers
28
+ --accessor option_accessor=RW
29
+ --main SymbolTable
30
+ --title 'SymbolTable API Documentation'
31
+ #{t.prerequisites.join(' ')}
32
+ SH
33
+ end
34
+
35
+ # PACKAGING & INSTALLATION ####################################################
36
+
37
+ if defined?(Gem)
38
+ $spec = eval("#{File.read('symboltable.gemspec')}")
39
+
40
+ directory 'dist'
41
+
42
+ def package(ext='')
43
+ "dist/#{$spec.name}-#{$spec.version}" + ext
44
+ end
45
+
46
+ file package('.gem') => %w< dist > + $spec.files do |f|
47
+ sh "gem build symboltable.gemspec"
48
+ mv File.basename(f.name), f.name
49
+ end
50
+
51
+ file package('.tar.gz') => %w< dist > + $spec.files do |f|
52
+ sh "git archive --format=tar HEAD | gzip > #{f.name}"
53
+ end
54
+
55
+ desc "Build packages"
56
+ task :package => %w< .gem .tar.gz >.map {|e| package(e) }
57
+
58
+ desc "Build and install as local gem"
59
+ task :install => package('.gem') do |t|
60
+ sh "gem install #{package('.gem')}"
61
+ end
62
+
63
+ desc "Upload gem to rubygems.org"
64
+ task :release => package('.gem') do |t|
65
+ sh "gem push #{package('.gem')}"
66
+ end
67
+ end
@@ -0,0 +1,54 @@
1
+ # A Hash that forces all keys to be symbols.
2
+ #
3
+ # See http://github.com/mjijackson/symboltable for more information.
4
+ class SymbolTable < Hash
5
+
6
+ def initialize(hash=nil)
7
+ super()
8
+ merge!(hash) unless hash.nil?
9
+ end
10
+
11
+ # Returns +true+ if the given key may be used in this table.
12
+ def valid_key?(key)
13
+ key.respond_to?(:to_sym)
14
+ end
15
+
16
+ def key?(key)
17
+ super(key) || (valid_key?(key) && super(key.to_sym))
18
+ end
19
+
20
+ def [](key)
21
+ super(key.to_sym) if valid_key?(key)
22
+ end
23
+
24
+ def store(key, val)
25
+ if valid_key?(key)
26
+ val = SymbolTable.new(val) if Hash === val && !(SymbolTable === val)
27
+ super(key.to_sym, val)
28
+ end
29
+ end
30
+ alias :[]= :store
31
+
32
+ def merge!(other_hash)
33
+ raise ArgumentError unless Hash === other_hash
34
+ other_hash.each do |k, v|
35
+ if block_given? && key?(k)
36
+ self[k] = yield(k, self[k], v)
37
+ else
38
+ self[k] = v
39
+ end
40
+ end
41
+ end
42
+ alias :update :merge!
43
+
44
+ def method_missing(sym, *args)
45
+ if sym.to_s =~ /(.+)=$/
46
+ self[$1] = args[0]
47
+ elsif args.empty?
48
+ self[sym]
49
+ else
50
+ super(sym, *args)
51
+ end
52
+ end
53
+
54
+ end
@@ -0,0 +1,27 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'symboltable'
3
+ s.version = '0.1'
4
+ s.date = '2010-04-08'
5
+
6
+ s.summary = 'A Symbols-only Hash for Ruby'
7
+ s.description = 'A Symbols-only Hash for Ruby'
8
+
9
+ s.author = 'Michael J. I. Jackson'
10
+ s.email = 'mjijackson@gmail.com'
11
+
12
+ s.require_paths = %w< lib >
13
+
14
+ s.files = Dir['lib/**/*.rb'] +
15
+ Dir['test/*.rb'] +
16
+ %w< symboltable.gemspec Rakefile README >
17
+
18
+ s.test_files = s.files.select {|path| path =~ /^test\/.*.rb/ }
19
+
20
+ s.add_development_dependency('rake')
21
+
22
+ s.has_rdoc = true
23
+ s.rdoc_options = %w< --line-numbers --inline-source --title SymbolTable --main SymbolTable >
24
+ s.extra_rdoc_files = %w< README >
25
+
26
+ s.homepage = 'http://github.com/mjijackson/symboltable'
27
+ end
@@ -0,0 +1,126 @@
1
+ libdir = File.dirname(File.dirname(__FILE__)) + '/lib'
2
+ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
3
+
4
+ require 'test/unit'
5
+ require 'symboltable'
6
+
7
+ class SymbolTableTest < Test::Unit::TestCase
8
+
9
+ def test_empty
10
+ t = SymbolTable.new
11
+
12
+ assert_equal(nil, t[:a])
13
+ assert_equal(nil, t['a'])
14
+ end
15
+
16
+ def test_bracket
17
+ t = SymbolTable.new
18
+
19
+ t[:a] = 1
20
+ assert_equal(1, t[:a])
21
+ assert_equal(1, t['a'])
22
+
23
+ t['b'] = 1
24
+ assert_equal(1, t[:b])
25
+ assert_equal(1, t['b'])
26
+
27
+ assert_equal([:a, :b], t.keys)
28
+ assert_equal([1, 1], t.values)
29
+ end
30
+
31
+ def test_store
32
+ t = SymbolTable.new
33
+
34
+ t.store(:a, 1)
35
+ assert_equal(1, t[:a])
36
+ assert_equal(1, t['a'])
37
+
38
+ t.store('b', 1)
39
+ assert_equal(1, t[:b])
40
+ assert_equal(1, t['b'])
41
+
42
+ assert_equal([:a, :b], t.keys)
43
+ assert_equal([1, 1], t.values)
44
+ end
45
+
46
+ def test_update
47
+ t = SymbolTable.new
48
+
49
+ t.update(:a => 1)
50
+ assert_equal(1, t[:a])
51
+ assert_equal(1, t['a'])
52
+
53
+ t.update('b' => 1)
54
+ assert_equal(1, t[:b])
55
+ assert_equal(1, t['b'])
56
+
57
+ assert_equal([:a, :b], t.keys)
58
+ assert_equal([1, 1], t.values)
59
+ end
60
+
61
+ def test_merge!
62
+ t = SymbolTable.new
63
+
64
+ t.merge!(:a => 1)
65
+ assert_equal(1, t[:a])
66
+ assert_equal(1, t['a'])
67
+
68
+ t.merge!('b' => 1)
69
+ assert_equal(1, t[:b])
70
+ assert_equal(1, t['b'])
71
+
72
+ assert_equal([:a, :b], t.keys)
73
+ assert_equal([1, 1], t.values)
74
+ end
75
+
76
+ def test_method_missing
77
+ t = SymbolTable.new
78
+
79
+ t.a = 1
80
+ assert_equal(1, t[:a])
81
+ assert_equal(1, t['a'])
82
+ assert_equal(1, t.a)
83
+
84
+ assert_equal([:a], t.keys)
85
+ assert_equal([1], t.values)
86
+ end
87
+
88
+ def test_nested_tables
89
+ t = SymbolTable.new
90
+
91
+ t[:a] = {:a => 1}
92
+ assert_equal(1, t.a[:a])
93
+ assert_equal(1, t.a['a'])
94
+
95
+ t[:a] = {'a' => 1}
96
+ assert_equal(1, t.a[:a])
97
+ assert_equal(1, t.a['a'])
98
+ end
99
+
100
+ def test_key?
101
+ t = SymbolTable.new
102
+
103
+ t[:a] = 1
104
+ assert(t.key?(:a))
105
+ assert(t.key?('a'))
106
+ end
107
+
108
+ def test_new
109
+ t = SymbolTable[:a, 1]
110
+
111
+ assert_equal(1, t[:a])
112
+ assert_equal(1, t['a'])
113
+ end
114
+
115
+ def test_merge
116
+ t = SymbolTable.new
117
+ t[:a] = 1
118
+ b = t.merge(:a => 2)
119
+
120
+ assert_equal([:a], t.keys)
121
+ assert_equal([1], t.values)
122
+ assert_equal([:a], b.keys)
123
+ assert_equal([2], b.values)
124
+ end
125
+
126
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: symboltable
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ version: "0.1"
9
+ platform: ruby
10
+ authors:
11
+ - Michael J. I. Jackson
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+
16
+ date: 2010-04-08 00:00:00 -06:00
17
+ default_executable:
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: rake
21
+ prerelease: false
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ segments:
27
+ - 0
28
+ version: "0"
29
+ type: :development
30
+ version_requirements: *id001
31
+ description: A Symbols-only Hash for Ruby
32
+ email: mjijackson@gmail.com
33
+ executables: []
34
+
35
+ extensions: []
36
+
37
+ extra_rdoc_files:
38
+ - README
39
+ files:
40
+ - lib/symboltable.rb
41
+ - test/symboltable.rb
42
+ - symboltable.gemspec
43
+ - Rakefile
44
+ - README
45
+ has_rdoc: true
46
+ homepage: http://github.com/mjijackson/symboltable
47
+ licenses: []
48
+
49
+ post_install_message:
50
+ rdoc_options:
51
+ - --line-numbers
52
+ - --inline-source
53
+ - --title
54
+ - SymbolTable
55
+ - --main
56
+ - SymbolTable
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ requirements: []
74
+
75
+ rubyforge_project:
76
+ rubygems_version: 1.3.6
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: A Symbols-only Hash for Ruby
80
+ test_files:
81
+ - test/symboltable.rb