Excluding inputs from a schema?

Is there a good way to exclude inputs from a schema? For example, if I wanted to keep track of how many views a product is getting. However, I don’t want users to be able insert the starting number of views of their product. This is what I have, I’m sure if there’s a better way to do it:

defmodule Commerce.Catalog.Product do
  use Ecto.Schema
  import Ecto.Changeset

  @optional_create_fields [:id, :inserted_at, :updated_at]
  @forbidden_update_fields [:id, :inserted_at, :updated_at]
  @forbidden_create_fields [:views]
  @optional_and_forbidden_create_fields @forbidden_create_fields ++ @optional_create_fields


  schema "products" do
    field :description, :string
    field :price, :decimal
    field :title, :string
    field :views, :integer, default: 0
    field :sku, :integer

    belongs_to :user, Commerce.Accounts.User
    timestamps()
  end

  defp all_fields do
    __MODULE__.__schema__(:fields)
  end

  @doc false
  def create_changeset(product, attrs) do
    product
    |> cast(attrs, all_fields() -- @forbidden_create_fields)
    |> validate_required(all_fields() -- @optional_and_forbidden_create_fields)
    |> unique_constraint([:user_id, :sku])
  end

  @doc false
  def update_changeset(product = %__MODULE__{}, attrs) do
    product
    |> cast(attrs, all_fields() -- @forbidden_create_fields)
    |> validate_required(all_fields() -- @optional_and_forbidden_create_fields)
    |> unique_constraint([:user_id, :sku])
  end
end
1 Like

I’d start by explicitly defining what may be changed per changeset instead of defining everything being allowed just to then be required to be vigilant in removing all the fields, which aren’t.

2 Likes