我正在尝试使用Decoratex库来填充我的用户模型中的某些虚拟字段,但是我无法避免以下错误:
no function clause matching in Decoratex.decorate/1
This functions just call the configured function to each field passing
the model structure it self and it store the result in the virtual field.
"""
@spec decorate(nil) :: nil
def decorate(nil), do: nil
@spec decorate(struct) :: struct
def decorate(%module{} = element) do
module.__decorations__ |> Enum.reduce(element, &do_decorate/2)
end
作为示例,我试图将user_age键值添加到模型结构中。该模型是:
defmodule InformAPI.UTL.User_take_list do
use Ecto.Schema
use Decoratex.Schema
# alias InformAPI.UTL.UTLHelpers
import Ecto.Changeset
decorations do
decorate_field :user_age, :integer, &UTLHelpers.calculate_user_age/1
end
schema "user_take_lists" do
field :date_of_birth, :date
field :first_name, :string
field :last_name, :string
field :user_id, :string
field :needs_senior_review, :boolean
field :stable, :boolean
field :list_date, :date
belongs_to :consultant, InformAPI.UTL.User_take_list_consultant
timestamps()
decorations()
end
def changeset(user_take_list, attrs) do
user_take_list
|> cast(attrs, [:user_id, :first_name, :date_of_birth, :last_name, :needs_senior_review, :list_date, :stable, :consultant_id])
|> validate_required([:user_id, :first_name, :date_of_birth, :last_name, :needs_senior_review, :consultant_id, :stable])
end
end
当前已将calculate_user_age函数配置为仅返回结果:
defmodule InformAPI.UTL.UTLHelpers do
alias InformAPI.UTL.User_take_list
def calculate_user_age(struct) do
x = [1,2,3,4,5,6]
Enum.count(x)
end
end
然后在控制器的Index函数上调用所需的Decoratex.decorate:
defmodule InformAPIWeb.User_take_listController do
import Ecto.Query, warn: false
use InformAPIWeb, :controller
use Filterable.Phoenix.Controller
alias InformAPI.UTL
alias InformAPI.UTL.User_take_list
alias InformAPI.Repo
action_fallback InformAPIWeb.FallbackController
filterable do
filter review(query, value, _conn) do
IO.inspect(query)
query |> where(needs_senior_review: ^value)
end
@options param: :dateFrom, cast: :date
filter dateFrom(query, value, _conn) do
query |> where([d], d.list_date >= ^value)
end
@options param: :dateTo, cast: :date
filter dateTo(query, value, _conn) do
query |> where([d], d.list_date <= ^value)
end
@options param: :conid, cast: :integer
filter conID(query, value, _conn) do
query |> where([d], d.consultant_id <= ^value)
end
end
def index(conn, params) do
with {:ok, query, filter_values} <- apply_filters(User_take_list, conn),
user_take_lists <- Repo.all(query) |>Decoratex.decorate,
do: render(conn, "index.json", user_take_lists: user_take_lists, meta: filter_values)
end
def show(conn, %{"id" => id}) do
user_take_list = UTL.get_user_take_list!(id)
render(conn, "show.json", user_take_list: user_take_list)
end
end
我对Elixir很陌生,我无法追究此错误的性质。如果检查该结构,则可以看到一个user_age字段,该字段的值为nil,但我不知道问题是由我自己的辅助函数引起的还是由我使用DecorateX.decorate引起的。
根据注释中的要求,出现带有堆栈跟踪的完整错误:
[info] GET /api/user_take_list
[debug] Processing with InformAPIWeb.User_take_listController.index/2
Parameters: %{}
Pipelines: [:api]
[debug] QUERY OK source="user_take_lists" db=0.0ms decode=16.0ms
SELECT m0."id", m0."date_of_birth", m0."first_name", m0."last_name", m0."user_id", m0."needs_senior_review", m0."stable", m0."list_date", m0."consultant_id", m0."inserted_at", m0."updated_at" FROM "user_take_lists" AS m0 []
[info] Sent 500 in 141ms
[error] #PID<0.390.0> running InformAPIWeb.Endpoint (cowboy_protocol) terminated
Server: localhost:4000 (http)
Request: GET /api/user_take_list
** (exit) an exception was raised:
** (FunctionClauseError) no function clause matching in Decoratex.decorate/1
(decoratex) lib/decoratex.ex:145: Decoratex.decorate([%InformAPI.UTL.User_take_list{__meta__: #Ecto.Schema.Metadata<:loaded, "user_take_lists">, consultant: #Ecto.Association.NotLoaded<association :consultant is not loaded>, consultant_id: 3, date_of_birth: ~D[1987-02-13], first_name: "Hal", id: 1, inserted_at: ~N[2018-09-19 10:58:49.194000], last_name: "Bradley", list_date: ~D[2018-09-13], needs_senior_review: true, user_age: nil, user_id: "D00001", stable: true, updated_at: ~N[2018-09-19 10:58:49.194000]}, %InformAPI.UTL.User_take_list{__meta__: #Ecto.Schema.Metadata<:loaded, "user_take_lists">, consultant: #Ecto.Association.NotLoaded<association :consultant is not loaded>, consultant_id: 3, date_of_birth: ~D[1987-02-13], first_name: "Isobel", id: 2, inserted_at: ~N[2018-09-19 10:58:49.211000], last_name: "Rogers", list_date: ~D[2018-09-13], needs_senior_review: false, user_age: nil, user_id: "D00001", stable: true, updated_at: ~N[2018-09-19 10:58:49.211000]}, %InformAPI.UTL.User_take_list{__meta__: #Ecto.Schema.Metadata<:loaded, "user_take_lists">, consultant: #Ecto.Association.NotLoaded<association :consultant is not loaded>, consultant_id: 2, date_of_birth: ~D[1987-02-13], first_name: "Oliver", id: 3, inserted_at: ~N[2018-09-19 10:58:49.220000], last_name: "Barton", list_date: ~D[2018-09-13], needs_senior_review: true, user_age: nil, user_id: "D00001", stable: true, updated_at: ~N[2018-09-19 10:58:49.220000]}])
(inform_api) lib/inform_api_web/controllers/user_take_list_controller.ex:37: InformAPIWeb.User_take_listController.index/2
(inform_api) lib/inform_api_web/controllers/user_take_list_controller.ex:1: InformAPIWeb.User_take_listController.action/2
(inform_api) lib/inform_api_web/controllers/user_take_list_controller.ex:1: InformAPIWeb.User_take_listController.phoenix_controller_pipeline/2
(inform_api) lib/inform_api_web/endpoint.ex:1: InformAPIWeb.Endpoint.instrument/4
(phoenix) lib/phoenix/router.ex:278: Phoenix.Router.__call__/1
(inform_api) lib/inform_api_web/endpoint.ex:1: InformAPIWeb.Endpoint.plug_builder_call/2
(inform_api) lib/plug/debugger.ex:122: InformAPIWeb.Endpoint."call (overridable 3)"/2
(inform_api) lib/inform_api_web/endpoint.ex:1: InformAPIWeb.Endpoint.call/2
(plug) lib/plug/adapters/cowboy/handler.ex:16: Plug.Adapters.Cowboy.Handler.upgrade/4
(cowboy) c:/Users/dbradley/Projects/inform-api/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4
答案 0 :(得分:1)
根据decoratex的文档,Decoratex.decorate/1
接受一个项目,而不是一个列表。
更改
Repo.all(query) |> Decoratex.decorate
到
Repo.all(query) |> Enum.map(&Decoratex.decorate/1)
应该工作。