Ask A Question


You’re not receiving notifications from this thread.

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"

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

Super nice!


yeah, I wondered why he didn't just put billing and shipping in the scopes... glad to know that the scopes work normally from this context


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, i keep wondering how to avoid incorrect get first 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.

Join the discussion
Create an account Log in

Want to stay up-to-date with Ruby on Rails?

Join 83,038+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.