I’m slightly confused by your wording… items_a and items_b, the plural makes me think it’s a has_many, but you then you said hash_one so I’m assuming that. SO, I actually have a mostly working on a library to handle this more gracefully as we had a few tables like that at my old work. But since I stopped working there I lost motivation. I could post what I have, though. The API is basically:
schema "items" do
field :foo, :string
one :item do
belongs_to :item_one, Item_1
belongs_to :item_two, Item_2
belongs_to :item_three, Item_3
end
def changeset(item, attrs) do
item
|> cast(attrs, [:foo])
|> cast_one_assoc(:item)
end
end
It basically adds sister versions of a few functions with _one added (kinda like _embeds versions), so cast_one, put_one_)assoc, and get_one_assoc (for each you can refer to them by the first argument to the one macro). There is also MyRepo.preload_one (which is a stupid name and I think that function is unfinished for nested preloads). I can post what I have if you’re interested.
Otherwise, as far as preloading goes, you can do this and it’s efficient:
Repo.preload(items, [:item_a, :item_b, :item_c)
When preloading it will simply ignore the associations whose ids are nil. I would definitely hide this in a function, though, as they get unweildly if you are preloading a lot.


















