primary_keys_test.rb 11.0 KB
Newer Older
1
require "cases/helper"
2
require 'support/schema_dumping_helper'
J
Jeremy Kemper 已提交
3
require 'models/topic'
4
require 'models/reply'
J
Jeremy Kemper 已提交
5 6 7 8
require 'models/subscriber'
require 'models/movie'
require 'models/keyboard'
require 'models/mixed_case_monkey'
9
require 'models/dashboard'
D
Initial  
David Heinemeier Hansson 已提交
10

11
class PrimaryKeysTest < ActiveRecord::TestCase
12
  fixtures :topics, :subscribers, :movies, :mixed_case_monkeys
D
Initial  
David Heinemeier Hansson 已提交
13

14
  def test_to_key_with_default_primary_key
15
    topic = Topic.new
16
    assert_nil topic.to_key
17
    topic = Topic.find(1)
18
    assert_equal [1], topic.to_key
19 20 21 22
  end

  def test_to_key_with_customized_primary_key
    keyboard = Keyboard.new
23
    assert_nil keyboard.to_key
24 25
    keyboard.save
    assert_equal keyboard.to_key, [keyboard.id]
26 27
  end

28 29 30 31 32
  def test_read_attribute_with_custom_primary_key
    keyboard = Keyboard.create!
    assert_equal keyboard.key_number, keyboard.read_attribute(:id)
  end

33 34 35
  def test_to_key_with_primary_key_after_destroy
    topic = Topic.find(1)
    topic.destroy
36
    assert_equal [1], topic.to_key
37 38
  end

D
Initial  
David Heinemeier Hansson 已提交
39 40
  def test_integer_key
    topic = Topic.find(1)
41
    assert_equal(topics(:first).author_name, topic.author_name)
D
Initial  
David Heinemeier Hansson 已提交
42
    topic = Topic.find(2)
43
    assert_equal(topics(:second).author_name, topic.author_name)
D
Initial  
David Heinemeier Hansson 已提交
44 45 46

    topic = Topic.new
    topic.title = "New Topic"
47
    assert_nil topic.id
48
    assert_nothing_raised { topic.save! }
D
Initial  
David Heinemeier Hansson 已提交
49 50 51 52 53 54
    id = topic.id

    topicReloaded = Topic.find(id)
    assert_equal("New Topic", topicReloaded.title)
  end

55
  def test_customized_primary_key_auto_assigns_on_save
56
    Keyboard.delete_all
57
    keyboard = Keyboard.new(:name => 'HHKB')
58
    assert_nothing_raised { keyboard.save! }
59
    assert_equal keyboard.id, Keyboard.find_by_name('HHKB').id
60 61
  end

62
  def test_customized_primary_key_can_be_get_before_saving
63
    keyboard = Keyboard.new
64 65
    assert_nil keyboard.id
    assert_nothing_raised { assert_nil keyboard.key_number }
66 67 68 69 70 71 72 73 74
  end

  def test_customized_string_primary_key_settable_before_save
    subscriber = Subscriber.new
    assert_nothing_raised { subscriber.id = 'webster123' }
    assert_equal 'webster123', subscriber.id
    assert_equal 'webster123', subscriber.nick
  end

D
Initial  
David Heinemeier Hansson 已提交
75
  def test_string_key
76 77 78 79
    subscriber = Subscriber.find(subscribers(:first).nick)
    assert_equal(subscribers(:first).name, subscriber.name)
    subscriber = Subscriber.find(subscribers(:second).nick)
    assert_equal(subscribers(:second).name, subscriber.name)
D
Initial  
David Heinemeier Hansson 已提交
80 81 82 83 84

    subscriber = Subscriber.new
    subscriber.id = "jdoe"
    assert_equal("jdoe", subscriber.id)
    subscriber.name = "John Doe"
85
    assert_nothing_raised { subscriber.save! }
86
    assert_equal("jdoe", subscriber.id)
D
Initial  
David Heinemeier Hansson 已提交
87 88 89 90 91 92

    subscriberReloaded = Subscriber.find("jdoe")
    assert_equal("John Doe", subscriberReloaded.name)
  end

  def test_find_with_more_than_one_string_key
93
    assert_equal 2, Subscriber.find(subscribers(:first).nick, subscribers(:second).nick).length
D
Initial  
David Heinemeier Hansson 已提交
94
  end
J
Jeremy Kemper 已提交
95

D
Initial  
David Heinemeier Hansson 已提交
96
  def test_primary_key_prefix
97
    old_primary_key_prefix_type = ActiveRecord::Base.primary_key_prefix_type
D
Initial  
David Heinemeier Hansson 已提交
98
    ActiveRecord::Base.primary_key_prefix_type = :table_name
99
    Topic.reset_primary_key
D
Initial  
David Heinemeier Hansson 已提交
100 101 102
    assert_equal "topicid", Topic.primary_key

    ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore
103
    Topic.reset_primary_key
D
Initial  
David Heinemeier Hansson 已提交
104 105 106
    assert_equal "topic_id", Topic.primary_key

    ActiveRecord::Base.primary_key_prefix_type = nil
107
    Topic.reset_primary_key
D
Initial  
David Heinemeier Hansson 已提交
108
    assert_equal "id", Topic.primary_key
109 110
  ensure
    ActiveRecord::Base.primary_key_prefix_type = old_primary_key_prefix_type
D
Initial  
David Heinemeier Hansson 已提交
111
  end
J
Jeremy Kemper 已提交
112

113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
  def test_delete_should_quote_pkey
    assert_nothing_raised { MixedCaseMonkey.delete(1) }
  end
  def test_update_counters_should_quote_pkey_and_quote_counter_columns
    assert_nothing_raised { MixedCaseMonkey.update_counters(1, :fleaCount => 99) }
  end
  def test_find_with_one_id_should_quote_pkey
    assert_nothing_raised { MixedCaseMonkey.find(1) }
  end
  def test_find_with_multiple_ids_should_quote_pkey
    assert_nothing_raised { MixedCaseMonkey.find([1,2]) }
  end
  def test_instance_update_should_quote_pkey
    assert_nothing_raised { MixedCaseMonkey.find(1).save }
  end
128
  def test_instance_destroy_should_quote_pkey
129 130
    assert_nothing_raised { MixedCaseMonkey.find(1).destroy }
  end
131 132

  def test_supports_primary_key
133
    assert_nothing_raised do
134 135 136 137
      ActiveRecord::Base.connection.supports_primary_key?
    end
  end

138 139 140 141 142
  if ActiveRecord::Base.connection.supports_primary_key?
    def test_primary_key_returns_value_if_it_exists
      klass = Class.new(ActiveRecord::Base) do
        self.table_name = 'developers'
      end
143 144

      assert_equal 'id', klass.primary_key
145 146
    end

147 148 149 150
    def test_primary_key_returns_nil_if_it_does_not_exist
      klass = Class.new(ActiveRecord::Base) do
        self.table_name = 'developers_projects'
      end
151 152

      assert_nil klass.primary_key
153 154
    end
  end
155 156 157 158 159 160 161

  def test_quoted_primary_key_after_set_primary_key
    k = Class.new( ActiveRecord::Base )
    assert_equal k.connection.quote_column_name("id"), k.quoted_primary_key
    k.primary_key = "foo"
    assert_equal k.connection.quote_column_name("foo"), k.quoted_primary_key
  end
J
Jon Leighton 已提交
162

163 164 165 166
  def test_auto_detect_primary_key_from_schema
    MixedCaseMonkey.reset_primary_key
    assert_equal "monkeyID", MixedCaseMonkey.primary_key
  end
167 168 169 170 171 172 173 174 175

  def test_primary_key_update_with_custom_key_name
    dashboard = Dashboard.create!(dashboard_id: '1')
    dashboard.id = '2'
    dashboard.save!

    dashboard = Dashboard.first
    assert_equal '2', dashboard.id
  end
176 177 178 179 180 181 182

  if current_adapter?(:PostgreSQLAdapter)
    def test_serial_with_quoted_sequence_name
      column = MixedCaseMonkey.columns_hash[MixedCaseMonkey.primary_key]
      assert_equal "nextval('\"mixed_case_monkeys_monkeyID_seq\"'::regclass)", column.default_function
      assert column.serial?
    end
183 184 185 186 187 188

    def test_serial_with_unquoted_sequence_name
      column = Topic.columns_hash[Topic.primary_key]
      assert_equal "nextval('topics_id_seq'::regclass)", column.default_function
      assert column.serial?
    end
189
  end
190 191 192
end

class PrimaryKeyWithNoConnectionTest < ActiveRecord::TestCase
193
  self.use_transactional_tests = false
194

195 196 197
  unless in_memory_db?
    def test_set_primary_key_with_no_connection
      connection = ActiveRecord::Base.remove_connection
198

199 200
      model = Class.new(ActiveRecord::Base)
      model.primary_key = 'foo'
201

202
      assert_equal 'foo', model.primary_key
203

204
      ActiveRecord::Base.establish_connection(connection)
205

206 207
      assert_equal 'foo', model.primary_key
    end
208
  end
D
Initial  
David Heinemeier Hansson 已提交
209
end
210

R
Ryuta Kamizono 已提交
211
class PrimaryKeyAnyTypeTest < ActiveRecord::TestCase
212 213
  include SchemaDumpingHelper

214
  self.use_transactional_tests = false
R
Ryuta Kamizono 已提交
215 216 217 218 219 220 221 222 223 224

  class Barcode < ActiveRecord::Base
  end

  setup do
    @connection = ActiveRecord::Base.connection
    @connection.create_table(:barcodes, primary_key: "code", id: :string, limit: 42, force: true)
  end

  teardown do
225
    @connection.drop_table(:barcodes, if_exists: true)
R
Ryuta Kamizono 已提交
226 227 228 229 230
  end

  def test_any_type_primary_key
    assert_equal "code", Barcode.primary_key

231 232 233 234
    column = Barcode.column_for_attribute(Barcode.primary_key)
    assert_not column.null unless current_adapter?(:SQLite3Adapter)
    assert_equal :string, column.type
    assert_equal 42, column.limit
R
Ryuta Kamizono 已提交
235
  end
236 237 238 239 240

  test "schema dump primary key includes type and options" do
    schema = dump_table_schema "barcodes"
    assert_match %r{create_table "barcodes", primary_key: "code", id: :string, limit: 42}, schema
  end
R
Ryuta Kamizono 已提交
241 242
end

243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
class CompositePrimaryKeyTest < ActiveRecord::TestCase
  include SchemaDumpingHelper

  self.use_transactional_tests = false

  def setup
    @connection = ActiveRecord::Base.connection
    @connection.create_table(:barcodes, primary_key: ["region", "code"], force: true) do |t|
      t.string :region
      t.integer :code
    end
  end

  def teardown
    @connection.drop_table(:barcodes, if_exists: true)
  end

  def test_composite_primary_key
    assert_equal ["region", "code"], @connection.primary_keys("barcodes")
  end

264 265
  def test_primary_key_issues_warning
    warning = capture(:stderr) do
266
      assert_nil @connection.primary_key("barcodes")
267 268 269 270
    end
    assert_match(/WARNING: Rails does not support composite primary key\./, warning)
  end

271 272 273 274 275 276
  def test_collectly_dump_composite_primary_key
    schema = dump_table_schema "barcodes"
    assert_match %r{create_table "barcodes", primary_key: \["region", "code"\]}, schema
  end
end

A
Abdelkader Boudih 已提交
277
if current_adapter?(:Mysql2Adapter)
278
  class PrimaryKeyWithAnsiQuotesTest < ActiveRecord::TestCase
279
    self.use_transactional_tests = false
280

V
Vipul A M 已提交
281
    def test_primary_key_method_with_ansi_quotes
282 283 284 285 286 287 288
      con = ActiveRecord::Base.connection
      con.execute("SET SESSION sql_mode='ANSI_QUOTES'")
      assert_equal "id", con.primary_key("topics")
    ensure
      con.reconnect!
    end
  end
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314

  class PrimaryKeyBigintNilDefaultTest < ActiveRecord::TestCase
    include SchemaDumpingHelper

    self.use_transactional_tests = false

    def setup
      @connection = ActiveRecord::Base.connection
      @connection.create_table(:bigint_defaults, id: :bigint, default: nil, force: true)
    end

    def teardown
      @connection.drop_table :bigint_defaults, if_exists: true
    end

    test "primary key with bigint allows default override via nil" do
      column = @connection.columns(:bigint_defaults).find { |c| c.name == 'id' }
      assert column.bigint?
      assert_not column.auto_increment?
    end

    test "schema dump primary key with bigint default nil" do
      schema = dump_table_schema "bigint_defaults"
      assert_match %r{create_table "bigint_defaults", id: :bigint, default: nil}, schema
    end
  end
315
end
316

A
Abdelkader Boudih 已提交
317
if current_adapter?(:PostgreSQLAdapter, :Mysql2Adapter)
318
  class PrimaryKeyBigSerialTest < ActiveRecord::TestCase
319 320
    include SchemaDumpingHelper

321
    self.use_transactional_tests = false
322 323 324 325 326 327

    class Widget < ActiveRecord::Base
    end

    setup do
      @connection = ActiveRecord::Base.connection
328 329 330 331 332
      if current_adapter?(:PostgreSQLAdapter)
        @connection.create_table(:widgets, id: :bigserial, force: true)
      else
        @connection.create_table(:widgets, id: :bigint, force: true)
      end
333 334 335
    end

    teardown do
336 337
      @connection.drop_table :widgets, if_exists: true
      Widget.reset_column_information
338 339
    end

340 341 342 343 344
    test "primary key column type with bigserial" do
      column_type = Widget.type_for_attribute(Widget.primary_key)
      assert_equal :integer, column_type.type
      assert_equal 8, column_type.limit
    end
345

346
    test "primary key with bigserial are automatically numbered" do
347 348 349
      widget = Widget.create!
      assert_not_nil widget.id
    end
350 351 352 353

    test "schema dump primary key with bigserial" do
      schema = dump_table_schema "widgets"
      if current_adapter?(:PostgreSQLAdapter)
354
        assert_match %r{create_table "widgets", id: :bigserial, force: :cascade}, schema
355
      else
356
        assert_match %r{create_table "widgets", id: :bigint, force: :cascade}, schema
357 358
      end
    end
359

A
Abdelkader Boudih 已提交
360
    if current_adapter?(:Mysql2Adapter)
361
      test "primary key column type with options" do
362
        @connection.create_table(:widgets, id: :primary_key, limit: 8, unsigned: true, force: true)
363 364 365 366
        column = @connection.columns(:widgets).find { |c| c.name == 'id' }
        assert column.auto_increment?
        assert_equal :integer, column.type
        assert_equal 8, column.limit
367
        assert column.unsigned?
368 369
      end
    end
370 371
  end
end