Ecto与多个计划的关联

时间:2016-01-16 03:13:54

标签: associations elixir ecto

我们说我有这些模式:

defmodule Sample.Post do
  use Ecto.Schema

  schema "post" do
    field :title
    has_many :comments, Sample.Comment
  end
end

defmodule Sample.User do
  use Ecto.Schema

  schema "user" do
    field :name
    has_many :comments, Sample.Comment
  end
end

defmodule Sample.Comment do
  use Ecto.Schema

  schema "comment" do
    field :text
    belongs_to :post, Sample.Post
    belongs_to :user, Sample.User
  end
end

我的问题是如何使用Ecto.build_assoc保存评论?

iex> post = Repo.get(Post, 13)
%Post{id: 13, title: "Foo"}
iex> comment = Ecto.build_assoc(post, :comments)
%Comment{id: nil, post_id: 13, user_id: nil}

到目前为止还可以,我需要做的就是使用相同的函数在我的user_id结构中设置Comment,但是因为build_assoc的返回值是Comment struct,我不能使用相同的函数

iex> user = Repo.get(User, 1)
%User{id: 1, name: "Bar"}
iex> Ecto.build_assoc(user, :comment, comment)
** (UndefinedFunctionError) undefined function: Sample.Comment.delete/2
...

我有两种选择,但它们对我来说都不合适:

首先是手动设置user_id

iex> comment = %{comment| user_id: user.id}
%Comment{id: nil, post_id: 13, user_id: 1}

第二个是将结构转换为地图并且...我甚至不想去那里

有什么建议吗?

2 个答案:

答案 0 :(得分:8)

为什么不想让convert struct映射?这真的很容易。

ng-bind-html期望将属性映射作为最后一个值。在内部,它会尝试删除键build_assoc。结构具有编译时保证,它们将包含所有已定义的字段,因此您将获得:

:__meta__

但你可以写:

** (UndefinedFunctionError) undefined function: Sample.Comment.delete/2

一切都会正常。

答案 1 :(得分:4)

将其与build_assoc

一起传递
iex> comment = Ecto.build_assoc(post, :comments, user_id: 1)
%Comment{id: nil, post_id: 13, user_id: 1}

查看here了解详情。