2017-02-21 68 views
1

路過的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) 

在我的控制器的方法,我發現UserMerchant記錄這是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_idmerchant_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_idmerchant_id作爲參數嗎?

+0

只有測試失敗? –

+0

測試通過,但所述控制器操作失敗 – DogEatDog

+0

檢查這一行:'變更= MyRewards.create_deposit_changeset(%{ 「USER_ID」=> customer.id, 「MERCHANT_ID」=> merchant.id, 「量」=>量})' ...從你的場景中沒有函數子句匹配,它是正確的嗎? –

回答

2

的問題是,我的設置作爲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和鳳凰,注意你的回購插入!