Schemas with common fields

Hi, all! Suppose I have 2 schemas mapping 2 similar external API responses:

defmodule Foo do
  use Ecto.Schema

  embedded_schema do
    belongs_to :common_field_1, CommonField

    field :common_field_2, :integer
    field :common_field_3, :string

    field :foo_specific_field, :integer
  end

  def changeset(params) do
    %Foo{}
    |> cast(...)
    |> validate_common_fields()
    |> validate_foo_specific_fields()
  end

  def validate_common_fields(%Ecto.Changeset{} = changeset) do
    # Uses only common fields
  end

  def validate_foo_specific_fields(%Ecto.Changeset{} = changeset) do
    # Uses common and specific fields
  end
end

defmodule Bar do
  use Ecto.Schema

  embedded_schema do
    belongs_to :common_field_1, CommonField

    field :common_field_2, :integer
    field :common_field_3, :string

    field :bar_specific_field1, :integer
    field :bar_specific_field2, :string
  end

  def changeset(params) do
    %Bar{}
    |> cast(...)
    |> validate_common_fields()
    |> validate_bar_specific_fields()
  end

  def validate_common_fields(%Ecto.Changeset{} = changeset) do
    # Uses only common fields
  end

  def validate_bar_specific_fields(%Ecto.Changeset{} = changeset) do
    # Uses common and specific fields
  end
end

What is the best way to avoid dup code in that case? I can move common validations in another module. But how to deal with common fields in schema definitions?

1 Like

In theory you can do it exactly like it is done in ecto itself with the timestamps/1 and implement it as a macro.

But for only two schemas, I do not think its worth the effort…


Implementation:

1 Like

I would expect this to be a case of driving DRYness to far. Those API resonses are currently similar, but will they stay that way in the future? Will changes happen in both responses at the same time? Having common validation is a nice option to prevent having to fix business rules in two places, but the schema is just a static representation without many moving parts.

@NobbZ @LostKobrakai Thank both of you, guys. I understand your concerns on overDRYing schema definitions. In our case we have not 2 but 5 such schemas. Perhaps, we will consider requesting external API refactoring.