database_introspection 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|