2017-07-15 38 views
1

在我的鳳凰計劃驗證,我必須通過一個連接錶鏈接的帖子和標籤模式需要put_assoc

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爲true並且添加:要求驗證的標籤不按我想象的那樣工作。

回答

1

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], required: true) 
    |> 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 

void驗證成功時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> 
+0

根據我的測試,提供了一個空的清單,要求put_assoc:真不拋出任何錯誤。相反,put_assoc在傳遞的參數爲nil時會拋出一個錯誤,無論是否設置爲true:true。 – kuan

+0

謝謝@kuan,我已經更新了用validate_length來驗證的答案,它應該處理空列表大小寫。 –