Current section
Files
Jump to
Current section
Files
lib/transla_table.ex
defmodule TranslaTable do
@moduledoc """
`TranslaTable` is a helper library for creating a translation schema inside your ecto schema.
## Translation
Inside your `config.exs` add your locale config
config :transla_table, :config, locale_schema: MyApp.Locale
To define a translation schema it just need to use the `TranslaTable` helper inside your schema to be translated
defmodule MyApp.Post do
use Ecto.Schema
use TranslaTable.Schema,
translation_schema: MyApp.PostTranslation
import Ecto.Changeset
alias MyApp.PostTranslation
schema "post" do
field :title, :string
field :description, :string
field :author, :string
field :slug, :string
has_many_translations()
timestamps()
end
@doc false
def changeset(post, attrs) do
post
|> cast(attrs, [:title, :description, :author, :slug])
|> cast_translation()
end
end
Then create the translation module
defmodule MyApp.PostTranslation
use TranslaTable,
schema: MyApp.Post,
fields: [:title, :description, :slug]
end
Then the TranslaTable Macro will create a schema with the given fields and make the relation with your `Locale` schema.
"""
defmacro __using__(opts) do
prepare =
quote bind_quoted: [opts: opts] do
{{schema, pk_type}, table, fields, {locale_schema, pk_lang_type}} =
TranslaTable.Schema.Ecto.compile_args(opts)
@schema schema
@pk_type pk_type
@table table
@fields fields
@locale_schema locale_schema
@pk_lang_type pk_lang_type
@table_foreign_id (Atom.to_string(@table) <> "_id") |> String.to_existing_atom()
def __trans_schema__(:fields), do: @fields |> Enum.map(fn {field, _type} -> field end)
def __trans_schema__(:table), do: @table
def __trans_schema__(:table_foreign_id), do: @table_foreign_id
end
contents =
quote do
use Ecto.Schema
import Ecto.Changeset
@primary_key {:id, @pk_type, autogenerate: true}
@foreign_key_type @pk_type
schema "#{@table}_translation" do
belongs_to @table, @schema
belongs_to :locale, @locale_schema, type: @pk_lang_type
Enum.each(@fields, fn {f, t} ->
field f, t
end)
timestamps()
end
@foreign_keys ~w"#{@table}_id locale_id"a
@doc false
def changeset(translation, attrs) do
translation
|> cast(
attrs,
Enum.map(@fields, fn {f, _t} -> f end) ++ @foreign_keys
)
|> unique_constraint(@foreign_keys)
end
end
quote do
unquote(prepare)
unquote(contents)
end
end
end