Skip to content

(option to) Use Kernel.struct!/2 to be stricter about making structs #22

@dylan-chong

Description

@dylan-chong

Kernel.struct!/2 is stricter (see docs), which will prevent the ignorance of @enforce_keys and prevent invalid struct keys being passed.

If you want some code to do the two checks independently, you could add something like this:

  use ExConstructor, check_enforce_keys: true, check_no_invalid_args: true

  ...

  # pass @enforce_keys as 2nd param
  def check_enforce_keys(args, enforce_keys) do
    arg_keys =
      args
      |> Map.new
      |> Map.keys
      |> MapSet.new
    required_keys = enforce_keys |> MapSet.new

    if not MapSet.subset?(required_keys, arg_keys) do
      raise(
        ArgumentError,
        "Requires keys #{required_keys |> Enum.to_list |> inspect} "
        <> "but only #{arg_keys |> Enum.to_list |> inspect} "
        <> "were given"
      )
    end
  end

  def check_no_invalid_args(args, module) do
    arg_keys =
      args
      |> Map.new
      |> Map.keys
      |> MapSet.new
    valid_keys =
      module
      |> struct([])
      |> Map.from_struct
      |> Map.keys
      |> MapSet.new

    if not MapSet.subset?(arg_keys, valid_keys) do
      raise(
        KeyError,
        "Allowed keys are #{valid_keys |> Enum.to_list |> inspect} "
        <> "but #{arg_keys |> Enum.to_list |> inspect} "
        <> "were given"
      )
    end
  end

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions