Building has_one from has_many Associations Discussion
Great tip! I use something similar for designating the thumbnail-image of a gallery of images. Something along these lines:
class Gallery
has_many :images
has_one :thumbnail, -> { where(thumbnail: true) }, class_name: "Image"
end
One of the benefits over this approach versus having a regular thumbnail
method, is that you can eager-load the thumbnails and prevent N+1 problems using @galleries = Gallery.includes(:thumbnail)
If you need more flexibility, I think you can also use DelegatedTypes. For example if ShippingAddress needs a specific attribute or logic that BillingAddress doesn't need.
And since the enum has created scopes for billing
and shipping
, you can DRY those associations up a little with:
has_one :billing_address, -> { merge(Address.billing) }, class_name: "Address"
has_one :shipping_address, -> { merge(Address.shipping) }, class_name: "Address"
Since the target of merge
is already an Address
collection, you can even use the scope methods directly:
has_one :billing_address, -> { billing }, class_name: :Address
has_one :shipping_address, -> { shipping }, class_name: :Address
Thanks for the video!
Don't forget to also add unique constraints at the database level to make sure an Account can only have one shipping and one billing address.
Thanks all for contributing to the conversation! I've added a link to a blog post in the episode notes about this topic and included some things around validating uniqueness.