61

This questions stems from: How to link form after creating rails join table

I am creating the join table between my Product and Category Models.

What should the join table be named? categories_products or category_products or something else?

Community
  • 1
  • 1
Yogzzz
  • 2,735
  • 5
  • 36
  • 56

4 Answers4

77

categories_products. Both plural. In lexical order.

Quote:

Unless the name of the join table is explicitly specified by using the :join_table option, Active Record creates the name by using the lexical order of the class names. So a join between customer and order models will give the default join table name of “customers_orders” because “c” outranks “o” in lexical ordering.

knarewski
  • 91
  • 7
Zabba
  • 64,285
  • 47
  • 179
  • 207
  • 5
    How come ActiveRecord model `CategoryProduct` doesn't pick up this table automatically? It seems to be looking for `category_products`. I have to specify `self.table_name = "categories_products"` – konyak Dec 17 '14 at 20:48
  • 2
    A model named `CategoryProduct`, is different from the join table name that rails calculates for many to many. The question is about the join table, not a model named CategoryProduct. – Zabba Dec 18 '14 at 20:57
  • Side note: if you want to use `uuid` as primary key for your tables, you need to specify it explicitly by doing `create_join_table(:products, :categories, column_options: {type: :uuid}) ` in your migration. Source: https://blog.bigbinary.com/2016/06/16/rails-5-create-join-table-with-uuid.html – Francois Jan 09 '19 at 10:37
  • 7
    If anyone else isn't familiar with the term "lexical order", a quick search tells me it's basically a fancy way of saying "alphabetical order". – Jason Swett Feb 04 '19 at 15:46
54

Rails 4

Pay attention that from Rails 4 there are some new rules.

Specifies a many-to-many relationship with another class. This associates two classes via an intermediate join table. Unless the join table is explicitly specified as an option, it is guessed using the lexical order of the class names. So a join between Developer and Project will give the default join table name of “developers_projects” because “D” precedes “P” alphabetically.

Note that this precedence is calculated using the < operator for String. This means that if the strings are of different lengths, and the strings are equal when compared up to the shortest length, then the longer string is considered of higher lexical precedence than the shorter one. For example, one would expect the tables “paper_boxes” and “papers” to generate a join table name of “papers_paper_boxes” because of the length of the name “paper_boxes”, but it in fact generates a join table name of “paper_boxes_papers”. Be aware of this caveat, and use the custom :join_table option if you need to.

If your tables share a common prefix, it will only appear once at the beginning. For example, the tables “catalog_categories” and “catalog_products” generate a join table name of “catalog_categories_products”.

=> Docs for Rails v4.2.7

# alphabetically order
developers + projects                 -->  developers_projects 

# precedence is calculated with '<', lengthier strings have precedence 
# if the string are equal compared to the shortest length
paper_boxes + papers                  -->  paper_boxes_papers  

# common prefix omitted
catalog_categories + catalog_products -->  catalog_categories_products 

Rails 5

The rule are still pretty the same. With Rails 5 we have a new helper for creating join tables with migrations:

class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[5.0]
  def change
    create_join_table :developers, :projects
  end
end

=> Edge docs for Rails

damoiser
  • 6,058
  • 3
  • 40
  • 66
  • 1
    You seem to be mixing plurals and singulars in your example(or rather the docs are mixing them). Shouldn't it be: `developer + project --> developer_projects` `paper_box + paper --> paper_box_papers` `catalog_category + catalog_product --> catalog_category_products` – DickieBoy Jan 13 '15 at 15:51
  • @DickieBoy I have retake the text (taken on the docs) and sketched it in the final example. I think (but not sure 100%) that they are rights. – damoiser Jan 14 '15 at 16:29
  • 2
    @DickieBoy - The join-table names are always two plurals together (so your examples do not match the default convention). The documentation refers to individual models like `Project` (singular, the table name for which would be `projects`) and individual tables like `papers` (plural, the model would be `Paper`) - both correct, just from different contexts. – mltsy Jan 22 '15 at 22:52
  • @damoiser The helper was available in Rails 4: http://apidock.com/rails/v4.0.2/ActiveRecord/ConnectionAdapters/SchemaStatements/create_join_table – sbonami Jan 02 '17 at 17:41
  • you have probably right @sbonami - I checked the api.rubyonrails.org documentation but there was not yet defined ( [v4.0.2](http://api.rubyonrails.org/v4.0.2/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_and_belongs_to_many) vs. [edge](http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_and_belongs_to_many) ) - it was probably not yet defined as "standard" or the docs of v4.0.2 was not updated correctly – damoiser Jan 04 '17 at 14:18
3

Join tables in Rails must be created in alphabetical order only. Keep this point in mind every time you create a join table.

For example, if you want to create a join table between project table and collaborator table you must name it like below.

Syntax: first_table_name(UNDERSCORE)second_table_name

# Names must be in alphabetical order and also in plural
# Decide which is your first table name based on the alphabetical order

Example: Creating Join Table between Project And Collaborator

Collaborator-Project

collaborators_projects   
# you should name it  like this; In alphabetical order with plural names

Example 2: Creating Join Table between BlogPost table and User Table

BlogPost-User

blog_posts_users      # In alphabetical order with plural names
Prabhakar
  • 6,458
  • 2
  • 40
  • 51
1

The new create_join_table migration creates a join table that has no corresponding model, so no naming convention is required for the model name.

To access the join, you must declare has_and_belongs_to_many on the two tables, and access them through the association created.

Taylored Web Sites
  • 1,017
  • 1
  • 9
  • 15