Eugene Kalenkovich
audience.except(&:can_see_this).each do |person|
  # Please!
  person.move(:closer)
end
           
          
         
         
             
           
             
             
             
             
          
test:
  adapter: postgresql  # mysql2
  database: your_db_test
            
def concurrently processes = 10
  processes.times do
    fork do
      yield
    end
  end
  assert Process.waitall.map(&:last).all? &:success?
end
            
def concurrently processes = 10
  processes.times do
    fork do
      yield
    end
  end
  assert Process.waitall.map(&:last).all? &:success?
end
            
def concurrently processes = 10
  processes.times do
    fork do
      yield
    end
  end
  assert Process.waitall.map(&:last).all? &:success?
end
            
def concurrently processes = 10
  ActiveRecord::Base.remove_connection
  processes.times do
    fork do
      begin
        ActiveRecord::Base.establish_connection
        yield
      rescue => e
        puts "#{e.class.name}: #{e}" && exit 1
      ensure
        ActiveRecord::Base.remove_connection
      end
    end
  end
  ActiveRecord::Base.establish_connection
  assert Process.waitall.map(&:last).all? &:success?
end  
          
def concurrently processes = 10
  ActiveRecord::Base.remove_connection
  processes.times do
    fork do
      begin
        ActiveRecord::Base.establish_connection
        yield
      rescue => e
        puts "#{e.class.name}: #{e}" && exit 1
      ensure
        ActiveRecord::Base.remove_connection
      end
    end
  end
  ActiveRecord::Base.establish_connection
  assert Process.waitall.map(&:last).all? &:success?
end
          
def concurrently processes = 10
  ActiveRecord::Base.remove_connection
  processes.times do
    fork do
      begin
        ActiveRecord::Base.establish_connection
        yield
      rescue => e
        puts "#{e.class.name}: #{e}" && exit 1
      ensure
        ActiveRecord::Base.remove_connection
      end
    end
  end
  ActiveRecord::Base.establish_connection
  assert Process.waitall.map(&:last).all? &:success?
end
           
          
        
class Number < ActiveRecord::Base
  # t.integer :value
end   
          
describe Number do
  it 'should have unique values' do
    concurrently do
      10.times do
        Number.where(value: Number.count).first_or_create
      end
    end
    Number.count.must_equal Number.select('distinct value').count
  end
end
          
describe Number do
  it 'should have unique values' do
    concurrently do
      10.times do
        Number.where(value: Number.count).first_or_create
      end
    end
    Number.count.must_equal Number.select('distinct value').count
  end
end
          
describe Number do
  it 'should have unique values' do
    concurrently do
      10.times do
        Number.where(value: Number.count).first_or_create
      end
    end
    Number.count.must_equal Number.select('distinct value').count
  end
end
          
1) Failure:
test_0001_should_have_unique_values(Number) :
Expected: 49
  Actual: 99
          
> Number.where(value: 3).first_or_create
  Number Load (16.2ms)  SELECT "numbers".* FROM "numbers" WHERE "numbers"."value" = 3 LIMIT 1
   (0.2ms)  BEGIN
  SQL (9.0ms)  INSERT INTO "numbers" ("value") VALUES ($1) RETURNING "id"  [["value", 3]]
   (0.4ms)  COMMIT
            
> Number.where(value: 3).first_or_create
  Number Load (16.2ms)  SELECT "numbers".* FROM "numbers" WHERE "numbers"."value" = 3 LIMIT 1
   (0.2ms)  BEGIN
  SQL (9.0ms)  INSERT INTO "numbers" ("value") VALUES ($1) RETURNING "id"  [["value", 3]]
   (0.4ms)  COMMIT
            
> Number.where(value: 3).first_or_create
  Number Load (16.2ms)  SELECT "numbers".* FROM "numbers" WHERE "numbers"."value" = 3 LIMIT 1
   (0.2ms)  BEGIN
  SQL (9.0ms)  INSERT INTO "numbers" ("value") VALUES ($1) RETURNING "id"  [["value", 3]]
   (0.4ms)  COMMIT
            
> Number.where(value: 3).first_or_create
  Number Load (0.4ms)  SELECT "numbers".* FROM "numbers" WHERE "numbers"."value" = 3 LIMIT 1
            
> Number.where(value: 3).first_or_create
  Number Load (0.4ms)  SELECT "numbers".* FROM "numbers" WHERE "numbers"."value" = 3 LIMIT 1
            
> Number.where(value: 3).first_or_create
  Number Load (16.2ms)  SELECT "numbers".* FROM "numbers" WHERE "numbers"."value" = 3 LIMIT 1
   (0.2ms)  BEGIN
  SQL (9.0ms)  INSERT INTO "numbers" ("value") VALUES ($1) RETURNING "id"  [["value", 3]]
   (0.4ms)  COMMIT
            
> Number.where(value: 3).first_or_create
  Number Load (16.2ms)  SELECT "numbers".* FROM "numbers" WHERE "numbers"."value" = 3 LIMIT 1
   (0.2ms)  BEGIN
  SQL (9.0ms)  INSERT INTO "numbers" ("value") VALUES ($1) RETURNING "id"  [["value", 3]]
   (0.4ms)  COMMIT
            
> Number.where(value: 3).first_or_create
  Number Load (16.2ms)  SELECT "numbers".* FROM "numbers" WHERE "numbers"."value" = 3 LIMIT 1
   (0.2ms)  BEGIN
  SQL (9.0ms)  INSERT INTO "numbers" ("value") VALUES ($1) RETURNING "id"  [["value", 3]]
   (0.4ms)  COMMIT
            
> Number.where(value: 3).first_or_create
  Number Load (0.4ms)  SELECT "numbers".* FROM "numbers" WHERE "numbers"."value" = 3 LIMIT 1
            
> Number.where(value: 3).first_or_create
  Number Load (0.4ms)  SELECT "numbers".* FROM "numbers" WHERE "numbers"."value" = 3 LIMIT 1
            
> Number.where(value: 3).first_or_create
  Number Load (0.4ms)  SELECT "numbers".* FROM "numbers" WHERE "numbers"."value" = 3 LIMIT 1
   (0.2ms)  BEGIN
  SQL (0.3ms)  INSERT INTO "numbers" ("value") VALUES ($1) RETURNING "id"  [["value", 3]]
   (0.5ms)  COMMIT
             
          
        
class ValidatedNumber < ActiveRecord::Base
  validates :value, uniqueness: true
end
            
describe ValidatedNumber do
  it 'should have unique values' do
    concurrently do
      10.times do
        ValidatedNumber.create{|r| r.value = ValidatedNumber.count}
      end
    end
    unique = ValidatedNumber.select("distinct value").count
    ValidatedNumber.count.must_equal unique
  end
end
            
1) Failure:
test_0001_should_have_unique_values(ValidatedNumber):
Expected: 37
  Actual: 96
            
> ValidatedNumber.create(value: 1)
   (0.1ms)  BEGIN
  ValidatedNumber Exists (25.2ms)  SELECT 1 AS one FROM "validated_numbers" WHERE "validated_numbers"."value" = 1 LIMIT 1
  SQL (14.7ms)  INSERT INTO "validated_numbers" ("value") VALUES ($1) RETURNING "id"  [["value", 1]]
   (0.7ms)  COMMIT
            
> ValidatedNumber.create(value: 1)
   (0.1ms)  BEGIN
  ValidatedNumber Exists (25.2ms)  SELECT 1 AS one FROM "validated_numbers" WHERE "validated_numbers"."value" = 1 LIMIT 1
  SQL (14.7ms)  INSERT INTO "validated_numbers" ("value") VALUES ($1) RETURNING "id"  [["value", 1]]
   (0.7ms)  COMMIT
           
            
        
class CreateConstrainedNumbers < ActiveRecord::Migration
  def change
    create_table :constrained_numbers do |t|
      t.integer :value
    end
    add_index :constrained_numbers, :value, unique: true
  end
end
          
class CreateConstrainedNumbers < ActiveRecord::Migration
  def change
    create_table :constrained_numbers do |t|
      t.integer :value
    end
    add_index :constrained_numbers, :value, unique: true
  end
end
          
# Running tests:
ActiveRecord::RecordNotUnique: PG::Error: ERROR:  duplicate key value violates unique constraint "index_constrained_numbers_on_value"
DETAIL:  Key (value)=(0) already exists.
: INSERT INTO "constrained_numbers" ("value") VALUES ($1) RETURNING "id"
ActiveRecord::RecordNotUnique: PG::Error: ERROR:  duplicate key value violates unique constraint "index_constrained_numbers_on_value"
DETAIL:  Key (value)=(0) already exists.
: INSERT INTO "constrained_numbers" ("value") VALUES ($1) RETURNING "id"
ActiveRecord::RecordNotUnique: PG::Error: ERROR:  duplicate key value violates unique constraint "index_constrained_numbers_on_value"
DETAIL:  Key (value)=(0) already exists.
: INSERT INTO "constrained_numbers" ("value") VALUES ($1) RETURNING "id"
ActiveRecord::RecordNotUnique: PG::Error: ERROR:  duplicate key value violates unique constraint "index_constrained_numbers_on_value"
DETAIL:  Key (value)=(0) already exists.
: INSERT INTO "constrained_numbers" ("value") VALUES ($1) RETURNING "id"
ActiveRecord::RecordNotUnique: PG::Error: ERROR:  duplicate key value violates unique constraint "index_constrained_numbers_on_value"
DETAIL:  Key (value)=(0) already exists.
: INSERT INTO "constrained_numbers" ("value") VALUES ($1) RETURNING "id"
[...]
          
# Running tests:
ActiveRecord::RecordNotUnique: PG::Error: ERROR:  duplicate key value violates unique constraint "index_constrained_numbers_on_value"
DETAIL:  Key (value)=(0) already exists.
: INSERT INTO "constrained_numbers" ("value") VALUES ($1) RETURNING "id"
ActiveRecord::RecordNotUnique: PG::Error: ERROR:  duplicate key value violates unique constraint "index_constrained_numbers_on_value"
DETAIL:  Key (value)=(0) already exists.
: INSERT INTO "constrained_numbers" ("value") VALUES ($1) RETURNING "id"
ActiveRecord::RecordNotUnique: PG::Error: ERROR:  duplicate key value violates unique constraint "index_constrained_numbers_on_value"
DETAIL:  Key (value)=(0) already exists.
: INSERT INTO "constrained_numbers" ("value") VALUES ($1) RETURNING "id"
ActiveRecord::RecordNotUnique: PG::Error: ERROR:  duplicate key value violates unique constraint "index_constrained_numbers_on_value"
DETAIL:  Key (value)=(0) already exists.
: INSERT INTO "constrained_numbers" ("value") VALUES ($1) RETURNING "id"
ActiveRecord::RecordNotUnique: PG::Error: ERROR:  duplicate key value violates unique constraint "index_constrained_numbers_on_value"
DETAIL:  Key (value)=(0) already exists.
: INSERT INTO "constrained_numbers" ("value") VALUES ($1) RETURNING "id"
[...]
           
          
        
class SafeNumber < ActiveRecord::Base
  def self.first_or_create_where(*args)
    where(*args).first_or_create
  rescue ActiveRecord::RecordNotUnique
    retry
  end
end
          
class SafeNumber < ActiveRecord::Base
  def self.first_or_create_where(*args)
    where(*args).first_or_create
  rescue ActiveRecord::RecordNotUnique
    retry
  end
end
          
# Running tests:
.
Finished tests in 8.337332s, 0.1199 tests/s, 0.2399 assertions/s.
1 tests, 2 assertions, 0 failures, 0 errors, 0 skips
          
ActiveRecord::StatementInvalid: Mysql2::Error: Deadlock found when trying to get lock; try restarting transaction: INSERT INTO `safe_numbers` (`value`) VALUES (132)
ActiveRecord::StatementInvalid: Mysql2::Error: Deadlock found when trying to get lock; try restarting transaction: INSERT INTO `safe_numbers` (`value`) VALUES (132)
F
          
ActiveRecord::StatementInvalid: Mysql2::Error: Deadlock found when trying to get lock; try restarting transaction: INSERT INTO `safe_numbers` (`value`) VALUES (132)
ActiveRecord::StatementInvalid: Mysql2::Error: Deadlock found when trying to get lock; try restarting transaction: INSERT INTO `safe_numbers` (`value`) VALUES (132)
F
          
def self.first_or_create_where(*args)
  where(*args).first_or_create
rescue ActiveRecord::RecordNotUnique
  retry
rescue ActiveRecord::StatementInvalid => e
  retry if e.message =~ /Deadlock/
  # Thank you, MySQL and Mysql2!
  raise
end
          
def self.first_or_create_where(*args)
  where(*args).first_or_create
rescue ActiveRecord::RecordNotUnique
  retry
rescue ActiveRecord::StatementInvalid => e
  retry if e.message =~ /Deadlock/
  # Thank you, MySQL and Mysql2!
  raise
end
          
# Running tests:
.
Finished tests in 3.234423s, 0.3092 tests/s, 0.6183 assertions/s.
1 tests, 2 assertions, 0 failures, 0 errors, 0 skips
          
class Dog < ActiveRecord::Base
  has_one :head
  has_many :legs
end
          
class Head < ActiveRecord::Base
  belongs_to :dog
end
class Leg < ActiveRecord::Base
  belongs_to :dog
end
          
20.times{ Dog.create }
concurrently do
  begin
    headless = Dog.includes(:head).where(heads: {dog_id: nil}).first
    headless && headless.create_head
    legless = Dog.includes(:legs).where(legs: {dog_id: nil}).first
    legless && legless.legs = 4.times.map{ Leg.create }
  end while headless || legless
end
          
20.times{ Dog.create }
concurrently do
  begin
    headless = Dog.includes(:head).where(heads: {dog_id: nil}).first
    headless && headless.create_head
    legless = Dog.includes(:legs).where(legs: {dog_id: nil}).first
    legless && legless.legs = 4.times.map{ Leg.create }
  end while headless || legless
end
          
20.times{ Dog.create }
concurrently do
  begin
    headless = Dog.includes(:head).where(heads: {dog_id: nil}).first
    headless && headless.create_head
    legless = Dog.includes(:legs).where(legs: {dog_id: nil}).first
    legless && legless.legs = 4.times.map{ Leg.create }
  end while headless || legless
end
          
20.times{ Dog.create }
concurrently do
  begin
    headless = Dog.includes(:head).where(heads: {dog_id: nil}).first
    headless && headless.create_head
    legless = Dog.includes(:legs).where(legs: {dog_id: nil}).first
    legless && legless.legs = 4.times.map{ Leg.create }
  end while headless || legless
end
          
Dog.all_str.must_equal "20 dogs with 1 head and 4 legs"
          
--- expected
+++ actual
@@ -1 +1 @@
-"20 dogs with 1 head and 4 legs"
+"3 dogs with 1 head and 8 legs, 2 dogs with 2 heads and 28 legs, 2 dogs with 1 head and 12 legs, 1 dog with 1 head and 4 legs, 1 dog with 4 heads and 24 legs, 1 dog with 4 heads and 32 legs, 1 dog with 3 heads and 16 legs, 1 dog with 2 heads and 32 legs, 1 dog with 1 head and 16 legs, 1 dog with 6 heads and 8 legs, 1 dog with 1 head and 20 legs, 1 dog with 2 heads and 16 legs, 1 dog with 4 heads and 36 legs, 1 dog with 5 heads and 24 legs, 1 dog with 8 heads and 20 legs, 1 dog with 2 heads and 40 legs"
          
--- expected
+++ actual
@@ -1 +1 @@
-"20 dogs with 1 head and 4 legs"
+"3 dogs with 1 head and 8 legs, 2 dogs with 2 heads and 28 legs, 2 dogs with 1 head and 12 legs, 1 dog with 1 head and 4 legs, 1 dog with 4 heads and 24 legs, 1 dog with 4 heads and 32 legs, 1 dog with 3 heads and 16 legs, 1 dog with 2 heads and 32 legs, 1 dog with 1 head and 16 legs, 1 dog with 6 heads and 8 legs, 1 dog with 1 head and 20 legs, 1 dog with 2 heads and 16 legs, 1 dog with 4 heads and 36 legs, 1 dog with 5 heads and 24 legs, 1 dog with 8 heads and 20 legs, 1 dog with 2 heads and 40 legs"
           
          
        
> Dog.first.create_head
  Dog Load (0.3ms)  SELECT "dogs".* FROM "dogs" LIMIT 1
   (0.1ms)  BEGIN
  SQL (12.0ms)  INSERT INTO "heads" ("dog_id") VALUES ($1) RETURNING "id"  [["dog_id", 1]]
   (0.9ms)  COMMIT
  Head Load (0.2ms)  SELECT "heads".* FROM "heads" WHERE "heads"."dog_id" = 1 LIMIT 1
   (0.1ms)  BEGIN
   (0.2ms)  UPDATE "heads" SET "dog_id" = NULL WHERE "heads"."id" = 1
   (0.4ms)  COMMIT
          
> Dog.first.create_head
  Dog Load (0.3ms)  SELECT "dogs".* FROM "dogs" LIMIT 1
   (0.1ms)  BEGIN
  SQL (12.0ms)  INSERT INTO "heads" ("dog_id") VALUES ($1) RETURNING "id"  [["dog_id", 1]]
   (0.9ms)  COMMIT
  Head Load (0.2ms)  SELECT "heads".* FROM "heads" WHERE "heads"."dog_id" = 1 LIMIT 1
   (0.1ms)  BEGIN
   (0.2ms)  UPDATE "heads" SET "dog_id" = NULL WHERE "heads"."id" = 1
   (0.4ms)  COMMIT
          
> Dog.first.create_head
  Dog Load (0.3ms)  SELECT "dogs".* FROM "dogs" LIMIT 1
   (0.1ms)  BEGIN
  SQL (12.0ms)  INSERT INTO "heads" ("dog_id") VALUES ($1) RETURNING "id"  [["dog_id", 1]]
   (0.9ms)  COMMIT
  Head Load (0.2ms)  SELECT "heads".* FROM "heads" WHERE "heads"."dog_id" = 1 LIMIT 1
   (0.1ms)  BEGIN
   (0.2ms)  UPDATE "heads" SET "dog_id" = NULL WHERE "heads"."id" = 1
   (0.4ms)  COMMIT
          
> Dog.first.create_head
  Dog Load (0.3ms)  SELECT "dogs".* FROM "dogs" LIMIT 1
   (0.1ms)  BEGIN
  SQL (12.0ms)  INSERT INTO "heads" ("dog_id") VALUES ($1) RETURNING "id"  [["dog_id", 1]]
   (0.9ms)  COMMIT
  Head Load (0.2ms)  SELECT "heads".* FROM "heads" WHERE "heads"."dog_id" = 1 LIMIT 1
   (0.1ms)  BEGIN
   (0.2ms)  UPDATE "heads" SET "dog_id" = NULL WHERE "heads"."id" = 1
   (0.4ms)  COMMIT
          
> Dog.first.create_head
  Dog Load (0.3ms)  SELECT "dogs".* FROM "dogs" LIMIT 1
   (0.1ms)  BEGIN
  SQL (12.0ms)  INSERT INTO "heads" ("dog_id") VALUES ($1) RETURNING "id"  [["dog_id", 1]]
   (0.9ms)  COMMIT
  Head Load (0.2ms)  SELECT "heads".* FROM "heads" WHERE "heads"."dog_id" = 1 LIMIT 1
   (0.1ms)  BEGIN
   (0.2ms)  UPDATE "heads" SET "dog_id" = NULL WHERE "heads"."id" = 1
   (0.4ms)  COMMIT
           
        
>   Dog.first.legs = Leg.all.sample(4)
  Dog Load (0.3ms)  SELECT "dogs".* FROM "dogs" LIMIT 1
  Leg Load (0.2ms)  SELECT "legs".* FROM "legs"
  Leg Load (0.3ms)  SELECT "legs".* FROM "legs" WHERE "legs"."dog_id" = 1
   (0.1ms)  BEGIN
   (0.2ms)  UPDATE "legs" SET "dog_id" = 1 WHERE "legs"."id" = 6
   (0.2ms)  UPDATE "legs" SET "dog_id" = 1 WHERE "legs"."id" = 3
   (0.2ms)  UPDATE "legs" SET "dog_id" = 1 WHERE "legs"."id" = 10
   (0.1ms)  UPDATE "legs" SET "dog_id" = 1 WHERE "legs"."id" = 5
   (0.5ms)  COMMIT
          
> Dog.first.legs = Leg.all.sample(4)
  Dog Load (0.4ms)  SELECT "dogs".* FROM "dogs" LIMIT 1
  Leg Load (0.3ms)  SELECT "legs".* FROM "legs"
  Leg Load (0.3ms)  SELECT "legs".* FROM "legs" WHERE "legs"."dog_id" = 1
   (0.1ms)  BEGIN
  SQL (0.3ms)  UPDATE "legs" SET "dog_id" = NULL WHERE "legs"."dog_id" = 1 AND "legs"."id" IN (10, 5)
   (0.2ms)  UPDATE "legs" SET "dog_id" = 1 WHERE "legs"."id" = 2
   (0.2ms)  UPDATE "legs" SET "dog_id" = 1 WHERE "legs"."id" = 9
   (0.6ms)  COMMIT
          
> Dog.first.legs = Leg.all.sample(4)
  Dog Load (0.4ms)  SELECT "dogs".* FROM "dogs" LIMIT 1
  Leg Load (0.3ms)  SELECT "legs".* FROM "legs"
  Leg Load (0.3ms)  SELECT "legs".* FROM "legs" WHERE "legs"."dog_id" = 1
   (0.1ms)  BEGIN
  SQL (0.3ms)  UPDATE "legs" SET "dog_id" = NULL WHERE "legs"."dog_id" = 1 AND "legs"."id" IN (10, 5)
   (0.2ms)  UPDATE "legs" SET "dog_id" = 1 WHERE "legs"."id" = 2
   (0.2ms)  UPDATE "legs" SET "dog_id" = 1 WHERE "legs"."id" = 9
   (0.6ms)  COMMIT
           
        unique.fix :db, diy: true, mysql: mysql?
headless = Dog.includes(:head).where(heads: {dog_id: nil}).first
headless && Dog.transaction do
  headless.lock!
  headless.create_head
end
legless = Dog.includes(:legs).where(legs: {dog_id: nil}).first
legless && Dog.transaction do
  legless.lock!
  legless.legs = 4.times.map{ Leg.create }
end
          
headless = Dog.includes(:head).where(heads: {dog_id: nil}).first
headless && Dog.transaction do
  headless.lock!
  headless.create_head
end
legless = Dog.includes(:legs).where(legs: {dog_id: nil}).first
legless && Dog.transaction do
  legless.lock!
  legless.legs = 4.times.map{ Leg.create }
end
          
1 tests, 2 assertions, 0 failures, 0 errors, 0 skips
          
--- expected
+++ actual
@@ -1 +1 @@
-"50 dogs with 1 head and 4 legs"
+"30 dogs with 1 head and 4 legs, 11 dogs with 2 heads and 4 legs, 4 dogs with 3 heads and 4 legs, 4 dogs with 4 heads and 4 legs, 1 dog with 5 heads and 4 legs"
           
        
> Dog.first.create_head
  Dog Load (0.3ms)  SELECT "dogs".* FROM "dogs" LIMIT 1
   (0.1ms)  BEGIN
  SQL (12.0ms)  INSERT INTO "heads" ("dog_id") VALUES ($1) RETURNING "id"  [["dog_id", 1]]
   (0.9ms)  COMMIT
  Head Load (0.2ms)  SELECT "heads".* FROM "heads" WHERE "heads"."dog_id" = 1 LIMIT 1
   (0.1ms)  BEGIN
   (0.2ms)  UPDATE "heads" SET "dog_id" = NULL WHERE "heads"."id" = 1
   (0.4ms)  COMMIT
          
> Dog.first.head = Head.create
  Dog Load (39.8ms)  SELECT "dogs".* FROM "dogs" LIMIT 1
   (0.1ms)  BEGIN
  SQL (49.1ms)  INSERT INTO "heads" ("dog_id") VALUES ($1) RETURNING "id"  [["dog_id", nil]]
   (0.6ms)  COMMIT
"replace"
  Head Load (0.4ms)  SELECT "heads".* FROM "heads" WHERE "heads"."dog_id" = 1 LIMIT 1
   (0.1ms)  BEGIN
   (0.4ms)  UPDATE "heads" SET "dog_id" = NULL WHERE "heads"."id" = 2
   (0.2ms)  UPDATE "heads" SET "dog_id" = 1 WHERE "heads"."id" = 3
   (0.5ms)  COMMIT
          
headless = Dog.includes(:head).where(heads: {dog_id: nil}).first
headless && Dog.transaction do
  headless.lock!
  headless.head = Head.create
end
legless = Dog.includes(:legs).where(legs: {dog_id: nil}).first
legless && Dog.transaction do
  legless.lock!
  legless.legs = 4.times.map{ Leg.create }
end
          
# Running tests:
.
Finished tests in 2.527906s, 0.3956 tests/s, 0.7912 assertions/s.
1 tests, 2 assertions, 0 failures, 0 errors, 0 skips
          
headless = Dog.includes(:head).where(heads: {dog_id: nil}).first
if headless
  headless.create_head
  Head.update_all({ dog_id: nil },
    { id: Head.where(dog_id: headless.id).order(:id).pluck(:id)[0..-2] })
end
legless = Dog.includes(:legs).where(legs: {dog_id: nil}).first
if legless
  legless.legs = 4.times.map{ Leg.create }
  Leg.update_all({ dog_id: nil },
    { id: Leg.where(dog_id: legless.id).order(:id).pluck(:id)[0..-5] })
end
          
headless = Dog.includes(:head).where(heads: {dog_id: nil}).first
if headless
  headless.create_head
  Head.update_all({ dog_id: nil },
    { id: Head.where(dog_id: headless.id).order(:id).pluck(:id)[0..-2] })
end
legless = Dog.includes(:legs).where(legs: {dog_id: nil}).first
if legless
  legless.legs = 4.times.map{ Leg.create }
  Leg.update_all({ dog_id: nil },
    { id: Leg.where(dog_id: legless.id).order(:id).pluck(:id)[0..-5] })
end
          
headless = Dog.includes(:head).where(heads: {dog_id: nil}).first
if headless
  headless.create_head
  Head.update_all({ dog_id: nil },
    { id: Head.where(dog_id: headless.id).order(:id).pluck(:id)[0..-2] })
end
legless = Dog.includes(:legs).where(legs: {dog_id: nil}).first
if legless
  legless.legs = 4.times.map{ Leg.create }
  Leg.update_all({ dog_id: nil },
    { id: Leg.where(dog_id: legless.id).order(:id).pluck(:id)[0..-5] })
end
          
# Running tests:
.
Finished tests in 2.957711s, 0.3956 tests/s, 0.7912 assertions/s.
1 tests, 2 assertions, 0 failures, 0 errors, 0 skips
          
remove_column :extra_columns, :extra
          
> ExtraColumn.create
   (0.2ms)  BEGIN
  SQL (34.9ms)  INSERT INTO "extra_columns" ("extra", "value") VALUES ($1, $2) RETURNING "id"  [["extra", nil], ["value", nil]]
   (0.2ms)  ROLLBACK
ActiveRecord::StatementInvalid: PG::Error: ERROR:  column "extra" of relation "extra_columns" does not exist at character 30
: INSERT INTO "extra_columns" ("extra", "value") VALUES ($1, $2) RETURNING "id"
          
> ExtraColumn.create
   (0.2ms)  BEGIN
  SQL (34.9ms)  INSERT INTO "extra_columns" ("extra", "value") VALUES ($1, $2) RETURNING "id"  [["extra", nil], ["value", nil]]
   (0.2ms)  ROLLBACK
ActiveRecord::StatementInvalid: PG::Error: ERROR:  column "extra" of relation "extra_columns" does not exist at character 30
: INSERT INTO "extra_columns" ("extra", "value") VALUES ($1, $2) RETURNING "id"
           
          
        
def columns
  @columns ||= connection.schema_cache.columns[table_name].map do |col|
    col = col.dup
    col.primary = (col.name == primary_key)
    col
  end
end
           3.2
 3.2
class ExtraColumn < ActiveRecord::Base
  def self.columns
    @my_columns ||= super.reject{ |c|
      c.name == 'extra'
    }
  end
end
            
remove_column :extra_columns, :extra
             
         
               
            
            
               
               
            
            
               
               
            
            
               
               
            
            
               
               
            
         
               
            
            
               
               
            
            
               
               
            
            
               
               
            
         
               
            
            
               
               
            
            
               
               
            
        
config.action_controller.asset_host = "//your.super.asset.host"
          
config.assets.digest = true
          Concurrency of development with deployment . . . has almost always proven counterproductive
Harold Brown
 
           
          I Can Haz Four Volunteers?
 
          
        Rails is omakase. A team of chefs picked out the ingredients, designed the APIs, and arranged the order of consumption on your behalf according to their idea of what would make for a tasty full-stack framework.
DHH