我将在此处显示一些相关代码,但如果您需要完整代码,可以在Github上找到它:https://github.com/maple-leaf/phoenix_todo
user_model:
defmodule PhoenixTodo.User do
use PhoenixTodo.Web, :model
@derive {Poison.Encoder, only: [:name, :email, :bio, :todos]}
schema "users" do
field :name, :string
field :age, :integer
field :email, :string
field :bio, :string
has_many :todos, PhoenixTodo.Todo
timestamps()
end
@doc """
Builds a changeset based on the `struct` and `params`.
"""
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:name])
|> validate_required([])
end
end
todo_model:
defmodule PhoenixTodo.Todo do
use PhoenixTodo.Web, :model
@derive {Poison.Encoder, only: [:title, :content]}
schema "todos" do
field :title, :string
field :content, :string
belongs_to :user, PhoenixTodo.User
timestamps()
end
@doc """
Builds a changeset based on the `struct` and `params`.
"""
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [])
|> validate_required([])
end
end
user_controller:
defmodule PhoenixTodo.UserController do
use PhoenixTodo.Web, :controller
alias PhoenixTodo.User
def index(conn, _params) do
json(conn, User |> Repo.all() |> Repo.preload(:todos))
end
def show(conn, %{"id" => id}) do
json(conn, User|> Repo.get(id) |> Repo.preload(:todos))
end
def create(conn, data) do
user = User.changeset(%User{}, data)
#user = User.changeset(%User{}, %{name: "xxx", todos: [%PhoenixTodo.Todo{}]})
json conn, user
end
end
我可以从:index
和:show
获取所有用户或查询特定用户,但:create
将始终引发有关association
的错误。
请求:curl -H "Content-Type: application/json" -X POST -d '{"name": "abc"}' http://localhost:4000/api/users
出现错误:cannot encode association :todos from PhoenixTodo.User to JSON because the association was not loaded. Please make sure you have preloaded the association or remove it from the data to be encoded
:todos
时如何预加载:create
?创建用户时todos
不是必填字段,我们可以忽略该关联吗?
答案 0 :(得分:0)
最后,我让它发挥作用。
事实证明json conn user
很重要。似乎json
会调用Poison
来编码Ecto.Changeset
,而不是Ecto.Model
,它会按changeset
返回。所以我们应该将Ecto.Model
传递给json。
以下是我的表现方式。
user = User.changeset(%User{}, data)
IO.inspect user # Ecto.Changeset
{:ok, u1} = Repo.insert(user)
IO.inspect u1 # Model!!
json conn, u1 |> Repo.preload(:todos) # now we can successfully preload :todos