Skip to content

Instantly share code, notes, and snippets.

@ssnickolay
Last active September 10, 2017 12:58
Show Gist options
  • Save ssnickolay/27488186d4544445ae4e47f20047e29a to your computer and use it in GitHub Desktop.
Save ssnickolay/27488186d4544445ae4e47f20047e29a to your computer and use it in GitHub Desktop.
Ecto form object example
defmodule InventoryCore.ProductForm do
  import Ecto.Changeset
  use Ecto.Schema

  alias InventoryCore.Product
  alias InventoryCore.SpreeProduct
  alias InventoryCore.EbayProduct

  embedded_schema do
    field :title, :string
    field :description, :string
    field :price, :decimal

    field :spree_taxon_ids, {:array, :integer}
    field :spree_properties, {:array, :map}
    field :ebay_category_id, :integer
    field :ebay_secondary_category_id, :integer
    field :ebay_sub_title, :string
    field :ebay_specifics, {:array, :map}
  end

  @fields ~w(title description price spree_taxon_ids spree_properties ebay_category_id ebay_secondary_category_id ebay_sub_title ebay_specifics)a
  @required_fields ~w(title description price spree_taxon_ids ebay_category_id)a
  @max_title_length 80
  @max_ebay_sub_title_length 55

  def build(product, params) do
    InventoryCore.ProductForm
      |> struct(product |> serialize)
      |> cast(params, @fields)
      |> validate_required(@required_fields)
      |> validate_length(:title, max: @max_title_length)
      |> validate_length(:ebay_sub_title, max: @max_ebay_sub_title_length)
  end

  def serialize(%Product{ebay_product: %EbayProduct{}, spree_product: %SpreeProduct{}} = product) do
    %{
      id: product.id,
      title: product.title,
      description: product.description,
      price: product.price,
      spree_taxon_ids: product.spree_product.taxon_ids,
      spree_properties: product.spree_product.properties,
      ebay_category_id: product.ebay_product.category_id,
      ebay_secondary_category_id: product.ebay_product.secondary_category_id,
      ebay_sub_title: product.ebay_product.sub_title,
      ebay_specifics: product.ebay_product.specifics
    }
  end

  def serialize(_), do: %{}

  def attributes(form) do
    form.data
      |> Map.drop([:__struct__])
      |> Map.merge(form.changes)
  end
end

Usage (CRU[D]):

  1. New:
form = ProductForm.build(%Product{spree_product: %SpreeProduct{}, , ebay_product: %EbayProduct{})
  1. Edit:
product =
  Product
  |> Repo.get(id)
  |> Repo.preload(:ebay_product)
  |> Repo.preload(:spree_product)
form = ProductForm.build(product, %{})
  1. Create\Update:
form = ProductForm.build(product, product_params) # product_params - params from request
form.valid? # true\false
attributes = ProductForm.attributes(form)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment