外生 - 预紧协会创建与母公司的关联记录时
路过的1父记录的ID值一对多关联的时候创建一个子记录时,我收到一个关联的错误。外生 - 预紧协会创建与母公司的关联记录时
错误说我需要预装User
这是一个父记录到Transaction
,
1) test creates and renders resource when data is valid (MyRewardsWeb.TransactionControllerTest)
test/controllers/transaction_controller_test.exs:36
** (RuntimeError) attempting to cast or change association `user` from `MyRewards.Transaction` that was not loaded. Please preload your associations before manipulating them thr
ough changesets
stacktrace:
(ecto) lib/ecto/changeset/relation.ex:66: Ecto.Changeset.Relation.load!/2
(ecto) lib/ecto/repo/schema.ex:514: anonymous fn/4 in Ecto.Repo.Schema.surface_changes/4
(elixir) lib/enum.ex:1623: Enum."-reduce/3-lists^foldl/2-0-"/3
(ecto) lib/ecto/repo/schema.ex:503: Ecto.Repo.Schema.surface_changes/4
(ecto) lib/ecto/repo/schema.ex:186: Ecto.Repo.Schema.do_insert/4
(my_rewards_web) web/controllers/transaction_controller.ex:20: MyRewardsWeb.TransactionController.create/2
(my_rewards_web) web/controllers/transaction_controller.ex:1: MyRewardsWeb.TransactionController.action/2
(my_rewards_web) web/controllers/transaction_controller.ex:1: MyRewardsWeb.TransactionController.phoenix_controller_pipeline/2
(my_rewards_web) lib/my_rewards_web/endpoint.ex:1: MyRewardsWeb.Endpoint.instrument/4
(my_rewards_web) lib/phoenix/router.ex:261: MyRewardsWeb.Router.dispatch/2
(my_rewards_web) web/router.ex:1: MyRewardsWeb.Router.do_call/2
(my_rewards_web) lib/my_rewards_web/endpoint.ex:1: MyRewardsWeb.Endpoint.phoenix_pipeline/1
(my_rewards_web) lib/my_rewards_web/endpoint.ex:1: MyRewardsWeb.Endpoint.call/2
(phoenix) lib/phoenix/test/conn_test.ex:224: Phoenix.ConnTest.dispatch/5
test/controllers/transaction_controller_test.exs:41: (test)
在我的控制器的方法,我发现User
和Merchant
记录这是Transaction
结构的两家母公司记录和传递创建变更集时的相应记录ID
def create(conn, %{"merchant_id" => merchant_id, "mobile" => mobile, "amount" => amount}) do
customer = MyRewards.find_user!(%{"mobile" => mobile})
merchant = Repo.get(MyRewards.Merchant, merchant_id)
changeset = MyRewards.create_deposit_changeset(%{"user_id" => customer.id, "merchant_id" => merchant.id, "amount" => amount })
case Repo.insert(changeset) do
{:ok, transaction} ->
conn
|> put_status(:created)
|> put_resp_header("location", transaction_path(conn, :show, transaction))
|> render("show.json", transaction: transaction)
{:error, changeset} ->
conn
|> put_status(:unprocessable_entity)
|> render(MyRewardsWeb.ChangesetView, "error.json", changeset: changeset)
end
end
该函数只是将信息传递并返回变更集:
def create_deposit_changeset(user_id: user_id, merchant_id: merchant_id, amount: amount) do
MyRewards.Transaction.deposit(%MyRewards.Transaction{}, %{ merchant_id: merchant_id, user_id: user_id, amount: Money.new(amount) })
end
在结构,我有关系,并且正确地投了user_id
和merchant_id
作为Transaction
外生结构定义的参数。
defmodule MyRewards.Transaction do
@entry_types [:credit, :debit]
use MyRewards.Model
schema "my_rewards_transactions" do
field :amount, Money.Ecto.Type
field :type, :string
belongs_to :user, MyRewards.User
belongs_to :merchant, MyRewards.Merchant
timestamps()
end
@doc """
Builds a changeset based on the `struct` and `params`.
"""
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:amount, :type, :user_id, :merchant_id])
|> validate_required([:amount, :type])
end
def deposit(struct, params) do
struct
|> cast(%{type: "debit"}, [:type])
|> changeset(params)
end
def widthdraw(struct, params) do
struct
|> cast(%{type: "credit"}, [:type])
|> changeset(params)
end
end
当我在我的测试情况下,测试功能,它进入交易罚款。
MyRewards.create_deposit_changeset(user_id: customer.id, merchant_id: merchant.id, amount: x)
但是,当我在Phoenix控制器中运行它时,它失败。我不确定为什么它失败或要求预加载父协会。我应该在某处做put_assoc
而不是直接将user_id
和merchant_id
作为参数吗?
的问题是,我的设置作为OTP应用程序不能共享外生的预装的方面。在凤凰城我的网络侧是好的,但我不能提交变更的控制器,因为在凤凰应用的Repo
是不一样的参考,因为这是OTP的应用程序,这是造成预紧错误的变更。
我已经提取的原因,是由于!
我在我原来的设置错失。
我改变了我的控制器回看起来像这样的地方返回{:ok, transaction}
这样
case MyRewards.create_deposit(%{"user_id" => customer.id, "merchant_id" => merchant.id, "amount" => amount }) do
{:ok, transaction} ->
conn
|> put_status(:created)
|> put_resp_header("location", transaction_path(conn, :show, transaction))
|> render("show.json", transaction: transaction)
{:error, changeset} ->
conn
|> put_status(:unprocessable_entity)
|> render(MyRewardsWeb.ChangesetView, "error.json", changeset: changeset)
end
这是不同的,因为我不是返回变更。我在OTP应用程序中执行Repo.insert并返回事务。
def create_deposit(%{"user_id" => user_id, "merchant_id" => merchant_id, "amount" => amount }) do
MyRewards.Transaction.deposit(%MyRewards.Transaction{}, %{ merchant_id: merchant_id, user_id: user_id, amount: Money.new(amount) })
|> MyRewards.Repo.insert
end
为什么我从这个改变了原来的原因是因为我用的是|> MyRewards.Repo.insert!
代替|> MyRewards.Repo.insert
....这!
爆炸末改变功能的,只返回结构中的回报,而不是返回状态和结构像{:ok, transaction}
这是控制器所期待的。
总之,如果你有你的应用分成OTP和凤凰,注意你的回购插入!
。
只有测试失败? –
测试通过,但所述控制器操作失败 – DogEatDog
检查这一行:'变更= MyRewards.create_deposit_changeset(%{ “USER_ID”=> customer.id, “MERCHANT_ID”=> merchant.id, “量”=>量})' ...从你的场景中没有函数子句匹配,它是正确的吗? –