首页 > 解决方案 > 如何正确设置凤凰城银行的存款功能

问题描述

我正在尝试创建一个基本的在线银行,客户可以在其中创建账户并将存款存入他们的账户。这是我第一次使用 Phoenix 和 Elixir,存款功能遇到了很多麻烦。我的想法是,客户存款所需的只是他们的账户 ID 和金额。因此,我在 user_controller 中为此创建了一个函数,该函数将 ID 与金额一起输入,但是,no function clause matching in SpBankWeb.UserController.deposit/2当我尝试发布到其中时,我在邮递员中遇到了可怕的错误......可能是由于我如何发布到它或如何我的逻辑是结构化的——或者可能两者兼而有之。

我的 POST 请求包含这个作为正文{"id" :{"amount":200.0}},并且正确的路由http://localhost:4000/api/deposit(我需要对此进行任何更改吗?)。这导致输入,除了没有函数匹配错误,

# 2
%{"id" => %{"amount" => 200.0}} 
  1. 这是让我感到困惑的第一件事,因为我的函数需要一个 ID 和一个金额,如上所示 - 为什么这不匹配? 对应的用户函数如下:

用户控制器:

defmodule SpBankWeb.UserController do
  use SpBankWeb, :controller

  alias SpBank.Account
  alias SpBank.Account.User

  action_fallback SpBankWeb.FallbackController

  def index(conn, _params) do
    users = Account.list_users()
    render(conn, "index.json", users: users)
  end

  def create(conn, %{"user" => user_params}) do
    with {:ok, %User{} = user} <- Account.create_user(user_params) do
      conn
      |> put_status(:created)
      |> put_resp_header("location", Routes.user_path(conn, :show, user))
      |> render("show.json", user: user)
    end
  end

  def deposit(conn, %{"id" => id, "amount" => amount}) do
    user = Account.get_user!(id)
    with {:ok, %User{} = user} <- Account.deposit(user, amount) do
      render(conn, "show.json", user: user)
    end
  end
  1. 或者,是否由于路由器如下所示而出现问题。例如,为什么我需要在此处指定 POST 的路由,而对于其他 user_controller 方法,这些方法只是带有 /users 的“资源”?

路由器.ex:

defmodule SpBankWeb.Router do
  use SpBankWeb, :router

  pipeline :api do
    plug :accepts, ["json"]
  end

  scope "/api", SpBankWeb do
    pipe_through :api
    resources "/users", UserController, except: [:new, :edit]
    resources "/transactions", UserController, except: [:new, :edit]
    post "/deposit", UserController, :deposit
  end

Account.Transactions.ex:

defmodule SpBank.Account.Transaction do
  use Ecto.Schema
  import Ecto.Changeset
  alias SpBank.Account.User

  schema "transactions" do
    belongs_to :user, User
    field :amount, :decimal

    timestamps()
  end

  @doc false
  def changeset(transaction, attrs) do
    transaction
    |> cast(attrs, [:id, :amount])
    |> assoc_constraint(:user)
    |> validate_required([:id, :amount])
  end
end

Account.user.ex:

defmodule SpBank.Account.User do
  use Ecto.Schema
  import Ecto.Changeset
  alias SpBank.Account.Transaction
  schema "users" do
    # field :id 
    field :amount, :decimal
    field :name, :string
    has_many :transactions, Transaction 
    timestamps()
  end

  @doc false
  def changeset(user, attrs) do
    user
    |> cast(attrs, [:name, :amount])
    |> validate_required([:name, :amount])
  end
end

标签: elixirphoenix-framework

解决方案


推荐阅读