database-model-generator 0.6.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.
@@ -0,0 +1,176 @@
1
+ require 'spec_helper'
2
+ require 'support/oracle_connection'
3
+ require 'oracle/model/generator'
4
+
5
+ RSpec.describe Oracle::Model::Generator do
6
+ include_context 'Oracle connection'
7
+
8
+ let(:generator) { described_class.new(connection) }
9
+
10
+ describe 'class information' do
11
+ it 'has the correct version number' do
12
+ expect(Oracle::Model::Generator::VERSION).to eq('0.5.0')
13
+ end
14
+ end
15
+
16
+ describe '#initialize' do
17
+ it 'accepts an OCI8 connection object' do
18
+ expect { described_class.new(connection) }.not_to raise_error
19
+ end
20
+
21
+ it 'sets up instance variables correctly' do
22
+ expect(generator.connection).to eq(connection)
23
+ expect(generator.constraints).to eq([])
24
+ expect(generator.primary_keys).to eq([])
25
+ expect(generator.foreign_keys).to eq([])
26
+ expect(generator.dependencies).to eq([])
27
+ expect(generator.belongs_to).to eq([])
28
+ expect(generator.column_info).to eq([])
29
+ expect(generator.table).to be_nil
30
+ expect(generator.model).to be_nil
31
+ end
32
+ end
33
+
34
+ describe '#generate' do
35
+ it 'responds to the generate method' do
36
+ expect(generator).to respond_to(:generate)
37
+ end
38
+
39
+ it 'works with a table name' do
40
+ expect { generator.generate('employees') }.not_to raise_error
41
+ end
42
+
43
+ it 'works with a view name' do
44
+ expect { generator.generate('emp_details_view', true) }.not_to raise_error
45
+ end
46
+
47
+ context 'when generating from a table' do
48
+ before { generator.generate('employees') }
49
+
50
+ it 'sets the table name in uppercase' do
51
+ expect(generator.table).to eq('EMPLOYEES')
52
+ end
53
+
54
+ it 'generates a model name from the table name' do
55
+ expect(generator.model).to eq('Employee')
56
+ end
57
+
58
+ it 'sets view to false' do
59
+ expect(generator.view).to be false
60
+ end
61
+
62
+ it 'populates column information' do
63
+ expect(generator.column_info).to be_an(Array)
64
+ expect(generator.column_info).not_to be_empty
65
+ end
66
+
67
+ it 'finds primary keys' do
68
+ expect(generator.primary_keys).to be_an(Array)
69
+ expect(generator.primary_keys).to include('employee_id')
70
+ end
71
+
72
+ it 'populates constraints information' do
73
+ expect(generator.constraints).to be_an(Array)
74
+ expect(generator.constraints).not_to be_empty
75
+ end
76
+ end
77
+
78
+ context 'when generating from a view' do
79
+ before { generator.generate('emp_details_view', true) }
80
+
81
+ it 'sets the table name in uppercase' do
82
+ expect(generator.table).to eq('EMP_DETAILS_VIEW')
83
+ end
84
+
85
+ it 'generates the correct model name' do
86
+ expect(generator.model).to eq('EmpDetailsView')
87
+ end
88
+
89
+ it 'sets view to true' do
90
+ expect(generator.view).to be true
91
+ end
92
+ end
93
+ end
94
+
95
+ describe '#model' do
96
+ it 'returns the active record model name' do
97
+ generator.generate('emp_details_view', true)
98
+ expect(generator).to respond_to(:model)
99
+ expect(generator.model).to eq('EmpDetailsView')
100
+ end
101
+
102
+ it 'removes trailing s from model names' do
103
+ generator.generate('employees')
104
+ expect(generator.model).to eq('Employee')
105
+ end
106
+ end
107
+
108
+ describe '#table' do
109
+ it 'returns the uppercased table name' do
110
+ generator.generate('emp_details_view', true)
111
+ expect(generator).to respond_to(:table)
112
+ expect(generator.table).to eq('EMP_DETAILS_VIEW')
113
+ end
114
+ end
115
+
116
+ describe '#primary_keys' do
117
+ it 'returns an array of primary keys' do
118
+ generator.generate('employees')
119
+ expect(generator.primary_keys).to be_an(Array)
120
+ expect(generator.primary_keys).to include('employee_id')
121
+ end
122
+ end
123
+
124
+ describe '#column_info' do
125
+ it 'returns an array of column metadata' do
126
+ generator.generate('employees')
127
+ expect(generator.column_info).to be_an(Array)
128
+ expect(generator.column_info.length).to be > 0
129
+ end
130
+ end
131
+
132
+ describe '#constraints' do
133
+ it 'returns an array of constraint information' do
134
+ generator.generate('employees')
135
+ expect(generator.constraints).to be_an(Array)
136
+ expect(generator.constraints).not_to be_empty
137
+ end
138
+ end
139
+
140
+ describe '#foreign_keys' do
141
+ it 'returns an array of foreign key names' do
142
+ generator.generate('employees')
143
+ expect(generator.foreign_keys).to be_an(Array)
144
+ end
145
+ end
146
+
147
+ describe '#belongs_to' do
148
+ it 'returns an array of parent tables' do
149
+ generator.generate('employees')
150
+ expect(generator.belongs_to).to be_an(Array)
151
+ end
152
+ end
153
+
154
+ describe '#dependencies' do
155
+ it 'returns an array of dependent objects' do
156
+ generator.generate('employees', true)
157
+ expect(generator).to respond_to(:dependencies)
158
+ expect(generator.dependencies).to be_an(Array)
159
+
160
+ # Only check for Hash if there are dependencies
161
+ if generator.dependencies.any?
162
+ expect(generator.dependencies.first).to be_a(Hash)
163
+ end
164
+ end
165
+ end
166
+
167
+ describe '#view' do
168
+ it 'correctly identifies tables vs views' do
169
+ generator.generate('employees')
170
+ expect(generator.view).to be false
171
+
172
+ generator.generate('emp_details_view', true)
173
+ expect(generator.view).to be true
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,30 @@
1
+ # Load the library we're testing
2
+ require_relative '../lib/oracle-model-generator'
3
+
4
+ # RSpec configuration for Oracle Model Generator
5
+ RSpec.configure do |config|
6
+ # Use the expect() syntax rather than should syntax
7
+ config.expect_with :rspec do |expectations|
8
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
9
+ end
10
+
11
+ # Use the new mock framework syntax
12
+ config.mock_with :rspec do |mocks|
13
+ mocks.verify_partial_doubles = true
14
+ end
15
+
16
+ # Enable color output
17
+ config.color = true
18
+
19
+ # Use documentation format for output
20
+ config.formatter = :documentation
21
+
22
+ # Run specs in random order to surface order dependencies
23
+ config.order = :random
24
+
25
+ # Allow filtering tests by tags
26
+ config.filter_run_when_matching :focus
27
+
28
+ # Shared context for setting up test data
29
+ config.shared_context_metadata_behavior = :apply_to_host_groups
30
+ end
@@ -0,0 +1,126 @@
1
+ require 'oci8'
2
+
3
+ # Shared context for Oracle database connection and test data
4
+ RSpec.shared_context 'Oracle connection' do
5
+ before(:context) do
6
+ @oracle_connection = begin
7
+ # In Docker environment, use the service name instead of localhost
8
+ host = ENV['ORACLE_HOST'] || 'localhost'
9
+ port = ENV['ORACLE_PORT'] || '1521'
10
+ sid = ENV['ORACLE_SID'] || 'freepdb1'
11
+ database_str = "#{host}:#{port}/#{sid}"
12
+
13
+ OCI8.new(
14
+ ENV['ORACLE_USER'] || 'hr',
15
+ ENV['ORACLE_PASSWORD'] || 'oracle',
16
+ database_str
17
+ )
18
+ rescue OCIError => e
19
+ warn "Database connection failed: #{e.message}"
20
+ warn "Make sure Oracle database is running and accessible"
21
+ warn "Connection string: #{ENV['ORACLE_HOST'] || 'localhost'}:#{ENV['ORACLE_PORT'] || '1521'}/#{ENV['ORACLE_SID'] || 'freepdb1'}"
22
+ warn "User: #{ENV['ORACLE_USER'] || 'hr'}"
23
+ raise e
24
+ end
25
+ setup_test_data
26
+ end
27
+
28
+ after(:context) do
29
+ # Cleanup test tables and views
30
+ cleanup_test_data
31
+
32
+ # Close the connection
33
+ @oracle_connection&.logoff
34
+ end
35
+
36
+ # Use a method instead of let for context-level variables
37
+ def connection
38
+ @oracle_connection
39
+ end
40
+
41
+ private
42
+
43
+ def setup_test_data
44
+ # Create test tables and views if they don't exist
45
+ setup_sample_data
46
+ end
47
+
48
+ def cleanup_test_data
49
+ # Drop test views first (to avoid dependency issues)
50
+ begin
51
+ @oracle_connection.exec('DROP VIEW hr.employees_by_department') rescue nil
52
+ rescue => e
53
+ # Ignore errors if views don't exist
54
+ end
55
+
56
+ # Note: We don't drop HR schema tables as they might be used by other tests
57
+ end
58
+
59
+ def setup_sample_data
60
+ # Check if employees table exists and has data
61
+ begin
62
+ cursor = @oracle_connection.parse('SELECT COUNT(*) FROM employees')
63
+ cursor.exec
64
+ count = cursor.fetch[0]
65
+ cursor.close
66
+
67
+ if count == 0
68
+ # Insert sample data into employees table
69
+ @oracle_connection.exec(<<~SQL)
70
+ INSERT INTO employees (employee_id, first_name, last_name, email, phone_number,
71
+ hire_date, job_id, salary, commission_pct, manager_id, department_id)
72
+ VALUES (1, 'John', 'Doe', 'john.doe@example.com', '555-1234',
73
+ DATE '2020-01-15', 'IT_PROG', 5000, NULL, NULL, 60)
74
+ SQL
75
+
76
+ @oracle_connection.exec(<<~SQL)
77
+ INSERT INTO employees (employee_id, first_name, last_name, email, phone_number,
78
+ hire_date, job_id, salary, commission_pct, manager_id, department_id)
79
+ VALUES (2, 'Jane', 'Smith', 'jane.smith@example.com', '555-5678',
80
+ DATE '2021-03-10', 'IT_PROG', 5500, NULL, 1, 60)
81
+ SQL
82
+
83
+ @oracle_connection.commit
84
+ end
85
+
86
+ # Check if departments table exists and has data
87
+ cursor = @oracle_connection.parse('SELECT COUNT(*) FROM departments')
88
+ cursor.exec
89
+ dept_count = cursor.fetch[0]
90
+ cursor.close
91
+
92
+ if dept_count == 0
93
+ # Insert sample data into departments table
94
+ @oracle_connection.exec(<<~SQL)
95
+ INSERT INTO departments (department_id, department_name, manager_id, location_id)
96
+ VALUES (60, 'IT', 1, 1700)
97
+ SQL
98
+
99
+ @oracle_connection.exec(<<~SQL)
100
+ INSERT INTO departments (department_id, department_name, manager_id, location_id)
101
+ VALUES (50, 'Shipping', NULL, 1500)
102
+ SQL
103
+
104
+ @oracle_connection.commit
105
+ end
106
+
107
+ # Create a test view if it doesn't exist
108
+ begin
109
+ @oracle_connection.exec(<<~SQL)
110
+ CREATE OR REPLACE VIEW hr.employees_by_department AS
111
+ SELECT e.employee_id, e.first_name, e.last_name, e.email,
112
+ d.department_name, d.department_id
113
+ FROM employees e
114
+ JOIN departments d ON e.department_id = d.department_id
115
+ SQL
116
+ rescue => e
117
+ # View creation might fail if tables don't exist yet, that's okay
118
+ warn "Could not create test view: #{e.message}"
119
+ end
120
+
121
+ rescue => e
122
+ warn "Could not set up sample data: #{e.message}"
123
+ # Continue with tests even if sample data setup fails
124
+ end
125
+ end
126
+ end
data.tar.gz.sig ADDED
Binary file
metadata ADDED
@@ -0,0 +1,162 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: database-model-generator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.6.0
5
+ platform: ruby
6
+ authors:
7
+ - Daniel J. Berger
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIEcDCCAtigAwIBAgIBATANBgkqhkiG9w0BAQsFADA/MREwDwYDVQQDDAhkamJl
14
+ cmc5NjEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYDY29t
15
+ MB4XDTE4MDMxODE1MjIwN1oXDTI4MDMxNTE1MjIwN1owPzERMA8GA1UEAwwIZGpi
16
+ ZXJnOTYxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
17
+ bTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALgfaroVM6CI06cxr0/h
18
+ A+j+pc8fgpRgBVmHFaFunq28GPC3IvW7Nvc3Y8SnAW7pP1EQIbhlwRIaQzJ93/yj
19
+ u95KpkP7tA9erypnV7dpzBkzNlX14ACaFD/6pHoXoe2ltBxk3CCyyzx70mTqJpph
20
+ 75IB03ni9a8yqn8pmse+s83bFJOAqddSj009sGPcQO+QOWiNxqYv1n5EHcvj2ebO
21
+ 6hN7YTmhx7aSia4qL/quc4DlIaGMWoAhvML7u1fmo53CYxkKskfN8MOecq2vfEmL
22
+ iLu+SsVVEAufMDDFMXMJlvDsviolUSGMSNRTujkyCcJoXKYYxZSNtIiyd9etI0X3
23
+ ctu0uhrFyrMZXCedutvXNjUolD5r9KGBFSWH1R9u2I3n3SAyFF2yzv/7idQHLJJq
24
+ 74BMnx0FIq6fCpu5slAipvxZ3ZkZpEXZFr3cIBtO1gFvQWW7E/Y3ijliWJS1GQFq
25
+ 058qERadHGu1yu1dojmFRo6W2KZvY9al2yIlbkpDrD5MYQIDAQABo3cwdTAJBgNV
26
+ HRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUFZsMapgzJimzsbaBG2Tm8j5e
27
+ AzgwHQYDVR0RBBYwFIESZGpiZXJnOTZAZ21haWwuY29tMB0GA1UdEgQWMBSBEmRq
28
+ YmVyZzk2QGdtYWlsLmNvbTANBgkqhkiG9w0BAQsFAAOCAYEAW2tnYixXQtKxgGXq
29
+ /3iSWG2bLwvxS4go3srO+aRXZHrFUMlJ5W0mCxl03aazxxKTsVVpZD8QZxvK91OQ
30
+ h9zr9JBYqCLcCVbr8SkmYCi/laxIZxsNE5YI8cC8vvlLI7AMgSfPSnn/Epq1GjGY
31
+ 6L1iRcEDtanGCIvjqlCXO9+BmsnCfEVehqZkQHeYczA03tpOWb6pon2wzvMKSsKH
32
+ ks0ApVdstSLz1kzzAqem/uHdG9FyXdbTAwH1G4ZPv69sQAFAOCgAqYmdnzedsQtE
33
+ 1LQfaQrx0twO+CZJPcRLEESjq8ScQxWRRkfuh2VeR7cEU7L7KqT10mtUwrvw7APf
34
+ DYoeCY9KyjIBjQXfbj2ke5u1hZj94Fsq9FfbEQg8ygCgwThnmkTrrKEiMSs3alYR
35
+ ORVCZpRuCPpmC8qmqxUnARDArzucjaclkxjLWvCVHeFa9UP7K3Nl9oTjJNv+7/jM
36
+ WZs4eecIcUc4tKdHxcAJ0MO/Dkqq7hGaiHpwKY76wQ1+8xAh
37
+ -----END CERTIFICATE-----
38
+ date: 2025-07-24 00:00:00.000000000 Z
39
+ dependencies:
40
+ - !ruby/object:Gem::Dependency
41
+ name: getopt
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.6'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.6'
54
+ - !ruby/object:Gem::Dependency
55
+ name: rspec
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '3.12'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '3.12'
68
+ - !ruby/object:Gem::Dependency
69
+ name: ruby-oci8
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '2.2'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '2.2'
82
+ - !ruby/object:Gem::Dependency
83
+ name: tiny_tds
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: 3.2.1
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: 3.2.1
96
+ description: |2
97
+ The database-model-generator library allows you to generate an ActiveRecord
98
+ model from an existing Oracle table or view, as well as automatically
99
+ generate a baseline test file for test-unit or minitest.
100
+ email: djberg96@gmail.com
101
+ executables:
102
+ - dmg
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - CHANGES.md
107
+ - Gemfile
108
+ - LICENSE
109
+ - MANIFEST.md
110
+ - README.md
111
+ - Rakefile
112
+ - bin/dmg
113
+ - certs/djberg96_pub.pem
114
+ - database-model-generator.gemspec
115
+ - docker/README.md
116
+ - docker/oracle/Dockerfile
117
+ - docker/oracle/README.md
118
+ - docker/oracle/docker-compose.yml
119
+ - docker/oracle/test.sh
120
+ - docker/sqlserver/DOCKER.md
121
+ - docker/sqlserver/Dockerfile
122
+ - docker/sqlserver/SUPPORT.md
123
+ - docker/sqlserver/TESTING.md
124
+ - docker/sqlserver/docker-compose.yml
125
+ - docker/sqlserver/init-db.sql
126
+ - docker/sqlserver/run_tests.sh
127
+ - docker/sqlserver/setup-db.sh
128
+ - docker/sqlserver/test-Dockerfile
129
+ - docker/sqlserver/test.sh
130
+ - lib/database_model_generator.rb
131
+ - lib/oracle/model/generator.rb
132
+ - lib/sqlserver/model/generator.rb
133
+ - spec/oracle_model_generator_spec.rb
134
+ - spec/spec_helper.rb
135
+ - spec/support/oracle_connection.rb
136
+ homepage: http://www.github.com/djberg96/database-model-generator
137
+ licenses:
138
+ - Apache-2.0
139
+ metadata: {}
140
+ post_install_message:
141
+ rdoc_options: []
142
+ require_paths:
143
+ - lib
144
+ required_ruby_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ required_rubygems_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ requirements: []
155
+ rubygems_version: 3.5.22
156
+ signing_key:
157
+ specification_version: 4
158
+ summary: A Ruby library for generating Rails AR models from existing tables.
159
+ test_files:
160
+ - spec/oracle_model_generator_spec.rb
161
+ - spec/spec_helper.rb
162
+ - spec/support/oracle_connection.rb
metadata.gz.sig ADDED
Binary file