

Waffle.Ecto — waffle\_ecto v0.0.12

 try {

 var settings = JSON.parse(localStorage.getItem('ex\_doc:settings') || '{}');

 if (settings.theme === 'dark' ||

 ((settings.theme === 'system' || settings.theme == null) &&

 window.matchMedia('(prefers-color-scheme: dark)').matches)

 ) {

 document.body.classList.add('dark')

 }

 } catch (error) { }

 

Settings

Waffle.Ecto

(waffle\_ecto v0.0.12)

===============================================

Waffle.Ecto provides an integration with [`Waffle`](https://hexdocs.pm/waffle/1.1.6/Waffle.html) and [`Ecto`](https://hexdocs.pm/ecto/3.9.4/Ecto.html).

Waffle attachments should be stored in a string column, with a name indicative of the attachment.

```

create table :users do

 add :avatar, :string

end

```

[how-to-add-waffle\_ecto-to-your-project](#module-how-to-add-waffle_ecto-to-your-project)

 How to add `waffle_ecto` to your project

------------------------------------------------------------------------------------------------------------------------------------

* add [Schema](Waffle.Ecto.Schema.html) to the model

* configure [Definition](Waffle.Ecto.Definition.html) for uploader

[pages](#module-pages)

 Pages

------------------------------

* [How to use `:id` in filepath](filepath-with-id.html)

[Link to this section](#summary)

 Summary

==========================================

[Types](#types)

----------------

[t()](#t:t/0)

[Link to this section](#types)

Types

=====================================

[Link to this type](#t:t/0 "Link to this type")

t()

===

```

@type t() :: %{file_name: [String.t](https://hexdocs.pm/elixir/String.html#t:t/0)(), updated_at: [DateTime.t](https://hexdocs.pm/elixir/DateTime.html#t:t/0)()}

```





Waffle.Ecto.Definition — waffle\_ecto v0.0.12

 try {

 var settings = JSON.parse(localStorage.getItem('ex\_doc:settings') || '{}');

 if (settings.theme === 'dark' ||

 ((settings.theme === 'system' || settings.theme == null) &&

 window.matchMedia('(prefers-color-scheme: dark)').matches)

 ) {

 document.body.classList.add('dark')

 }

 } catch (error) { }

 

Settings

Waffle.Ecto.Definition

(waffle\_ecto v0.0.12)

==========================================================

Provides a set of functions to ease integration with Waffle and Ecto.

In particular:

* Definition of a custom Ecto Type responsible for storing the images

* URL generation with a cache-busting timestamp query parameter

[example](#module-example)

 Example

------------------------------------

```

defmodule MyApp.Uploaders.AvatarUploader do

 use Waffle.Definition

 use Waffle.Ecto.Definition

 # ...

end

```

[url-generation](#module-url-generation)

 URL generation

---------------------------------------------------------

Both public and signed urls will include the timestamp for cache

busting, and are retrieved the exact same way as using Waffle

directly.

```

user = Repo.get(User, 1)

# To receive a single rendition:

MyApp.Uploaders.AvatarUploader.url({user.avatar, user}, :thumb)

#=> "https://bucket.s3.amazonaws.com/uploads/avatars/1/thumb.png?v=63601457477"

# To receive all renditions:

MyApp.Uploaders.AvatarUploader.urls({user.avatar, user})

#=> %{original: "https://.../original.png?v=1234", thumb: "https://.../thumb.png?v=1234"}

# To receive a signed url:

MyApp.Uploaders.AvatarUploader.url({user.avatar, user}, signed: true)

MyApp.Uploaders.AvatarUploader.url({user.avatar, user}, :thumb, signed: true)

```





Waffle.Ecto.Schema — waffle\_ecto v0.0.12

 try {

 var settings = JSON.parse(localStorage.getItem('ex\_doc:settings') || '{}');

 if (settings.theme === 'dark' ||

 ((settings.theme === 'system' || settings.theme == null) &&

 window.matchMedia('(prefers-color-scheme: dark)').matches)

 ) {

 document.body.classList.add('dark')

 }

 } catch (error) { }

 

Settings

Waffle.Ecto.Schema

(waffle\_ecto v0.0.12)

======================================================

Defines helpers to work with changeset.

Add a using statement `use Waffle.Ecto.Schema` to the top of your

ecto schema, and specify the type of the column in your schema as

`MyApp.Avatar.Type`.

Attachments can subsequently be passed to Waffle's storage though a

Changeset [`cast_attachments/3`](#cast_attachments/3) function, following the syntax of

`cast/3`.

[example](#module-example)

 Example

------------------------------------

```

defmodule MyApp.User do

 use MyApp.Web, :model

 use Waffle.Ecto.Schema

 schema "users" do

 field :name, :string

 field :avatar, MyApp.Uploaders.AvatarUploader.Type

 end

 def changeset(user, params \\ :invalid) do

 user

 |> cast(params, [:name])

 |> cast\_attachments(params, [:avatar])

 |> validate\_required([:name, :avatar])

 end

end

```

[Link to this section](#summary)

 Summary

==========================================

[Functions](#functions)

------------------------

[cast\_attachments(changeset\_or\_data, params, allowed, options \\ [])](#cast_attachments/4)

Extracts attachments from params and converts it to the accepted format.

[check\_and\_apply\_scope(params, scope, options)](#check_and_apply_scope/3)

[convert\_params\_to\_binary(params)](#convert_params_to_binary/1)

[do\_apply\_changes(changeset)](#do_apply_changes/1)

[Link to this section](#functions)

Functions

=============================================

[Link to this macro](#cast_attachments/4 "Link to this macro")

cast\_attachments(changeset\_or\_data, params, allowed, options \\ [])

======================================================================

(macro)

Extracts attachments from params and converts it to the accepted format.

[options](#cast_attachments/4-options)

 Options

------------------------------------------------

* `:allow_urls` — fetches remote file if the string matches `~r/^https?:\/\//`

* `:allow_paths` — accepts any local path as file destination

[examples](#cast_attachments/4-examples)

 Examples

---------------------------------------------------

```

cast\_attachments(changeset, params, [:fetched\_remote\_file], allow\_urls: true)

```

[Link to this function](#check_and_apply_scope/3 "Link to this function")

check\_and\_apply\_scope(params, scope, options)

================================================

[Link to this function](#convert_params_to_binary/1 "Link to this function")

convert\_params\_to\_binary(params)

===================================

[Link to this function](#do_apply_changes/1 "Link to this function")

do\_apply\_changes(changeset)

=============================





Waffle.Ecto.Type — waffle\_ecto v0.0.12

 try {

 var settings = JSON.parse(localStorage.getItem('ex\_doc:settings') || '{}');

 if (settings.theme === 'dark' ||

 ((settings.theme === 'system' || settings.theme == null) &&

 window.matchMedia('(prefers-color-scheme: dark)').matches)

 ) {

 document.body.classList.add('dark')

 }

 } catch (error) { }

 

Settings

Waffle.Ecto.Type

(waffle\_ecto v0.0.12)

====================================================

Provides implementation for custom Ecto.Type behaviour.

[Link to this section](#summary)

 Summary

==========================================

[Functions](#functions)

------------------------

[cast(definition, args)](#cast/2)

[dump(definition, map)](#dump/2)

[load(definition, value)](#load/2)

[type()](#type/0)

[Link to this section](#functions)

Functions

=============================================

[Link to this function](#cast/2 "Link to this function")

cast(definition, args)

======================

[Link to this function](#dump/2 "Link to this function")

dump(definition, map)

=====================

[Link to this function](#load/2 "Link to this function")

load(definition, value)

=======================

[Link to this function](#type/0 "Link to this function")

type()

======





How to use :id in filepath — waffle\_ecto v0.0.12

 try {

 var settings = JSON.parse(localStorage.getItem('ex\_doc:settings') || '{}');

 if (settings.theme === 'dark' ||

 ((settings.theme === 'system' || settings.theme == null) &&

 window.matchMedia('(prefers-color-scheme: dark)').matches)

 ) {

 document.body.classList.add('dark')

 }

 } catch (error) { }

 

Settings

How to use `:id` in filepath

=========================================

In order to use `:id` attribute within file's path, we should separate

creation stage on two steps:

* persist the resource

* upload the file

It needs to be done because `:id` not yet exist on creation stage.

[example](#example)

 Example

-----------------------------

To implement this we should define `storage_dir/2` inside uploader

```

def storage\_dir(\_version, {\_file, scope}) do

 "uploads/avatar/#{scope.id}"

end

```

Then define two separate `changeset`s inside our resource

```

def changeset(user, attrs) do

 user

 |> cast(attrs, [:name])

 |> validate\_required([:name])

end

def avatar\_changeset(user, attrs) do

 user

 |> cast\_attachments(attrs, [:avatar])

 |> validate\_required([:avatar])

end

```

Finally, we can combine two stages into one action

```

Ecto.Multi.new()

|> Ecto.Multi.insert(:user, User.changeset(user, attrs))

|> Ecto.Multi.update(:user\_with\_avatar, &User.avatar\_changeset(&1.user, attrs))

|> Repo.transaction()

```

This can be used in a Phoenix app context like

```

defmodule Accounts do

 # ...

 

 def create\_user(attrs \\ %{}) do

 Ecto.Multi.new()

 |> Ecto.Multi.insert(:user, User.changeset(%User{}, attrs))

 |> Ecto.Multi.update(:user\_with\_avatar, &User.avatar\_changeset(&1.user, attrs))

 |> Repo.transaction()

 |> case do

 {:ok, %{user\_with\_avatar: user}} -> {:ok, user}

 {:error, \_, changeset, \_} -> {:error, changeset}

 end

 

 def update\_user(%User{} = user, attrs) do

 user

 |> User.changeset(attrs)

 |> User.avatar\_changeset(attrs)

 |> Repo.update()

 end

 

 def change\_user(%User{} = user, attrs \\ %{}) do

 user

 |> User.changeset(attrs)

 |> User.avatar\_changeset(attrs)

 end

 

 # ...

end

```

[← Previous Page

 

API Reference](api-reference.html)

