rails/rails — pull request #12634 by amrnt (2013-10-24 20:02:55+00:00)
Title: Migrations: reference to be the same type as primary key in the referenced table

Currently when you run a migration for `posts` table that have `t.belongs_to :user` or `add_reference :posts, :user` on `posts` table, it will generate `user_id` with type of `integer` — and it'll be **ALWAYS `integer`**.

But what if the `User` model has a primary key of string type? The generator will not take a look to see what type to set for the reference, it'll be set to `integer` and the relation will not work as expected.

#### Example:

##### Migration files:

`1_create_users.rb`:

```ruby
class CreateUser < ActiveRecord::Migration
def change
create_table :users, id: false do |t|
t.string :id, primary: true, limit: 23
t.string :name

t.timestamps
end
end
end
```

`2_create_posts.rb`:

```ruby
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.string :title
t.belongs_to :user

t.timestamps
end
# add_reference(:posts, :user)
end
end
```

##### Models:

`user.rb`:

```ruby
class User < ActiveRecord::Base
self.primary_key = :id

before_validation :generate_safe_random_id, on: :create
def generate_safe_random_id
self.id = SecureRandom.urlsafe_base64(17)
end
end
```

`post.rb`:

```ruby
class Post < ActiveRecord::Base
belongs_to :user
end

```
---

***Notice:*** The type of the reference will be detected only if the referenced table has already created. So if the migrations of creating `posts` table run first the `user_id` type will fallback to `integer`.

---

I haven't written any tests for this but I tried it on an example app (I will write tests once the concept is accepted).