I am trying to create a rudimentary online bank where customers can create accounts and make deposits into their accounts. This is the first time I’ve used Phoenix and Elixir and I’m having a lot of trouble with the deposit function. My thinking is that all a customer would need to deposit money is their account ID and the amount of money. I have therefore made a function for this in the user_controller which inputs the ID alongside the amount, however, I am getting the dreaded no function clause matching in SpBankWeb.UserController.deposit/2
error in postman when I try to post into it… perhaps due to how I am posting to it or how my logic is structured - or perhaps both of these things.
My POST request contains this as the body {"id" :{"amount":200.0}}
and is correctly to the route http://localhost:4000/api/deposit
(do I need to make any changes to this?). This results in the input, alongside the no function matching error,
# 2
%{"id" => %{"amount" => 200.0}}
- This is the first thing that is confusing me, as my function takes in an ID and an amount, which is what is shown above - why is this not matching? The corresponding user function is below:
User_controller:
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
- Or, does the problem arise instead due to the router as below. Why, for instance, did I need to specify the route of POST here when for the other user_controller methods these simply came with the ‘resources’ of /users?
Router.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