2016-01-20 35 views
3

正常工作:鳳凰框架和考慮下面的代碼驗證嵌入功能

image_1 = %Image{naturalHeight: "100", naturalWidth: 100} 

diffbot_objects = [ 
    %DiffbotObject{ 
    availability: true, 
    images: [ 
     image_1 
    ] 
    } 
] 

changeset = Ecto.Changeset.change(product) 
changeset = Ecto.Changeset.put_embed(changeset, :diffbot_objects, diffbot_objects) 

我怎樣才能確保字段上的圖像模型驗證?我可以使用Image模型上的changeset方法生成變更集(請參閱下文),但我無法使用嵌套變更集插入數據,它似乎必須是e struct。

我的圖像模型:

defmodule Shopshare.Product.DiffbotObject.Image do 
    use Shopshare.Web, :model 

    embedded_schema do 
    field :naturalHeight, :integer 
    field :naturalWidth, :integer 
    end 

    @required_fields ~w(naturalHeight, naturalWidth) 
    @optional_fields ~w() 

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

回答

4

我看到你正在使用put_embed,但我不認爲從產品架構。我不知道這是否是真正的問題。但我嘗試了一些可行的代碼。

我使用Blog和Post模型創建了一個新應用程序。我使用生成模型:

mix phoenix.gen.model Blog blogs name:string 
mix phoenix.gen.model Post posts title:string body:text blog_id:references:blogs 

我正在使用一個簡單的驗證所需的字段。讓我們更深入地瞭解博客模式:

defmodule MyApp.Blog do 
     use MyApp.Web, :model 

     schema "blogs" do 
     field :name, :string 
     has_many :posts, MyApp.Post 

     timestamps 
     end 

     @required_fields ~w(name) 
     @optional_fields ~w() 

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

我手動創建一個職位has_many協會(它沒有與我產生模型創建)。現在,我們有Post模型:現在

defmodule MyApp.Post do 
     use MyApp.Web, :model 

     schema "posts" do 
     field :title, :string 
     field :body, :string 
     belongs_to :blog, MyApp.Blog 

     timestamps 
     end 

     @required_fields ~w(title body) 
     @optional_fields ~w() 

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

,我們可以在IEx標誌(iex -S mix)玩:

iex(1)> blog_changeset = MyApp.Blog.changeset(%MyApp.Blog{}, %{name: "blog name"}) 
    %Ecto.Changeset{...} 

    iex(2)> blog_changeset.valid? 
    true 

    iex(3)> invalid_post_changeset = MyApp.Post.changeset(%MyApp.Post{}, %{}) 
    %Ecto.Changeset{...} 

    iex(4)> blog_changeset = Ecto.Changeset.put_assoc(blog_changeset, :posts, [invalid_post_changeset]) 
    %Ecto.Changeset{action: nil, 
    changes: %{name: "blog name", 
     posts: [%Ecto.Changeset{action: :insert, 
     changes: ..., constraints: [], 
     errors: [title: "can't be blank", body: "can't be blank"], filters: %{}, 
     ...]}, ..., 
    model: %MyApp.Blog{...}, optional: [], opts: [], params: %{"name" => "blog name"}, 
    prepare: [], repo: nil, required: [:name], 
    types: %{...}, 
    valid?: false, validations: []} 

    iex(5)> blog_changeset.valid? 
    false 

我抑制一些輸出集中的錯誤。 Changeset就像一棵樹。所以,你可以擁有父變更集和孩子。與你的代碼不同的是,我使用的是put_assochttps://hexdocs.pm/ecto/Ecto.Changeset.html#put_assoc/4)(也許是關係,但我沒有看到你的模式)。

行爲從put_assoc預期:

如果聯想沒有任何變化,它會被跳過。如果關聯無效,則更改集將被標記爲無效。如果給定的價值不是一個關聯,它就會增加。

我希望這可以幫助你。

+0

這是一個了不起的答案埃裏克,感謝你寫了。我最終在自己的表中實現了一些東西,所以我無法測試你的答案,但是要感謝它被打出來喜歡這個。 – Samuel