鉴于以下代码工作正常:
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 方法生成变更集(见下文),但我无法使用嵌套变更集插入数据,它似乎必须是 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
最佳答案
我看到你正在使用 put_embed
但我没有看到产品的架构。我不知道这是否是真正的问题。但我尝试了一些有效的代码。
我使用博客和帖子模型创建了一个新应用程序。我使用了生成模型:
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_assoc
( https://hexdocs.pm/ecto/Ecto.Changeset.html#put_assoc/4 )(也许关系也是如此,但我没有看到您的架构)。来自
put_assoc
的预期行为:If the association has no changes, it will be skipped. If the association is invalid, the changeset will be marked as invalid. If the given value is not an association, it will raise.
我希望这可以帮助你。
关于elixir - Phoenix 框架和验证嵌入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34897957/