IvanRublev / Domo

A library to validate values of nested structs with their type spec t() and associated precondition functions

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Runtime checks are not executed in development

darioghilardi opened this issue · comments

Environment

  • Elixir version: 1.13.4
  • Domo version: 1.5.3
  • TypedStruct version: 0.3.0

Actual behavior

First of all: thanks a lot for this great library.

Here is the issue: I defined a module like this:

defmodule DomoTest.Schema do
  use Domo
  use TypedStruct

  typedstruct enforce: true do
    field(:one, String.t())
    field(:two, boolean())
    field(:three, integer())
  end
end

When running iex -S mix the library works as expected:

iex> DomoTest.Schema.new(%{one: "aaa", two: 23, three: false})  
{:error,
 [
   two: "Invalid value 23 for field :two of %DomoTest.Schema{}. Expected the value matching the false | true type.",
   three: "Invalid value false for field :three of %DomoTest.Schema{}. Expected the value matching the integer() type."
 ]}

But when running the phoenix server in development mode the library doesn't work as expected:

DomoTest.Schema.new(%{one: "aaa", two: 23, three: false})  
{:ok, %DomoTest.Schema{one: "aaa", three: false, two: 23}}

I created a minimal repository to replicate the issue. The creation of the struct happens in page_controller.ex.

Note however that if I start the phoenix app with MIX_ENV=prod domo starts to do its job and for the exact same code returns:

{:error,
 [
   two: "Invalid value 23 for field :two of %DomoTest.Schema{}. Expected the value matching the false | true type.",
   three: "Invalid value false for field :three of %DomoTest.Schema{}. Expected the value matching the integer() type."
 ]}

Expected behavior

I expect a consistent behavior, with runtime checks executed in development.

Thank you.

From a quick debugging session it seems that Phoenix's CodeReloader triggers Mix.Tasks.Compile.DomoCompiler.run every time, but the code paths never end up calling Mix.Tasks.Compile.DomoCompiler.stop_plan_collection, thus causing the generated .new/.new! functions to always skip validation.

Thanks!

Thank you! 👍

Hey,
@darioghilardi thanks for raising the issue, and thanks @razielgn for the diagnostics.
Yes, the stop_plan_collection function was never called because elixirs :after_compile hook is not executed because Phoenix runs compilers one by one with Mix.Task.run("compile.xxx") instead of compile.all. That's by Phoenix design.

As for the solution, you can upgrade to Domo version 1.5.4 with :domo_phoenix_hot_reload compile task included, which you can put after :elixir to the compilers list in the mix.exs file and to the reloadable_compilers list in the config file. As the following:

# in mix.exs
compilers: [:domo_compiler] ++ Mix.compilers() ++ [:domo_phoenix_hot_reload]

# in dev.exs
config :my_app, MyApp.Endpoint,
  reloadable_compilers: [:phoenix, :domo_compiler] ++ Mix.compilers() ++ [:domo_phoenix_hot_reload]

This brings fast prototyping with Phoenix and Domo back on track 🤘