vt-elixir / ja_serializer

JSONAPI.org Serialization in Elixir.
Other
641 stars 148 forks source link

cannot use relationship named `location` #327

Open btkostner opened 5 years ago

btkostner commented 5 years ago

Having a view like so (minified):

defmodule HalWeb.V2.Inventory.MovementView do
  use HalWeb, :v2_view

  has_one :location,
    serializer: LocationView,
    link: :location_link

  def location_link(movement, conn),
    do: inventory_location_path(conn, :show, movement.location_id)
end

results in an error during compile:

== Compilation error in file lib/hal_web/views/v2/inventory/movement.ex ==
** (ArgumentError) cannot set attribute @location inside function/macro
    (elixir) lib/kernel.ex:2842: Kernel.do_at/5
    (elixir) expanding macro: Kernel.@/1
    lib/hal_web/views/v2/inventory/movement.ex:12: HalWeb.V2.Inventory.MovementView.location/2
    expanding macro: JaSerializer.DSL.location/1
    lib/hal_web/views/v2/inventory/movement.ex:12: HalWeb.V2.Inventory.MovementView.location/2

This was not a problem in 0.13.0, but is in 0.15.0.

OTP: 22 Elixir: 1.8.2

beerlington commented 5 years ago

Unfortunately with the DSL there are some reserved keywords that cause weird behavior when they are used. In this case it's an unhelpful compilation error. I've been adding more useful compiler errors as they come up and will add one for this case. The only workaround that I know of is to use the relationship/2 callback directly.

If it's just the one relationship, you should be able to replace has_one with the following (untested but something close to this):

def relationships(movement, conn) do
  %{
    location: %HasOne{
      serializer:  LocationView,
      links: [
        related: location_link(movement, conn)
      ],
      data: movement.location
    }
  }
end

def location_link(movement, conn),
  do: inventory_location_path(conn, :show, movement.location_id)