Once I added this HABTM, one of my 'through' relationships, on a non-habtm model, seems to have broke?

I’m a rails newb and have been Googling about this, but I’m still stumped.

Not showing everything here, but basically it should be a pretty common setup so I’m sure others know what I’m doing wrong.

  • A meter can belong to many meter_groups
  • A meter_group can have many meters.
  • A user can ‘subscribe’ to viewing a meter_group (Subscription) so he should be able to see the meters that are in that meter_group of the subscription (think subscribing to a topic in a forum.)

Initially I was only allowing a single meter to belong to only one meter_group and the following test and relationship of a Subscription worked fine:

class Subscription < ActiveRecord::Base belongs_to :user, :foreign_key => “user_id”

belongs_to :meter_group, :foreign_key => “meter_group_id” has_many :meters, :through => :meter_group end

test “group1 and group2 belong to rachel” do user = User.find_by_login(“rachel”)

subscriptions = Subscription.find_all_by_user_id([user.id](http://user.id))
subscriptions.each do |s|
  meters = s.meters
  meters.each do |m|
    puts "meter = #{p m}"

  end
end

end

However now things are not working since I created some HABTM relationships for meter_group and meters. I end up with the following error:

ActiveRecord::HasManyThroughSourceAssociationMacroError: Invalid source reflection macro :has_and_belongs_to_many for has_many :meters, :through => :meter_group. Use :source to specify the source reflection.

Here are some of the other relevant tables and migrations (stripped of a few non-related fields):

class MeterGroup < ActiveRecord::Base belongs_to :user, :foreign_key => “user_id” has_and_belongs_to_many :meters

end

class Meter < ActiveRecord::Base has_and_belongs_to_many :meter_groups belongs_to :user, :foreign_key => “user_id” end

#Migrations (removed some cols and drop section)

class CreateMeterGroups < ActiveRecord::Migration def self.up create_table :meter_groups do |t| t.string :name t.string :description t.integer :user_id

  t.timestamps

end

end end

class CreateMeters < ActiveRecord::Migration def self.up create_table :meters do |t| t.integer :meter_type_id t.integer :scale_id t.integer :user_id

  t.string :name
  t.string :description

  t.timestamps
end

end end

class CreateMetersMeterGroups < ActiveRecord::Migration def self.up create_table :meter_groups_meters, :id => false do |t|

  t.integer :meter_id
  t.integer :meter_group_id

  t.timestamps
end

end end

class CreateSubscriptions < ActiveRecord::Migration def self.up create_table :subscriptions do |t|

  t.integer :user_id
  t.integer :meter_group_id
 
  t.timestamps
end

end end

I’m a rails newb and have been Googling about this, but I’m still stumped.

Not showing everything here, but basically it should be a pretty common setup so I’m sure others know what I’m doing wrong.

  • A meter can belong to many meter_groups
  • A meter_group can have many meters.
  • A user can ‘subscribe’ to viewing a meter_group (Subscription) so he should be able to see the meters that are in that meter_group of the subscription (think subscribing to a topic in a forum.)

Initially I was only allowing a single meter to belong to only one meter_group and the following test and relationship of a Subscription worked fine:

class Subscription < ActiveRecord::Base belongs_to :user, :foreign_key => “user_id”

belongs_to :meter_group, :foreign_key => “meter_group_id” has_many :meters, :through => :meter_group end

test “group1 and group2 belong to rachel” do user = User.find_by_login(“rachel”)

subscriptions = Subscription.find_all_by_user_id([user.id](http://user.id))
subscriptions.each do |s|
  meters = s.meters
  meters.each do |m|
    puts "meter = #{p m}"



  end
end

end

As a side note, there isn’t an issue if I try to get meters directly from the meter_group. For example in the above test it works if changed to: test “group1 and group2 belong to rachel” do user = User.find_by_login(“rachel”) subscriptions = Subscription.find_all_by_user_id(user.id) subscriptions.each do |s| meter_group = s.meter_group meters = meter_group.meters meters.each do |m| puts “meter = #{p m}” end end end

I would start by getting rid of the :foreign_key specifications unless you are doing something non standard.

I would start by getting rid of the :foreign_key specifications

unless you are doing something non standard.

Ok, thanks. I removed them. (Didn’t fix the issue but does look a lot cleaner.)

oh you need to add the has_many for the join table

has_many :meter_goup has_many :meters, :through => :meter_group

I take it you mean on the Subscription table? which currently looks like:

class Subscription < ActiveRecord::Base

belongs_to :user

belongs_to :meter_group

has_many :meters, :through => :meter_group

end

But a Subscription doesn’t have many mete groups, a subscription can only be tied to a single meterGroup and has a fk to the meter_group table.

Or are you saying for the other join table “meter_groups_meters” I need to make a MeterGroupsMeter model object and add the relationships you described?

For reference The other relevant tables are:

class Meter < ActiveRecord::Base has_and_belongs_to_many :meter_groups belongs_to :user end

class MeterGroup < ActiveRecord::Base belongs_to :user

has_and_belongs_to_many :meters end

sorry I misread your tables. The has_many :through is looking for a join table with ids for both sides which is the cause of the error, same kind of table as a HABTM join table.

class Author < ActiveRecord::Base     has_many :authorships     has_many :books, :through => :authorships   end

  class Authorship < ActiveRecord::Base     belongs_to :author     belongs_to :book   end