ecto_enum, 在模型中,支持枚举的Ecto扩展

分享于 

6分钟阅读

GitHub

  繁體 雙語
Ecto extension to support enums in models
  • 源代码名称:ecto_enum
  • 源代码网址:http://www.github.com/gjaldon/ecto_enum
  • ecto_enum源代码文档
  • ecto_enum源代码下载
  • Git URL:
    git://www.github.com/gjaldon/ecto_enum.git
    Git Clone代码到本地:
    git clone http://www.github.com/gjaldon/ecto_enum
    Subversion代码到本地:
    $ svn co --depth empty http://www.github.com/gjaldon/ecto_enum
    Checked out revision 1.
    $ cd repo
    $ svn up trunk
    
    EctoEnum

    Hex.pm versionHex.pm downloadsInline docsBuild Status

    EctoEnum是一个Ecto扩展,用于支持Ecto模型中的枚举。

    用法

    首先,我们将 ecto_enum 添加到 mix.exs:

    defdepsdo [{:ecto_enum, "~> 1.0"}]end

    运行 mix deps.get 以安装 ecto_enum

    然后我们必须定义我们的enum。 我们可以在单独的文件中做到这一点,因为定义一个 enum 只是定义一个 MODULE。 我们这样做:

    # lib/my_app/ecto_enums.eximportEctoEnumdefenum StatusEnum, registered:0, active:1, inactive:2, archived:3

    定义之后,EctoEnum 可以像其他 Ecto.Type 一样通过将它传递到模型块的模式中的字段来使用。 例如:

    defmoduleUserdouseEcto.Schema schema "users"do field :status, StatusEnumendend

    在上述示例中,:status 将像 enum 一样运行,允许你将 integeratom 或者 string 传递给它。 这用于保存模型。调用 Ecto.Changeset.cast/4 或者在状态字段中执行查询。 让我们来做几个例子:

    iex> user =Repo.insert!(%User{status:0})
    iex>Repo.get(User, user.id).status:registerediex> %{changes: changes} = cast(%User{}, %{"status"=>"active"}, ~w(status), [])
    iex> changes.status:activeiex> from(u inUser, where: u.status == ^:registered) |>Repo.all() |> length1

    传递自定义 enum 类型无法识别的值将导致错误。

    反射

    enum 类型 StatusEnum 还将有一个反射函数,用于在运行时检查 enum 映射。

    iex>StatusEnum.__enum_map__()
    [registered:0, active:1, inactive:2, archived:3]
    iex>StatusEnum.__valid_values__()
    [0, 1, 2, 3, :registered, :active, :inactive, :archived, "active", "archived","inactive", "registered"]

    还有一个 helper 函数,它利用了称为 valid_value?(value)__valid_values__() 反射。

    iex>StatusEnum.valid_value?(:registered)trueiex>StatusEnum.valid_value?("invalid")false

    使用postgres类型的enum

    枚举 Postgres 中的类型现在支持。 要使用EctoEnum类型的enum,请使用 defenum/3 宏,而不要使用 defenum/2。 我们这样做:

    # lib/my_app/ecto_enums.eximportEctoEnumdefenum StatusEnum, :status, [:registered, :active, :inactive, :archived]

    第二个参数是你要在Postgres中创建的新类型所使用的NAME。 注意 defenum/3 需要的是( 可能是字符串)的列表而不是在 defenum/2 中的关键字列表。 另一个显著区别是,你不能再使用整数代替原子或者字符串作为 enum 类型中的值。 给出上代码意味着你只能传递以下值:

    [:registered, :active, :inactive, :archived, "registered", "active", "inactive", "archived"]

    在迁移中,你可以使用 helper 函数,例如:

    defupdoStatusEnum.create_type
     create table(:users_pg) do add :status, :statusendenddefdowndo drop table(:users_pg)
     StatusEnum.drop_typeend

    create_type/0drop_type/0 在自定义 enum 模块中自动为你定义。

    重要的注释/技巧

    Postgres

    • 请记住 ALTER TYPE.. . ADD VALUE 无法在事务块内执行。 这意味着在迁移内部运行这个命令要求你将 MODULE 属性 @disable_ddl_transaction 设置为 true。 例如:
    defmoduleMyApp.Repo.Migrations.AddToGenderEnumdouseEcto.Migration@disable_ddl_transactiontruedefupdoEcto.Migration.execute "ALTER TYPE gender ADD VALUE 'other'"enddefdowndoendend
    • 请注意,没有简单的方法除去 enum 值。 它不受支持,你必须创建一个没有值的新类型。 这里是一些工作。 最好避免删除 enum 值。

    重要链接


    ext  SUP  模式  enum  ecto  枚举  
    相关文章