17

Right. This simply refuses to work. Been at this for hours.

album model

class Album < ActiveRecord::Base
  has_many :features, through: :join_table1
end

features model

class Feature < ActiveRecord::Base
  has_many :albums, through: :join_table1
end

join_table1 model

class JoinTable1 < ActiveRecord::Base
  belongs_to :features
  belongs_to :albums
end

join_table1 schema

album_id | feature_id

albums schema

id | title | release_date | genre | artist_id | created_at | updated_at | price | image_path

features schema

id | feature | created_at | updated_at

Upon raking the test database, and running this integration test:

require 'test_helper'

class DataFlowTest < ActionDispatch::IntegrationTest
  test "create new user" do
    album = albums(:one)
    feature = features(:one)
    album.features
  end
end

I get

ActiveRecord::HasManyThroughAssociationNotFoundError: Could not find the association :join_table1 in model Album

Why is this?

ndnenkov
  • 35,425
  • 9
  • 72
  • 104
Starkers
  • 10,273
  • 21
  • 95
  • 158

4 Answers4

24

You need to add has_many :album_features both to Album and Feature models (given that you rename JoinTable1 model to more meaningful AlbumFeature, and corresponding table would be album_features), as :through references association - your error is exactly about it.

Or you can use has_and_belongs_to_many so there will be no need to define special link model. But in that case you must name your table albums_features.

biomancer
  • 1,284
  • 1
  • 9
  • 20
  • 2
    I don't think the naming convention of the join table matters with a has_many, through relationship. – Starkers Sep 24 '13 at 10:21
  • You cannot have 2 models with name Feature, that is what matters. – biomancer Sep 24 '13 at 10:28
  • Also, name of an activerecord model should correspond its table name. – biomancer Sep 24 '13 at 10:51
  • if the naming convention mattered, would you name it album_features or features_album ? As @starkers mentioned it doesn't. I had the same problem, and adding has_many both to Album and Features in addition to through is the only relevant part of the answer. – msanjay Mar 20 '15 at 08:47
  • 1
    @msanjay Yes, you're right, naming doesn't matter with has_many : through (although it does matter with has_and_belongs_to_many, afaik alphabetic order is used to decide what comes first in table name), this was addressed to the first version of question which had 2 errors in it. The question was updated, so I'll update the answer too, thanks. – biomancer Mar 20 '15 at 17:05
16

Just define the models as follow

album model

class Album < ActiveRecord::Base
  has_many :join_table1
  has_many :features, through: :join_table1
end

features model

class Feature < ActiveRecord::Base
  has_many :join_table1
  has_many :albums, through: :join_table1
end

join_table1 model

class JoinTable1 < ActiveRecord::Base
  belongs_to :features
  belongs_to :albums
end
a14m
  • 7,808
  • 8
  • 50
  • 67
1

happened to me as well. made it work by adding the join table as has_many to both models. like this: connection model:

module Alerts
  class AlertIncidentConnection < ActiveRecord::Base
    belongs_to :incident
    belongs_to :alert
  end
end 

alert model:

module Alerts
  class Alert < ActiveRecord::Base
    has_many :alert_incident_connections, class_name: 'Alerts::AlertIncidentConnection'
    has_many :incidents, through: :alert_incident_connections,class_name: 'Alerts::Incident', dependent: :destroy
  end
end

incident model:

module Alerts
  class Incident < ActiveRecord::Base    
    has_many :alert_incident_connections, class_name: 'Alerts::AlertIncidentConnection'
    has_many :alerts, through: :alert_incident_connections,class_name: 'Alerts::Alert' ,dependent: :destroy
  end
end

migration file:

class CreateTableAlertIncidentConnections < ActiveRecord::Migration
  def change
    create_table :alert_incident_connections do |t|
      t.references :alert, null: false, index: true
      t.references :incident, null: false, index: true
      t.timestamps
    end
  end
end

usage:

alert.incidents << incident
alert.save!
Ehud
  • 105
  • 5
0

Similarly like @mad_raz answered, but join table needs to have singulars for belongs_to, like this:

class JoinTable1 < ActiveRecord::Base
  belongs_to :feature
  belongs_to :album
end

Complete associations tutorial https://kolosek.com/rails-join-table/

Nesha Zoric
  • 6,218
  • 42
  • 34