Search code examples
ruby-on-railsrubymany-to-manyassociations

Associations Setup Correctly Results in a Uninitialized Constant


I have a simple many_to_many relationship between User and Stake through UserStake, everything seems to be setup correctly but results in a NameError (uninitialized constant User::Stakes):

#db/schema.rb
ActiveRecord::Schema.define(version: 2020_12_19_070749) do

  create_table "stakes", force: :cascade do |t|
    t.string "address"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

  create_table "user_stakes", force: :cascade do |t|
    t.integer "user_id"
    t.integer "stake_id"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end

  create_table "users", force: :cascade do |t|
    t.string "username"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.string "password_digest"
  end

end
#app/models/stake.rb
class Stake < ApplicationRecord
    has_many :active_stakes
    has_many :user_stakes
    has_many :users, through: :user_stakes
end

#app/models/user.rb
class User < ApplicationRecord
    has_many :user_stakes
    has_many :stakes, through: :user_stakes
    
    has_secure_password
end

#app/models/user_stake.rb
class UserStake < ApplicationRecord
    belongs_to :users
    belongs_to :stakes
end

When I try the association through rails c the following error NameError (uninitialized constant User::Stakes) appears:

2.6.3 :019 > s
 => #<Stake id: 310524, address: "stake1u8003gtvhcunzzmy85nfnk6kafd8lks2mykfzf0n4hq4...", created_at: "2020-12-08 12:08:25", updated_at: "2020-12-08 12:08:25"> 
2.6.3 :020 > u
 => #<User id: 21, username: "s324xexd", created_at: "2020-12-19 00:16:31", updated_at: "2020-12-19 00:16:31", password_digest: [FILTERED]> 
2.6.3 :021 > u.stakes << s
Traceback (most recent call last):
        1: from (irb):21
NameError (uninitialized constant User::Stakes)
2.6.3 :022 > u.stakes
Traceback (most recent call last):
        2: from (irb):22
        1: from (irb):22:in `rescue in irb_binding'
NameError (uninitialized constant User::Stakes)

Solution

  • belongs_to associations must use the singular term.

    #app/models/user_stake.rb
    class UserStake < ApplicationRecord
        belongs_to :user
        belongs_to :stake
    end
    

    The belongs_to Association

    belongs_to associations must use the singular term. If you used the pluralized form in the above example for the author association in the Book model and tried to create the instance by Book.create(authors: @author), you would be told that there was an "uninitialized constant Book::Authors". This is because Rails automatically infers the class name from the association name. If the association name is wrongly pluralized, then the inferred class will be wrongly pluralized too.