rails-bigint-pk 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/.gitignore +8 -0
  2. data/.rspec +2 -0
  3. data/.rvmrc +1 -0
  4. data/.travis.yml +3 -0
  5. data/.vim/snippets/rspec.snippets +4 -0
  6. data/.vimrc +2 -0
  7. data/Changelog +11 -0
  8. data/Gemfile +4 -0
  9. data/Guardfile +20 -0
  10. data/LICENSE +7 -0
  11. data/Rakefile +6 -0
  12. data/Readme.md +61 -0
  13. data/lib/bigint_pk.rb +92 -0
  14. data/lib/bigint_pk/version.rb +3 -0
  15. data/lib/generators/bigint_pk.rb +5 -0
  16. data/lib/generators/bigint_pk/install_generator.rb +21 -0
  17. data/lib/generators/bigint_pk/templates/bigint_pk.rb +9 -0
  18. data/lib/generators/bigint_pk/templates/migration.rb +20 -0
  19. data/rails-bigint-pk.gemspec +37 -0
  20. data/spec/fixtures/Gemfile +8 -0
  21. data/spec/fixtures/mysql_database.yml +13 -0
  22. data/spec/fixtures/postgresql_database.yml +12 -0
  23. data/spec/fixtures/sqlite3_database.yml +11 -0
  24. data/spec/fixtures/test_rails_app/app/models/empire.rb +2 -0
  25. data/spec/fixtures/test_rails_app/app/models/ruler.rb +4 -0
  26. data/spec/fixtures/test_rails_app/db/migrate/19000101100000_create_empires_and_rulers.rb +10 -0
  27. data/spec/fixtures/test_rails_app/db/migrate/19000102100000_update_rulers_add_favourite_ruler.rb +7 -0
  28. data/spec/integration/generator_spec.rb +40 -0
  29. data/spec/integration/schema_spec.rb +222 -0
  30. data/spec/migration_spec.rb +102 -0
  31. data/spec/monkey_patch/connection_adapters_spec.rb +149 -0
  32. data/spec/spec_helper.rb +61 -0
  33. data/spec/support/cmd.rb +42 -0
  34. data/spec/support/file_utils.rb +7 -0
  35. data/spec/support/logging.rb +5 -0
  36. data/spec/support/rails.rb +32 -0
  37. data/spec/support/rspec.rb +3 -0
  38. metadata +340 -0
@@ -0,0 +1,8 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ /tmp
6
+ /tags
7
+ /gems.tags
8
+ /bin
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --debugger
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm --create 1.9.3
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
@@ -0,0 +1,4 @@
1
+ snippet t
2
+ they '${1}' do
3
+ ${2}
4
+ end
data/.vimrc ADDED
@@ -0,0 +1,2 @@
1
+ set wildignore+=**/tmp/**
2
+ set tags+=./gems.tags
@@ -0,0 +1,11 @@
1
+ ## 0.0.2 (19 February 2013)
2
+
3
+ Bug Fixes:
4
+
5
+ - `references` uses 64bit keys for `change_table` now.
6
+ - work with polymorphic associations (@Bishop, #12)
7
+
8
+
9
+ ## 0.0.1 (19 November 2012)
10
+
11
+ Initial version.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in rails-bigint-pk.gemspec
4
+ gemspec
@@ -0,0 +1,20 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec', cli: '--tag ~integration' do
5
+ watch('spec/spec_helper.rb'){ 'spec' }
6
+ watch(%r{spec/support/*}){ 'spec' }
7
+ watch(%r{^spec/(?!integration/).+_spec\.rb})
8
+
9
+ watch(%r{^lib/bigint_pk\.rb}){ 'spec/monkey_patch/connection_adapters_spec.rb' }
10
+ end
11
+
12
+ guard 'bundler' do
13
+ watch('Gemfile')
14
+ watch(/^.+\.gemspec/)
15
+ end
16
+
17
+ guard 'ctags-bundler', :src_path => ["lib", "spec/support"] do
18
+ watch(/^(app|lib|spec\/support)\/.*\.rb$/)
19
+ watch('Gemfile.lock')
20
+ end
data/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2012 VerticalResponse Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new :spec
5
+
6
+ task default: :spec
@@ -0,0 +1,61 @@
1
+ ## rails-bigint-pk [![Build Status](https://secure.travis-ci.org/VerticalResponse/rails-bigint-pk.png?branch=master)](https://travis-ci.org/VerticalResponse/rails-bigint-pk)
2
+
3
+ ### Overview
4
+
5
+ rails-bigint-pk aims to be a simple, transparent way to use 64bit primary keys
6
+ in mysql and postgres.
7
+
8
+ ### Requirements
9
+
10
+ rails-bigint-pk has been tested with rails 3.2.12, which at the time of writing
11
+ is the latest patch version for 3.2. If you use a higher patch version, it is
12
+ recommended to run the test suite against your version of rails and activerecord.
13
+
14
+ ### Installation & Usage
15
+
16
+ * Add the following to your `Gemfile`
17
+ `gem 'rails-bigint-pk', git: 'https://github.com/VerticalResponse/rails-bigint-pk.git'`
18
+
19
+ * Run the generator
20
+ `rails generate bigint_pk:install`
21
+
22
+ This will create an initializer that enables 64 bit primary and foreign keys by
23
+ changing the default primary key type, and using `limit: 8` for foreign keys
24
+ created via `references`.
25
+
26
+ It will also create a migration to update all existing primary and foreign keys.
27
+
28
+
29
+ ### Gotchas
30
+
31
+ When adding foreign key columns, be sure to use `references` and not
32
+ `add_column`.
33
+
34
+ ```ruby
35
+ change_table :my_table do |t|
36
+ t.references :other_table
37
+ end
38
+
39
+ # Doing this will not use 64bit ints
40
+ add_column :my_table, :other_table_id, :int
41
+ ```
42
+
43
+
44
+ ### Running Tests Against Later Versions of Rails
45
+
46
+ ```bash
47
+ git clone git://github.com/VerticalResponse/rails-bigint-pk.git
48
+ cd rails-bigint-pk
49
+
50
+ # edit rails-bigint-pk.gemspec or Gemfile to set the version of activerecord to
51
+ # the one you are using
52
+
53
+ bundle install
54
+
55
+ # verify that Gemfile.lock's entry for activerecord matches the version you want
56
+ # to test against.
57
+
58
+ # This will run integration specs against all supported database types, and
59
+ # requires running servers for postgres and mysql.
60
+ rake spec
61
+ ```
@@ -0,0 +1,92 @@
1
+ require 'active_support/all'
2
+ require 'bigint_pk/version'
3
+
4
+ module BigintPk
5
+ mattr_accessor :enabled
6
+
7
+ autoload :Generators, 'generators/bigint_pk'
8
+
9
+ def self.setup
10
+ yield self
11
+ end
12
+
13
+ def self.enabled= value
14
+ install_patches! if value
15
+ end
16
+
17
+
18
+ def self.update_primary_key table_name, key_name
19
+ update_key table_name, key_name, true
20
+ end
21
+
22
+ def self.update_foreign_key table_name, key_name
23
+ update_key table_name, key_name, false
24
+ end
25
+
26
+ private
27
+
28
+ def self.install_patches!
29
+ install_primary_key_patches!
30
+ install_foreign_key_patches!
31
+ end
32
+
33
+ def self.install_primary_key_patches!
34
+ ActiveRecord::Base.establish_connection
35
+ ca = ActiveRecord::ConnectionAdapters
36
+
37
+ if ca.const_defined? :PostgreSQLAdapter
38
+ ca::PostgreSQLAdapter::NATIVE_DATABASE_TYPES[:primary_key] = 'bigserial primary key'
39
+ end
40
+
41
+ if ca.const_defined? :AbstractMysqlAdapter
42
+ ca::AbstractMysqlAdapter::NATIVE_DATABASE_TYPES[:primary_key] =
43
+ 'bigint(20) DEFAULT NULL auto_increment PRIMARY KEY'
44
+ end
45
+ end
46
+
47
+ def self.install_foreign_key_patches!
48
+ [ ActiveRecord::ConnectionAdapters::TableDefinition,
49
+ ActiveRecord::ConnectionAdapters::Table].each do |abstract_table_type|
50
+
51
+ abstract_table_type.class_eval do
52
+ def references_with_default_bigint_fk *args
53
+ options = args.extract_options!
54
+ options.reverse_merge! limit: 8
55
+ # Limit shouldn't affect "#{col}_type" column in polymorphic reference.
56
+ # But don't change value if it isn't simple 'true'.
57
+ # Examples:
58
+ # t.references :subject, null: false, polymorphic: true ==> t.integer :subject_id, limit: 8, null: false
59
+ # t.string :subject_type, null: false
60
+ # t.references :subject, polymorphic: { limit: 120 } ==> t.integer :subject_id, limit: 8
61
+ # t.string :subject_type, limit: 120
62
+ options[:polymorphic] = options.except(:polymorphic, :limit) if options[:polymorphic] == true
63
+ references_without_default_bigint_fk( *args, options )
64
+ end
65
+ alias_method_chain :references, :default_bigint_fk
66
+ end
67
+ end
68
+ end
69
+
70
+
71
+ def self.update_key table_name, key_name, is_primary_key
72
+ c = ActiveRecord::Base.connection
73
+ case c.adapter_name
74
+ when 'PostgreSQL'
75
+ c.execute %Q{
76
+ ALTER TABLE #{c.quote_table_name table_name}
77
+ ALTER COLUMN #{c.quote_column_name key_name}
78
+ TYPE bigint
79
+ }.gsub(/\s+/, ' ').strip
80
+ when /^MySQL/i
81
+ c.execute %Q{
82
+ ALTER TABLE #{c.quote_table_name table_name}
83
+ MODIFY COLUMN #{c.quote_column_name key_name}
84
+ bigint(20) DEFAULT NULL #{'auto_increment' if is_primary_key}
85
+ }.gsub(/\s+/, ' ').strip
86
+ when 'SQLite'
87
+ # noop; sqlite always has 64bit pkeys
88
+ else
89
+ raise "Unsupported adapter '#{c.adapter_name}'"
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,3 @@
1
+ module BigintPk
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,5 @@
1
+ module BigintPk
2
+ module Generators
3
+ autoload :InstallGenerator, 'generators/bigint_pk/install_generator'
4
+ end
5
+ end
@@ -0,0 +1,21 @@
1
+ require 'rails/generators'
2
+
3
+ module BigintPk
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.expand_path '../templates', __FILE__
7
+
8
+ desc 'Creates BigintPk initializer'
9
+
10
+
11
+ def create_initializer_file
12
+ template 'bigint_pk.rb', 'config/initializers/bigint_pk.rb'
13
+ end
14
+
15
+ def create_migration
16
+ version = Time.now.utc.strftime '%Y%m%d%H%M%S'
17
+ template "migration.rb", "db/migrate/#{version}_change_keys_to_bigint.rb"
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,9 @@
1
+ require 'bigint_pk'
2
+
3
+ BigintPk.setup do |config|
4
+ # Remove this line or set config.enabled to false to prevent future migrations
5
+ # from defaulting to 64bit ints. This does not affect the initial migration
6
+ # created during installation.
7
+ #
8
+ config.enabled = true
9
+ end
@@ -0,0 +1,20 @@
1
+ # This file is auto-generated when running `rails generate bigint_pk:install`
2
+ # by the gem rails-bigint-pk (https://github.com/VerticalResponse/rails-bigint-pk).
3
+
4
+ class ChangeKeysToBigint < ActiveRecord::Migration
5
+ def change
6
+ Rails.application.eager_load!
7
+ ActiveRecord::Base.subclasses.select do |type|
8
+ connection.table_exists? type.table_name
9
+ end.each do |type|
10
+ BigintPk.update_primary_key type.table_name, type.primary_key
11
+
12
+ type.reflect_on_all_associations.select do |association|
13
+ ( association.macro == :belongs_to ) &&
14
+ connection.column_exists?( type.table_name, association.foreign_key )
15
+ end.each do |belongs_to_association|
16
+ BigintPk.update_foreign_key type.table_name, belongs_to_association.foreign_key
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,37 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "bigint_pk/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "rails-bigint-pk"
7
+ s.version = BigintPk::VERSION
8
+ s.authors = ["David J. Hamilton"]
9
+ s.email = ["dhamilton@verticalresponse.com"]
10
+ s.homepage = "https://github.com/VerticalResponse/rails-bigint-pk"
11
+ s.summary = %q{Easily use 64-bit primary keys in rails}
12
+ s.description = %q{Easily use 64-bit primary keys in rails.}
13
+
14
+ s.rubyforge_project = "rails-bigint-pk"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_runtime_dependency "activerecord", '~> 3.2.0'
22
+ s.add_runtime_dependency "railties", '~> 3.2.0'
23
+
24
+ s.add_development_dependency "rspec"
25
+ s.add_development_dependency "travis-lint"
26
+ s.add_development_dependency "rails"
27
+ s.add_development_dependency "debugger"
28
+ s.add_development_dependency "mysql2", '~> 0.3.10'
29
+ s.add_development_dependency "mysql", '~> 2.8.1'
30
+ s.add_development_dependency "pg", '~> 0.11'
31
+ s.add_development_dependency "sqlite3", '~> 1.3.6'
32
+ s.add_development_dependency "guard"
33
+ s.add_development_dependency "guard-rspec"
34
+ s.add_development_dependency "guard-bundler"
35
+ s.add_development_dependency "guard-ctags-bundler"
36
+ s.add_development_dependency "rb-fsevent"
37
+ end
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rails', '3.2.8'
4
+
5
+ gem 'pg', '~> 0.11'
6
+ gem 'mysql', '~> 2.8.1'
7
+ gem 'mysql2', '~> 0.3.10'
8
+ gem 'sqlite3', '~> 1.3.6'
@@ -0,0 +1,13 @@
1
+ common: &common
2
+ database: test_rails_app
3
+ adapter: mysql2
4
+ encoding: utf8
5
+ reconnect: false
6
+ pool: 5
7
+ host: localhost
8
+
9
+ development:
10
+ <<: *common
11
+
12
+ test:
13
+ <<: *common
@@ -0,0 +1,12 @@
1
+ common: &common
2
+ adapter: postgresql
3
+ database: test_rails_app
4
+ username: postgres
5
+ password:
6
+ host: localhost
7
+
8
+ development:
9
+ <<: *common
10
+
11
+ test:
12
+ <<: *common
@@ -0,0 +1,11 @@
1
+ common: &common
2
+ adapter: sqlite3
3
+ database: db/development.sqlite3
4
+ pool: 5
5
+ timeout: 5000
6
+
7
+ development:
8
+ <<: *common
9
+
10
+ test:
11
+ <<: *common
@@ -0,0 +1,2 @@
1
+ class Empire < ActiveRecord::Base
2
+ end
@@ -0,0 +1,4 @@
1
+ class Ruler < ActiveRecord::Base
2
+ belongs_to :empire
3
+ has_one :favourite_ruler, class_name: :Ruler
4
+ end
@@ -0,0 +1,10 @@
1
+ class CreateEmpiresAndRulers < ActiveRecord::Migration
2
+ def change
3
+ create_table :empires do |t|
4
+ end
5
+
6
+ create_table :rulers do |t|
7
+ t.references :empire
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,7 @@
1
+ class UpdateRulersAddFavouriteRuler < ActiveRecord::Migration
2
+ def change
3
+ change_table :rulers do |t|
4
+ t.references :favourite_ruler
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe BigintPk::Generators::InstallGenerator, :integration do
4
+ before do
5
+ in_directory( RailsDir ) do
6
+ run 'rails generate bigint_pk:install' do |stdout, stderr|
7
+ expect( stdout.read ).to_not include 'Could not find generator'
8
+ end
9
+ end
10
+ end
11
+
12
+ it 'creates a bigint_pk initializer' do
13
+ expect( File.exists? "#{RailsDir}/config/initializers/bigint_pk.rb").to be_true
14
+ end
15
+
16
+ it 'creates a bigint_pk migration' do
17
+ expect( Dir["#{RailsDir}/db/migrate/*change_keys_to_bigint.rb"].size ).to eq 1
18
+ end
19
+
20
+ context "when migrations are created after bigint-pk is installed" do
21
+ before do
22
+ in_directory ( RailsDir ) do
23
+ run 'rails g migration test_migration_after'
24
+ run 'rails g bigint_pk:install'
25
+ end
26
+ end
27
+
28
+ it "creates migration files in the correct order" do
29
+ Dir["#{RailsDir}/db/migrate/*rb"].sort.map do |migration_file|
30
+ File.basename( migration_file ).gsub(/^\d+_/, '')
31
+ end.should == %w[
32
+ create_empires_and_rulers.rb
33
+ update_rulers_add_favourite_ruler.rb
34
+ change_keys_to_bigint.rb
35
+ test_migration_after.rb
36
+ change_keys_to_bigint.rb
37
+ ]
38
+ end
39
+ end
40
+ end