Как тестировать модели с необходимыми ассоциациями

Использование Экто 2.0:

defmodule PlexServer.BoardInstanceTest do
  use PlexServer.ModelCase

  alias PlexServer.BoardInstance

  @valid_attrs %{board_pieces: [%PlexServer.BoardTileInstance{x: 0, y: 0}], empire: %PlexServer.EmpireInstance{}}
  @invalid_attrs %{}

  test "changeset with valid attributes" do
    changeset = BoardInstance.changeset(%BoardInstance{}, @valid_attrs)
    assert changeset.valid?
  end
end

defmodule PlexServer.BoardInstance do
  use PlexServer.Web, :model

  alias PlexServer.BoardTileInstance

  schema "board_instances" do  
    belongs_to :empire, PlexServer.EmpireInstance
    has_many :board_pieces, BoardTileInstance

    timestamps
  end

  @required_fields ~w()
  @optional_fields ~w()

  def changeset(model, params \\ :empty) do
    model
      |> cast(params, @required_fields, @optional_fields)
      |> cast_assoc(:board_pieces, required: true)
      |> cast_assoc(:empire, require: true)
  end
end

Мой тест не работает с

** (RuntimeError) кастинг ассоциаций с cast/3 не поддерживается, вместо этого используйте cast_assoc/3

Глядя на документацию, говорится, что cast_assoc/3 нужно вызывать после cast/3, поэтому я почти уверен, что мне не хватает чего-то важного, чтобы этот тест работал.

Изменить: обновил мой код и теперь получаю новую ошибку:

** (Ecto.CastError) ожидаемые параметры будут картой, получили: %PlexServer.BoardTileInstance{__meta__: #Ecto.Schema.Metadata<:built>, fleets: #Ecto.Association.NotLoaded<association :fleets is not loaded>, id: nil, inserted_at: nil, system: #Ecto.Association.NotLoaded<association :system is not loaded>, updated_at: nil, x: 0, y: 0}

Я предполагаю, что мои @valid_attrs каким-то образом искажены?


person Alejandro Huerta    schedule 22.06.2016    source источник
comment
Попробуйте удалить empire и board_pieces из @required_fields и добавить cast_assoc вместо :empire с required: true.   -  person Dogbert    schedule 22.06.2016
comment
Я внес предложенные вами изменения, @Dogbert, но, к сожалению, у меня все еще есть проблемы.   -  person Alejandro Huerta    schedule 22.06.2016
comment
Вы получаете ту же ошибку после внесения этих двух изменений?   -  person Dogbert    schedule 22.06.2016
comment
Попробуйте это: @valid_attrs %{board_pieces: [%{x: 0, y: 0}], empire: %{}}.   -  person Dogbert    schedule 22.06.2016
comment
@ Догберт, это сработало! Спасибо большое. Если вы хотите создать ответ, я приму его. Я предполагаю, что cast_assoc просто не ожидает передачи Ecto.Schema?   -  person Alejandro Huerta    schedule 22.06.2016


Ответы (1)


  1. Вам не нужно передавать имена ассоциаций в cast или validate_required. Вы должны удалить его из @required_fields. cast_assoc будет обрабатывать преобразование этих полей в структуры и, если вы передадите required: true, подтвердит их наличие. (Для тех, кто не читал комментарии выше, см. контекст в редакции 1 вопроса.)

  2. @valid_attrs должна быть обычной картой, такой же, как params в функциях контроллера Phoenix. cast_assoc будет обрабатывать преобразование необработанной карты в структуру. Итак, измените

    @valid_attrs %{board_pieces: [%PlexServer.BoardTileInstance{x: 0, y: 0}], empire: %PlexServer.EmpireInstance{}}
    

    to

    @valid_attrs %{board_pieces: [%{x: 0, y: 0}], empire: %{}}
    
person Dogbert    schedule 22.06.2016