Skip to content

Instantly share code, notes, and snippets.

@rsgrafx
Last active September 18, 2017 15:28
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rsgrafx/21746ddf4c3dc6a2ebf2a17de5055408 to your computer and use it in GitHub Desktop.
Save rsgrafx/21746ddf4c3dc6a2ebf2a17de5055408 to your computer and use it in GitHub Desktop.
Setting up Arc in a phoenix app that was ported from a rails app using paperclip.
# Ecto - Model
defmodule YourPhoenixApp.PaperclipAvatar do
use YourPhoenixApp.Web, :model
alias YourPhoenixApp.{Repo, PaperclipAvatar}
#
# There are places in my existing app where only the avatar image is required.
# So I created a module that sole purpose was to read that data.
#
schema "users" do
field :avatar_file_name, :string
field :avatar_content_type, :string
field :avatar_file_size, :integer
field :avatar_updated_at, Ecto.DateTime
end
@_epoch :calendar.datetime_to_gregorian_seconds({{1970, 1, 1}, {0, 0, 0}})
def paperclip_hash do
System.get_env("PAPERCLIP_HASH_SECRET")
end
def to_timestamp(datetime) do
datetime
|> Ecto.DateTime.to_erl
|> :calendar.datetime_to_gregorian_seconds
|> -@_epoch
end
end
# Arc Uploader
defmodule YourPhoenixApp.Avatar do
use Arc.Definition
use Arc.Ecto.Definition
alias YourPhoenixApp.{PaperclipAvatar, Repo}
# Include ecto support (requires package arc_ecto installed):
# use Arc.Ecto.Definition
# Override the persisted filenames:
@acl :public_read_write
@versions [:original, :thumb]
# To add a thumbnail version:
# Whitelist file extensions:
def validate({file, _}) do
~w(.jpg .jpeg .gif .png) |> Enum.member?(Path.extname(file.file_name))
end
# Define a thumbnail transformation:
# def transform(:thumb, _) do
# {:convert, "-strip -thumbnail 250x250^ -gravity center -extent 250x250 -format png"}
# end
# Override the persisted filenames:
# def filename(version, _) do
# version
# end
def __storage, do: Arc.Storage.S3
def storage_dir(style, base) do
{_, legacy} = base
case legacy do
%YourPhoenixApp.PaperclipAvatar{} -> paperclip_url(style, legacy)
_ -> _avatar_url_hash(style, legacy)
end
end
defp _avatar_url_hash(style, legacy) do
ecto_date = case Mix.env do
:dev -> legacy.created_at
:prod -> legacy.created_at
:test -> legacy.inserted_at
end
timestamp = ecto_date |> PaperclipAvatar.to_timestamp
hash = "users/avatars/#{legacy.id}/#{style}/#{timestamp}"
|> _encode |> String.downcase
"users/#{hash}/#{legacy.id}/#{style}"
end
def paperclip_url(style, legacy) do
coded = _storage_dir(style, legacy)
|> _encode
|> String.downcase
"users/#{coded}/#{legacy.id}/#{style}/"
end
defp _storage_dir(hash, legacy) do
timestamp = paperclip_timestamp(legacy)
"users/avatars/#{legacy.id}/#{hash}/#{timestamp}"
end
def paperclip_timestamp(%YourPhoenixApp.PaperclipAvatar{}=legacy) do
legacy.avatar_updated_at
|> YourPhoenixApp.PaperclipAvatar.to_timestamp
end
def paperclip_timestamp(not_legacy), do: :os.system_time(:seconds)
def _encode(url) do
:crypto.hmac(:sha, System.get_env("PAPERCLIP_HASH_SECRET"), url)
|> Base.encode16
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment