Skip to content

Instantly share code, notes, and snippets.

@radzserg
Created September 26, 2016 15:27
Show Gist options
  • Save radzserg/de3b1bd49e57874df935d66eab9dfe25 to your computer and use it in GitHub Desktop.
Save radzserg/de3b1bd49e57874df935d66eab9dfe25 to your computer and use it in GitHub Desktop.
defmodule App.Image do
use App.Web, :model
alias App.Image
alias App.Repo
schema "images" do
field :type, :string
field :path, :string
field :mime, :string
field :size, :integer
field :width, :integer
field :height, :integer
belongs_to :parent, App.Parent
timestamps()
end
@doc """
Builds a changeset based on the `struct` and `params`.
"""
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:type, :path, :mime, :size, :width, :height])
|> validate_required([:type, :path, :mime, :size])
end
@doc """
Creates image from provided URL
"""
def create_from_url(url, type) do
%HTTPoison.Response{body: body, headers: headers} = HTTPoison.get!(url)
mime = fetch_header_value(headers, "Content-Type")
size = fetch_header_value(headers, "Content-Length")
path = build_path(url, type)
changeset = Image.changeset(%Image{}, %{path: path, mime: mime,
size: size, type: type})
if changeset.valid? do
upload_manager = App.Pact.get("upload_manager")
case upload_manager.save!(body, path, %{content_type: mime}) do
:ok ->
case Repo.insert(changeset) do
{:ok, image} -> {:ok, image}
{:error, changeset} -> {:error, changeset}
end
{:error, reason} -> {:error, reason}
end
else
{:error, changeset}
end
end
def url(image) do
upload_manager = App.Pact.get("upload_manager")
upload_manager.url(image.path)
end
_ = """
Build path based on image type and base name
"""
defp build_path(image_url, type) do
uri = URI.parse(image_url)
basename = Path.basename(uri.path)
hash = random_string(32)
path = "#{type}/#{hash}/#{basename}"
path
end
_ = """
Generates uniq string to build uniq path
"""
defp random_string(length) do
:crypto.strong_rand_bytes(length) |> Base.url_encode64 |> binary_part(0, length)
end
_ = """
Fetch header from headers received with HTTPoison
"""
defp fetch_header_value(headers, needed_header) do
needed_header = String.downcase(needed_header)
header = Enum.find(headers, fn(header) ->
{header, _value} = header
String.downcase(header) == needed_header
end)
if header do
{header, value} = header
value
else
nil
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment