1

I'd like to create 2 has_many on the same model but that goes through a different model (which is a join table)

Here's the code:

class Content
  belongs_to :dis
  belongs_to :fac

  has_many :dis_representations, :through => :dis
  has_many :fac_representations, :through => :fac
end

class Fac
  has_many :fac_representations
  has_many :contents
end

class Dis
  has_many :dis_representations
  has_many :contents
end

class DisRepresentation
  belongs_to :user, :foreign_key => "e_user_id"
  belongs_to :dis
end

class FacRepresentation
  belongs_to :user, :foreign_key => "e_user_id"
  belongs_to :fac
end

class User
  has_many :dis_representations, :foreign_key => "e_user_id"
  has_many :fac_representations, :foreign_key => "e_user_id"
  has_many :dises, :through => :dis_representations
  has_many :facs, :through => :fac_representations
  has_many :contents, :through => :dises, :source => :contents
  has_many :contents, :through => :facs :source => :contents
end

Now I'd like to do this:

User.first.contents

If I do this, it almost works. The only problem is that only the second has_many :contents get's called.

Now I could solve it by creating a method like this:

def contents
    (dises + facs).map(&:contents).flatten
end

However, I loose all contents scopes if I do the above because contents becomes a simple array.

Is there any way around this? Maybe I'm using a completely wrong approach. Is there another way?

Thanks

Oktav
  • 2,143
  • 2
  • 20
  • 33
  • Just at first glance it looks like you have a lot of models. Do you really need that many? I presume that you want to be able to pull the first :content regardless of whether it is dis content or fac content. – edralph Jun 07 '12 at 13:13
  • I wish I could use less models :P Anyway, you're right, I'd like to get contents regardless of dis and fac. It's the same class but the dis and fac are different type of owners of a content. – Oktav Jun 07 '12 at 13:16

2 Answers2

0

If the dis and fac models are not significantly different then you could collapse them into a single set of models and introduce a 'type' attribute that lets you discriminate between these different types of content. Then you won't have an issue when trying to query it (it's only going to get worse as you want to write more complex queries) and it'll scale when you want to add more content types.

edralph
  • 1,831
  • 1
  • 14
  • 14
  • Good suggestion but, although Dis and Fac have the same schema they contain completely different data, and this data must be linked to the same content. A content must always have both fac and dis and I will not need to scale because I'm only using one of these 2 attributes to determine the ownership to a User. Also I need to know which one applies (if not both) to the user so I can't change my schema in such a manner. – Oktav Jun 07 '12 at 13:46
0

I'd use two different names for the contents associations, like dis_contents and fac_contents.

If you want to retrieve all Content objects with a single association, you should change your associations and use a polymorphic join table.

Maybe this example would help

has_many :through + polymorphic relationships

Community
  • 1
  • 1