├── test ├── test_helper.exs └── ecto_atom_test.exs ├── .gitignore ├── lib └── ecto_atom.ex ├── README.md ├── LICENSE ├── mix.lock ├── config └── config.exs └── mix.exs /test/test_helper.exs: -------------------------------------------------------------------------------- 1 | ExUnit.start() 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # The directory Mix will write compiled artifacts to. 2 | /_build 3 | 4 | # If you run "mix test --cover", coverage assets end up here. 5 | /cover 6 | 7 | # The directory Mix downloads your dependencies sources to. 8 | /deps 9 | 10 | # Where 3rd-party dependencies like ExDoc output generated docs. 11 | /doc 12 | 13 | # Ignore .fetch files in case you like to edit your project deps locally. 14 | /.fetch 15 | 16 | # If the VM crashes, it generates a dump, let's ignore it too. 17 | erl_crash.dump 18 | 19 | # Also ignore archive artifacts (built via "mix archive.build"). 20 | *.ez 21 | -------------------------------------------------------------------------------- /lib/ecto_atom.ex: -------------------------------------------------------------------------------- 1 | defmodule Ecto.Atom do 2 | 3 | @moduledoc """ 4 | 5 | Custom Type to support `:atom` 6 | 7 | defmodule Post do 8 | use Ecto.Schema 9 | schema "posts" do 10 | field :atom_field, Ecto.Atom 11 | end 12 | end 13 | """ 14 | 15 | @behaviour Ecto.Type 16 | 17 | def type, do: :string 18 | 19 | def cast(value) when is_atom(value), do: {:ok, value} 20 | def cast(_), do: :error 21 | 22 | def load(value), do: {:ok, String.to_existing_atom(value)} 23 | 24 | def dump(value) when is_atom(value), do: {:ok, Atom.to_string(value)} 25 | def dump(_), do: :error 26 | 27 | end 28 | -------------------------------------------------------------------------------- /test/ecto_atom_test.exs: -------------------------------------------------------------------------------- 1 | defmodule Ecto.AtomTest do 2 | use ExUnit.Case 3 | doctest Ecto.Atom 4 | 5 | test "cast with an atom" do 6 | assert Ecto.Atom.cast(:anatom) == {:ok, :anatom} 7 | end 8 | 9 | test "cast with failure" do 10 | assert Ecto.Atom.cast(1) == :error 11 | end 12 | 13 | test "load from a string" do 14 | assert Ecto.Atom.load("string") == {:ok, :string} 15 | end 16 | 17 | test "can load past dumped data" do 18 | { :ok, dumped_atom } = Ecto.Atom.dump :atom 19 | assert Ecto.Atom.load(dumped_atom) == { :ok, :atom } 20 | end 21 | 22 | test "dump :atom" do 23 | assert Ecto.Atom.dump(:atom) == {:ok, "atom"} 24 | end 25 | 26 | test "dump string" do 27 | assert Ecto.Atom.dump("string") == :error 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ecto.Atom 2 | 3 | Provide an Ecto custom type Ecto.Atom to manage `:atom`. 4 | 5 | ## Installation 6 | 7 | If [available in Hex](https://hex.pm/docs/publish), the package can be installed 8 | by adding `ecto_atom` to your list of dependencies in `mix.exs`: 9 | 10 | ```elixir 11 | def deps do 12 | [{:ecto_atom, "~> 1.0.0"}] 13 | end 14 | ``` 15 | 16 | ## Use 17 | 18 | ```elixir 19 | defmodule MyApp.User do 20 | use MyApp.Web, :model 21 | 22 | @primary_key {:id, :binary_id, autogenerate: true} 23 | @derive {Phoenix.Param, key: :id} 24 | 25 | schema "users" do 26 | field :email, :string 27 | field :provider, Ecto.Atom # :github => 'github' in DB 28 | field :uid, :string 29 | field :token, :string 30 | ... 31 | end 32 | end 33 | ``` 34 | 35 | Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) 36 | and published on [HexDocs](https://hexdocs.pm). Once published, the docs can 37 | be found at [https://hexdocs.pm/ecto_atom](https://hexdocs.pm/ecto_atom). 38 | 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Matthieu Pinte 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /mix.lock: -------------------------------------------------------------------------------- 1 | %{"decimal": {:hex, :decimal, "1.4.0", "fac965ce71a46aab53d3a6ce45662806bdd708a4a95a65cde8a12eb0124a1333", [:mix], [], "hexpm"}, 2 | "earmark": {:hex, :earmark, "1.2.3", "206eb2e2ac1a794aa5256f3982de7a76bf4579ff91cb28d0e17ea2c9491e46a4", [:mix], [], "hexpm"}, 3 | "ecto": {:hex, :ecto, "2.1.4", "d1ba932813ec0e0d9db481ef2c17777f1cefb11fc90fa7c142ff354972dfba7e", [:mix], [{:db_connection, "~> 1.1", [hex: :db_connection, repo: "hexpm", optional: true]}, {:decimal, "~> 1.2", [hex: :decimal, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.8.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: true]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.13.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"}, 4 | "ex_doc": {:hex, :ex_doc, "0.16.2", "3b3e210ebcd85a7c76b4e73f85c5640c011d2a0b2f06dcdf5acdb2ae904e5084", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"}, 5 | "poolboy": {:hex, :poolboy, "1.5.1", "6b46163901cfd0a1b43d692657ed9d7e599853b3b21b95ae5ae0a777cf9b6ca8", [:rebar], [], "hexpm"}} 6 | -------------------------------------------------------------------------------- /config/config.exs: -------------------------------------------------------------------------------- 1 | # This file is responsible for configuring your application 2 | # and its dependencies with the aid of the Mix.Config module. 3 | use Mix.Config 4 | 5 | # This configuration is loaded before any dependency and is restricted 6 | # to this project. If another project depends on this project, this 7 | # file won't be loaded nor affect the parent project. For this reason, 8 | # if you want to provide default values for your application for 9 | # 3rd-party users, it should be done in your "mix.exs" file. 10 | 11 | # You can configure for your application as: 12 | # 13 | # config :ecto_atom, key: :value 14 | # 15 | # And access this configuration in your application as: 16 | # 17 | # Application.get_env(:ecto_atom, :key) 18 | # 19 | # Or configure a 3rd-party app: 20 | # 21 | # config :logger, level: :info 22 | # 23 | 24 | # It is also possible to import configuration files, relative to this 25 | # directory. For example, you can emulate configuration per environment 26 | # by uncommenting the line below and defining dev.exs, test.exs and such. 27 | # Configuration from the imported file will override the ones defined 28 | # here (which is why it is important to import them last). 29 | # 30 | # import_config "#{Mix.env}.exs" 31 | -------------------------------------------------------------------------------- /mix.exs: -------------------------------------------------------------------------------- 1 | defmodule Ecto.Atom.Mixfile do 2 | use Mix.Project 3 | 4 | def project do 5 | [app: :ecto_atom, 6 | version: "1.0.0", 7 | elixir: "~> 1.4", 8 | build_embedded: Mix.env == :prod, 9 | start_permanent: Mix.env == :prod, 10 | description: description(), 11 | package: package(), 12 | deps: deps(), 13 | source_url: "https://github.com/matthieupinte/ecto_atom"] 14 | end 15 | 16 | # Configuration for the OTP application 17 | # 18 | # Type "mix help compile.app" for more information 19 | def application do 20 | # Specify extra applications you'll use from Erlang/Elixir 21 | [extra_applications: [:logger]] 22 | end 23 | 24 | defp description do 25 | """ 26 | Provide an Ecto custom type Ecto.Atom to manage `:atom`. 27 | """ 28 | end 29 | 30 | defp deps do 31 | [{:ecto, "~> 2.1"}, 32 | {:ex_doc, "~> 0.14", only: :dev, runtime: false}] 33 | end 34 | 35 | defp package do 36 | # These are the default files included in the package 37 | [ 38 | name: :ecto_atom, 39 | files: ["lib", "mix.exs", "README*", "LICENSE*"], 40 | maintainers: ["Matthieu Pinte"], 41 | licenses: ["MIT"], 42 | links: %{"GitHub" => "https://github.com/matthieupinte/ecto_atom"} 43 | ] 44 | end 45 | end 46 | --------------------------------------------------------------------------------