Add convenience to store images
This commit is contained in:
@@ -2,9 +2,22 @@ defmodule MusicLibrary.Assets do
|
|||||||
alias MusicLibrary.Assets.Asset
|
alias MusicLibrary.Assets.Asset
|
||||||
alias MusicLibrary.Repo
|
alias MusicLibrary.Repo
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Store any file type - the responsibility to correctly populate format and
|
||||||
|
properties is left to the caller.
|
||||||
|
"""
|
||||||
def store(params) do
|
def store(params) do
|
||||||
%Asset{}
|
%Asset{}
|
||||||
|> Asset.changeset(params)
|
|> Asset.changeset(params)
|
||||||
|> Repo.insert()
|
|> Repo.insert()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Store image files - properties will be computed automatically.
|
||||||
|
"""
|
||||||
|
def store_image(params) do
|
||||||
|
%Asset{}
|
||||||
|
|> Asset.image_changeset(params)
|
||||||
|
|> Repo.insert()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ defmodule MusicLibrary.Assets.Asset do
|
|||||||
|
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
|
|
||||||
|
alias Vix.Vips.Image
|
||||||
|
|
||||||
@primary_key {:hash, :string, autogenerate: false}
|
@primary_key {:hash, :string, autogenerate: false}
|
||||||
schema "assets" do
|
schema "assets" do
|
||||||
field :content, :binary
|
field :content, :binary
|
||||||
@@ -20,6 +22,15 @@ defmodule MusicLibrary.Assets.Asset do
|
|||||||
|> unique_constraint(:hash)
|
|> unique_constraint(:hash)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def image_changeset(asset, attrs) do
|
||||||
|
asset
|
||||||
|
|> cast(attrs, [:content, :format])
|
||||||
|
|> validate_required([:content, :format])
|
||||||
|
|> generate_hash()
|
||||||
|
|> generate_properties()
|
||||||
|
|> unique_constraint(:hash)
|
||||||
|
end
|
||||||
|
|
||||||
defp generate_hash(changeset) do
|
defp generate_hash(changeset) do
|
||||||
case get_change(changeset, :content) do
|
case get_change(changeset, :content) do
|
||||||
nil ->
|
nil ->
|
||||||
@@ -30,6 +41,25 @@ defmodule MusicLibrary.Assets.Asset do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp generate_properties(changeset) do
|
||||||
|
case get_change(changeset, :content) do
|
||||||
|
nil ->
|
||||||
|
changeset
|
||||||
|
|
||||||
|
content ->
|
||||||
|
put_change(changeset, :properties, get_image_properties(content))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp get_image_properties(content) do
|
||||||
|
{:ok, image} = Image.new_from_buffer(content)
|
||||||
|
|
||||||
|
%{
|
||||||
|
"width" => Image.width(image),
|
||||||
|
"height" => Image.height(image)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
defp hash(content) do
|
defp hash(content) do
|
||||||
:crypto.hash(:sha256, content) |> Base.encode16()
|
:crypto.hash(:sha256, content) |> Base.encode16()
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ defmodule MusicLibrary.AssetsTest do
|
|||||||
use MusicLibrary.DataCase
|
use MusicLibrary.DataCase
|
||||||
|
|
||||||
alias MusicLibrary.Assets
|
alias MusicLibrary.Assets
|
||||||
|
alias MusicLibrary.Fixtures
|
||||||
|
|
||||||
describe "store/1" do
|
describe "store/1" do
|
||||||
test "stores using the hash as key" do
|
test "stores using the hash as key" do
|
||||||
@@ -31,4 +32,19 @@ defmodule MusicLibrary.AssetsTest do
|
|||||||
assert [hash: {"has already been taken", _}] = changeset.errors
|
assert [hash: {"has already been taken", _}] = changeset.errors
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "store_image/1" do
|
||||||
|
test "computes properties automatically" do
|
||||||
|
params = %{
|
||||||
|
content: Fixtures.Records.marbles_cover_data(),
|
||||||
|
format: "image/jpeg"
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, asset} = Assets.store_image(params)
|
||||||
|
assert asset.hash == "599407DDF69907D4A60FE13CCAA824D25CF08DC124FD6AA3E8E7ECD98C885FFE"
|
||||||
|
assert asset.properties == %{"width" => 400, "height" => 396}
|
||||||
|
assert asset.content == Fixtures.Records.marbles_cover_data()
|
||||||
|
assert asset.format == "image/jpeg"
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user