geert 0.0.3 → 0.1.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.
- data/.gitignore +1 -0
- data/README.rdoc +19 -24
- data/VERSION +1 -1
- data/bin/geert +1 -1
- data/geert.gemspec +9 -5
- data/lib/geert.rb +16 -2
- data/lib/geert/association.rb +9 -2
- data/lib/geert/cli.rb +30 -36
- data/lib/geert/model.rb +17 -1
- data/lib/geert/project.rb +35 -24
- data/lib/options_parser.rb +111 -0
- data/spec/db/database.yml +10 -0
- data/spec/db/geert.sqlite3 +0 -0
- data/spec/db/schema.rb +34 -0
- data/spec/geert_spec.rb +97 -3
- data/spec/spec_helper.rb +13 -3
- metadata +7 -3
- data/.document +0 -5
data/.gitignore
CHANGED
data/README.rdoc
CHANGED
@@ -1,14 +1,22 @@
|
|
1
|
-
= Geert: "Geert's an Enterprise Entity Relation Tracker"
|
1
|
+
= Geert: "Geert's an Enterprise Entity Relation Tracker" ;)
|
2
2
|
|
3
3
|
Find missing foreign keys in ActiveRecord and create a migration to add them.
|
4
4
|
|
5
|
+
If you want to do it to keep your DBA happy, or want to generate a nice
|
6
|
+
ERD (see below), or you have a legitimate reason to add foreign keys later,
|
7
|
+
this gem might be for you.
|
8
|
+
|
5
9
|
== Usage
|
6
10
|
|
7
11
|
Go to your Rails application and type the command:
|
8
12
|
|
9
13
|
geert
|
10
14
|
|
11
|
-
And you'll get
|
15
|
+
And you'll get the migration you need right in your console. To generate a
|
16
|
+
migration, run:
|
17
|
+
|
18
|
+
geert --migration add_foreign_keys
|
19
|
+
|
12
20
|
Run "geert -h" for all possible options.
|
13
21
|
|
14
22
|
== A note of caution
|
@@ -19,6 +27,13 @@ It does try to get the proper type of constraint (restrict, nullify or delete),
|
|
19
27
|
but that might not be what you want. A properly tested application will help
|
20
28
|
you.
|
21
29
|
|
30
|
+
A quick summary of how geert decides which type of foreign key to use:
|
31
|
+
|
32
|
+
* Did you specify "has_many :foobars" with ":dependent => :delete_all"
|
33
|
+
or with ":dependent => :nullify", that geert will use that too.
|
34
|
+
* Can your foreign key be null in the database, than geert will nullify too.
|
35
|
+
* If your foreign key cannot be null, it will constrain usage.
|
36
|
+
|
22
37
|
== Generating an ERD
|
23
38
|
|
24
39
|
See a sample of the generated ERD here, based on Webistrano:
|
@@ -58,29 +73,9 @@ To install geert:
|
|
58
73
|
gem install geert --source http://gemcutter.org
|
59
74
|
|
60
75
|
It requires the foreigner gem as well, so please install that into your
|
61
|
-
project, before running the "geert" command.
|
62
|
-
|
63
|
-
In Rails < 3, edit config/environment.rb:
|
64
|
-
|
65
|
-
config.gem "matthuhiggins-foreigner", :lib => "foreigner", :source => "http://gemcutter.org"
|
66
|
-
|
67
|
-
In Rails 3, edit your Gemfile:
|
68
|
-
|
69
|
-
gem "matthuhiggins-foreigner", :require_as => "foreigner"
|
70
|
-
|
71
|
-
See http://github.com/matthuhiggins/foreigner for more info about foreigner.
|
72
|
-
|
76
|
+
project, before running the "geert" command. See
|
77
|
+
http://github.com/matthuhiggins/foreigner for more info about foreigner.
|
73
78
|
|
74
|
-
== Note on Patches/Pull Requests
|
75
|
-
|
76
|
-
* Fork the project.
|
77
|
-
* Make your feature addition or bug fix.
|
78
|
-
* Add tests for it. This is important so I don't break it in a future version
|
79
|
-
unintentionally.
|
80
|
-
* Commit, do not mess with rakefile, version, or history. (if you want to have
|
81
|
-
your own version, that is fine but bump version in a commit by itself I can
|
82
|
-
ignore when I pull)
|
83
|
-
* Send me a pull request. Bonus points for topic branches.
|
84
79
|
|
85
80
|
== Copyright
|
86
81
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
data/bin/geert
CHANGED
data/geert.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{geert}
|
8
|
-
s.version = "0.0
|
8
|
+
s.version = "0.1.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Iain Hecker"]
|
12
|
-
s.date = %q{2009-11-
|
12
|
+
s.date = %q{2009-11-23}
|
13
13
|
s.default_executable = %q{geert}
|
14
14
|
s.description = %q{Find foreign keys in ActiveRecord and create a migration to add them}
|
15
15
|
s.email = %q{iain@iain.nl}
|
@@ -18,8 +18,7 @@ Gem::Specification.new do |s|
|
|
18
18
|
"README.rdoc"
|
19
19
|
]
|
20
20
|
s.files = [
|
21
|
-
".
|
22
|
-
".gitignore",
|
21
|
+
".gitignore",
|
23
22
|
"README.rdoc",
|
24
23
|
"Rakefile",
|
25
24
|
"VERSION",
|
@@ -30,7 +29,11 @@ Gem::Specification.new do |s|
|
|
30
29
|
"lib/geert/cli.rb",
|
31
30
|
"lib/geert/model.rb",
|
32
31
|
"lib/geert/project.rb",
|
32
|
+
"lib/options_parser.rb",
|
33
33
|
"sample-erd.png",
|
34
|
+
"spec/db/database.yml",
|
35
|
+
"spec/db/geert.sqlite3",
|
36
|
+
"spec/db/schema.rb",
|
34
37
|
"spec/geert_spec.rb",
|
35
38
|
"spec/spec.opts",
|
36
39
|
"spec/spec_helper.rb"
|
@@ -41,7 +44,8 @@ Gem::Specification.new do |s|
|
|
41
44
|
s.rubygems_version = %q{1.3.5}
|
42
45
|
s.summary = %q{Geert's a Enterprise Entity Relation Tracker}
|
43
46
|
s.test_files = [
|
44
|
-
"spec/
|
47
|
+
"spec/db/schema.rb",
|
48
|
+
"spec/geert_spec.rb",
|
45
49
|
"spec/spec_helper.rb"
|
46
50
|
]
|
47
51
|
|
data/lib/geert.rb
CHANGED
@@ -4,8 +4,22 @@ require File.dirname(__FILE__) + '/geert/association'
|
|
4
4
|
|
5
5
|
module Geert
|
6
6
|
|
7
|
-
def self.migration(path)
|
8
|
-
Project.new(path)
|
7
|
+
def self.migration(stdout, path, options = {})
|
8
|
+
project = Project.new(path, options)
|
9
|
+
if project.output.blank?
|
10
|
+
stdout.puts "No new foreign keys found to be added. Lucky you!"
|
11
|
+
exit
|
12
|
+
end
|
13
|
+
if options[:migration]
|
14
|
+
File.open(project.filename, 'w') do |f|
|
15
|
+
f.puts project.migration
|
16
|
+
end
|
17
|
+
stdout.puts "Generated migration #{project.filename}"
|
18
|
+
else
|
19
|
+
stdout.puts project.output
|
20
|
+
end
|
9
21
|
end
|
10
22
|
|
23
|
+
VERSION = File.read(File.dirname(__FILE__) + '/../VERSION').chomp
|
24
|
+
|
11
25
|
end
|
data/lib/geert/association.rb
CHANGED
@@ -7,6 +7,10 @@ module Geert
|
|
7
7
|
":#{source}, :#{target}#{options_string}" unless exclude?
|
8
8
|
end
|
9
9
|
|
10
|
+
def output
|
11
|
+
" :" + target + options_string unless exclude?
|
12
|
+
end
|
13
|
+
|
10
14
|
def polymorphic?
|
11
15
|
reflection.options[:polymorphic]
|
12
16
|
end
|
@@ -26,7 +30,6 @@ module Geert
|
|
26
30
|
private
|
27
31
|
|
28
32
|
def existing?
|
29
|
-
require "foreigner"
|
30
33
|
ActiveRecord::Base.connection.foreign_keys(source).any? do |fk|
|
31
34
|
fk.options[:column].to_s == column.to_s
|
32
35
|
end
|
@@ -57,13 +60,17 @@ module Geert
|
|
57
60
|
end
|
58
61
|
|
59
62
|
def nullify?
|
60
|
-
dependency_option == :nullify
|
63
|
+
dependency_option == :nullify || nullify_because_nullable?
|
61
64
|
end
|
62
65
|
|
63
66
|
def delete?
|
64
67
|
dependency_option == :delete_all
|
65
68
|
end
|
66
69
|
|
70
|
+
def nullify_because_nullable?
|
71
|
+
!delete? && model.columns_hash[column.to_s].null
|
72
|
+
end
|
73
|
+
|
67
74
|
def dependency_option
|
68
75
|
opposite_relation.options[:dependent] if opposite_relation
|
69
76
|
end
|
data/lib/geert/cli.rb
CHANGED
@@ -1,51 +1,45 @@
|
|
1
|
-
require '
|
2
|
-
require File.dirname(__FILE__) + '/project'
|
1
|
+
require File.dirname(__FILE__) + '/../options_parser'
|
3
2
|
|
4
3
|
module Geert
|
5
4
|
|
6
|
-
class CLI
|
5
|
+
class CLI < OptionsParser
|
7
6
|
|
8
|
-
def
|
7
|
+
def banner
|
8
|
+
<<-BANNER.gsub(/^ +/,'')
|
9
|
+
Find foreign keys in ActiveRecord and create a migration to add them.
|
9
10
|
|
10
|
-
|
11
|
+
Go to your Rails directory, or optionally provide the path to it.
|
11
12
|
|
12
|
-
|
13
|
-
Find foreign keys in ActiveRecord and create a migration to add them.
|
13
|
+
Please remember to read the readme, for further instructions.
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
Usage: geert [options] [DIRECTORY]
|
20
|
-
e.g. geert ~/projects/myapp
|
21
|
-
BANNER
|
22
|
-
|
23
|
-
opts.separator ""
|
24
|
-
|
25
|
-
opts.on(nil, "--readme", "Show the Readme.") do
|
26
|
-
stdout.puts File.read(File.dirname(__FILE__) + '/../../README.rdoc')
|
27
|
-
exit
|
28
|
-
end
|
29
|
-
|
30
|
-
opts.on("-h", "--help", "Show this help message.") do
|
31
|
-
stdout.puts opts
|
32
|
-
exit
|
33
|
-
end
|
34
|
-
|
35
|
-
opts.parse!(arguments)
|
15
|
+
Usage: geert [options] [DIRECTORY]
|
16
|
+
e.g. geert ~/projects/myapp
|
17
|
+
BANNER
|
18
|
+
end
|
36
19
|
|
37
|
-
|
20
|
+
parse :on, "-m", "--migration MIGRATION_NAME", "Generate a complete migration" do |name|
|
21
|
+
options[:migration] = name
|
22
|
+
end
|
38
23
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
24
|
+
after do
|
25
|
+
no_rails! unless File.exist?(environment)
|
26
|
+
require environment
|
27
|
+
require 'foreigner'
|
28
|
+
require gem_path("lib", "geert")
|
29
|
+
Geert.migration(stdout, directory, options)
|
30
|
+
end
|
43
31
|
|
44
|
-
|
45
|
-
|
32
|
+
def no_rails!
|
33
|
+
stdout.puts "Error: #{directory} is not a valid Rails application"
|
34
|
+
halt!
|
35
|
+
end
|
46
36
|
|
47
|
-
|
37
|
+
def environment
|
38
|
+
File.join(directory, "config", "environment.rb")
|
39
|
+
end
|
48
40
|
|
41
|
+
def directory
|
42
|
+
arguments[-1] || Dir.pwd
|
49
43
|
end
|
50
44
|
|
51
45
|
end
|
data/lib/geert/model.rb
CHANGED
@@ -12,8 +12,12 @@ module Geert
|
|
12
12
|
activerecord? && reflections.any?
|
13
13
|
end
|
14
14
|
|
15
|
+
def output
|
16
|
+
output_string if usable? && association_output.any?
|
17
|
+
end
|
18
|
+
|
15
19
|
def migration
|
16
|
-
associations.map(&:migration).compact.sort
|
20
|
+
associations.map(&:migration).compact.sort if usable?
|
17
21
|
end
|
18
22
|
|
19
23
|
def associations
|
@@ -24,8 +28,20 @@ module Geert
|
|
24
28
|
model.table_name
|
25
29
|
end
|
26
30
|
|
31
|
+
def columns_hash(*args)
|
32
|
+
model.columns_hash(*args)
|
33
|
+
end
|
34
|
+
|
27
35
|
private
|
28
36
|
|
37
|
+
def association_output
|
38
|
+
associations.map(&:output).compact
|
39
|
+
end
|
40
|
+
|
41
|
+
def output_string
|
42
|
+
[ "\n", model.class_name + " " + ("-" * (80 - model.class_name.size)) ] + association_output
|
43
|
+
end
|
44
|
+
|
29
45
|
def activerecord?
|
30
46
|
model.ancestors.include?(ActiveRecord::Base)
|
31
47
|
end
|
data/lib/geert/project.rb
CHANGED
@@ -2,57 +2,68 @@ module Geert
|
|
2
2
|
|
3
3
|
class Project
|
4
4
|
|
5
|
-
attr_reader :path
|
5
|
+
attr_reader :path, :options
|
6
6
|
|
7
|
-
def initialize(path)
|
8
|
-
@path = path
|
9
|
-
load_rails
|
7
|
+
def initialize(path, options = {})
|
8
|
+
@path, @options = path, options
|
10
9
|
end
|
11
10
|
|
12
11
|
def migration
|
13
|
-
<<-MIGRATION
|
14
|
-
class
|
15
|
-
|
16
|
-
#{migration_up}
|
17
|
-
|
12
|
+
<<-MIGRATION.gsub(/^ {6}/,'')
|
13
|
+
class #{migration_name.camelize} < ActiveRecord::Migration
|
14
|
+
def self.up
|
15
|
+
#{cleanup migration_up}
|
16
|
+
end
|
18
17
|
|
19
|
-
|
20
|
-
#{migration_down}
|
21
|
-
|
22
|
-
end
|
18
|
+
def self.down
|
19
|
+
#{cleanup migration_down}
|
20
|
+
end
|
21
|
+
end
|
23
22
|
MIGRATION
|
24
23
|
end
|
25
24
|
|
26
|
-
def
|
27
|
-
|
25
|
+
def filename
|
26
|
+
@filename ||= File.join(path, "db", "migrate", Time.now.strftime("%Y%m%d%H%M%S") + "_" + migration_name + ".rb")
|
28
27
|
end
|
29
28
|
|
30
|
-
def
|
31
|
-
|
29
|
+
def output
|
30
|
+
models.map(&:output).flatten.compact
|
32
31
|
end
|
33
32
|
|
33
|
+
private
|
34
|
+
|
34
35
|
def migration_lines
|
35
|
-
@migration_lines ||= models.map(&:migration).
|
36
|
+
@migration_lines ||= models.map(&:migration).flatten
|
37
|
+
end
|
38
|
+
|
39
|
+
def migration_name
|
40
|
+
options[:migration].to_s.underscore
|
41
|
+
end
|
42
|
+
|
43
|
+
def migration_up
|
44
|
+
migration_lines.map(&modify_line("add")).join("\n")
|
45
|
+
end
|
46
|
+
|
47
|
+
def migration_down
|
48
|
+
migration_lines.reverse.map(&modify_line("remove")).join("\n")
|
36
49
|
end
|
37
50
|
|
38
51
|
def modify_line(command)
|
39
52
|
lambda { |line| line.present? ? " #{command}_foreign_key #{line}" : "\n" }
|
40
53
|
end
|
41
54
|
|
42
|
-
private
|
43
|
-
|
44
55
|
def models
|
45
56
|
model_files.map { |file| Model.new(file.camelize.constantize) }
|
46
57
|
end
|
47
58
|
|
48
|
-
def load_rails
|
49
|
-
require File.join(path, 'config', 'environment')
|
50
|
-
end
|
51
|
-
|
52
59
|
def model_files
|
53
60
|
Dir.glob("#{path}/app/models/*.rb").map { |file| File.basename(file, ".rb") }
|
54
61
|
end
|
55
62
|
|
63
|
+
def cleanup(line)
|
64
|
+
line.gsub(/(\n\n)+/m, "\n")
|
65
|
+
end
|
66
|
+
|
56
67
|
end
|
57
68
|
|
58
69
|
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
# You can extend this class to use a wrapper around the default
|
4
|
+
# Ruby OptionParser. If you see this, feel free to copy it to your own gem.
|
5
|
+
# Copyright 2009, Iain Hecker. Released under the MIT License.
|
6
|
+
class OptionsParser
|
7
|
+
|
8
|
+
attr_accessor :stdout, :arguments
|
9
|
+
|
10
|
+
# Call the excute method from your bin file:
|
11
|
+
#
|
12
|
+
# #!/usr/bin/env ruby
|
13
|
+
# require File.dirname(__FILE__) + "/../lib/your_gem/cli")
|
14
|
+
# YourGem::CLI.execute(STDOUT, ARGV)
|
15
|
+
def self.execute(stdout, arguments = [])
|
16
|
+
cli = new(stdout, arguments)
|
17
|
+
cli.instance_eval(&@before) if @before
|
18
|
+
cli.parse
|
19
|
+
cli.instance_eval(&@after) if @after
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(stdout, arguments)
|
23
|
+
@stdout, @arguments = stdout, arguments
|
24
|
+
end
|
25
|
+
|
26
|
+
def options
|
27
|
+
(@options || {}).merge(self.class.options)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Define your application specific command line options.
|
31
|
+
# This gets passed to OptionParser.
|
32
|
+
# The first argument is the method to call, the rest is you world expect
|
33
|
+
#
|
34
|
+
# Example:
|
35
|
+
#
|
36
|
+
# class CLI < OptionsParser
|
37
|
+
# parse(:on, "-v", "Show version") { stdout.puts YourGem::Version }
|
38
|
+
def self.parse(*args, &code)
|
39
|
+
parse_options << [ args, code ] unless args.empty?
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.parse_options
|
43
|
+
@parse_options ||= []
|
44
|
+
end
|
45
|
+
|
46
|
+
# Define what needs to be done after parsing the options.
|
47
|
+
# Similar to RSpec's after.
|
48
|
+
def self.after(&code)
|
49
|
+
@after = code
|
50
|
+
end
|
51
|
+
|
52
|
+
# Define what needs to be done before parsing the options.
|
53
|
+
# Similar to RSpec's before.
|
54
|
+
def self.before(&code)
|
55
|
+
@before = code
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.options
|
59
|
+
@options ||= {}
|
60
|
+
end
|
61
|
+
|
62
|
+
# Override to alter the separator
|
63
|
+
def separator; "" end
|
64
|
+
|
65
|
+
# Override to alter the banner
|
66
|
+
def banner; "" end
|
67
|
+
|
68
|
+
# Does the main work or parsing the options
|
69
|
+
def parse
|
70
|
+
OptionParser.new do |opts|
|
71
|
+
opts.banner = banner
|
72
|
+
opts.separator separator
|
73
|
+
parse_options(opts)
|
74
|
+
opts.separator separator
|
75
|
+
opts.on "--readme", "Show the Readme", &readme
|
76
|
+
opts.on "-v", "--version", "Show version", &version
|
77
|
+
opts.on "-h", "--help", "Show this help message", &help(opts)
|
78
|
+
opts.parse! arguments
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
# Wrapper around File.join, but relative to the root of your gem.
|
85
|
+
def gem_path(*segments)
|
86
|
+
File.join(File.dirname(__FILE__), "..", *segments)
|
87
|
+
end
|
88
|
+
|
89
|
+
def readme
|
90
|
+
lambda { stdout.puts File.read(gem_path('README.rdoc')); halt! }
|
91
|
+
end
|
92
|
+
|
93
|
+
def help(opts)
|
94
|
+
lambda { stdout.puts opts; halt! }
|
95
|
+
end
|
96
|
+
|
97
|
+
def version
|
98
|
+
lambda { stdout.puts File.read(gem_path('VERSION')); halt! }
|
99
|
+
end
|
100
|
+
|
101
|
+
def parse_options(opts)
|
102
|
+
self.class.parse_options.each { |option| opts.__send__(*option[0], &option[-1]) }
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
# Exits the application. For stubbing purposes. Use halt! in your CLI too!
|
107
|
+
def halt!
|
108
|
+
exit
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
Binary file
|
data/spec/db/schema.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
ActiveRecord::Migration.verbose = false
|
2
|
+
ActiveRecord::Schema.define(:version => Geert::VERSION) do
|
3
|
+
|
4
|
+
# The other end of the relation
|
5
|
+
create_table :posts, :force => true do |t|
|
6
|
+
t.string :name
|
7
|
+
end
|
8
|
+
|
9
|
+
# Comments have a foreign key that can be nil
|
10
|
+
create_table :comments, :force => true do |t|
|
11
|
+
t.integer :post_id, :null => true
|
12
|
+
end
|
13
|
+
|
14
|
+
# Topics have a foreign key that cannot be nil
|
15
|
+
create_table :topics, :force => true do |t|
|
16
|
+
t.integer :post_id, :null => false
|
17
|
+
end
|
18
|
+
|
19
|
+
# Tags are for testing polymporphic relations
|
20
|
+
create_table :tags, :force => true do |t|
|
21
|
+
t.string :name
|
22
|
+
end
|
23
|
+
|
24
|
+
create_table :taggings, :force => true do |t|
|
25
|
+
t.integer :tag_id
|
26
|
+
t.integer :tagged_id
|
27
|
+
t.string :tagged_type
|
28
|
+
end
|
29
|
+
|
30
|
+
# The relation has a different name here
|
31
|
+
create_table :subscriptions, :force => true do |t|
|
32
|
+
t.integer :writing_id
|
33
|
+
end
|
34
|
+
end
|
data/spec/geert_spec.rb
CHANGED
@@ -1,7 +1,101 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
2
|
|
3
|
-
describe
|
4
|
-
|
5
|
-
|
3
|
+
describe Geert do
|
4
|
+
|
5
|
+
describe "making migration lines" do
|
6
|
+
|
7
|
+
subject { Geert::Model }
|
8
|
+
|
9
|
+
it "should make dependent nullify if dependent has been set in active record" do
|
10
|
+
class Post < ActiveRecord::Base
|
11
|
+
has_many :comments, :dependent => :nullify
|
12
|
+
end
|
13
|
+
class Comment < ActiveRecord::Base
|
14
|
+
belongs_to :post
|
15
|
+
end
|
16
|
+
subject.new(Comment).migration.should include(":comments, :posts, :dependent => :nullify")
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should make dependent delete if dependent has been set in active record" do
|
20
|
+
class Post < ActiveRecord::Base
|
21
|
+
has_many :comments, :dependent => :delete_all
|
22
|
+
end
|
23
|
+
class Comment < ActiveRecord::Base
|
24
|
+
belongs_to :post
|
25
|
+
end
|
26
|
+
subject.new(Comment).migration.should include(":comments, :posts, :dependent => :delete")
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should make dependent constraint if foreign key cannot be nil" do
|
30
|
+
class Post < ActiveRecord::Base
|
31
|
+
has_many :topics
|
32
|
+
end
|
33
|
+
class Topic < ActiveRecord::Base
|
34
|
+
belongs_to :post
|
35
|
+
end
|
36
|
+
subject.new(Topic).migration.should include(":topics, :posts")
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should make dependent nullify if foreign key can be nil" do
|
40
|
+
class Post < ActiveRecord::Base
|
41
|
+
has_many :comments
|
42
|
+
end
|
43
|
+
class Comment < ActiveRecord::Base
|
44
|
+
belongs_to :post
|
45
|
+
end
|
46
|
+
subject.new(Comment).migration.should include(":comments, :posts, :dependent => :nullify")
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should not make migration lines for polymorphic relations" do
|
50
|
+
class Tagging < ActiveRecord::Base
|
51
|
+
belongs_to :tagged, :polymorphic => true
|
52
|
+
end
|
53
|
+
class Post < ActiveRecord::Base
|
54
|
+
has_many :taggings, :as => :tagged
|
55
|
+
end
|
56
|
+
subject.new(Tagging).migration.should == []
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should not make migration lines for relations that use a polymorphic relation" do
|
60
|
+
class Tag < ActiveRecord::Base
|
61
|
+
has_many :taggings
|
62
|
+
has_many :tagged_posts, :through => :taggings, :source => :post, :conditions => { :tagged_type => "Post" }
|
63
|
+
end
|
64
|
+
class Tagging < ActiveRecord::Base
|
65
|
+
belongs_to :tagged, :polymorphic => true
|
66
|
+
end
|
67
|
+
class Post < ActiveRecord::Base
|
68
|
+
has_many :taggings, :as => :tagged
|
69
|
+
end
|
70
|
+
subject.new(Tagging).migration.should == []
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should not make migration lines for existing foreign keys" do
|
74
|
+
if ActiveRecord::Base.connection.adapter_name =~ /sqlite/i
|
75
|
+
pending "SQLite doesn't support foreign keys.\nConfigure spec/db/database.yml and run DB=mysql rake spec"
|
76
|
+
end
|
77
|
+
ActiveRecord::Base.connection.add_foreign_key :comments, :posts
|
78
|
+
class Post < ActiveRecord::Base
|
79
|
+
has_many :subscriptions
|
80
|
+
end
|
81
|
+
class Comment < ActiveRecord::Base
|
82
|
+
belongs_to :post
|
83
|
+
end
|
84
|
+
subject.new(Comment).migration.should == []
|
85
|
+
ActiveRecord::Base.connection.remove_foreign_key :comments, :posts
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should specify the column name, when different from Rails conventions" do
|
89
|
+
class Post < ActiveRecord::Base
|
90
|
+
has_many :comments, :dependent => :nullify
|
91
|
+
end
|
92
|
+
class Subscription < ActiveRecord::Base
|
93
|
+
belongs_to :writing, :class_name => "Post"
|
94
|
+
end
|
95
|
+
regex = /:column => "writing_id"/
|
96
|
+
subject.new(Subscription).migration.first.should =~ regex
|
97
|
+
end
|
98
|
+
|
6
99
|
end
|
100
|
+
|
7
101
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,9 +1,19 @@
|
|
1
|
-
|
2
|
-
$LOAD_PATH.unshift(
|
1
|
+
spec_dir = File.dirname(__FILE__)
|
2
|
+
$LOAD_PATH.unshift(spec_dir)
|
3
|
+
$LOAD_PATH.unshift(File.join(spec_dir, '..', 'lib'))
|
3
4
|
require 'geert'
|
4
5
|
require 'spec'
|
5
6
|
require 'spec/autorun'
|
7
|
+
require 'activerecord'
|
8
|
+
|
9
|
+
ActiveRecord::Base.logger = Logger.new(spec_dir + "/debug.log")
|
10
|
+
databases = YAML::load(IO.read(spec_dir + "/db/database.yml"))
|
11
|
+
ActiveRecord::Base.establish_connection(databases[ENV["DB"] || "sqlite3"])
|
12
|
+
|
13
|
+
require 'foreigner'
|
14
|
+
load(File.join(spec_dir, "db", "schema.rb"))
|
15
|
+
|
6
16
|
|
7
17
|
Spec::Runner.configure do |config|
|
8
|
-
|
18
|
+
|
9
19
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: geert
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Iain Hecker
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-11-
|
12
|
+
date: 2009-11-23 00:00:00 +01:00
|
13
13
|
default_executable: geert
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -41,7 +41,6 @@ extensions: []
|
|
41
41
|
extra_rdoc_files:
|
42
42
|
- README.rdoc
|
43
43
|
files:
|
44
|
-
- .document
|
45
44
|
- .gitignore
|
46
45
|
- README.rdoc
|
47
46
|
- Rakefile
|
@@ -53,7 +52,11 @@ files:
|
|
53
52
|
- lib/geert/cli.rb
|
54
53
|
- lib/geert/model.rb
|
55
54
|
- lib/geert/project.rb
|
55
|
+
- lib/options_parser.rb
|
56
56
|
- sample-erd.png
|
57
|
+
- spec/db/database.yml
|
58
|
+
- spec/db/geert.sqlite3
|
59
|
+
- spec/db/schema.rb
|
57
60
|
- spec/geert_spec.rb
|
58
61
|
- spec/spec.opts
|
59
62
|
- spec/spec_helper.rb
|
@@ -86,5 +89,6 @@ signing_key:
|
|
86
89
|
specification_version: 3
|
87
90
|
summary: Geert's a Enterprise Entity Relation Tracker
|
88
91
|
test_files:
|
92
|
+
- spec/db/schema.rb
|
89
93
|
- spec/geert_spec.rb
|
90
94
|
- spec/spec_helper.rb
|