data_factory 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +4 -2
- data/lib/data_factory/base_api.rb +23 -9
- data/lib/data_factory/base_dsl.rb +18 -5
- data/lib/data_factory/exceptions.rb +2 -1
- data/test/base_api_test.rb +33 -0
- data/test/base_dsl_test.rb +8 -0
- data/test/helper.rb +3 -2
- data/test/sanity.rb +4 -4
- metadata +50 -33
- checksums.yaml +0 -7
data/README.md
CHANGED
@@ -60,7 +60,9 @@ To use DataFactory, create a class for each table you want to interface with, an
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
In the class definition, use the set_table_name method to map the class to a particular table on the database.
|
63
|
+
In the class definition, use the set_table_name method to map the class to a particular table on the database. If the table is not owned by the user you connect to the database as, then prefix the table with the schema name:
|
64
|
+
|
65
|
+
set_table_name "hr.employees"
|
64
66
|
|
65
67
|
Optionally, you can specify default values for columns in the table with the set_column_default method, which takes the table name followed by a value for the column, or a block that generates the value each time it is called, as with the email example.
|
66
68
|
|
@@ -177,4 +179,4 @@ I may make improvements in the future to remove this limitation and improve the
|
|
177
179
|
|
178
180
|
|
179
181
|
|
180
|
-
|
182
|
+
|
@@ -25,6 +25,18 @@ module DataFactory
|
|
25
25
|
self.class.table_name
|
26
26
|
end
|
27
27
|
|
28
|
+
def schema_name
|
29
|
+
self.class.schema_name
|
30
|
+
end
|
31
|
+
|
32
|
+
def fully_qualified_table_name
|
33
|
+
if self.class.schema_name
|
34
|
+
"#{schema_name}.#{table_name}"
|
35
|
+
else
|
36
|
+
table_name
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
28
40
|
def column_details # :nodoc:
|
29
41
|
self.class.column_details
|
30
42
|
end
|
@@ -98,7 +110,7 @@ module DataFactory
|
|
98
110
|
# variabled are stored in @binds.
|
99
111
|
def generate_insert
|
100
112
|
@binds = Array.new
|
101
|
-
@insert_statement = "insert into #{
|
113
|
+
@insert_statement = "insert into #{fully_qualified_table_name} ("
|
102
114
|
@insert_statement << column_details.keys.sort.map { |k| column_detail(k).column_name }.join(',')
|
103
115
|
@insert_statement << ') values ('
|
104
116
|
@insert_statement << column_details.keys.sort.map { |k|
|
@@ -163,17 +175,22 @@ module DataFactory
|
|
163
175
|
end
|
164
176
|
|
165
177
|
case col.data_type
|
166
|
-
when '
|
178
|
+
when 'VARCHAR2', 'CLOB'
|
167
179
|
random_string_upto_length(col.data_length)
|
180
|
+
when 'CHAR'
|
181
|
+
random_string_of_length(col.data_length)
|
168
182
|
when 'RAW'
|
169
183
|
random_hex_string_upto_length(col.data_length)
|
170
|
-
when 'DATE', 'DATETIME',
|
184
|
+
when 'DATE', 'DATETIME', /TIMESTAMP/
|
171
185
|
Time.now
|
172
186
|
when 'NUMBER', 'INTEGER'
|
173
187
|
scale = 2
|
174
188
|
if col.data_scale && col.data_scale == 0
|
175
|
-
|
189
|
+
# No point in generating massive numbers (eg 10**38), so limit to 10**10
|
190
|
+
max_precision = col.data_precision < 10 ? col.data_precision : 10
|
191
|
+
random_integer((10**max_precision) - 1)
|
176
192
|
else
|
193
|
+
# TODO - generate actual random number obeying presision and scale
|
177
194
|
22.23
|
178
195
|
end
|
179
196
|
|
@@ -198,9 +215,6 @@ module DataFactory
|
|
198
215
|
# max_right = 10**scale - 1
|
199
216
|
# "#{random_integer(max_left)}.#{random_integer(max_right)}".to_f
|
200
217
|
# end
|
201
|
-
when 'NUMBER'
|
202
|
-
23.34
|
203
|
-
when 'INTEGER'
|
204
218
|
else
|
205
219
|
nil
|
206
220
|
end
|
@@ -210,7 +224,7 @@ module DataFactory
|
|
210
224
|
case col.data_type
|
211
225
|
when 'CHAR', 'VARCHAR2', 'CLOB', 'RAW'
|
212
226
|
String
|
213
|
-
when 'DATE', 'DATETIME',
|
227
|
+
when 'DATE', 'DATETIME', /TIMESTAMP/
|
214
228
|
Time
|
215
229
|
when 'INTEGER'
|
216
230
|
Integer
|
@@ -237,7 +251,7 @@ module DataFactory
|
|
237
251
|
def validate_columns(params)
|
238
252
|
params.keys.each do |k|
|
239
253
|
unless column_details.has_key? k.upcase
|
240
|
-
raise DataFactory::ColumnNotInTable, "Column #{k.upcase} is not in #{
|
254
|
+
raise DataFactory::ColumnNotInTable, "Column #{k.upcase} is not in #{fully_qualified_table_name}"
|
241
255
|
end
|
242
256
|
end
|
243
257
|
end
|
@@ -32,7 +32,7 @@ module DataFactory
|
|
32
32
|
|
33
33
|
module BaseDSL
|
34
34
|
|
35
|
-
attr_reader :table_name, :column_details, :column_defaults, :meta_data_loaded, :populate_nullable_columns
|
35
|
+
attr_reader :table_name, :schema_name, :column_details, :column_defaults, :meta_data_loaded, :populate_nullable_columns
|
36
36
|
|
37
37
|
# Pass a database interface object to be used by all DataFactory sub-classes
|
38
38
|
# The interface must implement the following two methods:
|
@@ -65,8 +65,16 @@ module DataFactory
|
|
65
65
|
# Defines the table a subclass of DataFactory interacts with on the database. This
|
66
66
|
# method stores the tables in a class instance variable (@table_name) that is shared by
|
67
67
|
# all instances of the class, but is not inherited with subclasses.
|
68
|
+
# The table name can optionally be prefixed with the schema - 'schema.table'
|
68
69
|
def set_table_name(tab)
|
69
|
-
|
70
|
+
parts = tab.to_s.upcase.split(/\./)
|
71
|
+
if parts.length == 2
|
72
|
+
@table_name = parts[1]
|
73
|
+
@schema_name = parts[0]
|
74
|
+
else
|
75
|
+
@table_name = parts[0]
|
76
|
+
@schema_name = nil
|
77
|
+
end
|
70
78
|
@populate_nullable_columns = false
|
71
79
|
end
|
72
80
|
|
@@ -75,7 +83,7 @@ module DataFactory
|
|
75
83
|
# cause values to be generated for nullable columns in the same way as for not null columns
|
76
84
|
# @example
|
77
85
|
# class MyTab < DataFactory::Base
|
78
|
-
# set_table_name 'my_table'
|
86
|
+
# set_table_name 'schema.my_table'
|
79
87
|
# populate_nullable_columns
|
80
88
|
# end
|
81
89
|
def set_populate_nullable_columns
|
@@ -148,8 +156,9 @@ module DataFactory
|
|
148
156
|
data_scale,
|
149
157
|
column_id,
|
150
158
|
nullable
|
151
|
-
from
|
159
|
+
from all_tab_columns
|
152
160
|
where table_name = ?
|
161
|
+
and owner = #{@schema_name.nil? ? 'user' : "'#{@schema_name}'"}
|
153
162
|
order by column_id asc"
|
154
163
|
|
155
164
|
database_interface.execute_sql(table_details_sql, @table_name).each_array do |r|
|
@@ -163,6 +172,10 @@ module DataFactory
|
|
163
172
|
c.nullable = r[6] == 'N' ? false : true
|
164
173
|
@column_details[r[0].upcase] = c
|
165
174
|
end
|
175
|
+
# If there are no columns, then the table does not exist!
|
176
|
+
if @column_details.keys.length == 0
|
177
|
+
raise DataFactory::TableNotExist, "Table #{schema_name.nil? ? '' : schema_name+'.'}#{table_name} does not exist"
|
178
|
+
end
|
166
179
|
@meta_data_loaded = true
|
167
180
|
# This is needed here as some column defaults will have been set
|
168
181
|
# before the meta_data was loaded and hence will not have been checked
|
@@ -180,7 +193,7 @@ module DataFactory
|
|
180
193
|
|
181
194
|
def validate_column_default(column_name, column_value)
|
182
195
|
unless @column_details.has_key? column_name
|
183
|
-
raise DataFactory::ColumnNotInTable, "Column #{column_name.to_s.upcase} is not in #{table_name}"
|
196
|
+
raise DataFactory::ColumnNotInTable, "Column #{column_name.to_s.upcase} is not in #{schema_name.nil? ? '' : schema_name+'.'}#{table_name}"
|
184
197
|
end
|
185
198
|
end
|
186
199
|
|
@@ -2,5 +2,6 @@ module DataFactory
|
|
2
2
|
class TableNotSet < Exception; end
|
3
3
|
class DatabaseInterfaceNotSet < Exception; end
|
4
4
|
class ColumnNotInTable < Exception; end
|
5
|
-
class NoInsertStatement < Exception; end
|
5
|
+
class NoInsertStatement < Exception; end
|
6
|
+
class TableNotExist < Exception; end
|
6
7
|
end
|
data/test/base_api_test.rb
CHANGED
@@ -32,6 +32,17 @@ class BaseAPITest < Test::Unit::TestCase
|
|
32
32
|
assert_equal('FOOBAR', instance.table_name)
|
33
33
|
end
|
34
34
|
|
35
|
+
def test_fully_qualified_table_name_correct_when_no_schema
|
36
|
+
instance = @klass.new
|
37
|
+
assert_equal('FOOBAR', instance.fully_qualified_table_name)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_fully_qualified_table_name_correct_when_schema
|
41
|
+
@klass.set_table_name('sch.foobar')
|
42
|
+
instance = @klass.new
|
43
|
+
assert_equal('SCH.FOOBAR', instance.fully_qualified_table_name)
|
44
|
+
end
|
45
|
+
|
35
46
|
def test_column_default_is_retrieved
|
36
47
|
@klass.set_column_default('COL1', 'abcd')
|
37
48
|
instance = @klass.new
|
@@ -146,7 +157,29 @@ class BaseAPITest < Test::Unit::TestCase
|
|
146
157
|
end
|
147
158
|
end
|
148
159
|
|
160
|
+
def test_generate_data_for_char_field_is_always_full_column_width
|
161
|
+
instance = @klass.new
|
162
|
+
instance.generate_column_data
|
163
|
+
assert_equal(20, instance.column_value('COL14').length)
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_generate_data_for_small_integer_is_correct_precision
|
167
|
+
instance = @klass.new
|
168
|
+
1.upto(15) do
|
169
|
+
instance.generate_column_data
|
170
|
+
assert instance.column_value('COL15') < 10
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def test_generate_data_for_bigger_integer_is_correct_precision
|
175
|
+
instance = @klass.new
|
176
|
+
1.upto(30) do
|
177
|
+
instance.generate_column_data
|
178
|
+
assert instance.column_value('COL16') < 9999
|
179
|
+
end
|
180
|
+
end
|
149
181
|
|
182
|
+
|
150
183
|
# TODO - tests for generate insert
|
151
184
|
# TODO - tests for
|
152
185
|
|
data/test/base_dsl_test.rb
CHANGED
@@ -23,6 +23,14 @@ class BaseDSLTest < Test::Unit::TestCase
|
|
23
23
|
assert_equal('FOOBAR', @klass.table_name)
|
24
24
|
end
|
25
25
|
|
26
|
+
def test_schema_dot_table_can_be_set_as_a_class_instance_variable
|
27
|
+
@klass.set_table_name('sch.foobar')
|
28
|
+
assert_equal('FOOBAR', @klass.table_name)
|
29
|
+
assert_equal('SCH', @klass.schema_name)
|
30
|
+
assert_equal('FOOBAR', @klass.instance_variable_get('@table_name'))
|
31
|
+
assert_equal('SCH', @klass.instance_variable_get('@schema_name'))
|
32
|
+
end
|
33
|
+
|
26
34
|
def test_db_interface_is_set_as_a_class_variable
|
27
35
|
dbklass = Class.new
|
28
36
|
@klass.set_database_interface(dbklass)
|
data/test/helper.rb
CHANGED
@@ -43,8 +43,9 @@ module TestHelper
|
|
43
43
|
['col11','raw', 20, nil, nil, 11,'Y'],
|
44
44
|
['col12','raw', 20, nil, nil, 12,'N'],
|
45
45
|
['col13','char', 20, nil, nil, 13,'Y'],
|
46
|
-
['col14','char', 20, nil, nil, 14,'N']
|
47
|
-
|
46
|
+
['col14','char', 20, nil, nil, 14,'N'],
|
47
|
+
['col15','number', 20, 1, 0, 15,'N'],
|
48
|
+
['col16','integer', 20, 4, 9, 16,'N']
|
48
49
|
]
|
49
50
|
data.each do |d|
|
50
51
|
yield d
|
data/test/sanity.rb
CHANGED
@@ -6,17 +6,17 @@ require 'simple_oracle_jdbc'
|
|
6
6
|
require 'data_factory'
|
7
7
|
|
8
8
|
#interface = DataFactory::DBInterface::Oracle.create('sodonnel', 'sodonnel', 'local11gr2')
|
9
|
-
interface = SimpleOracleJDBC::Interface.create('sodonnel', 'sodonnel', '
|
9
|
+
interface = SimpleOracleJDBC::Interface.create('sodonnel', 'sodonnel', 'DB12C', '192.168.0.1', '1521')
|
10
10
|
|
11
11
|
DataFactory::Base.set_database_interface(interface)
|
12
12
|
|
13
13
|
class Foo < DataFactory::Base
|
14
|
-
set_table_name "
|
15
|
-
set_column_default "
|
14
|
+
set_table_name "sodonnel.employee"
|
15
|
+
set_column_default "FIRST_NAME", 'john'
|
16
16
|
end
|
17
17
|
|
18
18
|
|
19
|
-
f = Foo.create!("
|
19
|
+
f = Foo.create!("id" => 1001, :date_added => Time.now)
|
20
20
|
f.column_values.keys.each do |k|
|
21
21
|
puts f.column_values[k]
|
22
22
|
end
|
metadata
CHANGED
@@ -1,61 +1,78 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: data_factory
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Stephen O'Donnell
|
8
|
-
autorequire:
|
9
|
+
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2015-07-16 00:00:00.000000000 Z
|
12
13
|
dependencies: []
|
13
|
-
description: Generates data to insert into database tables, allowing columns to be
|
14
|
-
defaulted or overriden. Intended to be used when testing wide tables where many
|
15
|
-
not null columns may need to be populated but are not part of the test
|
14
|
+
description: Generates data to insert into database tables, allowing columns to be defaulted or overriden. Intended to be used when testing wide tables where many not null columns may need to be populated but are not part of the test
|
16
15
|
email: stephen@betteratoracle.com
|
17
16
|
executables: []
|
18
17
|
extensions: []
|
19
18
|
extra_rdoc_files:
|
20
19
|
- README.md
|
21
20
|
files:
|
22
|
-
-
|
23
|
-
|
24
|
-
-
|
25
|
-
|
26
|
-
-
|
27
|
-
|
28
|
-
-
|
29
|
-
|
30
|
-
-
|
31
|
-
|
32
|
-
-
|
33
|
-
|
34
|
-
-
|
35
|
-
|
36
|
-
-
|
21
|
+
- !binary |-
|
22
|
+
dGVzdC9iYXNlX2FwaV90ZXN0LnJi
|
23
|
+
- !binary |-
|
24
|
+
dGVzdC9iYXNlX2RzbF90ZXN0LnJi
|
25
|
+
- !binary |-
|
26
|
+
dGVzdC9oZWxwZXIucmI=
|
27
|
+
- !binary |-
|
28
|
+
dGVzdC9zYW5pdHkucmI=
|
29
|
+
- !binary |-
|
30
|
+
dGVzdC90ZXN0X3J1bm5lci5yYg==
|
31
|
+
- !binary |-
|
32
|
+
bGliL2RhdGFfZmFjdG9yeS5yYg==
|
33
|
+
- !binary |-
|
34
|
+
bGliL2RhdGFfZmFjdG9yeS9iYXNlLnJi
|
35
|
+
- !binary |-
|
36
|
+
bGliL2RhdGFfZmFjdG9yeS9iYXNlX2FwaS5yYg==
|
37
|
+
- !binary |-
|
38
|
+
bGliL2RhdGFfZmFjdG9yeS9iYXNlX2RzbC5yYg==
|
39
|
+
- !binary |-
|
40
|
+
bGliL2RhdGFfZmFjdG9yeS9iYXNlX2ZhY3RvcnkucmI=
|
41
|
+
- !binary |-
|
42
|
+
bGliL2RhdGFfZmFjdG9yeS9jb2x1bW4ucmI=
|
43
|
+
- !binary |-
|
44
|
+
bGliL2RhdGFfZmFjdG9yeS9leGNlcHRpb25zLnJi
|
45
|
+
- !binary |-
|
46
|
+
bGliL2RhdGFfZmFjdG9yeS9yYW5kb20ucmI=
|
47
|
+
- !binary |-
|
48
|
+
UmFrZWZpbGUucmI=
|
49
|
+
- !binary |-
|
50
|
+
UkVBRE1FLm1k
|
37
51
|
homepage: http://betteratoracle.com
|
38
52
|
licenses: []
|
39
|
-
|
40
|
-
post_install_message:
|
53
|
+
post_install_message:
|
41
54
|
rdoc_options: []
|
42
55
|
require_paths:
|
43
56
|
- lib
|
44
57
|
required_ruby_version: !ruby/object:Gem::Requirement
|
45
58
|
requirements:
|
46
|
-
- - '>='
|
59
|
+
- - ! '>='
|
47
60
|
- !ruby/object:Gem::Version
|
48
|
-
version:
|
61
|
+
version: !binary |-
|
62
|
+
MA==
|
63
|
+
none: false
|
49
64
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
65
|
requirements:
|
51
|
-
- - '>='
|
66
|
+
- - ! '>='
|
52
67
|
- !ruby/object:Gem::Version
|
53
|
-
version:
|
68
|
+
version: !binary |-
|
69
|
+
MA==
|
70
|
+
none: false
|
54
71
|
requirements: []
|
55
|
-
rubyforge_project:
|
56
|
-
rubygems_version:
|
57
|
-
signing_key:
|
58
|
-
specification_version:
|
59
|
-
summary: A gem to generate template insert statements for use when unit testing database
|
60
|
-
code
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 1.8.25
|
74
|
+
signing_key:
|
75
|
+
specification_version: 3
|
76
|
+
summary: A gem to generate template insert statements for use when unit testing database code
|
61
77
|
test_files: []
|
78
|
+
has_rdoc: true
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: 9e822bc63cfb321de0f6c8c84644c1c34b1cf46e
|
4
|
-
data.tar.gz: 8669da85bf543f5f6cf3c96dbdf035211a973ea8
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: be85d1e78d4a80058fdb8b4dc4b81bae88679eafd27a5231cf4f461af621bb8c47a58a334f3b0c18863df1f9fa6a85ef44df976251fe52db463ea8ff2a8881d2
|
7
|
-
data.tar.gz: b30aedf808030b04d31f080a91b33b30f9bbcc297474d82ff193a06aa3f85d5e3c874fa9379b70e2ac8cb8076cfbe2cc6dde170e3aeea0d5fee51ce028b2e725
|