geert 0.0.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.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/README.rdoc ADDED
@@ -0,0 +1,87 @@
1
+ = Geert: "Geert's an Enterprise Entity Relation Tracker"
2
+
3
+ Find missing foreign keys in ActiveRecord and create a migration to add them.
4
+
5
+ == Usage
6
+
7
+ Go to your Rails application and type the command:
8
+
9
+ geert
10
+
11
+ And you'll get all the possible migrations you can have for your application.
12
+ Run "geert -h" for all possible options.
13
+
14
+ == A note of caution
15
+
16
+ Foreign key constraints have a real impact on your application. Geert can't
17
+ always see the difference between the desired and unwanted foreign keys.
18
+ It does try to get the proper type of constraint (restrict, nullify or delete),
19
+ but that might not be what you want. A properly tested application will help
20
+ you.
21
+
22
+ == Generating an ERD
23
+
24
+ See a sample of the generated ERD here, based on Webistrano:
25
+
26
+ http://github.com/finalist/geert/blob/master/sample-erd.png
27
+
28
+ Click on raw for full size. Can't link directly, because github will show
29
+ it directly, which is rather awkward.
30
+
31
+ If you run on a Mac, this is really easy. You'll might have to sacrifice a
32
+ database for it, and you'll need at least graphviz and Sequel Pro.
33
+
34
+ * Run geert
35
+ * Migrate your database, apply all foreign keys for the best effect.
36
+ * Open the database in Sequel Pro
37
+ * Select: File -> Export -> Graphviz dotfile
38
+ * Save the dotfile
39
+ * In the console:
40
+
41
+ dot -Tsvg your_database.dot > your_database.svg
42
+
43
+ * If you have librsvg installed, you can also generate a png file:
44
+
45
+ dot -Tsvg your_database.dot | rsvg-convert -o your_database.png
46
+
47
+ You can find these applications here:
48
+
49
+ * Sequel Pro: http://sequelpro.com
50
+ * Graphviz: http://graphviz.org
51
+ * librsvg: sudo port install librsvg (warning, has a lot of X11 dependencies)
52
+
53
+
54
+ == Installation
55
+
56
+ To install geert:
57
+
58
+ gem install geert --source http://gemcutter.org
59
+
60
+ 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
+
73
+
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
+
85
+ == Copyright
86
+
87
+ Copyright (c) 2009 Iain Hecker. Released under the MIT License.
data/Rakefile ADDED
@@ -0,0 +1,46 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "geert"
8
+ gem.summary = %Q{Geert's a Enterprise Entity Relation Tracker}
9
+ gem.description = %Q{Find foreign keys in ActiveRecord and create a migration to add them}
10
+ gem.email = "iain@iain.nl"
11
+ gem.homepage = "http://github.com/finalist/geert"
12
+ gem.authors = ["Iain Hecker"]
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ gem.add_runtime_dependency "matthuhiggins-foreigner"
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
20
+ end
21
+
22
+ require 'spec/rake/spectask'
23
+ Spec::Rake::SpecTask.new(:spec) do |spec|
24
+ spec.libs << 'lib' << 'spec'
25
+ spec.spec_files = FileList['spec/**/*_spec.rb']
26
+ end
27
+
28
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
29
+ spec.libs << 'lib' << 'spec'
30
+ spec.pattern = 'spec/**/*_spec.rb'
31
+ spec.rcov = true
32
+ end
33
+
34
+ task :spec => :check_dependencies
35
+
36
+ task :default => :spec
37
+
38
+ require 'rake/rdoctask'
39
+ Rake::RDocTask.new do |rdoc|
40
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
41
+
42
+ rdoc.rdoc_dir = 'rdoc'
43
+ rdoc.title = "geert #{version}"
44
+ rdoc.rdoc_files.include('README*')
45
+ rdoc.rdoc_files.include('lib/**/*.rb')
46
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
data/bin/geert ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/geert/cli")
3
+ Geert::CLI.execute(STDOUT, ARGV)
data/geert.gemspec ADDED
@@ -0,0 +1,64 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{geert}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Iain Hecker"]
12
+ s.date = %q{2009-11-19}
13
+ s.default_executable = %q{geert}
14
+ s.description = %q{Find foreign keys in ActiveRecord and create a migration to add them}
15
+ s.email = %q{iain@iain.nl}
16
+ s.executables = ["geert"]
17
+ s.extra_rdoc_files = [
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ ".document",
22
+ ".gitignore",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "bin/geert",
27
+ "geert.gemspec",
28
+ "lib/geert.rb",
29
+ "lib/geert/association.rb",
30
+ "lib/geert/cli.rb",
31
+ "lib/geert/model.rb",
32
+ "lib/geert/project.rb",
33
+ "sample-erd.png",
34
+ "spec/geert_spec.rb",
35
+ "spec/spec.opts",
36
+ "spec/spec_helper.rb"
37
+ ]
38
+ s.homepage = %q{http://github.com/finalist/geert}
39
+ s.rdoc_options = ["--charset=UTF-8"]
40
+ s.require_paths = ["lib"]
41
+ s.rubygems_version = %q{1.3.5}
42
+ s.summary = %q{Geert's a Enterprise Entity Relation Tracker}
43
+ s.test_files = [
44
+ "spec/geert_spec.rb",
45
+ "spec/spec_helper.rb"
46
+ ]
47
+
48
+ if s.respond_to? :specification_version then
49
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
50
+ s.specification_version = 3
51
+
52
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
53
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
54
+ s.add_runtime_dependency(%q<matthuhiggins-foreigner>, [">= 0"])
55
+ else
56
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
57
+ s.add_dependency(%q<matthuhiggins-foreigner>, [">= 0"])
58
+ end
59
+ else
60
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
61
+ s.add_dependency(%q<matthuhiggins-foreigner>, [">= 0"])
62
+ end
63
+ end
64
+
@@ -0,0 +1,49 @@
1
+ module Geert
2
+
3
+ class Association
4
+
5
+ attr_reader :reflection, :model
6
+
7
+ def exclude?
8
+ polymorphic? or uses_polymorphic?
9
+ end
10
+
11
+ def migration
12
+ "add_foreign_key :#{source}, :#{target}, #{options_string}" unless exclude?
13
+ end
14
+
15
+ def polymorphic?
16
+ reflection.options[:polymorphic]
17
+ end
18
+
19
+ def uses_polymorphic?
20
+ model.associations.select(&:polymorphic?).map(&:column).include?(column)
21
+ end
22
+
23
+ def column
24
+ reflection.primary_key_name
25
+ end
26
+
27
+ def source
28
+ model.table_name
29
+ end
30
+
31
+ def target
32
+ reflection.table_name
33
+ end
34
+
35
+ def options
36
+ {:column => column}
37
+ end
38
+
39
+ def options_string
40
+ options.inspect.gsub(/\A\{(.*)\}\z/, '\\1')
41
+ end
42
+
43
+ def initialize(reflection, model)
44
+ @reflection, @model = reflection, model
45
+ end
46
+
47
+ end
48
+
49
+ end
data/lib/geert/cli.rb ADDED
@@ -0,0 +1,53 @@
1
+ require 'optparse'
2
+ require File.dirname(__FILE__) + '/project'
3
+
4
+ module Geert
5
+
6
+ class CLI
7
+
8
+ def self.execute(stdout, arguments=[])
9
+
10
+ parser = OptionParser.new do |opts|
11
+
12
+ opts.banner = <<-BANNER.gsub(/^ +/,'')
13
+ Find foreign keys in ActiveRecord and create a migration to add them.
14
+
15
+ Go to your Rails directory, or optionally provide the path to it.
16
+
17
+ Please remember to read the readme, for further instructions.
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)
36
+
37
+ directory = arguments[-1] || Dir.pwd
38
+
39
+ unless File.exist?(File.join(directory, "config", "environment.rb"))
40
+ stdout.puts "Error: #{directory} is not a valid Rails application.\n\n"
41
+ stdout.puts opts; exit
42
+ end
43
+
44
+ require File.dirname(__FILE__) + '/../geert'
45
+ puts Geert.migration(directory)
46
+
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+
53
+ end
@@ -0,0 +1,39 @@
1
+ module Geert
2
+
3
+ class Model
4
+
5
+ attr_reader :model
6
+
7
+ def initialize(model)
8
+ @model = model
9
+ end
10
+
11
+ def usable?
12
+ activerecord? && reflections.any?
13
+ end
14
+
15
+ def migration
16
+ associations.map(&:migration).compact.join("\n") if usable?
17
+ end
18
+
19
+ def associations
20
+ @associations ||= reflections.map { |reflection| Association.new(reflection, self) }
21
+ end
22
+
23
+ def table_name
24
+ model.table_name
25
+ end
26
+
27
+ private
28
+
29
+ def activerecord?
30
+ model.ancestors.include?(ActiveRecord::Base)
31
+ end
32
+
33
+ def reflections
34
+ @reflection ||= model.reflect_on_all_associations(:belongs_to)
35
+ end
36
+
37
+ end
38
+
39
+ end
@@ -0,0 +1,32 @@
1
+ module Geert
2
+
3
+ class Project
4
+
5
+ attr_reader :path
6
+
7
+ def initialize(path)
8
+ @path = path
9
+ load_rails
10
+ end
11
+
12
+ def migration
13
+ models.map(&:migration).select(&:present?).join("\n\n")
14
+ end
15
+
16
+ private
17
+
18
+ def models
19
+ model_files.map { |file| Model.new(file.camelize.constantize) }
20
+ end
21
+
22
+ def load_rails
23
+ require File.join(path, 'config', 'environment')
24
+ end
25
+
26
+ def model_files
27
+ Dir.glob("#{path}/app/models/*.rb").map { |file| File.basename(file, ".rb") }
28
+ end
29
+
30
+ end
31
+
32
+ end
data/lib/geert.rb ADDED
@@ -0,0 +1,11 @@
1
+ require File.dirname(__FILE__) + '/geert/project'
2
+ require File.dirname(__FILE__) + '/geert/model'
3
+ require File.dirname(__FILE__) + '/geert/association'
4
+
5
+ module Geert
6
+
7
+ def self.migration(path)
8
+ Project.new(path).migration
9
+ end
10
+
11
+ end
data/sample-erd.png ADDED
Binary file
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Geert" do
4
+ it "fails" do
5
+ fail "hey buddy, you should probably rename this file and start specing for real"
6
+ end
7
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'geert'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: geert
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Iain Hecker
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-19 00:00:00 +01:00
13
+ default_executable: geert
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.2.9
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: matthuhiggins-foreigner
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description: Find foreign keys in ActiveRecord and create a migration to add them
36
+ email: iain@iain.nl
37
+ executables:
38
+ - geert
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README.rdoc
43
+ files:
44
+ - .document
45
+ - .gitignore
46
+ - README.rdoc
47
+ - Rakefile
48
+ - VERSION
49
+ - bin/geert
50
+ - geert.gemspec
51
+ - lib/geert.rb
52
+ - lib/geert/association.rb
53
+ - lib/geert/cli.rb
54
+ - lib/geert/model.rb
55
+ - lib/geert/project.rb
56
+ - sample-erd.png
57
+ - spec/geert_spec.rb
58
+ - spec/spec.opts
59
+ - spec/spec_helper.rb
60
+ has_rdoc: true
61
+ homepage: http://github.com/finalist/geert
62
+ licenses: []
63
+
64
+ post_install_message:
65
+ rdoc_options:
66
+ - --charset=UTF-8
67
+ require_paths:
68
+ - lib
69
+ required_ruby_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
74
+ version:
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: "0"
80
+ version:
81
+ requirements: []
82
+
83
+ rubyforge_project:
84
+ rubygems_version: 1.3.5
85
+ signing_key:
86
+ specification_version: 3
87
+ summary: Geert's a Enterprise Entity Relation Tracker
88
+ test_files:
89
+ - spec/geert_spec.rb
90
+ - spec/spec_helper.rb