鉴于以下代码可以正常工作:
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模型上验证字段?我可以使用Image模型上的changeset方法生成一个变更集(请参见下文),但是我无法使用嵌套的变更集插入数据,看起来它必须是结构化的。
我的图像模型:
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
最佳答案
我看到您正在使用put_embed
,但看不到产品的架构。我不知道这是否是真正的问题。但是我尝试了一些有效的代码。
我使用Blog and Post模型创建了一个新应用。我使用了生成模型:
mix phoenix.gen.model Blog blogs name:string
mix phoenix.gen.model Post posts title:string body:text blog_id:references:blogs
我正在对必填字段使用简单的验证。让我们更深入地研究Blog模型:
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_assoc
(https://hexdocs.pm/ecto/Ecto.Changeset.html#put_assoc/4)(也许也是这种关系,但是我没有看到您的架构)。put_assoc
的预期行为:如果关联没有更改,它将被跳过。如果关联无效,则变更集将被标记为无效。如果给定的值不是关联,它将提高。
希望对您有所帮助。