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 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 #{table_name} ("
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 'CHAR', 'VARCHAR2', 'CLOB'
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', 'TIMESTAMP'
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
- random_integer(9999)
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', 'TIMESTAMP'
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 #{table_name}"
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
- @table_name = tab.to_s.upcase
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 user_tab_columns
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
@@ -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
 
@@ -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)
@@ -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
@@ -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', 'local11gr2.world', 'localhost', '1521')
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 "employees"
15
- set_column_default "EMP_NAME", 'john'
14
+ set_table_name "sodonnel.employee"
15
+ set_column_default "FIRST_NAME", 'john'
16
16
  end
17
17
 
18
18
 
19
- f = Foo.create!("emp_id" => 1001)
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.2.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: 2013-11-20 00:00:00.000000000 Z
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
- - test/base_api_test.rb
23
- - test/base_dsl_test.rb
24
- - test/helper.rb
25
- - test/sanity.rb
26
- - test/test_runner.rb
27
- - lib/data_factory/base.rb
28
- - lib/data_factory/base_api.rb
29
- - lib/data_factory/base_dsl.rb
30
- - lib/data_factory/base_factory.rb
31
- - lib/data_factory/column.rb
32
- - lib/data_factory/exceptions.rb
33
- - lib/data_factory/random.rb
34
- - lib/data_factory.rb
35
- - Rakefile.rb
36
- - README.md
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
- metadata: {}
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: '0'
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: '0'
68
+ version: !binary |-
69
+ MA==
70
+ none: false
54
71
  requirements: []
55
- rubyforge_project:
56
- rubygems_version: 2.0.3
57
- signing_key:
58
- specification_version: 4
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