elixir - Phoenix 框架和验证嵌入

标签 elixir phoenix-framework

鉴于以下代码工作正常:

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/

相关文章:

elixir - 使一个字段在 ecto 中独一无二

elixir - 手动添加 gettext 翻译键

linux - 如何设置 Elixir 项目以通过 amqp 使用 RabbitMQ?

struct - Plug.Conn.Unfetched 未实现 Access 行为

elixir - 如何通过迁移更改 Ecto 模型中的列名?

phoenix-framework - 如何让 Phoenix LiveView 更新?

elixir - 埃克托+ Elixir : How do I query a hashmap field?

elixir - 重定向后 Flash 会保留,但常规分配不会

elixir - Phoenix Presence 通过交替元数据跨多个 channel 跟踪用户

testing - 使用 IEx 调试 phoenix 测试