Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: e23f481133
Fetching contributors…

Cannot retrieve contributors at this time

file 144 lines (124 sloc) 4.443 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
require 'test_helper'
require 'flexmock'

require 'active_record/connection_adapters/mysql2_adapter'

class PrefixModel < ActiveRecord::Base
  data_fabric :prefix => 'prefix'
end

class ShardModel < ActiveRecord::Base
  data_fabric :shard_by => :city
end

class TheWholeEnchilada < ActiveRecord::Base
  data_fabric :prefix => 'fiveruns', :replicated => true, :shard_by => :city
end

class AdapterMock < ActiveRecord::ConnectionAdapters::AbstractAdapter
  # Minimum required to perform a find with no results.
  def columns(table_name, name=nil)
    [ActiveRecord::ConnectionAdapters::Column.new('id', 0, :integer, false)]
  end
  def primary_key(name)
    :id
  end
  def adapter_name
    'mysql2'
  end
  def select(sql, name=nil, bindings=nil)
    []
  end
  def execute(sql, name=nil)
    []
  end
  def tables
    ["enchiladas", "the_whole_burritos"]
  end
  def table_exists?(name)
    true
  end
  def last_inserted_id(result)
    1
  end
  def method_missing(name, *args)
    raise ArgumentError, "#{self.class.name} missing '#{name}': #{args.inspect}"
  end

  def self.visitor_for(pool)
    Arel::Visitors::MySQL.new(pool)
  end
end

class RawConnection
  def method_missing(name, *args)
    puts "#{self.class.name} missing '#{name}': #{args.inspect}"
  end
end

class ConnectionTest < MiniTest::Unit::TestCase
  include FlexMock::TestCase

  def test_should_install_into_arbase
    assert PrefixModel.methods.map(&:to_s).include?('data_fabric')
  end

  def test_prefix_connection_name
    setup_configuration_for PrefixModel, 'prefix_test'
    assert_equal 'prefix_test', PrefixModel.connection.connection_name
  end

  def test_shard_connection_name
    setup_configuration_for ShardModel, 'city_austin_test'
    # ensure unset means error
    assert_raises ArgumentError do
      ShardModel.connection.connection_name
    end
    DataFabric.activate_shard(:city => 'austin', :category => 'art') do
      assert_equal 'city_austin_test', ShardModel.connection.connection_name
    end
    # ensure it got unset
    assert_raises ArgumentError do
      ShardModel.connection.connection_name
    end
  end

  def test_respond_to_connection_methods
    setup_configuration_for ShardModel, 'city_austin_test'
    DataFabric.activate_shard(:city => 'austin', :category => 'art') do
      assert ShardModel.connection.respond_to?(:columns)
      assert ShardModel.connection.respond_to?(:primary_key)
      assert !ShardModel.connection.respond_to?(:nonexistent_method)
    end
  end

  def test_respond_to_connection_proxy_methods
    setup_configuration_for ShardModel, 'city_austin_test'
    DataFabric.activate_shard(:city => 'austin', :category => 'art') do
      assert ShardModel.connection.respond_to?(:with_master)
      assert !ShardModel.connection.respond_to?(:nonexistent_method)
    end
  end

  def test_enchilada
    setup_configuration_for TheWholeEnchilada, 'fiveruns_city_dallas_test_slave'
    setup_configuration_for TheWholeEnchilada, 'fiveruns_city_dallas_test_master'
    DataFabric.activate_shard :city => :dallas do
      assert_equal 'fiveruns_city_dallas_test_slave', TheWholeEnchilada.connection.connection_name

      # Should use the slave
      assert_raises ActiveRecord::RecordNotFound do
        TheWholeEnchilada.find(1)
      end

      # Should use the master
      mmmm = TheWholeEnchilada.new
      mmmm.instance_variable_set(:@attributes, { 'id' => 1 })
      assert_raises ActiveRecord::RecordNotFound do
        mmmm.reload
      end
      # ...but immediately set it back to default to the slave
      assert_equal 'fiveruns_city_dallas_test_slave', TheWholeEnchilada.connection.connection_name

      # Should use the master
      TheWholeEnchilada.transaction do
        mmmm.save!
      end
      TheWholeEnchilada.verify_active_connections!
      TheWholeEnchilada.clear_active_connections!
      TheWholeEnchilada.clear_all_connections!
    end

    TheWholeEnchilada.verify_active_connections!
    TheWholeEnchilada.clear_active_connections!
    TheWholeEnchilada.clear_all_connections!
  end

  private

  def setup_configuration_for(clazz, name)
    flexmock(ActiveRecord::Base).should_receive(:mysql2_connection).and_return(AdapterMock.new(RawConnection.new))
    ActiveRecord::Base.configurations ||= HashWithIndifferentAccess.new
    ActiveRecord::Base.configurations[name] = HashWithIndifferentAccess.new({ :adapter => 'mysql2', :database => name, :host => 'localhost'})
  end
end
Something went wrong with that request. Please try again.