database_introspection 0.0.9

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cb2ff4ce8131add8f4e7cfc4830240d8ba45df98
4
+ data.tar.gz: 524b268bdb6f8f11bd6ef6798c00dbf5c5e34bff
5
+ SHA512:
6
+ metadata.gz: ac56205a6698c903436d4d5935861abad37fce34a7fc0e3652b5f33def754270fb71af500e4dff03a77d9a5ac93efd6456e29787ca0036302cfc83f5d2fc397c
7
+ data.tar.gz: 3f8fd05f31a29d3cecf0b72d29427c1d5c9121cb42736a96cde92a49bff786f62026ac59e1e6c893ca619dd28a989503bc0050be6026c5c040c703dc059edf70
data/.gitignore ADDED
@@ -0,0 +1,47 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ # Standard
19
+ *~
20
+ # Standard Rails project
21
+ /tmp/
22
+ /log/
23
+ /db/*.sqlite3
24
+ # SASS CSS generation
25
+ /public/stylesheets/.sass-cache/
26
+ # Netbeans
27
+ /nbproject/
28
+ # Sublime Text 2 project
29
+ *.sublime-project
30
+ *.sublime-workspace
31
+ *(copie)*
32
+ # RVM
33
+ .rvmrc
34
+ # VisualRuby
35
+ .vr_settings.yaml
36
+ # Emacs
37
+ *#
38
+ *\#
39
+ \#*
40
+ .#*
41
+ \#*\#
42
+ # Geany
43
+ *.geany
44
+ # RubyMine
45
+ .idea
46
+ #RedCar
47
+ .redcar
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in database_introspection.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Laurent
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,107 @@
1
+ # Database Introspection
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.
4
+
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
+ 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.
7
+
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ gem 'database_introspection'
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install database_introspection
22
+
23
+ ## Usage
24
+
25
+ ### Basic database introspection
26
+
27
+ To introspect the database, you just have to call the following method:
28
+
29
+ ```ruby
30
+ DynamicModel.introspect_database
31
+ ```
32
+
33
+ By default it will analyse all database tables starting by "user_defined_", and will create ActiveRecord::Base descendant to handle them.
34
+
35
+ For example if your database contains the following tables:
36
+
37
+ ```
38
+ user_defined_table1
39
+ user_defined_table2
40
+ user_defined_table3
41
+ user_defined_table4
42
+ ```
43
+ The call to `DynamicModel.introspect_database`, will inject the following classes in your application:
44
+
45
+ ```ruby
46
+ DynamicModel::ManagedDomains::UserDefined::Table1
47
+ DynamicModel::ManagedDomains::UserDefined::Table2
48
+ DynamicModel::ManagedDomains::UserDefined::Table3
49
+ DynamicModel::ManagedDomains::UserDefined::Table4
50
+ ```
51
+
52
+ ### Architecture
53
+
54
+ #### Classes and modules generated
55
+
56
+ * `DynamicModel` is the module that contains methods to introspect the database.
57
+ * `DynamicModel::ManagedDomain` contains some methods to manipulate the domains introspected.
58
+ * Then for example in the first example, `DynamicModel::ManagedDomains::UserDefined` is a module created dynamically from the domain name (ie tables prefix). It contains itself some methods to easily manipulate the tables or generated classes of this particular domain.
59
+ * The `DynamicModel::ManagedDomains::UserDefined::Tablex` classes are descendants of ActiveRecord::Base that you will use in your application.
60
+
61
+ Of course if you provide another domain name (ie tables prefix) the corresponding modules and classes will be created accordingly. Running:
62
+
63
+ ```ruby
64
+ DynamicModel.introspect_database :another_domain
65
+ ```
66
+
67
+ On a database containing the following tables:
68
+
69
+ ```
70
+ another_domain_table1
71
+ another_domain_table2
72
+ ```
73
+
74
+ Will inject the following classes in your application:
75
+
76
+ ```ruby
77
+ DynamicModel::ManagedDomains::AnotherDomain::Table1
78
+ DynamicModel::ManagedDomains::AnotherDomain::Table2
79
+ ```
80
+ and of course the following module:
81
+ ```ruby
82
+ DynamicModel::ManagedDomains::AnotherDomain
83
+ ```
84
+
85
+ #### Generated classes
86
+
87
+ 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
+
89
+ ### Database relationships
90
+
91
+ Provided you follow the standard rails rules for ids, for example:
92
+
93
+ if `user_defined_table1` contains `user_defined_table2_id` (not yet implemented) or `table2_id`, the introspector will understand there is a relationship between the tables and create the ActiveRecord associations accordingly adding all the standard helper methods to the generated classes !
94
+
95
+ ## To do
96
+
97
+ * Improve Readme.
98
+ * Add code comments.
99
+ * Improve table relationship introspection.
100
+
101
+ ## Contributing
102
+
103
+ 1. Fork it
104
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
105
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
106
+ 4. Push to the branch (`git push origin my-new-feature`)
107
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'database_introspection/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "database_introspection"
8
+ spec.version = DatabaseIntrospection::VERSION
9
+ spec.authors = ["L.Briais"]
10
+ spec.email = ["lbnetid+rb@gmail.com"]
11
+ spec.description = %q{This gem will generate classes (by default ActiveRecord::Base descendants) from database introspection}
12
+ spec.summary = %q{Database Introspection}
13
+ spec.homepage = "https://github.com/lbriais/database_introspection"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+
24
+ spec.add_runtime_dependency "activemodel", ">= 3.2.13"
25
+ spec.add_runtime_dependency "activerecord", ">= 3.2.13"
26
+ spec.add_runtime_dependency "activeresource", ">= 3.2.13"
27
+ spec.add_runtime_dependency "activesupport", ">= 3.2.13"
28
+
29
+
30
+ end
@@ -0,0 +1,39 @@
1
+ module DynamicModel::ActiveRecordExtension
2
+
3
+ def self.included(base) # :nodoc:
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ # Be very careful with what is added here as it may conflict with whatever is generated by active record.
8
+ module InstanceMethods
9
+
10
+ end
11
+
12
+ # This one, only for the class
13
+ module ClassMethods
14
+ def to_param
15
+ "#{self.name_space}/#{self.list_name}"
16
+ end
17
+
18
+ def display_name
19
+ self.name.gsub(/^.*::([^:]+)$/, "\\1").titleize
20
+ end
21
+
22
+ def domain
23
+ puts name.gsub(/^.*::[^:]+$/, '')
24
+ name.gsub(/::[^:]+$/, '').constantize
25
+ end
26
+
27
+ def name_space
28
+ self.name.gsub( /DynamicModel::ManagedDomains::([^:]+)::.*$/, "\\1") .underscore
29
+ end
30
+
31
+ def list_name
32
+ self.name.gsub( /^.*::([^:]+)$/, "\\1") .underscore.pluralize
33
+ end
34
+
35
+ end
36
+
37
+ include InstanceMethods
38
+
39
+ end
@@ -0,0 +1,28 @@
1
+ require 'active_record'
2
+
3
+ module DynamicModel::DomainExtension
4
+
5
+ def model_classes
6
+ self.constants.map {|sym| "#{self.name}::#{sym.to_s}".constantize}
7
+ end
8
+
9
+ def table_names
10
+ ActiveRecord::Base.connection.tables.grep(/^#{prefix}_/)
11
+ end
12
+
13
+ def scoped_table_names
14
+ table_names.map{|table_name| table_name.gsub /^#{prefix}_/, ''}
15
+ end
16
+
17
+ def prefix
18
+ DynamicModel::ManagedDomains.to_hash[self]
19
+ end
20
+
21
+ def add_table(scoped_table_name, &block)
22
+ DynamicModel.add_table scoped_table_name, table_prefix: prefix, &block
23
+ end
24
+
25
+ def model_class(scoped_table_name)
26
+ Hash[scoped_table_names.zip model_classes][scoped_table_name]
27
+ end
28
+ end
@@ -0,0 +1,23 @@
1
+ # Namespace for domains
2
+ module DynamicModel::ManagedDomains
3
+ def self.domain_prefixes
4
+ constants.map {|c| c.to_s.underscore}
5
+ end
6
+
7
+ def self.domain_modules
8
+ constants.map {|c| "#{self.name}::#{c.to_s}".constantize}
9
+ end
10
+
11
+ def self.to_hash
12
+ Hash[domain_modules.zip domain_prefixes]
13
+ end
14
+
15
+ def self.tables
16
+ self.domain_modules.map {|mod| mod.table_names}.flatten
17
+ end
18
+
19
+ def self.domain_module(table_prefix)
20
+ Hash[domain_prefixes.zip domain_modules][table_prefix]
21
+ end
22
+
23
+ end
@@ -0,0 +1,13 @@
1
+ require 'active_record'
2
+ class DynamicModel::Migration < ActiveRecord::Migration
3
+ def self.create_with(name, &block)
4
+ create_table name.to_sym do |t|
5
+ block.call(t) if block_given?
6
+ begin
7
+ t.timestamps
8
+ rescue
9
+ puts "Cannot create timestamps... Probably already created."
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,163 @@
1
+ # -*- coding: utf-8 -*-
2
+ class DynamicModel::RelationsAnalyser
3
+ KEY_IDENTIFIER = /_id$/
4
+
5
+ attr_reader :alterations
6
+
7
+ def initialize(klasses)
8
+ @klasses = klasses
9
+ @alterations = {}
10
+ end
11
+
12
+ def run
13
+ raise "cannot rerun analysis with the same object... Create a new instance !" if @did_run
14
+ return if @klasses.empty?
15
+ @domain = @klasses[0].domain
16
+ introspect_belongs_to
17
+ verify_if_has_many_relations_could_be_actually_has_one
18
+ discover_has_many_through_from_belongs_to
19
+ apply_alterations
20
+ @did_run = true
21
+ end
22
+
23
+
24
+ private
25
+
26
+ def discover_has_many_through_from_belongs_to
27
+ puts "Has_many_through analysis started."
28
+ @alterations.each do |model, alterations|
29
+ alterations[:has_many_though] ||= []
30
+ alterations.each do |association_type, associations|
31
+ next unless association_type == :belongs_to
32
+ # If there is only one belongs_to, there cannot be a has_many_through
33
+ next if associations.size < 2
34
+ analyses_has_many_through_association model, associations
35
+ end
36
+ end
37
+ ensure
38
+ puts "Has_many_though analysis completed."
39
+ end
40
+
41
+ def introspect_belongs_to
42
+ puts "Belongs_to analysis started."
43
+ scoped_table_names_hash = Hash[@domain.scoped_table_names.zip @domain.model_classes]
44
+ @klasses.each do |klass|
45
+ @alterations[klass] ||= {}
46
+ # Find attributes ending by "_id"
47
+ klass.attribute_names.grep(KEY_IDENTIFIER) do |attr_name|
48
+ if klass.columns_hash[attr_name].type == :integer
49
+ # Check if there is a table in the domain that may be linked to this field
50
+ candidate_table_name = attr_name.gsub(KEY_IDENTIFIER, '').pluralize
51
+ candidate_target_class = scoped_table_names_hash[candidate_table_name]
52
+ # Creates a belongs_to relation
53
+ if scoped_table_names_hash.keys.include? candidate_table_name
54
+ @alterations[klass][:belongs_to] ||= []
55
+ @alterations[klass][:belongs_to] << {
56
+ key: attr_name,
57
+ class: candidate_target_class
58
+ }
59
+ # and the reverse, by default has_many
60
+ @alterations[candidate_target_class] ||= {}
61
+ @alterations[candidate_target_class][:has_many] ||= []
62
+ @alterations[candidate_target_class][:has_many] << {
63
+ class: klass
64
+ }
65
+ end
66
+ end
67
+ end
68
+ end
69
+ ensure
70
+ puts "Belongs_to analysis completed."
71
+ end
72
+
73
+
74
+ def verify_if_has_many_relations_could_be_actually_has_one
75
+ puts "Has_many analysis started."
76
+ @alterations.each do |model, alterations|
77
+ alterations[:has_one] ||= []
78
+ alterations.each do |association_type, associations|
79
+ next unless association_type == :has_many
80
+ associations.map! do |description|
81
+ if analyses_has_many_association model, description
82
+ # This is actually a has_one
83
+ alterations[:has_one] << description
84
+ nil
85
+ else
86
+ description
87
+ end
88
+ end
89
+ associations.compact!
90
+ end
91
+ end
92
+ ensure
93
+ puts "Has_many analysis completed."
94
+ end
95
+
96
+ def analyses_has_many_through_association(model, associations)
97
+ # As there are multiple belongs_to in this class, all combinations
98
+ # should lead to a has_many_through
99
+ # Waouh, Ruby rocks !!
100
+ associations.combination(2).each do |left, right|
101
+ @alterations[left[:class]][:has_many_through] ||= []
102
+ @alterations[right[:class]][:has_many_through] ||= []
103
+
104
+
105
+ @alterations[left[:class]][:has_many_through] << {
106
+ self_key: left[:key],
107
+ key: right[:key],
108
+ middle_class: model,
109
+ class: right[:class]
110
+ }
111
+ @alterations[right[:class]][:has_many_through] << {
112
+ self_key: right[:key],
113
+ key: left[:key],
114
+ middle_class: model,
115
+ class: left[:class]
116
+ }
117
+ end
118
+ end
119
+
120
+ def analyses_has_many_association(model, description)
121
+ # If one day I figure out how to determine if a has_many relation could be a has_one,
122
+ # should be implemented here... Doesn't look like solvable...
123
+ false
124
+ end
125
+
126
+
127
+ def apply_alterations
128
+ @alterations.each do |model, alterations|
129
+ puts "Processing alterations for #{model.list_name}"
130
+ alterations.each do |association_type, associations|
131
+ associations.each do |description|
132
+ method_name = "add_#{association_type}_behaviour"
133
+ self.send method_name, model, description
134
+ end
135
+ end
136
+ end
137
+ end
138
+
139
+
140
+ def add_belongs_to_behaviour(model, description)
141
+ field_name = description[:key].gsub KEY_IDENTIFIER, ''
142
+ model.belongs_to field_name, :foreign_key => description[:key], :class_name => description[:class].name
143
+ puts " - belongs_to :#{field_name}, :foreign_key => #{description[:key]}, :class_name => #{description[:class].name}"
144
+ end
145
+
146
+ def add_has_many_behaviour(model, description)
147
+ field_name = description[:class].list_name
148
+ model.has_many field_name, :class_name => description[:class].name
149
+ puts " - has_many :#{field_name}, :class_name => #{description[:class].name}"
150
+ end
151
+
152
+ def add_has_many_through_behaviour(model, description)
153
+ puts " - has_many #{description[:class]} through #{description[:middle_class]}"
154
+ end
155
+
156
+
157
+ def add_has_one_behaviour(model, description)
158
+ field_name = description[:class].list_name.singularize
159
+ model.has_one field_name, :class_name => description[:class].name
160
+ puts " - has_one :#{field_name}, :class_name => #{description[:class].name}"
161
+ end
162
+
163
+ end
@@ -0,0 +1,56 @@
1
+ require 'active_record'
2
+
3
+ class DynamicModel::TablesAnalyser
4
+
5
+ attr_reader :domain, :klasses_analysed
6
+
7
+ def initialize(domain, base_class = ActiveRecord::Base)
8
+ @domain = domain
9
+ @base_class = base_class
10
+ define_domain_module
11
+ @klasses_analysed = []
12
+ end
13
+
14
+ def scan_database
15
+ # Introspect database tables and creates ActiveRecord descendants in the name space module
16
+ @domain_module.table_names.map do |table_name|
17
+ inject_class table_name
18
+ end
19
+ @domain_module.model_classes
20
+ end
21
+
22
+ private
23
+
24
+
25
+ def inject_class(table_name)
26
+ short_model_name = table_name.gsub(/#{@domain_module.prefix}_/, '').singularize.camelize
27
+ klass = nil
28
+ if @domain_module.constants.include? short_model_name.to_sym
29
+ klass = @domain_module.const_get short_model_name
30
+ puts "Found #{klass.name} that already handles #{table_name}"
31
+ else
32
+ klass = @domain_module.const_set short_model_name, Class.new(@base_class)
33
+ puts "Created #{klass.name} to handle #{table_name}"
34
+ # Adds some class methods
35
+ klass.send :include, DynamicModel::ActiveRecordExtension
36
+ end
37
+
38
+ # Maps the class to the correct table
39
+ klass.table_name = table_name
40
+ # Adds attributes accessible for mass assign
41
+ klass.attr_accessible *(klass.attribute_names - [klass.primary_key])
42
+ end
43
+
44
+ def define_domain_module
45
+ domain_name = @domain.singularize.camelize
46
+ @domain_module = nil
47
+ if DynamicModel::ManagedDomains.constants.include? domain_name.to_sym
48
+ @domain_module = DynamicModel::ManagedDomains.const_get domain_name
49
+ else
50
+ @domain_module = DynamicModel::ManagedDomains.const_set(domain_name, Module.new)
51
+ @domain_module.extend DynamicModel::DomainExtension
52
+ end
53
+ end
54
+
55
+
56
+ end
@@ -0,0 +1,31 @@
1
+ require 'active_record'
2
+
3
+ module DynamicModel
4
+
5
+ # Creates ActiveRecord::Base descendants from the database.
6
+ # ActiveRecord descendant classes are dynamically created from database introspection in their own namespace
7
+ # (DynamicModel::<NameSpace>::) The name of the module NameSpace is derived from table_prefix.
8
+ def self.introspect_database(table_prefix = :user_defined, base_class = ActiveRecord::Base)
9
+ 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
17
+ end
18
+
19
+ # Creates a new table with auto numbered id in the database with the name prefix provided
20
+ # by creating a live migration.
21
+ # If block is provided it will behave like create_table method for migrations, allowing
22
+ # to create any other column.
23
+ def self.add_table(scoped_table_name, table_prefix: :user_defined, &block)
24
+ scoped_table_name = scoped_table_name.to_s
25
+ table_prefix = table_prefix.to_s
26
+ real_table_name = scoped_table_name.underscore.pluralize
27
+ Migration::create_with "#{table_prefix}_#{real_table_name}", &block
28
+ end
29
+
30
+
31
+ end
@@ -0,0 +1,3 @@
1
+ module DatabaseIntrospection
2
+ VERSION = "0.0.9"
3
+ end
@@ -0,0 +1,13 @@
1
+ require 'database_introspection/version'
2
+ require 'database_introspection/dynamic_model'
3
+ require 'database_introspection/dynamic_model/active_record_extension'
4
+ require 'database_introspection/dynamic_model/domain_extension'
5
+ require 'database_introspection/dynamic_model/managed_domains'
6
+ require 'database_introspection/dynamic_model/tables_analyser'
7
+ require 'database_introspection/dynamic_model/relations_analyser'
8
+ require 'database_introspection/dynamic_model/migration'
9
+
10
+
11
+ module DatabaseIntrospection
12
+ # Your code goes here...
13
+ end
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: database_introspection
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.9
5
+ platform: ruby
6
+ authors:
7
+ - L.Briais
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-05-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activemodel
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: 3.2.13
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: 3.2.13
55
+ - !ruby/object:Gem::Dependency
56
+ name: activerecord
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 3.2.13
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: 3.2.13
69
+ - !ruby/object:Gem::Dependency
70
+ name: activeresource
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: 3.2.13
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: 3.2.13
83
+ - !ruby/object:Gem::Dependency
84
+ name: activesupport
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: 3.2.13
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: 3.2.13
97
+ description: This gem will generate classes (by default ActiveRecord::Base descendants)
98
+ from database introspection
99
+ email:
100
+ - lbnetid+rb@gmail.com
101
+ executables: []
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - .gitignore
106
+ - Gemfile
107
+ - LICENSE.txt
108
+ - README.md
109
+ - Rakefile
110
+ - database_introspection.gemspec
111
+ - lib/database_introspection.rb
112
+ - lib/database_introspection/dynamic_model.rb
113
+ - lib/database_introspection/dynamic_model/active_record_extension.rb
114
+ - lib/database_introspection/dynamic_model/domain_extension.rb
115
+ - lib/database_introspection/dynamic_model/managed_domains.rb
116
+ - lib/database_introspection/dynamic_model/migration.rb
117
+ - lib/database_introspection/dynamic_model/relations_analyser.rb
118
+ - lib/database_introspection/dynamic_model/tables_analyser.rb
119
+ - lib/database_introspection/version.rb
120
+ homepage: https://github.com/lbriais/database_introspection
121
+ licenses:
122
+ - MIT
123
+ metadata: {}
124
+ post_install_message:
125
+ rdoc_options: []
126
+ require_paths:
127
+ - lib
128
+ required_ruby_version: !ruby/object:Gem::Requirement
129
+ requirements:
130
+ - - '>='
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - '>='
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ requirements: []
139
+ rubyforge_project:
140
+ rubygems_version: 2.0.0.rc.2
141
+ signing_key:
142
+ specification_version: 4
143
+ summary: Database Introspection
144
+ test_files: []
145
+ has_rdoc: