ramen 0.4.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.
- data/doc/doc_resources/MetaData_Class_Diagram.gif +0 -0
- data/doc/doc_resources/MetaData_Class_Diagram.png +0 -0
- data/doc/doc_resources/Thumbs.db +0 -0
- data/lib/ramen/core.rb +75 -0
- data/lib/ramen/default_logger.rb +29 -0
- data/lib/ramen/engine/engine.rb +34 -0
- data/lib/ramen/engine/mysql.rb +225 -0
- data/lib/ramen/engine/sql2005.rb +377 -0
- data/lib/ramen/home.rb +162 -0
- data/lib/ramen/metadata/column.rb +38 -0
- data/lib/ramen/metadata/database.rb +137 -0
- data/lib/ramen/metadata/foreign_key.rb +71 -0
- data/lib/ramen/metadata/foreign_key_column.rb +51 -0
- data/lib/ramen/metadata/index.rb +71 -0
- data/lib/ramen/metadata/index_column.rb +49 -0
- data/lib/ramen/metadata/key_constraint.rb +56 -0
- data/lib/ramen/metadata/metadata.rb +10 -0
- data/lib/ramen/metadata/primary_key.rb +71 -0
- data/lib/ramen/metadata/primary_key_column.rb +49 -0
- data/lib/ramen/metadata/schema.rb +86 -0
- data/lib/ramen/metadata/table.rb +202 -0
- data/lib/ramen/ramen_error.rb +16 -0
- data/lib/ramen/ramen_hash.rb +143 -0
- data/lib/ramen/ramen_module.rb +52 -0
- data/lib/ramen/row_data_gateway.rb +89 -0
- data/lib/ramen/version.rb +16 -0
- data/lib/ramen.rb +62 -0
- data/readme.txt +159 -0
- data/test/config/config.yml +19 -0
- data/test/helper.rb +18 -0
- data/test/mysql_create_test_db.sql +47 -0
- data/test/sql2005_create_test_db.sql +45 -0
- data/test/test_bugs.rb +32 -0
- data/test/test_core.rb +63 -0
- data/test/test_default_logger.rb +38 -0
- data/test/test_home.rb +33 -0
- data/test/test_ramen.rb +274 -0
- data/test/test_ramen_hash.rb +78 -0
- data/test/test_ramen_module.rb +21 -0
- metadata +99 -0
data/readme.txt
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
= Ramen -- Making your database edible
|
|
2
|
+
by Gregory N. Houston
|
|
3
|
+
|
|
4
|
+
Ramen creates an object model from your database's metadata (Schema, Tables,
|
|
5
|
+
Columns, Indexes, Keys). This metadata is sometimes called
|
|
6
|
+
_data_ _dictionary_, _system_ _catalog_, or _INFORMATION_ _SCHEMA_.
|
|
7
|
+
|
|
8
|
+
Version:: 0.4.0 SQL Server 2005 and MySQL 5.0.
|
|
9
|
+
|
|
10
|
+
It is easy to support additional database engines. All that is needed are
|
|
11
|
+
the SQL statements to query the metadata, and maybe a few tweaks to the
|
|
12
|
+
unit tests. Please contact the author if you want help getting Ramen to
|
|
13
|
+
support another database.
|
|
14
|
+
|
|
15
|
+
== Links:
|
|
16
|
+
|
|
17
|
+
Start Here:: http://ramen.rubyforge.org
|
|
18
|
+
|
|
19
|
+
Project:: http://rubyforge.org/projects/ramen
|
|
20
|
+
Documents:: http://ramen.rubyforge.org
|
|
21
|
+
RubyGems:: Install with: <b>gem install ramen</b>
|
|
22
|
+
Download:: Download from RubyForge at http://rubyforge.org/projects/ramen/
|
|
23
|
+
Authors Blog:: http://ghouston.blogspot.com
|
|
24
|
+
Browse Source:: link:rcov/index.html
|
|
25
|
+
|
|
26
|
+
== LICENSE:
|
|
27
|
+
|
|
28
|
+
(The MIT License + Free Software Foundation Advertising Prohibition)
|
|
29
|
+
|
|
30
|
+
Copyright (c) 2007 Gregory N. Houston
|
|
31
|
+
|
|
32
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
33
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
34
|
+
in the Software without restriction, including without limitation the rights
|
|
35
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
36
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
37
|
+
furnished to do so, subject to the following conditions:
|
|
38
|
+
|
|
39
|
+
The above copyright notice and this permission notice shall be included in
|
|
40
|
+
all copies or substantial portions of the Software.
|
|
41
|
+
|
|
42
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
43
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
44
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
45
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
46
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
47
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
48
|
+
THE SOFTWARE.
|
|
49
|
+
|
|
50
|
+
Except as contained in this notice, the name(s) of the above copyright holders
|
|
51
|
+
shall not be used in advertising or otherwise to promote the sale, use or other
|
|
52
|
+
dealings in this Software without prior written authorization.
|
|
53
|
+
|
|
54
|
+
== Examples:
|
|
55
|
+
|
|
56
|
+
== Design:
|
|
57
|
+
|
|
58
|
+
Ramen loads the INFORMATION SCHEMA from the database into Ruby objects
|
|
59
|
+
using the RowDataGateway pattern (Martin Fowler. Patterns of Enterprise
|
|
60
|
+
Application Architecture. Addison Wesley Longman, Reading, MA, 2003). The
|
|
61
|
+
resulting structure is:
|
|
62
|
+
|
|
63
|
+
link:doc_resources/MetaData_Class_Diagram.png
|
|
64
|
+
|
|
65
|
+
Thus if a client wishes to get the Employee table in the HumanResources schema:
|
|
66
|
+
|
|
67
|
+
require 'ramen'
|
|
68
|
+
db = Ramen.create( :connection => DBI.connect( ...database connection... ))
|
|
69
|
+
employee_table = db.schema['HumanResources'].table['Employee']
|
|
70
|
+
|
|
71
|
+
Ramen exposes each column in the INFORMATION SCHEMA as attributes on the Ruby
|
|
72
|
+
object. For example, on SQL 2005 a table in sys.table has the following
|
|
73
|
+
meta-data:
|
|
74
|
+
|
|
75
|
+
select * from sys.tables where name ='Employee'
|
|
76
|
+
|
|
77
|
+
...type_desc create_date modify_date is_ms_shipped ...
|
|
78
|
+
...----------- ----------------------- ----------------------- ------------- ...
|
|
79
|
+
...USER_TABLE 2005-10-14 01:58:32.663 2005-10-14 01:59:52.287 0 ...
|
|
80
|
+
|
|
81
|
+
Ramen's RowDataGateway maps these columns directly to attributes on the table
|
|
82
|
+
object in ruby.
|
|
83
|
+
|
|
84
|
+
employee_table.type_desc #=> "USER_TABLE"
|
|
85
|
+
employee_table.create_date #=> #<DBI::Timestamp...>
|
|
86
|
+
employee_table.is_ms_shipped #=> 0
|
|
87
|
+
|
|
88
|
+
The attributes are database engine specific. On different database engines
|
|
89
|
+
(Sql 2005, MySQL, etc) the objects will contain the data columns
|
|
90
|
+
returned by the engine's INFORMATION SCHEMA. In the near future, Ramen will
|
|
91
|
+
provide a Facade mapping engine specific attributes to generic attributes. For
|
|
92
|
+
example in SQL 2005 the Index attribute .is_unique and MySQL's .non_unique
|
|
93
|
+
attributes would be mapped to .unique?.
|
|
94
|
+
|
|
95
|
+
Ramen does not "Rubify" the database names into Ruby names. This is important
|
|
96
|
+
since Ramen's focus is the database, not Ruby. The only restriction that Ramen
|
|
97
|
+
imposes is the "name" and "object_id" or "id" columns need renaming to names
|
|
98
|
+
like "schema_name" or "table_id" in the records returned in queries. This
|
|
99
|
+
avoids clashing with attributes that already exist on Ruby objects, and
|
|
100
|
+
it makes it clear which ID or NAME is being returned.
|
|
101
|
+
|
|
102
|
+
Since different databases use
|
|
103
|
+
Internally Ramen collects objects into a specialized Hash that can access
|
|
104
|
+
objects by either name or id. For example, when getting a table a client
|
|
105
|
+
can use either table_name or table_id.
|
|
106
|
+
|
|
107
|
+
hr_schema.table['Employee']
|
|
108
|
+
hr_schema.table[12345]
|
|
109
|
+
|
|
110
|
+
Ramen was developed to support the Noodle project (also on Rubyforge). As
|
|
111
|
+
Noodle is developed, Ramen's API will improve.
|
|
112
|
+
|
|
113
|
+
== Database Support:
|
|
114
|
+
|
|
115
|
+
Currently, Ramen only supports SQL Server 2005 and MySQL 5.0. However, Ramen was developed
|
|
116
|
+
with support for other databases in mind. As such, to support other databases
|
|
117
|
+
two changes are needed. First, the queries for the INFORMATION SCHEMA meta-data
|
|
118
|
+
would need writting. See the class Ramen::Sql2005 for the queries that would need
|
|
119
|
+
developing for another database. Second, the unit tests will need tweaking to
|
|
120
|
+
work with the new database engine (see test/sql2005_create_test_db.sql).
|
|
121
|
+
|
|
122
|
+
== Multiple Databases:
|
|
123
|
+
|
|
124
|
+
Ramen can create and use multiple instances of Ramen::Database at the same time.
|
|
125
|
+
This allow connecting to multiple databases at the same time.
|
|
126
|
+
|
|
127
|
+
== Connections:
|
|
128
|
+
|
|
129
|
+
Ramen::Database#new and Ramen.create accept a connection parameter. This
|
|
130
|
+
connection is only used during the call of the method. Ramen will not
|
|
131
|
+
hold on to connections. After the method returns, it is safe to use the
|
|
132
|
+
connection outside Ramen or to close it.
|
|
133
|
+
|
|
134
|
+
== Threading:
|
|
135
|
+
|
|
136
|
+
Ramen was developed to support Noodle and Unit Testing in a single-threaded
|
|
137
|
+
fashion. Thus Ramen does not take extra steps to make itself threadsafe. The
|
|
138
|
+
only section of Ramen's code that updates values is the creation process.
|
|
139
|
+
Once the database meta-data is loaded, Ramen's object are read-only
|
|
140
|
+
(not enforced, but as long as clients only use methods documented as
|
|
141
|
+
"for external use" it is safe). It is possible to use Ramen in a multi-threaded
|
|
142
|
+
system if Ramen::Database#new is treated as a critical section.
|
|
143
|
+
|
|
144
|
+
== Dependencies:
|
|
145
|
+
|
|
146
|
+
Ramen's connection must quack like DBI.
|
|
147
|
+
|
|
148
|
+
Ramen's logger must quack like Ramen::DefaultLogger which is a subset of Log4r.
|
|
149
|
+
So clients may use Ramen directly with Log4r.
|
|
150
|
+
|
|
151
|
+
== Performance:
|
|
152
|
+
|
|
153
|
+
Ramen was optimized for Unit Testing. It assumes that most clients will
|
|
154
|
+
request meta-data for at least 25% of the tables in the database. To optimize
|
|
155
|
+
for this situation, Ramen found loading the entire database's meta-data upon
|
|
156
|
+
creation of the Database object to have the best performance. In development
|
|
157
|
+
tests on an average PC running Ramen against a remote SQL 2005 Server database on
|
|
158
|
+
the same network segment that contained 322 tables, 3281 columns, 192 foreign
|
|
159
|
+
keys, the queries and creation of Ramen's objects took less than one second.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
## config.yml - Configuration for running the tests
|
|
2
|
+
## This is an example file, which contains the
|
|
3
|
+
## default settings.
|
|
4
|
+
## Overridden by defining a config_local.yml
|
|
5
|
+
##
|
|
6
|
+
## The top element is an environment name, which will be printed in
|
|
7
|
+
## error messages when a test against the environment fails
|
|
8
|
+
##
|
|
9
|
+
## Each environment needs an 'engine' and 'connection'
|
|
10
|
+
## engine = module name that contains engine's specific code.
|
|
11
|
+
## connection = DBI connection string, to connect to test database.
|
|
12
|
+
|
|
13
|
+
sqlserver2005:
|
|
14
|
+
engine: Ramen::Sql2005
|
|
15
|
+
connection: DBI:ODBC:ramen_test_sql2005
|
|
16
|
+
|
|
17
|
+
mysql50:
|
|
18
|
+
engine: Ramen::MySql500
|
|
19
|
+
connection: DBI:ODBC:ramen_test_mysql
|
data/test/helper.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright (c) 2007 Gregory N. Houston
|
|
3
|
+
# See ramen.rb for license information.
|
|
4
|
+
#++
|
|
5
|
+
|
|
6
|
+
module Ramen
|
|
7
|
+
class Helper
|
|
8
|
+
def Helper.load_config
|
|
9
|
+
begin
|
|
10
|
+
return YAML.load_file( './test/config/config_local.yml' )
|
|
11
|
+
rescue Errno::ENOENT
|
|
12
|
+
return YAML.load_file( './test/config/config.yml' )
|
|
13
|
+
end
|
|
14
|
+
raise "Unable to load configuration. #{__FILE__} #{__LINE__}"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
DROP DATABASE IF EXISTS RamenTestSchema;
|
|
2
|
+
DROP DATABASE IF EXISTS RamenTestSchema2;
|
|
3
|
+
|
|
4
|
+
CREATE DATABASE RamenTestSchema;
|
|
5
|
+
CREATE DATABASE RamenTestSchema2;
|
|
6
|
+
|
|
7
|
+
CREATE TABLE RamenTestSchema.Employee (
|
|
8
|
+
EmployeeID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
9
|
+
LoginID VARCHAR(256) NOT NULL,
|
|
10
|
+
ManagerID INTEGER UNSIGNED,
|
|
11
|
+
PRIMARY KEY (EmployeeID)
|
|
12
|
+
);
|
|
13
|
+
ALTER TABLE RamenTestSchema.Employee ADD UNIQUE INDEX IX_Employee_LoginID USING BTREE(LoginID);
|
|
14
|
+
ALTER TABLE RamenTestSchema.Employee ADD INDEX IX_Employee_ManagerID USING BTREE(ManagerID);
|
|
15
|
+
ALTER TABLE RamenTestSchema.Employee
|
|
16
|
+
ADD CONSTRAINT FK_Employee_Employee_ManagerID
|
|
17
|
+
FOREIGN KEY FK_Employee_Employee_ManagerID (ManagerID)
|
|
18
|
+
REFERENCES Employee (EmployeeID)
|
|
19
|
+
ON DELETE RESTRICT
|
|
20
|
+
ON UPDATE RESTRICT;
|
|
21
|
+
|
|
22
|
+
CREATE TABLE RamenTestSchema.EmployeeAddress (
|
|
23
|
+
EmployeeID INTEGER UNSIGNED NOT NULL,
|
|
24
|
+
AddressID INTEGER UNSIGNED NOT NULL,
|
|
25
|
+
PRIMARY KEY (EmployeeID, AddressID)
|
|
26
|
+
);
|
|
27
|
+
ALTER TABLE RamenTestSchema.EmployeeAddress
|
|
28
|
+
ADD CONSTRAINT FK_EmployeeAddress_Employee
|
|
29
|
+
FOREIGN KEY FK_EmployeeAddress_Employee (EmployeeID)
|
|
30
|
+
REFERENCES Employee (EmployeeID)
|
|
31
|
+
ON DELETE RESTRICT
|
|
32
|
+
ON UPDATE RESTRICT;
|
|
33
|
+
|
|
34
|
+
CREATE TABLE RamenTestSchema.Bug1 (
|
|
35
|
+
PkID INTEGER UNSIGNED NOT NULL,
|
|
36
|
+
PRIMARY KEY (PkID)
|
|
37
|
+
);
|
|
38
|
+
ALTER TABLE RamenTestSchema.Bug1
|
|
39
|
+
ADD CONSTRAINT FK_Bug1_Employee
|
|
40
|
+
FOREIGN KEY FK_Bug1_Employee (PkID)
|
|
41
|
+
REFERENCES Employee (EmployeeID)
|
|
42
|
+
ON DELETE RESTRICT
|
|
43
|
+
ON UPDATE RESTRICT;
|
|
44
|
+
/*
|
|
45
|
+
# Note, MySQL cant have a foreign key that spans schemas (databases).
|
|
46
|
+
# Some databases dont have this restriction.
|
|
47
|
+
*/
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/*
|
|
2
|
+
#--
|
|
3
|
+
# Copyright (c) 2007 Gregory N. Houston
|
|
4
|
+
# See ramen.rb for license information.
|
|
5
|
+
#++
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
USE MASTER
|
|
9
|
+
GO
|
|
10
|
+
|
|
11
|
+
IF EXISTS (SELECT name FROM sys.databases WHERE name = N'RamenTest')
|
|
12
|
+
DROP DATABASE RamenTest
|
|
13
|
+
GO
|
|
14
|
+
|
|
15
|
+
CREATE DATABASE RamenTest
|
|
16
|
+
GO
|
|
17
|
+
|
|
18
|
+
USE RamenTest
|
|
19
|
+
GO
|
|
20
|
+
|
|
21
|
+
CREATE SCHEMA RamenTestSchema2
|
|
22
|
+
CREATE TABLE Bug1 (PkID int
|
|
23
|
+
CONSTRAINT PK_Bug1_PkID PRIMARY KEY CLUSTERED (PkID ASC))
|
|
24
|
+
GO
|
|
25
|
+
|
|
26
|
+
CREATE SCHEMA RamenTestSchema
|
|
27
|
+
CREATE TABLE Employee (EmployeeID int, LoginID nvarchar(256), ManagerID int
|
|
28
|
+
CONSTRAINT PK_Employee_EmployeeID PRIMARY KEY CLUSTERED (EmployeeID ASC))
|
|
29
|
+
CREATE TABLE EmployeeAddress (EmployeeID int, AddressID int
|
|
30
|
+
CONSTRAINT PK_EmployeeAddress_EmployeeID_AddressID PRIMARY KEY CLUSTERED (EmployeeID ASC, AddressID ASC))
|
|
31
|
+
GO
|
|
32
|
+
|
|
33
|
+
CREATE UNIQUE NONCLUSTERED INDEX IX_Employee_LoginID ON RamenTestSchema.Employee (LoginID ASC)
|
|
34
|
+
CREATE NONCLUSTERED INDEX IX_Employee_ManagerID ON RamenTestSchema.Employee (ManagerID ASC)
|
|
35
|
+
ALTER TABLE RamenTestSchema.Employee ADD CONSTRAINT FK_Employee_Employee_ManagerID FOREIGN KEY(ManagerID) REFERENCES RamenTestSchema.Employee (EmployeeID)
|
|
36
|
+
ALTER TABLE RamenTestSchema.Employee CHECK CONSTRAINT FK_Employee_Employee_ManagerID
|
|
37
|
+
ALTER TABLE RamenTestSchema.EmployeeAddress ADD CONSTRAINT FK_EmployeeAddress_Employee FOREIGN KEY(EmployeeID) REFERENCES RamenTestSchema.Employee (EmployeeID)
|
|
38
|
+
ALTER TABLE RamenTestSchema.EmployeeAddress CHECK CONSTRAINT FK_EmployeeAddress_Employee
|
|
39
|
+
GO
|
|
40
|
+
|
|
41
|
+
ALTER TABLE RamenTestSchema2.Bug1 ADD CONSTRAINT FK_Bug1_Employee FOREIGN KEY(PkID) REFERENCES RamenTestSchema.Employee (EmployeeID)
|
|
42
|
+
GO
|
|
43
|
+
|
|
44
|
+
--CREATE SCHEMA Person
|
|
45
|
+
--GO
|
data/test/test_bugs.rb
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright (c) 2007 Gregory N. Houston
|
|
3
|
+
# See ramen.rb for license information.
|
|
4
|
+
#++
|
|
5
|
+
require 'lib/ramen'
|
|
6
|
+
|
|
7
|
+
=begin
|
|
8
|
+
Detected: 2008-02-18
|
|
9
|
+
Database Engine: Sql2005
|
|
10
|
+
Bug: Foreign Key Column @referenced_column fails if the ref column name is
|
|
11
|
+
different than the column name in the local table.
|
|
12
|
+
|
|
13
|
+
To reproduce:
|
|
14
|
+
RamenTestSchema2.Bug1 with a column PkID which references
|
|
15
|
+
RamenTestSchema.Employee (EmployeeID).
|
|
16
|
+
|
|
17
|
+
Other problems: Inspecting the code, found that Foreign Key Column doesn't
|
|
18
|
+
have an attribute for referenced_table_schema. What if the reference was to
|
|
19
|
+
a different schema? (Note, MySQL cant reference across schemas)
|
|
20
|
+
=end
|
|
21
|
+
|
|
22
|
+
module Ramen
|
|
23
|
+
module TestBugs
|
|
24
|
+
def t_bug1( key, db )
|
|
25
|
+
@name = "test_bug1_#{key}"
|
|
26
|
+
table_schema = (db.schema['RamenTestSchema'].table.has_key?('bug1')) ? 'RamenTestSchema' : 'RamenTestSchema2'
|
|
27
|
+
referenced_column = db.schema[table_schema].table['bug1'].fk['fk_bug1_employee'].column['pkid'].referenced_column
|
|
28
|
+
employee_id_column = db.schema['RamenTestSchema'].table['employee'].column['employeeid']
|
|
29
|
+
assert_same( referenced_column, employee_id_column, "referenced column must be employee id column in employee table." )
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
data/test/test_core.rb
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright (c) 2007 Gregory N. Houston
|
|
3
|
+
# See ramen.rb for license information.
|
|
4
|
+
#++
|
|
5
|
+
require 'test/unit'
|
|
6
|
+
require 'lib/ramen'
|
|
7
|
+
|
|
8
|
+
class TestCore < Test::Unit::TestCase
|
|
9
|
+
def testIsUpcase
|
|
10
|
+
assert "ABCDEFG".is_upcase?
|
|
11
|
+
assert !"abcdefg".is_upcase?
|
|
12
|
+
assert !"Abcdefg".is_upcase?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def testToDelimitedWords
|
|
16
|
+
assert_equal "foo", "Foo".to_delimited_words
|
|
17
|
+
assert_equal "foo_bar_baz", "FooBarBaz".to_delimited_words
|
|
18
|
+
assert_equal "", "".to_delimited_words
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_compare
|
|
22
|
+
assert_equal( -1, nil <=> 'foobar' )
|
|
23
|
+
assert_equal( nil, 'foobar' <=> nil )
|
|
24
|
+
assert_equal( 0, nil <=> nil )
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def test_singleton_class
|
|
28
|
+
a = TestCore
|
|
29
|
+
b = TestCore
|
|
30
|
+
c = "another instance" #these two strings are different instances of String
|
|
31
|
+
d = "another instance"
|
|
32
|
+
e = "no foo"
|
|
33
|
+
a.singleton_class.module_eval do
|
|
34
|
+
define_method :foo do
|
|
35
|
+
"a"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
b.singleton_class.module_eval do
|
|
39
|
+
define_method :foo do
|
|
40
|
+
"b"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
c.singleton_class.module_eval do
|
|
44
|
+
define_method :foo do
|
|
45
|
+
"c"
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
d.singleton_class.module_eval do
|
|
49
|
+
define_method :foo do
|
|
50
|
+
"d"
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
assert_equal( a.singleton_class, b.singleton_class )
|
|
54
|
+
assert_equal( "b", a.foo )
|
|
55
|
+
assert_equal( "b", b.foo )
|
|
56
|
+
assert_not_equal( c.singleton_class, d.singleton_class )
|
|
57
|
+
assert_equal( "c", c.foo )
|
|
58
|
+
assert_equal( "d", d.foo )
|
|
59
|
+
assert( !(e.respond_to? :foo) )
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright (c) 2007 Gregory N. Houston
|
|
3
|
+
# See ramen.rb for license information.
|
|
4
|
+
#++
|
|
5
|
+
|
|
6
|
+
require 'test/unit'
|
|
7
|
+
require 'lib/ramen'
|
|
8
|
+
|
|
9
|
+
module Ramen
|
|
10
|
+
# simple test
|
|
11
|
+
#
|
|
12
|
+
# ensures the logger interface (actually this was added for code coverage)
|
|
13
|
+
class TestDefaultLogger < Test::Unit::TestCase
|
|
14
|
+
def test_log
|
|
15
|
+
capture_stdout
|
|
16
|
+
logger = DefaultLogger.new
|
|
17
|
+
logger.debug 'debug'
|
|
18
|
+
logger.info 'info'
|
|
19
|
+
logger.warn 'warn'
|
|
20
|
+
logger.error 'error'
|
|
21
|
+
logger.fatal 'fatal'
|
|
22
|
+
result = restore_stdout
|
|
23
|
+
assert_equal "warn\nerror\nfatal\n", result
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def capture_stdout
|
|
27
|
+
@in, @out = IO.pipe
|
|
28
|
+
@stdout = $stdout
|
|
29
|
+
$stdout = @out
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def restore_stdout
|
|
33
|
+
$stdout = @stdout
|
|
34
|
+
@out.close
|
|
35
|
+
return @in.read
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
data/test/test_home.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright (c) 2007 Gregory N. Houston
|
|
3
|
+
# See ramen.rb for license information.
|
|
4
|
+
#++
|
|
5
|
+
|
|
6
|
+
require 'test/unit'
|
|
7
|
+
require 'lib/ramen'
|
|
8
|
+
|
|
9
|
+
module Ramen
|
|
10
|
+
class MockDBI
|
|
11
|
+
def execute( *args )
|
|
12
|
+
raise RamenError, "expected"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
class SilentLogger
|
|
16
|
+
def do_nothing( msg )
|
|
17
|
+
end
|
|
18
|
+
alias debug do_nothing
|
|
19
|
+
alias info do_nothing
|
|
20
|
+
alias warn do_nothing
|
|
21
|
+
alias error do_nothing
|
|
22
|
+
alias fatal do_nothing
|
|
23
|
+
end
|
|
24
|
+
class TestHome < Test::Unit::TestCase
|
|
25
|
+
def test_dbi_error
|
|
26
|
+
h = Home.new( :logger => SilentLogger.new )
|
|
27
|
+
assert_raise RamenError do
|
|
28
|
+
h.execute( MockDBI.new, 'i dont care')
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|