Search code examples
ruby-on-railsactiverecordassociationsrails-engines

Associations within Rails Engine not working


I'm building my first Rails engine and getting pretty confused already defining the associations between two models. For the reason of ease, let's say the name of the engine is Blorg, having two models Article and Author.

blorgh/article.rb

module Blorgh
  class Article < ApplicationRecord
    belongs_to :author, class_name: 'Blorg::Author',
                          foreign_key: 'blorg_author_id', optional: true

blorgh/author.rb

module Blorgh
  class Author < ApplicationRecord
    has_many :articles, class_name: 'Blorg::Article'

schema

create_table "blorgh_authors", force: :cascade do |t|
    t.string "name"
    t.boolean "inactive", default: false
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false

create_table "blorgh_articles", force: :cascade do |t|
    t.string "title"
    t.bigint "blorgh_author_id"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["blorgh_author_id"], name: "index_blorgh_article_on_author_id"

If I try to create an article or count the articles of an author via rails c, I get those errors:

article = Blorgh::Article.new(title: 'New Article')
article.save # expect true
# ==> NoMethodError: private method `attribute' called for #<Blorgh::Article:0x00007fdc3fad4d50>

author = Blorgh::Author.create # worked
author.articles.count # expect 0
# ==> ActiveRecord::StatementInvalid: PG::UndefinedColumn: ERROR:  column blorgh_articles.author_id does not exist

Does anyone know how I can achieve those in-engine associations correctly?


Solution

  • The second error ("column blorgh_articles.author_id does not exist") is because Rails assumes the foreign key on a has_many relationship is classname_id, which is author_id in your example. You correctly set the foreign key on the belongs_to side, but you need to specify on both sides of the relationship. So:

    module Blorgh
      class Author < ApplicationRecord
        has_many :articles, class_name: 'Blorg::Article', foreign_key: 'blorg_author_id'
    ...