mylescarrick-pg_migrations 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,9 @@
1
+ == 0.0.1 2009-07-15
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
5
+
6
+ == 0.0.2 2009-07-21
7
+
8
+ * Actually works now
9
+ * Some passing tests and stubs
data/Manifest.txt ADDED
@@ -0,0 +1,19 @@
1
+ History.txt
2
+ Manifest.txt
3
+ PostInstall.txt
4
+ README.rdoc
5
+ Rakefile
6
+ lib/pg_migrations.rb
7
+ lib/pg_migrations/migrations_helper.rb
8
+ pg_migrations.gemspec
9
+ script/console
10
+ script/destroy
11
+ script/generate
12
+ spec/fixtures/blueprints.rb
13
+ spec/fixtures/blueprints_helper.rb
14
+ spec/fixtures/migration_scaffold.rb
15
+ spec/fixtures/models.rb
16
+ spec/pg_migrations_spec.rb
17
+ spec/spec.opts
18
+ spec/spec_helper.rb
19
+ tasks/rspec.rake
data/PostInstall.txt ADDED
@@ -0,0 +1,5 @@
1
+
2
+ For more information on pg_migration, see http://github.com/mylescarrick/pg_migrations
3
+
4
+
5
+
data/README.rdoc ADDED
@@ -0,0 +1,54 @@
1
+ = pg_migrations
2
+
3
+ * http://github.com/mylescarick/pg_migrations
4
+
5
+ == DESCRIPTION:
6
+
7
+ Adds migration helpers to allow for postgres-specific stuff like real constraints
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * Add and remove foreign keys (with optional CASCADE DELETE)
12
+ * Add and remove unique constraints
13
+ * Set / unset mandatory columns
14
+
15
+ == SYNOPSIS:
16
+
17
+ ActiveRecord migrations are fine when we're just using features supported across MySQL, SQLite, Postgres, etc... but
18
+ if you're after the added security of 'real' referential integrity, etc then you're going to be using Postgres.
19
+
20
+ These helpers provide a simple way to keep your migrations free from hand-written SQL, and make it easy to use the
21
+ postgres coolness that will help keep your data reliable.
22
+
23
+ == REQUIREMENTS:
24
+
25
+ * Use Postgres >= 8.1
26
+
27
+ == INSTALL:
28
+
29
+ * sudo gem install mylescarrick-pg_migrations
30
+
31
+ == LICENSE:
32
+
33
+ (The MIT License)
34
+
35
+ Copyright (c) 2009 Myles Carrick
36
+
37
+ Permission is hereby granted, free of charge, to any person obtaining
38
+ a copy of this software and associated documentation files (the
39
+ 'Software'), to deal in the Software without restriction, including
40
+ without limitation the rights to use, copy, modify, merge, publish,
41
+ distribute, sublicense, and/or sell copies of the Software, and to
42
+ permit persons to whom the Software is furnished to do so, subject to
43
+ the following conditions:
44
+
45
+ The above copyright notice and this permission notice shall be
46
+ included in all copies or substantial portions of the Software.
47
+
48
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
49
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
50
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
51
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
52
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
53
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
54
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ require 'rubygems'
2
+ gem 'hoe', '>= 2.1.0'
3
+ require 'hoe'
4
+ require 'fileutils'
5
+ require 'activerecord'
6
+ require './lib/pg_migrations'
7
+
8
+ Hoe.plugin :newgem
9
+ # Hoe.plugin :website
10
+ # Hoe.plugin :cucumberfeatures
11
+
12
+ # Generate all the Rake tasks
13
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
14
+ $hoe = Hoe.spec 'pg_migrations' do
15
+ self.developer 'Myles Carrick', 'mylescarrick@gmail.com'
16
+ self.post_install_message = 'PostInstall.txt'
17
+ self.rubyforge_name = self.name
18
+ self.version = PgMigrations::GEM_VERSION
19
+ end
20
+
21
+ require 'newgem/tasks'
22
+ Dir['tasks/**/*.rake'].each { |t| load t }
23
+
@@ -0,0 +1,5 @@
1
+ require File.join(File.dirname(__FILE__),'pg_migrations/migrations_helper')
2
+
3
+ class PgMigrations
4
+ GEM_VERSION = '0.0.3'
5
+ end
@@ -0,0 +1,52 @@
1
+ module PostgresMigrationHelper
2
+ def add_foreign_key(from_table, from_column, to_table, options = {})
3
+ constraint_name = "fk_#{from_table}_#{from_column}"
4
+
5
+ sql= %{ALTER TABLE #{from_table}
6
+ ADD CONSTRAINT #{constraint_name}
7
+ FOREIGN KEY (#{from_column})
8
+ REFERENCES #{to_table}(id)
9
+ ON UPDATE RESTRICT}
10
+ sql << " ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED" if options[:cascade_delete]
11
+ execute sql
12
+ end
13
+
14
+ def remove_foreign_key(from_table, from_column, to_table)
15
+ constraint_name = "fk_#{from_table}_#{from_column}"
16
+
17
+ execute %{ALTER TABLE #{from_table}
18
+ DROP CONSTRAINT #{constraint_name}}
19
+ end
20
+
21
+ #Adds a UNIQUE CONSTRAINT on a number of fields
22
+ # eg. add_unique_constraint(users, table1_id, table2_id, table3_id)
23
+ def add_unique_constraint(from_table, *fields)
24
+ constraint_name = "#{from_table}_unique_on_#{fields.join('_')}"
25
+ constraint_name = "#{from_table}_unique_on_#{fields.join('_')}" if constraint_name.length > 60
26
+
27
+ sql = %{ALTER TABLE #{from_table}
28
+ ADD CONSTRAINT #{constraint_name}
29
+ UNIQUE (#{fields.join(',')})
30
+ }
31
+ execute sql
32
+ end
33
+
34
+ def remove_unique_constraint(from_table, *fields)
35
+ constraint_name = "#{from_table}_unique_on_#{fields.join('_')}"
36
+ constraint_name = "#{from_table}_unique_on_#{fields.join('_')}" if constraint_name.length > 60
37
+
38
+ execute %{ALTER TABLE #{from_table}
39
+ DROP CONSTRAINT #{constraint_name}}
40
+ end
41
+
42
+ def set_mandatory_column(table, column)
43
+ execute %{ALTER TABLE #{table}
44
+ ALTER COLUMN #{column} SET NOT NULL}
45
+ end
46
+
47
+ def unset_mandatory_column(table, column)
48
+ execute %{ALTER TABLE #{table}
49
+ ALTER COLUMN #{column} DROP NOT NULL}
50
+ end
51
+ end
52
+ ActiveRecord::ConnectionAdapters::AbstractAdapter.send :include, PostgresMigrationHelper
data/script/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/pg_migrations.rb'}"
9
+ puts "Loading pg_migrations gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,9 @@
1
+ Sham.title { Faker::Lorem.sentence }
2
+ Sham.body { Faker::Lorem.paragraph }
3
+
4
+ Post.blueprint do
5
+ end
6
+
7
+ Comment.blueprint do
8
+ post { Post.make }
9
+ end
@@ -0,0 +1,7 @@
1
+ def create_post_and_comments
2
+ post = Post.make
3
+ 5.times do
4
+ Comment.make(:post => post)
5
+ end
6
+ post
7
+ end
@@ -0,0 +1,30 @@
1
+ # Get an AR connection setup - create a DB and set this to something that's gonna work
2
+ # createuser tester -P
3
+ # createdb -O tester -E UTF8 pg_migrations_test
4
+ # Kinda sucks requiring you to set this up manually for tests... but we're testing a real database
5
+ # and of course this isn't gonna work in sqlite
6
+ ActiveRecord::Base.establish_connection(
7
+ :adapter => "postgresql",
8
+ :host => "localhost",
9
+ :database => "pg_migrations_test",
10
+ :username => "tester",
11
+ :password => "tester"
12
+ )
13
+
14
+ # and now the basic migrations - plain vanilla AR
15
+ ActiveRecord::Schema.define do
16
+ self.verbose = false
17
+
18
+ create_table :comments, :force => true do |t|
19
+ t.text :body
20
+ t.integer :post_id, :null => false
21
+
22
+ t.timestamps
23
+ end
24
+ create_table :posts, :force => true do |t|
25
+ t.string :title
26
+ t.text :body
27
+
28
+ t.timestamps
29
+ end
30
+ end
@@ -0,0 +1,3 @@
1
+ # (very) basic class definition
2
+ class Comment < ActiveRecord::Base ; belongs_to :post ; end
3
+ class Post < ActiveRecord::Base ; has_many :comments ; end
@@ -0,0 +1,50 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ def reload
4
+ load(File.join(File.dirname(__FILE__),'fixtures/migration_scaffold.rb'))
5
+ end
6
+
7
+ describe "setting up for business" do
8
+ it "should have a working Postgres connection" do
9
+ ActiveRecord::Base.connection.should be_an_instance_of(ActiveRecord::ConnectionAdapters::PostgreSQLAdapter)
10
+ end
11
+ end
12
+
13
+
14
+ describe "should properly when using the connection" do
15
+
16
+ it "should have its methods available when using AR" do
17
+ ActiveRecord::Base.connection.methods.should include("add_foreign_key")
18
+ end
19
+
20
+ end
21
+
22
+ describe "playing with foreign keys" do
23
+
24
+ before(:each) do
25
+ reload
26
+ @post = create_post_and_comments
27
+ end
28
+
29
+ it "should prevent deletion of kids if parents exist" do
30
+ ActiveRecord::Base.connection.add_foreign_key(:comments, :post_id, :posts)
31
+ lambda { @post.destroy }.should raise_error(ActiveRecord::StatementInvalid, /violates foreign key constraint/)
32
+ end
33
+
34
+ it "should should cascade delete when supposed to" do
35
+ ActiveRecord::Base.connection.add_foreign_key(:comments, :post_id, :posts, :cascade_delete => true)
36
+ #lambda { @post.destroy }.should raise_error(ActiveRecord::StatementInvalid, /violates foreign key constraint/)
37
+ post_id = @post.id
38
+ #Need to find_by_post_id for consistency - Post won't exist in a minute
39
+ Comment.find_all_by_post_id(post_id).size.should eql(5)
40
+ @post.destroy
41
+ Comment.find_all_by_post_id(post_id).size.should eql(0)
42
+ end
43
+
44
+ it "should add a unique constraint"
45
+
46
+ it "should make a field mandatory"
47
+
48
+ it "should remove the mandatory condition for a field"
49
+
50
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,17 @@
1
+ require 'rubygems'
2
+ require 'activerecord'
3
+ require 'spec'
4
+ require 'machinist'
5
+ require 'machinist/active_record'
6
+ require 'faker'
7
+ require 'spec/fixtures/models'
8
+ require 'spec/fixtures/migration_scaffold'
9
+ require 'spec/fixtures/blueprints'
10
+ require 'spec/fixtures/blueprints_helper'
11
+
12
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
13
+ require 'pg_migrations'
14
+
15
+ Spec::Runner.configure do |config|
16
+ config.before(:each) { Sham.reset }
17
+ end
data/tasks/rspec.rake ADDED
@@ -0,0 +1,21 @@
1
+ begin
2
+ require 'spec'
3
+ rescue LoadError
4
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
5
+ require 'spec'
6
+ end
7
+ begin
8
+ require 'spec/rake/spectask'
9
+ rescue LoadError
10
+ puts <<-EOS
11
+ To use rspec for testing you must install rspec gem:
12
+ gem install rspec
13
+ EOS
14
+ exit(0)
15
+ end
16
+
17
+ desc "Run the specs under spec/models"
18
+ Spec::Rake::SpecTask.new do |t|
19
+ t.spec_opts = ['--options', "spec/spec.opts"]
20
+ t.spec_files = FileList['spec/**/*_spec.rb']
21
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mylescarrick-pg_migrations
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Myles Carrick
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-08-25 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.3.2
24
+ version:
25
+ description: Adds migration helpers to allow for postgres-specific stuff like real constraints
26
+ email:
27
+ - mylescarrick@gmail.com
28
+ executables: []
29
+
30
+ extensions: []
31
+
32
+ extra_rdoc_files:
33
+ - History.txt
34
+ - Manifest.txt
35
+ - PostInstall.txt
36
+ files:
37
+ - History.txt
38
+ - Manifest.txt
39
+ - PostInstall.txt
40
+ - README.rdoc
41
+ - Rakefile
42
+ - lib/pg_migrations.rb
43
+ - lib/pg_migrations/migrations_helper.rb
44
+ - script/console
45
+ - script/destroy
46
+ - script/generate
47
+ - spec/fixtures/blueprints.rb
48
+ - spec/fixtures/blueprints_helper.rb
49
+ - spec/fixtures/migration_scaffold.rb
50
+ - spec/fixtures/models.rb
51
+ - spec/pg_migrations_spec.rb
52
+ - spec/spec.opts
53
+ - spec/spec_helper.rb
54
+ - tasks/rspec.rake
55
+ has_rdoc: false
56
+ homepage: http://github.com/mylescarick/pg_migrations
57
+ licenses:
58
+ post_install_message: PostInstall.txt
59
+ rdoc_options:
60
+ - --main
61
+ - README.rdoc
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: "0"
69
+ version:
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ version:
76
+ requirements: []
77
+
78
+ rubyforge_project: pg_migrations
79
+ rubygems_version: 1.3.5
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: Adds migration helpers to allow for postgres-specific stuff like real constraints
83
+ test_files: []
84
+