Last active
January 6, 2017 06:38
-
-
Save nimish-mehta/daa78539e5b00914739a335ab5648807 to your computer and use it in GitHub Desktop.
Alias elixir ecto columns from db columns, by using a separate virtual field per column for reading and writing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Define a macro to alias columns and collect them | |
defmodule ColumnAlias do | |
defmacro __using__(_) do | |
quote do | |
Module.register_attribute(__MODULE__, :column_aliases, accumulate: true) | |
import ColumnAlias, only: [alias_field: 3] | |
@before_compile ColumnAlias | |
end | |
end | |
defmacro alias_field(name, type, options) do | |
alias_name = Keyword.get(options, :alias_as) | |
passable_options = Keyword.delete(options, :alias_as) | |
quote do | |
field unquote(name), unquote(type), unquote(passable_options) | |
field unquote(alias_name), unquote(type), virtual: true | |
@column_aliases {unquote(alias_name), unquote(name)} | |
end | |
end | |
defmacro __before_compile__(_) do | |
quote do | |
def copy_from_aliases(%__MODULE__{} = og_struct, overwrite \\ true) do | |
Enum.reduce(@column_aliases, og_struct, fn ({alias_name, original_name}, acc) -> | |
value_to_copy = Map.get(acc, alias_name) | |
if overwrite || is_nil(Map.get(acc, original_name)) do | |
Map.put(acc, original_name, value_to_copy) | |
else | |
acc | |
end | |
end) | |
end | |
def copy_to_aliases(%__MODULE__{} = og_struct, overwrite \\ true) do | |
Enum.reduce(@column_aliases, og_struct, fn ({alias_name, original_name}, acc) -> | |
value_to_copy = Map.get(acc, original_name) | |
if overwrite || is_nil(Map.get(acc, alias_name)) do | |
Map.put(acc, alias_name, value_to_copy) | |
else | |
acc | |
end | |
end) | |
end | |
def __aliases__ do | |
@column_aliases | |
end | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bb = %PhoenixBlog.Post{aliased_name: 'name', aliased_body: 'body', body: 'real_body'} | |
%PhoenixBlog.Post{__meta__: #Ecto.Schema.Metadata<:built, "posts">, | |
aliased_body: 'body', aliased_name: 'name', body: 'real_body', id: nil, | |
inserted_at: nil, name: nil, updated_at: nil, | |
user: #Ecto.Association.NotLoaded<association :user is not loaded>, | |
user_id: nil} | |
IO.inspect bb.body | |
'real_body' | |
# Copy without overwriting | |
bb = PhoenixBlog.Post.copy_from_aliases bb, false | |
%PhoenixBlog.Post{__meta__: #Ecto.Schema.Metadata<:built, "posts">, | |
aliased_body: 'body', aliased_name: 'name', body: 'real_body', id: nil, | |
inserted_at: nil, name: 'name', updated_at: nil, | |
user: #Ecto.Association.NotLoaded<association :user is not loaded>, | |
user_id: nil} | |
IO.inspect bb.body | |
'real_body' | |
bb = PhoenixBlog.Post.copy_from_aliases bb | |
# Copy with overwriting default option | |
%PhoenixBlog.Post{__meta__: #Ecto.Schema.Metadata<:built, "posts">, | |
aliased_body: 'body', aliased_name: 'name', body: 'body', id: nil, | |
inserted_at: nil, name: 'name', updated_at: nil, | |
user: #Ecto.Association.NotLoaded<association :user is not loaded>, | |
user_id: nil} | |
bb.body | |
'body' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule PhoenixBlog.Post do | |
use PhoenixBlog.Web, :model | |
use ColumnAlias | |
schema "posts" do | |
alias_field :name, :string, alias_as: :aliased_name | |
alias_field :body, :string, alias_as: :aliased_body | |
belongs_to :user, PhoenixBlog.User | |
timestamps() | |
end | |
@doc """ | |
Builds a changeset based on the `struct` and `params`. | |
""" | |
def changeset(struct, params \\ %{}) do | |
struct | |
|> cast(params, [:name, :body]) | |
|> validate_required([:name, :body]) | |
end | |
end |
johnnyshields
commented
Jan 6, 2017
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment