When using has_many() and belongs_to() to simplify the creation of association methods between models, I wasn't sure if they'd be accurately reflective if the association methods had some additional steps out of the norm. For example, when looking at the many-to-many relationship of users to photos that's linked by a join table of comments, we could possibly write this as a method in the User model:
def commented_photos
my_comments = self.comments
array_of_photo_ids = Array.new
my_comments.each do |a_comment|
array_of_photo_ids.push(a_comment.photo_id)
end
matching_photos = Photo.where({ :id => array_of_photo_ids })
unique_matching_photos = matching_photos.distinct
return unique_matching_photos
end
However, if we reduce that to:
has_many(:commented_photos,
through: :comments,
source: :photo
)
It wouldn't be entirely accurate since we're omitting the step of ensuring we return only unique records (i.e. the line where we specify unique_matching_photos = matching_photos.distinct).
We could use the has_many method to create the method commented_photos, and then call the distinct method as a subsequent step, but if we wanted to include distinction within the method like it was initially written, it seems like the version of Rails we're on will determine how that'd be implemented.
For versions prior to Rails 4, you could add the :uniq option within the has_many associations:
has_many(:commented_photos,
:through => :comments,
:source => :photo,
:uniq => true
)
However, for more current versions of Rails (up to version 7 at time of this post), we'd now write querying method inside the scope block as such:
has_many(:commented_photos, -> {distinct},
through: :comments,
source: :photo
)
This was a good reminder on double checking that using associations may save time, but we'll have to be careful to not omit any steps that are "out of the standard", and how scoping would help address these situations.
Top comments (0)