13

Newer versions of rails let you specify that tables should be created with a uuid primary key like so:

create_table :foos, id: :uuid do |t|
  # ...
end

Which is great. And for a long time rails has supported creating join tables like so:

create_join_table :foos, :bars do |t|
  # ...
end

Also great. Except my tables have uuid primary keys and that generates foreign key columns of type integer instead of type uuid.

Looking over the documentation for create_join_table, I can't find anything obvious to change the column type. Is it possible to use create_join_table with uuids?

Or do I have create the join table manually:

create_table :bars_foos, id: false do |t|
  t.uuid :bar_id
  t.uuid :foo_id
end

3 Answers 3

13

Within Rails 5.0 you can use an additional option column_options on the create_join_table method to specify the type of your id columns. Your migration would then look like:

create_join_table :foos, :bars, column_options: {type: :uuid} do |t|
  t.index [:foo_id, :baar_id]
end
Sign up to request clarification or add additional context in comments.

1 Comment

Confirmed working with Rails 7 👍
9

There is no way of creating join tables with uuids.

As pointed out in the question create_table is the only option. The best way of emulating create_join_tables with uuid is by using create_tables as follows:

  • Run: rails g migration CreateFoosBars bars:references foos:references
  • The command will produce the following output which you will need to modify

generate output

class CreateBarFoos < ActiveRecord::Migration
  def change
    create_table :bars_foos, id: :uuid do |t|
      t.references :bars, foreign_key: true
      t.references :foo, foreign_key: true
    end
  end
end
  • Change id: uuid => id: false
  • Add type: uuid, index: true to the end of the references

final migration

class CreateBarFoos < ActiveRecord::Migration
  def change
    create_table :bars_foos, id: false do |t|
      t.references :bars, foreign_key: true, type: :uuid, index: true
      t.references :foo, foreign_key: true, type: :uuid, index: true
    end
  end
end

It would be good if Rails could add extra support for different id types in create_join_table, this could even be inferred by an existing migration.

Until then hopefully these steps will achieve the same result.

1 Comment

This is the right answer for the given version of Rails (4.2.x), and @anka's answer is correct for version 5 and up.
5

I should have looked at the code...

def create_join_table(table_1, table_2, options = {})
  join_table_name = find_join_table_name(table_1, table_2, options)

  column_options = options.delete(:column_options) || {}
  column_options.reverse_merge!(null: false)

  t1_column, t2_column = [table_1, table_2].map{ |t| t.to_s.singularize.foreign_key }

  create_table(join_table_name, options.merge!(id: false)) do |td|
    td.integer t1_column, column_options
    td.integer t2_column, column_options
    yield td if block_given?
  end
end

Columns are explicitly created as integers with no means to change them. Too bad...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.