代码生成与预期不同

Code generation different than expected

我正在按照 Programming Phoenix 这本书来构建给定的 Rumbl 应用程序。我的问题与我们使用生成器自动创建大量功能的章节有关。使用的命令是:

$ mix phoenix.gen.html Video videos user_id:references:users url:string title:string description:text

现在的问题是,在几个地方,书中给出的代码与我得到的代码之间存在差异。一个很好的例子是 web/models/video.ex 模块。我最终得到的代码是:

defmodule Rumbl.Video do
  use Rumbl.Web, :model

  schema "videos" do
    field :url, :string
    field :title, :string
    field :description, :string
    belongs_to :user, Rumbl.User

    timestamps()
  end

  @doc """
  Builds a changeset based on the `struct` and `params`.
  """
  def changeset(struct, params \ %{}) do
    struct
    |> cast(params, [:url, :title, :description])
    |> validate_required([:url, :title, :description])
  end
end

而在书中,changeset 函数给出为:

@required_fields ~w(url title description)
@optional_fields ~w()

def changeset(model, params \ :empty) do
  model
  |> cast(params, @required_fields, @optional_fields)

(请原谅后一段中的打字错误;我不得不手动输入)

我不明白为什么会有这种差异。会不会是因为版本差异?更重要的是,这种差异意味着什么?

是的,这是版本差异。 Phoenix 1.2 切换到使用 Ecto 2.0,它弃用了 Ecto.Changeset.cast 的 4 arity 版本,取而代之的是 3 arity one + 对 Ecto.Changeset.validate_required/3 的调用。 Ecto 2.0 也反对将 :empty 传递给 castthe changelog:

中记录了所有这些和更多更改

Highlights

Revamped changesets

Due to feedback, we have made three important changes to changesets:

  1. changeset.model has been renamed to changeset.data (we no longer have "models" in Ecto)
  2. Passing required and optional fields to cast/4 is deprecated in favor of cast/3 and validate_required/3
  3. The :empty atom in cast(source, :empty, required, optional) has been deprecated, please use an empty map or :invalid instead

To summarize those changes, instead of:

def changeset(user, params \ :empty) do
  user
  |> cast(params, [:name], [:age])
end

One should write:

def changeset(user, params \ %{}) do
  user
  |> cast(params, [:name, :age])
  |> validate_required([:name])
end

...