Phoenix 框架和验证嵌入
Phoenix frameworks and validating embeds
鉴于以下代码工作正常:
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)
如何确保字段在图像模型上得到验证?我可以使用图像模型上的变更集方法生成一个变更集(见下文),但我无法使用嵌套变更集插入数据,它似乎必须是 e 结构。
我的图片模型:
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
,但我没有看到产品的架构。我不知道这是否是真正的问题。但我尝试了一些有效的代码。
我用博客和 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_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.
希望对您有所帮助。
鉴于以下代码工作正常:
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)
如何确保字段在图像模型上得到验证?我可以使用图像模型上的变更集方法生成一个变更集(见下文),但我无法使用嵌套变更集插入数据,它似乎必须是 e 结构。
我的图片模型:
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
,但我没有看到产品的架构。我不知道这是否是真正的问题。但我尝试了一些有效的代码。
我用博客和 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_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.
希望对您有所帮助。