Rsim
Rsim - is image manager that allows to upload and fetch images easily. It is integrated with ecto and AWS S3.
# will upload image to s3, save to DB and provide image_id
{:ok, image_id} = Rsim.save_image_from_file(path, :user)
# will upload image to s3 from provided URL, save to DB and provide image_id
{:ok, image_id} = Rsim.save_image_from_url(url, :user)
# returns image src
{:ok, image_src} = Rsim.get_image_url(image_id)
# resize image on the fly, saves new resized image and returns image src
{:ok, image_src} = Rsim.get_image_url(image_id, 200, 150)
Installation
Add rsim
to your list of dependencies in mix.exs
:
def deps do
[
{:rsim, "~> 0.1.0"}
]
end
# add configuration
# currently only AWS S3 storage is suppoted so make sure
# you have config for :ex_aws as well
config :ex_aws,
access_key_id: "",
secret_access_key: "",
region: ""
config :rsim,
repo: MyApp.Repo,
s3: [bucket: "bucket-name"]
Copy and run migration to add images
table from priv/repo/migrations/
. Add image_id
to your application
tables that will have images.
def change do
alter table(:users) do
add(:image_id, references(:images, on_delete: :nothing, type: :binary_id))
end
create(index(:users, [:image_id]))
end
defmodule MyApp.Accounts.User do
use Ecto.Schema
schema "users" do
# other fields
belongs_to(:image, Rsim.EctoImage, type: :binary_id)
end
end
Real world example
defmodule MyApp.Accounts.Registrator do
def register_user(user_params) do
user_params = if !Map.has_key?(user_params, :image_id) && Map.has_key?(user_params, :image_url) do
Map.put(user_params, :image_id, save_image_from_url!(user_params.image_url))
sign_up_changeset(%User{}, user_params)
|> Repo.insert()
end
defp save_image_from_url!(url) when is_nil(url), do: nil
defp save_image_from_url!(url) do
# case Rsim.save_image_from_file(uploaded_file.path, :user) do
case Rsim.save_image_from_url(url, :user) do
{:ok, image} -> image.id
{:error, error} -> nil
end
end
end
defmodule MyApp.Accounts.Avatar do
alias MyApp.Accounts.User
def fetch_avatar_url(user = %User{}) do
fetch_image_url(user.image_id)
end
defp fetch_image_url(image_id) when is_nil(image_id), do: nil
defp fetch_image_url(image_id) do
# case Rsim.get_image_url(image_id) do # get original image URL
case Rsim.get_image_url(image_id, 150, 150) do # resize image on the fly and get image_url
{:ok, image_url} -> image_url
{:error, _} -> nil
end
end
end
How It Works
__________
| images |
|_________|
| id | - unique image id
| path | - path in storage
| mime | - image mime type
| size | - image file size
| width | - image width
| height | - image height
|parent_id| - reference for parent image (appears on resized images)
|_________|
|
|___________
__________ |
| users | |
|_________| |
| id | |
| etc | |
| image_id| ----|
| |
|_________|
When you upload new image via Rsim.save_image_from_file
or Rsim.save_image_from_url
it will be uploaded to storage.
(Currently only AWS s3 is supported). Then image info will be saved to images
table, including path in storage and
some metadata like image width/height, mime, file size. images.id
will be returned - it’s responsibility of your app
to save it to application tables that have images.
When you fetch image URL - storage will transform path to valid image source. You also can get resized image on the fly.
In that case new resized image will be saves with reference images.parent_id
to original image.