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