put_assoc 需要验证

问题描述 投票:0回答:1

在我的 phoenix 项目中,我有一个通过连接表链接的帖子和标签架构

schema "posts" do
    field :title, :string
    field :body, :string

    many_to_many :tags, App.Tag, join_through: App.PostsTags , on_replace: :delete
    timestamps()   
end?

如何确保使用 put_assoc 存在标签?

def changeset(struct, params \\ %{}) do
    struct
    |> cast(params, [:title, :body])
    |> put_assoc(:tags, parse_tags(params), required: true)
    |> validate_required([:title, :body, :tags])
end

put_assoc 上的 required: true 和添加 :tags 来验证 required 都不能像我想象的那样工作。

elixir phoenix-framework ecto
1个回答
6
投票

validate_length/3
可用于检查
tags
列表是否为空:

帖子架构:

defmodule MyApp.Blog.Post do
  use Ecto.Schema
  import Ecto.Changeset
  alias MyApp.Blog.Post


  schema "blog_posts" do
    field :body, :string
    field :title, :string
    many_to_many :tags, MyApp.Blog.Tag, join_through: "blog_posts_tags"

    timestamps()
  end

  @doc false
  def changeset(%Post{} = post, attrs) do
    post
    |> cast(attrs, [:title, :body])
    |> put_assoc(:tags, attrs[:tags])
    |> validate_required([:title, :body])
    |> validate_length(:tags, min: 1)
  end
end

标签架构:

defmodule MyApp.Blog.Tag do
  use Ecto.Schema
  import Ecto.Changeset
  alias MyApp.Blog.Tag


  schema "blog_tags" do
    field :name, :string

    timestamps()
  end

  @doc false
  def changeset(%Tag{} = tag, attrs) do
    tag
    |> cast(attrs, [:name])
    |> validate_required([:name])
  end
end

出现

tags
时验证成功:

iex(16)> Post.changeset(%Post{}, %{title: "Ecto Many-to-Many", body: "Lots of words", tags: [%{name: "tech"}]})
#Ecto.Changeset<action: nil,
 changes: %{body: "Lots of words",
   tags: [#Ecto.Changeset<action: :insert, changes: %{name: "tech"}, errors: [],
     data: #MyApp.Blog.Tag<>, valid?: true>], title: "Ecto Many-to-Many"},
 errors: [], data: #MyApp.Blog.Post<>, valid?: true>

tags
为空时产生错误:

iex(17)> Post.changeset(%Post{}, %{title: "Ecto Many-to-Many", body: "Lots of words", tags: []})
#Ecto.Changeset<action: nil,
 changes: %{body: "Lots of words", tags: [], title: "Ecto Many-to-Many"},
 errors: [tags: {"should have at least %{count} item(s)",
   [count: 1, validation: :length, min: 1]}], data: #MyApp.Blog.Post<>,
 valid?: false>

tags
为零时产生错误:

iex(18)> Post.changeset(%Post{}, %{title: "Ecto Many-to-Many", body: "Lots of words"})
#Ecto.Changeset<action: nil,
 changes: %{body: "Lots of words", title: "Ecto Many-to-Many"},
 errors: [tags: {"is invalid", [type: {:array, :map}]}],
 data: #MyApp.Blog.Post<>, valid?: false>
© www.soinside.com 2019 - 2024. All rights reserved.