Rails ActiveRecord joins方法中单复数表名使用规则咨询
joins Great question! This confusion boils down to a critical detail about how ActiveRecord's joins method works: when you pass symbols to joins, you're referencing association names defined in your Rails models, not raw database table names. The singular/plural form depends entirely on the type of association you've set up.
Let's break this down with your code example:
Core Rule: Association Type Determines Singular/Plural
- Plural symbols: Used for
has_manyorhas_and_belongs_to_manyassociations. These represent a collection of related records, so the name is pluralized. - Singular symbols: Used for
belongs_toorhas_oneassociations. These represent a single related record, so the name is singular.
Analyzing Your Code
Let's walk through each part of your joins calls:
product_attr_vals(plural)
YourProductmodel almost certainly has ahas_many :product_attr_valsassociation (since one product can have multiple attribute values). ActiveRecord looks for this plural-named association to build the join—using the singularproduct_attr_valwould fail because no such singular association exists in yourProductmodel.attr_val(singular)
YourProductAttrValmodel likely has abelongs_to :attr_val(orhas_one :attr_val) association. Since each product attribute value links to exactly one attribute value record, the association name is singular, so you use:attr_valhere.:product_model(singular)
Similarly, yourProductmodel has abelongs_to :product_modelassociation (one product belongs to one product model). This is a singular association, so you pass the singular symbol:product_model.
Bonus: When Would You Use Table Names?
If you ever need to write a custom join using raw table names (instead of model associations), you'd pass a string to joins instead of symbols, like:
Product.joins("INNER JOIN product_attr_vals ON products.id = product_attr_vals.product_id")
But the symbol-based syntax is preferred because it leverages your model's associations, keeping your code DRY and aligned with Rails conventions.
内容的提问来源于stack exchange,提问作者Augusto Carmo

