@@ -279,6 +279,53 @@ defmodule Ecto.Enum do
279279 |> Keyword . values ( )
280280 end
281281
282+ @ doc """
283+ Casts a value from the given `schema` and `field`.
284+
285+ ## Examples
286+
287+ Assuming this schema:
288+
289+ defmodule MySchema do
290+ use Ecto.Schema
291+
292+ schema "my_schema" do
293+ field :my_string_enum, Ecto.Enum, values: [:foo, :bar, :baz]
294+ field :my_integer_enum, Ecto.Enum, values: [foo: 1, bar: 2, baz: 5]
295+ end
296+ end
297+
298+ Then:
299+
300+ Ecto.Enum.cast_value(MySchema, :my_string_enum, "foo")
301+ #=> {:ok, :foo}
302+
303+ Ecto.Enum.cast_value(MySchema, :my_string_enum, :foo)
304+ #=> {:ok, :foo}
305+
306+ Ecto.Enum.cast_value(MySchema, :my_string_enum, "qux")
307+ #=> :error
308+
309+ Ecto.Enum.cast_value(MySchema, :my_integer_enum, 1)
310+ #=> {:ok, :foo}
311+
312+ Ecto.Enum.cast_value(MySchema, :my_integer_enum, :foo)
313+ #=> {:ok, :foo}
314+
315+ Ecto.Enum.cast_value(MySchema, :my_integer_enum, 6)
316+ #=> :error
317+
318+ `schema_or_types` can also be a types map. See `mappings/2` for more information.
319+ """
320+ @ spec cast_value ( module | map , atom , binary | atom | integer ) :: { :ok , atom } | :error
321+ def cast_value ( schema_or_types , field , value ) do
322+ params = get_params ( schema_or_types , field )
323+ case cast ( value , params ) do
324+ { :ok , casted_value } -> { :ok , casted_value }
325+ { :error , _reason } -> :error
326+ end
327+ end
328+
282329 @ doc """
283330 Returns the mappings between values and dumped values.
284331
@@ -317,25 +364,30 @@ defmodule Ecto.Enum do
317364
318365 """
319366 @ spec mappings ( module | map , atom ) :: keyword ( String . t ( ) | integer ( ) )
320- def mappings ( schema_or_types , field )
321-
322- def mappings ( types , field ) when is_map ( types ) do
323- case types do
324- % { ^ field => { :parameterized , { Ecto.Enum , % { mappings: mappings } } } } -> mappings
325- % { ^ field => { _ , { :parameterized , { Ecto.Enum , % { mappings: mappings } } } } } -> mappings
326- % { ^ field => _ } -> raise ArgumentError , "#{ field } is not an Ecto.Enum field"
327- % { } -> raise ArgumentError , "#{ field } does not exist"
328- end
367+ def mappings ( schema_or_types , field ) do
368+ get_params ( schema_or_types , field )
369+ |> Map . fetch! ( :mappings )
329370 end
330371
331- def mappings ( schema , field ) when is_atom ( schema ) do
372+ defp get_params ( schema_or_types , field )
373+
374+ defp get_params ( schema , field ) when is_atom ( schema ) do
332375 try do
333376 schema . __changeset__ ( )
334377 rescue
335378 _ in UndefinedFunctionError ->
336379 raise ArgumentError , "#{ inspect ( schema ) } is not an Ecto schema or types map"
337380 else
338- % { } = types -> mappings ( types , field )
381+ % { } = types -> get_params ( types , field )
382+ end
383+ end
384+
385+ defp get_params ( types , field ) when is_map ( types ) do
386+ case types do
387+ % { ^ field => { :parameterized , { Ecto.Enum , params } } } -> params
388+ % { ^ field => { _ , { :parameterized , { Ecto.Enum , params } } } } -> params
389+ % { ^ field => _ } -> raise ArgumentError , "#{ field } is not an Ecto.Enum field"
390+ % { } -> raise ArgumentError , "#{ field } does not exist"
339391 end
340392 end
341393end
0 commit comments