Cálculo do valor dos campos virtuais com DecorateX

votos
0

Eu estou tentando usar o Decoratex biblioteca para preencher alguns campos virtuais no meu modelo de usuário, mas eu sou incapaz de evitar o seguinte erro:

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

Como exemplo, eu estou tentando adicionar um valor de chave user_age ao modelo de estrutura. O modelo é:

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

A função calculate_user_age está atualmente configurado para apenas retornar um resultado:

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

E o Decoratex.decorate exigido é chamado a função Índice de meu controlador:

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

Eu sou muito novo para Elixir e eu não posso caçar a natureza desse erro. Se eu inspecionar o struct eu posso ver um campo user_age com um valor nulo, mas eu não sei se o problema é causado por minha própria função auxiliar ou pela maneira que eu estou usando DecorateX.decorate.

Conforme solicitado nos comentários, o erro completo com stacktrace:

[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
Publicado 19/09/2018 em 13:21
fonte usuário
Em outras línguas...                            


1 respostas

votos
1

De acordo com a documentação de decoratex, Decoratex.decorate/1aceita um único item, não uma lista.

Alterar

Repo.all(query) |> Decoratex.decorate

para

Repo.all(query) |> Enum.map(&Decoratex.decorate/1)

Deveria trabalhar.

Respondeu 19/09/2018 em 13:50
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more