Augusto Carmo
Augusto Carmo

Reputation: 4964

Rails ActiveRails joins - table name in plural/singular

I have the following "Query" using ActiveRecord:

Product.joins(product_attr_vals: [attr_val: [:attr]])
       .joins(:product_model)
       .where(product_models: {id: @product_model.id}, attrs: {id: attr.id})
       .distinct
       .count

I am not being able to understand why sometimes, in joins(), rails accept the table name in plural and others in singular.


Some info:

models/product_model_attr_val.rb

class ProductModelAttrVal < ApplicationRecord
  validates :product_model_id, uniqueness: { scope: :attr_val_id }

  belongs_to :product_model
  belongs_to :attr_val
end

db/migrate/db_creation.rb

create_table :product_model_attr_vals do |t|
  t.references :product_model, null: false, foreign_key: true
  t.references :attr_val, null: false, foreign_key: true

  t.timestamps
end

Upvotes: 1

Views: 2520

Answers (1)

Enrai
Enrai

Reputation: 593

The answer to when to use singular or plural lies in the name of the association. Usually has_many associations are named in plural, whereas belongs_to associations are named in singular. Behind the scenes when building the query ActiveRecord will make sure to always use the right table name (plural). In Rails there is the concept of "convention over configuration", which means a lot of stuff have a predefined approach that will work out of the box. E.g. take an association belongs_to :product. ActiveRecord will look for a column product_id in the table products and use it to load the product. Another example, has_many :products - ActiveRecord will look for a table called products and assume it has a column your_model_id. Thus it will load all the products for you model instance.

Back to your question, when to use singular or plural. If you are not sure, check your association definition in the respective model. In general, has_many associations use plural, belongs_to associations use singular. Here is an example with two models:

class Employee
  has_many :tasks
end

class Task
  belongs_to :employee
end

And here are some joins examples:

Employee.joins(:tasks) # plural due to has_many 
Task.joins(:employee) # singular due to belongs_to

Hope it was helpful!

Upvotes: 4

Related Questions