2016-01-20 38 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