Current section

7 Versions

Jump to

Compare versions

6 files changed
+76 additions
-15 deletions
  @@ -1,5 +1,7 @@
1 1 # Honu
2 2
3 + [![Hex.pm](https://img.shields.io/hexpm/v/honu)](https://hex.pm/packages/honu) [![Documentation](https://img.shields.io/badge/documentation-gray)](https://hexdocs.pm/honu/)
4 +
3 5 https://en.wikipedia.org/wiki/Green_sea_turtle#Taxonomy
4 6
5 7 **A WIP file upload and attachment library for Ecto**
  @@ -11,7 +13,7 @@ The package can be installed by adding `honu` to your list of dependencies in `m
11 13 ```elixir
12 14 def deps do
13 15 [
14 - {:honu, "~> 0.1.0"}
16 + {:honu, "~> 0.3.0"}
15 17 ]
16 18 end
17 19 ```
  @@ -38,4 +38,4 @@
38 38 {<<"optional">>,true},
39 39 {<<"repository">>,<<"hexpm">>},
40 40 {<<"requirement">>,<<"~> 0.11">>}]]}.
41 - {<<"version">>,<<"0.2.0">>}.
41 + {<<"version">>,<<"0.3.0">>}.
  @@ -5,6 +5,22 @@ defmodule Honu.Attachments do
5 5 alias Honu.Storage
6 6 alias Honu.Attachments.Blob
7 7
8 + def attached?(%Blob{}), do: true
9 + def attached?(%Ecto.Association.NotLoaded{}), do: false
10 + def attached?(nil), do: false
11 +
12 + def attached?(struct) when is_struct(struct) do
13 + struct
14 + |> Map.get(:blob)
15 + |> attached?()
16 + end
17 +
18 + def attached?(list) when is_list(list) do
19 + list
20 + |> Enum.map(&attached?/1)
21 + |> Enum.all?()
22 + end
23 +
8 24 def get_attachment_by_key!(key, repo) do
9 25 repo.get_by!(Blob, key: key)
10 26 end
  @@ -5,12 +5,17 @@ defmodule Honu.Attachments.Attachment do
5 5 alias Honu.Attachments.AttachmentMap
6 6 alias Honu.Attachments.Blob
7 7
8 - def attachments_changeset(changeset, attrs, attachments_names) do
9 - # TODO: Support both atom and string in map
10 - # Currently only string keys are supported
11 - Enum.reduce(attachments_names, changeset, fn {name, func}, cset ->
12 - attachment_changeset(cset, attrs, {to_string(name), func})
13 - end)
8 + def attachments_changeset(changeset, attrs, attachments_names)
9 + when is_list(attachments_names) do
10 + if convert?(attrs) do
11 + Enum.reduce(attachments_names, changeset, fn {name, func}, cset ->
12 + attachment_changeset(cset, attrs, {name, func})
13 + end)
14 + else
15 + Enum.reduce(attachments_names, changeset, fn {name, func}, cset ->
16 + attachment_changeset(cset, attrs, {Atom.to_string(name), func})
17 + end)
18 + end
14 19 end
15 20
16 21 defp attachment_changeset(changeset, attrs, {attachment_name, changeset_func})
  @@ -20,9 +25,16 @@ defmodule Honu.Attachments.Attachment do
20 25
21 26 changeset
22 27 |> cast(Map.put(attrs, attachment_name, attachments), [])
23 - |> cast_assoc(String.to_atom(attachment_name), with: changeset_func)
28 + |> cast_assoc(attachment_name |> to_string() |> String.to_existing_atom(),
29 + with: changeset_func
30 + )
24 31 |> prepare_changes(fn changeset ->
25 - blob_ids = get_blob_ids(changeset, String.to_atom(attachment_name))
32 + attachment_name =
33 + attachment_name
34 + |> to_string()
35 + |> String.to_existing_atom()
36 +
37 + blob_ids = get_blob_ids(changeset, attachment_name)
26 38 query = from(b in Blob, where: b.id in ^blob_ids)
27 39 changeset.repo.update_all(query, set: [deleted_at: NaiveDateTime.utc_now()])
28 40
  @@ -38,7 +50,10 @@ defmodule Honu.Attachments.Attachment do
38 50 changes when is_list(changes) ->
39 51 changes
40 52 |> Enum.filter(&(&1.action == :replace))
41 - |> Enum.map(&(&1.data.blob_id))
53 + |> Enum.map(& &1.data.blob_id)
54 +
55 + nil ->
56 + []
42 57
43 58 _change ->
44 59 get_has_one_blob_id(changeset, attachment_name)
  @@ -52,4 +67,11 @@ defmodule Honu.Attachments.Attachment do
52 67 attachment -> [attachment.blob_id]
53 68 end
54 69 end
70 +
71 + defp convert?(attrs) do
72 + attrs
73 + |> Map.keys()
74 + |> List.first()
75 + |> is_atom()
76 + end
55 77 end
  @@ -20,13 +20,22 @@ end
20 20 defimpl Honu.Attachments.AttachmentMap, for: Map do
21 21 def build(%{"file" => file} = attrs, attachment_name) do
22 22 %{
23 - "name" => attachment_name,
23 + "name" => to_string(attachment_name),
24 24 "blob" => Honu.Attachments.Blob.build(file)
25 25 }
26 26 |> Map.merge(Map.delete(attrs, "file"))
27 27 |> Map.delete("id")
28 28 end
29 29
30 + def build(%{file: file} = attrs, attachment_name) do
31 + %{
32 + name: to_string(attachment_name),
33 + blob: Honu.Attachments.Blob.build(file)
34 + }
35 + |> Map.merge(Map.delete(attrs, :file))
36 + |> Map.delete(:id)
37 + end
38 +
30 39 def build(%{"0" => map} = attrs, attachment_name) when is_map(map) do
31 40 Enum.reduce(attrs, %{}, fn attachment, acc ->
32 41 attachment
  @@ -35,8 +44,20 @@ defimpl Honu.Attachments.AttachmentMap, for: Map do
35 44 end)
36 45 end
37 46
38 - def build(attrs, attachment_name) do
39 - Map.merge(%{"name" => attachment_name}, attrs)
47 + def build(%{0 => map} = attrs, attachment_name) when is_map(map) do
48 + Enum.reduce(attrs, %{}, fn attachment, acc ->
49 + attachment
50 + |> build_one_with_index(attachment_name)
51 + |> Map.merge(acc)
52 + end)
53 + end
54 +
55 + def build(%{id: _} = attrs, attachment_name) do
56 + Map.merge(%{name: to_string(attachment_name)}, attrs)
57 + end
58 +
59 + def build(%{"id" => _} = attrs, attachment_name) do
60 + Map.merge(%{"name" => to_string(attachment_name)}, attrs)
40 61 end
41 62
42 63 defp build_one_with_index({id, attrs}, attachment_name) when is_map(attrs) do
Loading more files…