primary_keys_test.rb 10.8 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 133 134 135 136 137 138

  def test_supports_primary_key
    assert_nothing_raised NoMethodError do
      ActiveRecord::Base.connection.supports_primary_key?
    end
  end

  def test_primary_key_returns_value_if_it_exists
139 140 141 142
    klass = Class.new(ActiveRecord::Base) do
      self.table_name = 'developers'
    end

143
    if ActiveRecord::Base.connection.supports_primary_key?
144
      assert_equal 'id', klass.primary_key
145 146 147 148
    end
  end

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

153
    if ActiveRecord::Base.connection.supports_primary_key?
154
      assert_nil klass.primary_key
155 156
    end
  end
157 158 159 160 161 162 163

  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 已提交
164

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

  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
178 179 180 181 182 183 184

  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
185 186 187 188 189 190

    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
191
  end
192 193 194
end

class PrimaryKeyWithNoConnectionTest < ActiveRecord::TestCase
195
  self.use_transactional_tests = false
196

197 198 199
  unless in_memory_db?
    def test_set_primary_key_with_no_connection
      connection = ActiveRecord::Base.remove_connection
200

201 202
      model = Class.new(ActiveRecord::Base)
      model.primary_key = 'foo'
203

204
      assert_equal 'foo', model.primary_key
205

206
      ActiveRecord::Base.establish_connection(connection)
207

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

R
Ryuta Kamizono 已提交
213
class PrimaryKeyAnyTypeTest < ActiveRecord::TestCase
214 215
  include SchemaDumpingHelper

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

  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
227
    @connection.drop_table(:barcodes, if_exists: true)
R
Ryuta Kamizono 已提交
228 229 230 231 232 233 234 235 236
  end

  def test_any_type_primary_key
    assert_equal "code", Barcode.primary_key

    column_type = Barcode.type_for_attribute(Barcode.primary_key)
    assert_equal :string, column_type.type
    assert_equal 42, column_type.limit
  end
237 238 239 240 241

  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 已提交
242 243
end

244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
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

  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 已提交
271
if current_adapter?(:Mysql2Adapter)
272
  class PrimaryKeyWithAnsiQuotesTest < ActiveRecord::TestCase
273
    self.use_transactional_tests = false
274

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

  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
309
end
310

A
Abdelkader Boudih 已提交
311
if current_adapter?(:PostgreSQLAdapter, :Mysql2Adapter)
312
  class PrimaryKeyBigSerialTest < ActiveRecord::TestCase
313 314
    include SchemaDumpingHelper

315
    self.use_transactional_tests = false
316 317 318 319 320 321

    class Widget < ActiveRecord::Base
    end

    setup do
      @connection = ActiveRecord::Base.connection
322 323 324 325 326
      if current_adapter?(:PostgreSQLAdapter)
        @connection.create_table(:widgets, id: :bigserial, force: true)
      else
        @connection.create_table(:widgets, id: :bigint, force: true)
      end
327 328 329
    end

    teardown do
330 331
      @connection.drop_table :widgets, if_exists: true
      Widget.reset_column_information
332 333
    end

334 335 336 337 338
    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
339

340
    test "primary key with bigserial are automatically numbered" do
341 342 343
      widget = Widget.create!
      assert_not_nil widget.id
    end
344 345 346 347 348 349 350 351 352

    test "schema dump primary key with bigserial" do
      schema = dump_table_schema "widgets"
      if current_adapter?(:PostgreSQLAdapter)
        assert_match %r{create_table "widgets", id: :bigserial}, schema
      else
        assert_match %r{create_table "widgets", id: :bigint}, schema
      end
    end
353

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