database_introspection 0.1.0 → 0.1.1
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.
- checksums.yaml +4 -4
- data/README.md +7 -2
- data/lib/database_introspection/dynamic_model.rb +42 -9
- data/lib/database_introspection/dynamic_model/active_record_extension.rb +5 -1
- data/lib/database_introspection/dynamic_model/domain_extension.rb +4 -0
- data/lib/database_introspection/dynamic_model/migration.rb +8 -1
- data/lib/database_introspection/dynamic_model/tables_analyser.rb +4 -2
- data/lib/database_introspection/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 25c5d7a4888eafde894853b452a714f634b652ae
|
|
4
|
+
data.tar.gz: eb2e2cedbe5a5ff900049ba10fd485a1ed70e9bb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 76cee6c4b5202dceb394f5efd85f67928d173b73ab52aa7d6bfd2eb2be6c6adb6fb131cd822f9655b977efddc2d303ea8ebe55c42648db9921a29015b7c5086b
|
|
7
|
+
data.tar.gz: 69824f5c5e775c980fe1081f48c83a02c3f88a4ca812c5643ea9ba25221f5eee1152e606a350816316607775b2ff1d908c885b3ab3c7710a6bd14be845dee8cd
|
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Database Introspection
|
|
2
2
|
|
|
3
|
-
This gem will introspect the database and create __dynamically__ ActiveRecord::Base descendants that can be used by your application, including some Rails associations helper methods.
|
|
3
|
+
[This gem][gemref] will introspect the database and create __dynamically__ ActiveRecord::Base descendants that can be used by your application, including some Rails associations helper methods.
|
|
4
4
|
|
|
5
5
|
It is intended to be primarily used within rails applications but nothing prevents you to use standalone, provided the fact you are already connected to a database.
|
|
6
6
|
This gem does a bit the reverse action of what you do with Rails generator, when you want to generate the database from you migrations.
|
|
@@ -20,6 +20,8 @@ Or install it yourself as:
|
|
|
20
20
|
|
|
21
21
|
$ gem install database_introspection
|
|
22
22
|
|
|
23
|
+
Classes documentation is available [here](http://rubydoc.info/gems/database_introspection/0.1.0/frames)
|
|
24
|
+
|
|
23
25
|
## Usage
|
|
24
26
|
|
|
25
27
|
### Basic database introspection
|
|
@@ -86,7 +88,7 @@ DynamicModel::ManagedDomains::AnotherDomain
|
|
|
86
88
|
|
|
87
89
|
The classes generated will actually have some behaviour added by extending the module `DynamicModel::ActiveRecordExtension` to basically be aware of the domain they belong to.
|
|
88
90
|
|
|
89
|
-
###
|
|
91
|
+
### Table relationships
|
|
90
92
|
|
|
91
93
|
Provided you follow the standard rails rules for ids, for example:
|
|
92
94
|
|
|
@@ -105,3 +107,6 @@ if `user_defined_table1` contains `user_defined_table2_id` or simply `table2_id`
|
|
|
105
107
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
106
108
|
4. Push to the branch (`git push origin my-new-feature`)
|
|
107
109
|
5. Create new Pull Request
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
[gemref]: https://rubygems.org/gems/database_introspection "Rails Database Introspection gem"
|
|
@@ -2,29 +2,62 @@ require 'active_record'
|
|
|
2
2
|
|
|
3
3
|
module DynamicModel
|
|
4
4
|
|
|
5
|
+
@domain_analyser ||= {}
|
|
6
|
+
|
|
5
7
|
# Creates ActiveRecord::Base descendants from the database.
|
|
6
8
|
# ActiveRecord descendant classes are dynamically created from database introspection in their own namespace
|
|
7
9
|
# (DynamicModel::<NameSpace>::) The name of the module NameSpace is derived from table_prefix.
|
|
8
10
|
def self.introspect_database(table_prefix = :user_defined, base_class = ActiveRecord::Base)
|
|
11
|
+
if table_prefix.class == Array
|
|
12
|
+
table_prefix.each {|p| self.introspect_database p, base_class}
|
|
13
|
+
return
|
|
14
|
+
end
|
|
9
15
|
table_prefix = table_prefix.to_s
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
# Confines Activerecord classes into a module named from table_prefix
|
|
13
|
-
@domain_analyser[table_prefix] ||= DynamicModel::TablesAnalyser.new table_prefix, base_class
|
|
14
|
-
klasses = @domain_analyser[table_prefix].scan_database
|
|
15
|
-
relation_analyser = RelationsAnalyser.new klasses
|
|
16
|
-
relation_analyser.run
|
|
16
|
+
analyse_domain table_prefix, base_class
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
# Creates a new table with auto numbered id in the database with the name prefix provided
|
|
20
20
|
# by creating a live migration.
|
|
21
21
|
# If block is provided it will behave like create_table method for migrations, allowing
|
|
22
22
|
# to create any other column.
|
|
23
|
-
def self.add_table(scoped_table_name, table_prefix: :user_defined, &block)
|
|
23
|
+
def self.add_table(scoped_table_name, table_prefix: :user_defined, base_class: ActiveRecord::Base, &block)
|
|
24
|
+
for_action_on_table(scoped_table_name, table_prefix) do |table_prefix, real_table_name|
|
|
25
|
+
Migration::create_for "#{table_prefix}_#{real_table_name}", &block
|
|
26
|
+
end
|
|
27
|
+
ensure
|
|
28
|
+
analyse_domain table_prefix, base_class
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# Modifies a table in the database with the name prefix provided by creating a live migration.
|
|
33
|
+
# If block is provided it will behave like create_table method for migrations, allowing
|
|
34
|
+
# to create any other column.
|
|
35
|
+
def self.alter_table(scoped_table_name, table_prefix: :user_defined, base_class: ActiveRecord::Base, &block)
|
|
36
|
+
raise "Missing block parameter" unless block_given?
|
|
37
|
+
for_action_on_table(scoped_table_name, table_prefix) do |table_prefix, real_table_name|
|
|
38
|
+
Migration::update_for "#{table_prefix}_#{real_table_name}", &block
|
|
39
|
+
end
|
|
40
|
+
ensure
|
|
41
|
+
analyse_domain table_prefix, base_class
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def self.for_action_on_table(scoped_table_name, table_prefix)
|
|
47
|
+
raise "Missing block parameter" unless block_given?
|
|
24
48
|
scoped_table_name = scoped_table_name.to_s
|
|
25
49
|
table_prefix = table_prefix.to_s
|
|
26
50
|
real_table_name = scoped_table_name.underscore.pluralize
|
|
27
|
-
|
|
51
|
+
yield table_prefix, real_table_name
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def self.analyse_domain(table_prefix, base_class)
|
|
55
|
+
# Confines Activerecord classes into a module named from table_prefix
|
|
56
|
+
@domain_analyser[table_prefix] ||= DynamicModel::TablesAnalyser.new table_prefix, base_class
|
|
57
|
+
raise "You cannot change the base class for a domain" unless @domain_analyser[table_prefix].base_class == base_class
|
|
58
|
+
klasses = @domain_analyser[table_prefix].scan_database
|
|
59
|
+
relation_analyser = RelationsAnalyser.new klasses
|
|
60
|
+
relation_analyser.run
|
|
28
61
|
end
|
|
29
62
|
|
|
30
63
|
|
|
@@ -25,13 +25,17 @@ module DynamicModel::ActiveRecordExtension
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def name_space
|
|
28
|
-
self.name.gsub(
|
|
28
|
+
self.name.gsub(/DynamicModel::ManagedDomains::([^:]+)::.*$/, "\\1") .underscore
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def list_name
|
|
32
32
|
self.name.gsub( /^.*::([^:]+)$/, "\\1") .underscore.pluralize
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
+
def alter(&block)
|
|
36
|
+
self.domain.alter_table(self.list_name, &block)
|
|
37
|
+
end
|
|
38
|
+
|
|
35
39
|
end
|
|
36
40
|
|
|
37
41
|
include InstanceMethods
|
|
@@ -22,6 +22,10 @@ module DynamicModel::DomainExtension
|
|
|
22
22
|
DynamicModel.add_table scoped_table_name, table_prefix: prefix, &block
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
def alter_table(scoped_table_name, &block)
|
|
26
|
+
DynamicModel.alter_table scoped_table_name, table_prefix: prefix, &block
|
|
27
|
+
end
|
|
28
|
+
|
|
25
29
|
def model_class(scoped_table_name)
|
|
26
30
|
Hash[scoped_table_names.zip model_classes][scoped_table_name]
|
|
27
31
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require 'active_record'
|
|
2
2
|
class DynamicModel::Migration < ActiveRecord::Migration
|
|
3
|
-
def self.
|
|
3
|
+
def self.create_for(name, &block)
|
|
4
4
|
create_table name.to_sym do |t|
|
|
5
5
|
block.call(t) if block_given?
|
|
6
6
|
begin
|
|
@@ -10,4 +10,11 @@ class DynamicModel::Migration < ActiveRecord::Migration
|
|
|
10
10
|
end
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
|
+
|
|
14
|
+
def self.update_for(name, &block)
|
|
15
|
+
change_table name.to_sym do |t|
|
|
16
|
+
block.call(t) if block_given?
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
13
20
|
end
|
|
@@ -2,7 +2,7 @@ require 'active_record'
|
|
|
2
2
|
|
|
3
3
|
class DynamicModel::TablesAnalyser
|
|
4
4
|
|
|
5
|
-
attr_reader :domain, :klasses_analysed
|
|
5
|
+
attr_reader :domain, :base_class, :klasses_analysed
|
|
6
6
|
|
|
7
7
|
def initialize(domain, base_class = ActiveRecord::Base)
|
|
8
8
|
@domain = domain
|
|
@@ -28,13 +28,15 @@ class DynamicModel::TablesAnalyser
|
|
|
28
28
|
if @domain_module.constants.include? short_model_name.to_sym
|
|
29
29
|
klass = @domain_module.const_get short_model_name
|
|
30
30
|
puts "Found #{klass.name} that already handles #{table_name}"
|
|
31
|
+
klass.reset_column_information
|
|
31
32
|
else
|
|
32
33
|
klass = @domain_module.const_set short_model_name, Class.new(@base_class)
|
|
33
34
|
puts "Created #{klass.name} to handle #{table_name}"
|
|
34
35
|
# Adds some class methods
|
|
35
36
|
klass.send :include, DynamicModel::ActiveRecordExtension
|
|
36
37
|
end
|
|
37
|
-
|
|
38
|
+
# Disables STI
|
|
39
|
+
klass.inheritance_column = nil
|
|
38
40
|
# Maps the class to the correct table
|
|
39
41
|
klass.table_name = table_name
|
|
40
42
|
# Adds attributes accessible for mass assign
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: database_introspection
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- L.Briais
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2013-05-
|
|
11
|
+
date: 2013-05-25 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|