banditKing
banditKing

Reputation: 9579

Rails: How can I implement this relationship between these models? habtm? habtm through? Polymorphic?

I am storing my files on Amazon s3. Each file has many "consumers" and these consumers can be of any type(users, external apps, business_listings, etc). This calls for a many to many relationship. However, I also want to store certain attributes about each relationship. So I think that the best way to approach this would be to create a *has_and_belngs_to_many_through* relationship between the "s3_files" and the consumers

The question now is, since there are many type of consumers, I need to use polymorphic associations.

So based on this I would take the following steps:

1) Create a model: "resource_relationship"
2) Have these fields in it:
  t.string: consumer_type
  t.string: s3_fileType
  t.string: file_path
  t.string: consumer_type
  t.integer: s3_file.id
  t.integer: consumer.id
  t.integer: resource_relationship.id
 3) Add to the model:
     belongs_to: s3_file
     belongs_to: consumer
 4) add_index:[s3_file.id, consumer.id]

 5) Inside: s3_file
     nas_many: resource_relationships
     has_many:consumers :through=> :resource_relationships
 6) Inside: Users
     nas_many: resource_relationships
     has_many:s3_files :through=> :resource_relationships
 7) Inside: business_listings
     nas_many: resource_relationships
     has_many:s3_files :through=> :resource_relationships

My confusion lies in the polymorphic part of this relationship.

Since I donot have a "Consumer" model. I donot understand how that fits into this equation. I saw some tutorials online and came up with the above method and concept, but, Im uncertain if this si the correct way to approach this problem.

Essentially, I understand here that "Consumers" is like an interface that all the models "implement" and then the S3_file model can associate itself with any model that has "implemented" this interface. Question is how and where do the models: users and business_listings "implement" this "Consumer" interface. How do I set that up?

Upvotes: 0

Views: 142

Answers (1)

Kevin Bedell
Kevin Bedell

Reputation: 13414

Whenever you want to store attributes about the relationship between to models in a many-to-many relationship, generally the relationship is :has_many, :through.

I'd recommend beginning with this simpler approach and then considering polymorphism later, if you need to. For now, begin with just having a consumer_type attribute you can use if you need it.

consumer.rb:

class Consumer < ActiveRecord::Base
  has_many :resource_relationships
  has_many :s3_files, through: :resource_relationships
  validates_presence_of :consumer_type
end

resource_relationship.rb:

class ResourceRelationship < ActiveRecord::Base
  belongs_to :consumer
  belongs_to :s3_file
end

s3_file.rb

class S3File < ActiveRecord::Base
  has_many :resource_relationships
  has_many :consumers, through: :resource_relationships
  validates_presence_of :s3_fileType
  validates_presence_of :file_path
end

Notice that this simplifies as well the need to have attributes in the resource_relationships table -- those attributes are really attributes of the consumer and s3_file models anyway, so it may be best to just keep them there.

:has_many, :through I generally find to be more flexible and easier to modify as the relationships between your models changes.

Upvotes: 1

Related Questions