Ecto Associations with custom fields

Hello!
I am currently learning Elixir and Phoenix with the book “Phoenix in Action”. However, I am trying to implement the examples on an app that is usable for me. At the moment I’m stuck with the Ecto Associations. The book assumes that all content is created successively in the app. Accordingly, the names of the PK and FK do not matter. For my app, however, I want to import external content on a regular basis, where primary and foreign keys already exist and they also do not necessarily correspond to the standard Ecto conventions.

For example, I have the following tables:

properties:
property_id
attribute 1
attribute 2 etc.

owner:
owner_id
property_id_fk
attribute 1
attribute 2 etc.

I already tried different versions in my schemas and migrations but I just can’t get it to work. I thought something like

belongs_to :property, MyApp.Property, references: :property_id, foreign_key: :property_id_fk

will work, but so far I’m out of ‘luck’. Is someone able to help me or able to provide some nice sources to get a good grasp on Ecto Associations?

Posting an error message or a description of what happens when you try this will help a lot :slight_smile:

At first glance, this looks like it should work.

Side note on this point: consider renaming the fields as needed at import-time instead of bending your application data to match an external format.

1 Like

Thanks for the answer. In the meantime I have solved it myself. Unfortunately I could not manage to replace the default ID with my existing primary key. Instead I have now declared the existing primary key as a unique field and now I have kinda two IDs… But creating the associations was then possible.

I map the data during the import to my existing Ecto Schema, but the primary keys are often Strings.

Followup question:
I’m importing now two files, one with the properties and one with the owner. How do I build the associations between both tables? Right now my import code looks like this:

def import_shapefile_properties(path) do
    [{"properties", _proj, feature}] = Exshape.from_zip(path)

    Stream.drop(feature, 1)
    |> Stream.map(fn property ->
      %{
        # mapping of fields
      }
    end)
    |> Stream.chunk_every(1000)
    |> Stream.each(fn chunk ->
      Repo.insert_all(Property, chunk)
    end)
    |> Stream.run
  end

If create a single one, I can directly find out the associated parent and use Ecto.build_assoc(property, :owner) or something like this. How to handle it with such a mass import?