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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fd6b1e340f5f576df0fdc03f994f376069ace956
4
- data.tar.gz: 0401ddeac82d36e2a54c214cea8cf9c303db3322
3
+ metadata.gz: 25c5d7a4888eafde894853b452a714f634b652ae
4
+ data.tar.gz: eb2e2cedbe5a5ff900049ba10fd485a1ed70e9bb
5
5
  SHA512:
6
- metadata.gz: 7452dd3c478d085d73c1ad3245fd75e5440814be8c8b0d464e182ee63afadebbe31626ed3e3cd080c74c5fd12a74d4d3a189abf4490ff28218c991b622e0938f
7
- data.tar.gz: 4292876722bf17e645aaefc7fafd33021a7ecc6ceb239248a1449b78c8f0b504ea69200c274663e3a3baabd66f6aae1dc92060abdea8bf7972e8329f4889233b
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
- ### Database relationships
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
- @domain_analyser ||= {}
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
- Migration::create_with "#{table_prefix}_#{real_table_name}", &block
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( /DynamicModel::ManagedDomains::([^:]+)::.*$/, "\\1") .underscore
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.create_with(name, &block)
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
@@ -1,3 +1,3 @@
1
1
  module DatabaseIntrospection
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
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.0
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-18 00:00:00.000000000 Z
11
+ date: 2013-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler