Reputation: 9579
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
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