turntable 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +50 -0
- data/TODO +18 -0
- data/lib/turntable.rb +14 -0
- data/lib/turntable/columndefinition.rb +39 -0
- data/lib/turntable/row.rb +42 -0
- data/lib/turntable/table.rb +64 -0
- data/lib/turntable/tableheader.rb +49 -0
- metadata +78 -0
data/README
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#
|
2
|
+
# Turntable
|
3
|
+
# The hip-hop Ruby database
|
4
|
+
#
|
5
|
+
# Christian Koch <cfkoch@sdf.lonestar.org>
|
6
|
+
#
|
7
|
+
|
8
|
+
Turntable is a pure Ruby implementation of a relational database, similar in
|
9
|
+
spirit to SQLite. Unlike Sequel or any other object-relational mapper, Turntable
|
10
|
+
is built with Ruby from the ground up, and implements Rubyisms whenever
|
11
|
+
possible. It never goes anywhere near SQL.
|
12
|
+
|
13
|
+
Turntable databases include the Enumerable mixin, so all the methods available
|
14
|
+
there are also available for you:
|
15
|
+
|
16
|
+
turntable.
|
17
|
+
select { |film| film[:title] =~ /\AG/ }.
|
18
|
+
sort_by { |film| film[:year] }.
|
19
|
+
reverse.
|
20
|
+
detect { |film| film[:director] == "Francis Ford Coppola" }
|
21
|
+
|
22
|
+
#####
|
23
|
+
|
24
|
+
Turntable is released under a simplified BSD-style license.
|
25
|
+
|
26
|
+
Copyright (c) 2011 Christian Koch
|
27
|
+
All rights reserved.
|
28
|
+
|
29
|
+
Redistribution and use in source and binary forms, with or without
|
30
|
+
modification, are permitted provided that the following conditions
|
31
|
+
are met:
|
32
|
+
|
33
|
+
1. Redistributions of source code must retain the above copyright
|
34
|
+
notice, this list of conditions and the following disclaimer.
|
35
|
+
|
36
|
+
2. Redistributions in binary form must reproduce the above copyright
|
37
|
+
notice, this list of conditions and the following disclaimer in the
|
38
|
+
documentation and/or other materials provided with the distribution.
|
39
|
+
|
40
|
+
THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
41
|
+
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
42
|
+
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
43
|
+
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
44
|
+
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
45
|
+
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
46
|
+
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
47
|
+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
48
|
+
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
49
|
+
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
50
|
+
POSSIBILITY OF SUCH DAMAGE.
|
data/TODO
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
In no particular order:
|
2
|
+
|
3
|
+
* Somehow make every Row aware of its associated TableHeader without actually
|
4
|
+
shipping every Row with the TableHeader.
|
5
|
+
|
6
|
+
* Make Turntable marshallable.
|
7
|
+
|
8
|
+
* Figure out the best/most efficient way to serialize increasingly larger
|
9
|
+
tables.
|
10
|
+
|
11
|
+
* Implement all of the SortedSet methods which are not present in Enumerable in
|
12
|
+
such a way that does not require calling Turntable::Table#rows. (#delete_if,
|
13
|
+
first, etc.)
|
14
|
+
|
15
|
+
* Write simpler #inspect representations of all objects.
|
16
|
+
|
17
|
+
* Add the strict typing functionality, or figure out what to do with it at
|
18
|
+
least.
|
data/lib/turntable.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#
|
2
|
+
# columndefinition.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
module Turntable
|
6
|
+
|
7
|
+
# A Turntable::ColumnDefinition consists of a name, its position within a
|
8
|
+
# Turntable::TableHeader, and, optionally, its associated type.
|
9
|
+
#
|
10
|
+
# ColumnDefinitions are meant to be created and manipulated by a TableHeader.
|
11
|
+
# ColumnDefinition and its methods are not intended to be used directly by the
|
12
|
+
# end user.
|
13
|
+
#
|
14
|
+
class ColumnDefinition
|
15
|
+
|
16
|
+
include Comparable
|
17
|
+
|
18
|
+
# A ColumnDefinition is ``less than'' another if its position is smaller.
|
19
|
+
# Likewise, a ColumnDefinition is ``greater than'' another if its position
|
20
|
+
# is greater.
|
21
|
+
#
|
22
|
+
def <=>(another)
|
23
|
+
(self.position > another.position) ? (1) : (-1)
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_accessor :name
|
27
|
+
attr_reader :position, :type
|
28
|
+
|
29
|
+
# Creates a new ColumnDefinition. This method should not be used directly.
|
30
|
+
# Instead, create a new Turntable::TableHeader.
|
31
|
+
#
|
32
|
+
def initialize(name, position, type=nil)
|
33
|
+
@name = name
|
34
|
+
@position = position
|
35
|
+
@type = type
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
#
|
2
|
+
# row.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
require 'turntable/tableheader'
|
6
|
+
|
7
|
+
module Turntable
|
8
|
+
|
9
|
+
# A Turntable::Row represents one row in a Turntable::Table, according to the
|
10
|
+
# table's Turntable::TableHeader.
|
11
|
+
#
|
12
|
+
class Row
|
13
|
+
|
14
|
+
include Comparable
|
15
|
+
|
16
|
+
# A Row is ``less than'' another if its position is smaller. Likewise, a Row
|
17
|
+
# is ``greater than'' another if its position is larger.
|
18
|
+
#
|
19
|
+
def <=>(another)
|
20
|
+
(self.position > another.position) ? (1) : (-1)
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_reader :data, :position
|
24
|
+
|
25
|
+
# This method is not meant to be used directly. Refer to Turntable::Table.
|
26
|
+
#
|
27
|
+
def initialize(header, position, data_array)
|
28
|
+
@header = header # FIXME This makes IRB really ugly
|
29
|
+
@position = position
|
30
|
+
@data = data_array
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns the data found at a specific column.
|
34
|
+
# TODO @data should have this close by...
|
35
|
+
#
|
36
|
+
def [](column_name)
|
37
|
+
i = @header.detect { |column| column.name == column_name }.position
|
38
|
+
@data[i]
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
#
|
2
|
+
# table.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
require 'set'
|
6
|
+
require 'turntable/row'
|
7
|
+
|
8
|
+
module Turntable
|
9
|
+
|
10
|
+
# Turntable::Table is Turntable's main interface. It maintains an ordered list
|
11
|
+
# of Turntable::Row objects, according to a given Turntable::TableHeader.
|
12
|
+
#
|
13
|
+
# Internally, Turntable::Table implements a SortedSet. See the documentation
|
14
|
+
# for Turntable::TableHeader for the reasons why. Additionally, the SortedSet
|
15
|
+
# ensures that two otherwise identical rows will have differing positions
|
16
|
+
# within the table.
|
17
|
+
#
|
18
|
+
# Turntable::Table includes Enumerable, so every method there is available
|
19
|
+
# here. Also, calling Turntable::Table#rows returns the internal SortedSet, so
|
20
|
+
# you can gain access to the instance methods available for sets that way.
|
21
|
+
class Table
|
22
|
+
|
23
|
+
include Enumerable
|
24
|
+
|
25
|
+
def each
|
26
|
+
@rows.each { |row| yield row }
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_reader :header
|
30
|
+
attr_accessor :rows
|
31
|
+
|
32
|
+
# Associates a TableHeader with a new, empty Table.
|
33
|
+
#
|
34
|
+
def initialize(header)
|
35
|
+
@rows = SortedSet.new
|
36
|
+
@header = header
|
37
|
+
end
|
38
|
+
|
39
|
+
# Append a new Row to the Table.
|
40
|
+
#
|
41
|
+
# t = Turntable::Table.new(some_header)
|
42
|
+
# t.push "LP4", "Ratatat", 2010
|
43
|
+
#
|
44
|
+
def push(*data)
|
45
|
+
r = Row.new(@header, get_new_position, data)
|
46
|
+
@rows << r
|
47
|
+
end
|
48
|
+
|
49
|
+
# Determines the position of a new row. If there are no rows, then simply
|
50
|
+
# return 0.
|
51
|
+
#
|
52
|
+
def get_new_position
|
53
|
+
(@rows.empty?) ? (0) : (@rows.sort.last.position + 1)
|
54
|
+
end
|
55
|
+
private :get_new_position
|
56
|
+
|
57
|
+
# Retreives a row by its position.
|
58
|
+
#
|
59
|
+
def [](position)
|
60
|
+
@rows.detect { |row| row.position == position }
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
#
|
2
|
+
# tableheader.rb
|
3
|
+
#
|
4
|
+
|
5
|
+
require 'set'
|
6
|
+
require 'turntable/columndefinition'
|
7
|
+
|
8
|
+
module Turntable
|
9
|
+
|
10
|
+
# A Turntable::TableHeader maintains an ordered list of ColumnDefinition
|
11
|
+
# objects. This list is implemented as a SortedSet for three reasons:
|
12
|
+
#
|
13
|
+
# * It's apparently faster than Array.
|
14
|
+
# * The columns appear in order in IRB.
|
15
|
+
# * It ensures there are no duplicate column definitions.
|
16
|
+
#
|
17
|
+
class TableHeader
|
18
|
+
|
19
|
+
include Enumerable
|
20
|
+
|
21
|
+
def each
|
22
|
+
@columns.each { |column| yield column }
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :columns
|
26
|
+
|
27
|
+
# Creates a new TableHeader. The given column names should be symbols.
|
28
|
+
#
|
29
|
+
# Turntable::TableHeader.new(:album, :artist, :year)
|
30
|
+
#
|
31
|
+
def initialize(*column_names)
|
32
|
+
@columns = SortedSet.new
|
33
|
+
column_names.each_with_index do |column, i|
|
34
|
+
@columns << Turntable::ColumnDefinition.new(column, i)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns a ColumnDefinition by specifying its position within the
|
39
|
+
# TableHeader.
|
40
|
+
#
|
41
|
+
# th = Turntable::TableHeader.new(:album, :artist, :year)
|
42
|
+
# th[1] # => #<Turntable::ColumnDefinition @name=... @position=...>
|
43
|
+
#
|
44
|
+
def [](position)
|
45
|
+
@columns.detect { |column| column.position == position }
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: turntable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Christian Koch
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-03-31 00:00:00 -07:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: |
|
23
|
+
Turntable is a pure Ruby implementation of a relational database, similar in
|
24
|
+
spirit to SQLite. Unlike Sequel or any other object-relational mapper, Turntable
|
25
|
+
is built with Ruby from the ground up, and implements Rubyisms whenever
|
26
|
+
possible.
|
27
|
+
|
28
|
+
email: cfkoch@sdf.lonestar.org
|
29
|
+
executables: []
|
30
|
+
|
31
|
+
extensions: []
|
32
|
+
|
33
|
+
extra_rdoc_files: []
|
34
|
+
|
35
|
+
files:
|
36
|
+
- README
|
37
|
+
- TODO
|
38
|
+
- lib/turntable.rb
|
39
|
+
- lib/turntable/columndefinition.rb
|
40
|
+
- lib/turntable/row.rb
|
41
|
+
- lib/turntable/table.rb
|
42
|
+
- lib/turntable/tableheader.rb
|
43
|
+
has_rdoc: true
|
44
|
+
homepage:
|
45
|
+
licenses:
|
46
|
+
- 2-clause BSD
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
|
50
|
+
require_paths:
|
51
|
+
- - lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
none: false
|
54
|
+
requirements:
|
55
|
+
- - ">="
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
hash: 3
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
version: "0"
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
hash: 3
|
67
|
+
segments:
|
68
|
+
- 0
|
69
|
+
version: "0"
|
70
|
+
requirements: []
|
71
|
+
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 1.3.7
|
74
|
+
signing_key:
|
75
|
+
specification_version: 3
|
76
|
+
summary: The hip-hop Ruby database.
|
77
|
+
test_files: []
|
78
|
+
|