与多个方案的 Ecto 关联
Ecto association to more than one schemes
假设我有这些模式:
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}
到目前为止一切正常,我需要做的就是使用相同的函数在我的 Comment
结构中设置 user_id
,但是由于 return 的值 build_assoc
是 Comment
结构,我不能使用相同的功能
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}
第二个是将 struct 转换为 map 并且......我什至不想去那里
有什么建议吗?
您为什么不想将结构转换为映射?真的很简单。
build_assoc
期望属性映射作为最后一个值。它在内部尝试删除键 :__meta__
。结构有编译时保证,它们将包含所有定义的字段,所以你得到:
** (UndefinedFunctionError) undefined function: Sample.Comment.delete/2
但是你可以只写:
comment = Ecto.build_assoc(user, :comment, Map.from_struct comment)
一切都会正常进行。
随build_assoc
一起传递
iex> comment = Ecto.build_assoc(post, :comments, user_id: 1)
%Comment{id: nil, post_id: 13, user_id: 1}
查看 here 了解更多详情。
假设我有这些模式:
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}
到目前为止一切正常,我需要做的就是使用相同的函数在我的 Comment
结构中设置 user_id
,但是由于 return 的值 build_assoc
是 Comment
结构,我不能使用相同的功能
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}
第二个是将 struct 转换为 map 并且......我什至不想去那里
有什么建议吗?
您为什么不想将结构转换为映射?真的很简单。
build_assoc
期望属性映射作为最后一个值。它在内部尝试删除键 :__meta__
。结构有编译时保证,它们将包含所有定义的字段,所以你得到:
** (UndefinedFunctionError) undefined function: Sample.Comment.delete/2
但是你可以只写:
comment = Ecto.build_assoc(user, :comment, Map.from_struct comment)
一切都会正常进行。
随build_assoc
iex> comment = Ecto.build_assoc(post, :comments, user_id: 1)
%Comment{id: nil, post_id: 13, user_id: 1}
查看 here 了解更多详情。