-->

Ecto warning with embedded model

2019-08-12 09:02发布

问题:

I get this warning when casting

warning: casting embeds with cast/4 is deprecated, please use cast_embed/3 instead

I have the model Organization

defmodule Bonsai.Organization do
  use Bonsai.Web, :model
  alias Bonsai.OrganizationSettings

  schema "organizations" do
    field :name, :string
    field :currency, :string
    field :tenant, :string
    field :info, :map, default: %{}
    embeds_one :settings, OrganizationSettings, on_replace: :delete

    timestamps
  end

  @required_fields ~w(name currency tenant)
  @optional_fields ~w(info settings)

  @doc """
  """
  def changeset(model, params \\ %{}) do
    cast(model, params, @required_fields, @optional_fields)
    |> cast_embed(:settings)
    |> put_embed(:settings, OrganizationSettings.changeset(%OrganizationSettings{}, params[:settings] || %{}))
    |> change(%{info: params[:info] || %{}})
  end

end

And my embedded model OrganizationSettings

defmodule Bonsai.OrganizationSettings do
  use Ecto.Model
  #use Ecto.Changeset

  @primary_key {:id, :binary_id, autogenerate: true}
  #schema "" do
  embedded_schema do
    field :show_search_on_focus, :boolean, default: true
    field :theme, :string, default: "bonsai"
  end

  def changeset(model, params \\ %{}) do
    model
    |> cast(params, [:theme], [:show_search_on_focus])
    |> validate_inclusion(:theme, ["bonsai", "dark"])
  end

end

I have tried many ways but I'm doing something wrong please help

回答1:

I have updated to Ecto 2 and the changes are

# mix.exs
  defp deps do
    [{:phoenix, "~> 1.1.4"},
     {:postgrex, ">= 0.0.0"},
     {:phoenix_ecto, "~> 3.0.0-beta"},
     {:phoenix_html, "~> 2.5"},
     {:phoenix_live_reload, "~> 1.0", only: :dev},
     {:gettext, "~> 0.9"},
     {:cowboy, "~> 1.0"},
     {:poison, "~> 1.5.2"}]
  end

Then run `mix deps.update, and edit the files

  # In file test/support/model_case.ex
  setup tags do
    :ok = Ecto.Adapters.SQL.Sandbox.checkout(Bonsai.Repo)
  end

# In file test/test_helper.exs
#Ecto.Adapters.SQL.begin_test_transaction(Bonsai.Repo)
Ecto.Adapters.SQL.Sandbox.mode(Bonsai.Repo, :manual)

And my model Organization changeset

def changeset(model, params \\ %{}) do
    cast(model, params, [:name, :currency, :tenant])
    |> validate_required([:name, :currency, :tenant])
    |> cast_embed(:settings)
    |> put_embed(:settings, OrganizationSettings.changeset(%OrganizationSettings{}, params[:settings] || %{}))
    |> change(%{info: params[:info] || %{}})
  end


回答2:

See https://github.com/elixir-ecto/ecto/blob/cc92f05cb2f24c3206db9017e6c28ecf77ff100d/CHANGELOG.md - Revamped changesets. You're using deprecated cast/4 here:

cast(model, params, @required_fields, @optional_fields) cast(model, params, [:theme], [:show_search_on_focus])

Instead, use cast/3 and validate_required/3 as presented there in the example.