Add base infra to store assets
This commit is contained in:
@@ -0,0 +1,10 @@
|
|||||||
|
defmodule MusicLibrary.Assets do
|
||||||
|
alias MusicLibrary.Assets.Asset
|
||||||
|
alias MusicLibrary.Repo
|
||||||
|
|
||||||
|
def store(params) do
|
||||||
|
%Asset{}
|
||||||
|
|> Asset.changeset(params)
|
||||||
|
|> Repo.insert()
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
defmodule MusicLibrary.Assets.Asset do
|
||||||
|
use Ecto.Schema
|
||||||
|
|
||||||
|
import Ecto.Changeset
|
||||||
|
|
||||||
|
@primary_key {:hash, :string, autogenerate: false}
|
||||||
|
schema "assets" do
|
||||||
|
field :content, :binary
|
||||||
|
field :format, :string
|
||||||
|
field :properties, :map, default: %{}, read_after_writes: true
|
||||||
|
|
||||||
|
timestamps(type: :utc_datetime)
|
||||||
|
end
|
||||||
|
|
||||||
|
def changeset(asset, attrs) do
|
||||||
|
asset
|
||||||
|
|> cast(attrs, [:content, :format, :properties])
|
||||||
|
|> validate_required([:content, :format])
|
||||||
|
|> generate_hash()
|
||||||
|
|> unique_constraint(:hash)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp generate_hash(changeset) do
|
||||||
|
case get_change(changeset, :content) do
|
||||||
|
nil ->
|
||||||
|
changeset
|
||||||
|
|
||||||
|
content ->
|
||||||
|
put_change(changeset, :hash, hash(content))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp hash(content) do
|
||||||
|
:crypto.hash(:sha256, content) |> Base.encode16()
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
defmodule MusicLibrary.Repo.Migrations.CreateAssets do
|
||||||
|
use Ecto.Migration
|
||||||
|
|
||||||
|
def change do
|
||||||
|
create table(:assets, primary_key: false) do
|
||||||
|
add :hash, :string, primary_key: true
|
||||||
|
add :content, :binary, null: false
|
||||||
|
add :format, :string, null: false
|
||||||
|
add :properties, :map, default: %{}
|
||||||
|
|
||||||
|
timestamps(type: :utc_datetime)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
defmodule MusicLibrary.AssetsTest do
|
||||||
|
use MusicLibrary.DataCase
|
||||||
|
|
||||||
|
alias MusicLibrary.Assets
|
||||||
|
|
||||||
|
describe "store/1" do
|
||||||
|
test "stores using the hash as key" do
|
||||||
|
params = %{
|
||||||
|
content: "some content",
|
||||||
|
format: "text/plain",
|
||||||
|
properties: %{language: "english"}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, asset} = Assets.store(params)
|
||||||
|
assert asset.hash == "290F493C44F5D63D06B374D0A5ABD292FAE38B92CAB2FAE5EFEFE1B0E9347F56"
|
||||||
|
assert asset.properties == %{"language" => "english"}
|
||||||
|
assert asset.content == "some content"
|
||||||
|
assert asset.format == "text/plain"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "prevents duplicates" do
|
||||||
|
params = %{
|
||||||
|
content: "some content",
|
||||||
|
format: "text/plain",
|
||||||
|
properties: %{language: "english"}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert {:ok, _asset} = Assets.store(params)
|
||||||
|
assert {:error, changeset} = Assets.store(params)
|
||||||
|
|
||||||
|
assert [hash: {"has already been taken", _}] = changeset.errors
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user