How to integrate a common schema that may not have a true 'belongs_to' relationship

I have a very simple common schema (Address table) that I would like to use as a reference in multiple other Schemas. However, the concept of other tables belonging to Address seems a bit strange (for example, A company does not really belong to an address).

Furthermore, if I want to collect other table fields AND address fields in one form, I need to start with the Address and then build out the changeset to cast the assoc.

If I make other tables has_one: address then I need to add many foreign keys to the address table for every table that wants to store address info This also sounds strange where I need to allow null fkey refs.

I thought about just do it as two separate changesets in the form and then run them in a transaction but I am not sure how to construct the template for this if I want to avoid 2 separate form submissions.

This seems like a common pattern that I must be missing something very obvious. Could someone please show me how I can extract out common fields into a schema that does not have a clear belongs_to relationship and setup a single form where I can use the common schema?

I thought about embedded_schema but I worry I will have to make more changes to the table down the line and migration will be harder with embedded_schema

Thanks!

I guess address should be pretty generic and can be “shared” across relations other than company as well… (e.g. suppose you have also relation employee that needs an association with address as well)

Probably it makes sense to create an immediate table company_address that would consist of company_id and address_id
And now company could has_one: :company_address.

That sounds reasonable. Do you know how that will work with changesets / templates so the address info can be obtained in the same form as the company?

About schema and changeset

At first, I thought that

schema "company" do
 has_one: :address, thourgh: :company_address
 ...

should be good enough. However, now I see the note in docs has_many/has_one :through:

:through associations are read-only. For example, you cannot use Ecto.Changeset.cast_assoc/3 to modify through associations.

So that doesn’t fit well.
On the other hand we are dealing with a specific case of many_to_many/3 but, with a constraint of uniqueness. Please, take a look at those docs - they explain schema and changeset examples better than I’ll ever be able to =)

About templates

Unfortunately, personally I don’t have much experience with built in HTML helpers to put up a form that would reflect the schema.
However, take a look at this tutorial, you might find something useful there =)

belongs_to is a useful mnemonic device for thinking about the foreign-key relationship, but I wouldn’t let the linguistic baggage of the word block a correct implementation of the concept: It seems like exactly the relationship needed for your case.

  • Company’s changeset can do cast_assoc(:address)
  • the form for a Company can use inputs_for
2 Likes

Thank you @al2o3cr. I did not know I can use the Company structure’s changeset to cast_assoc on Address. This works great and it eliminates a lot of the other hacks.

I really wish there was an alias to belongs_to that is called contains or references :slight_smile: