Reject unknown struct keys with struct!/2

almirsarajcic

almirsarajcic

23 minutes ago

0 comments

Use struct!/2 when runtime attributes must contain only fields that belong to the struct.

defmodule Profile do
  @enforce_keys [:name]
  defstruct [:name, role: :member]
end

attrs = [name: "Ada", roel: :admin]

struct(Profile, attrs)
# => %Profile{name: "Ada", role: :member}

struct!(Profile, attrs)
# ** (KeyError) key :roel not found

struct/2 silently ignores keys the struct does not know. That can be useful when deliberately taking a compatible subset, but it can also turn a typo such as :roel into a successful-looking value that kept the default :role.

struct!/2 emulates struct literal checks at runtime. It rejects unknown fields, and when its first argument is a module, it also enforces fields declared with @enforce_keys. When its first argument is an existing struct, it validates keys like %Profile{profile | role: :admin} does.

String keys are invalid too. Do not solve that by calling String.to_atom/1 on external input. Convert only an explicit allowlist of accepted fields, then pass the result to struct!/2.

Kernel.struct!/2 docs

Comments (0)

Sign in with GitHub to join the discussion