# File Size for Ecto
[![Build Status](https://travis-ci.org/tlux/file_size_ecto.svg?branch=master)](https://travis-ci.org/tlux/file_size_ecto)
[![Coverage Status](https://coveralls.io/repos/github/tlux/file_size_ecto/badge.svg?branch=master)](https://coveralls.io/github/tlux/file_size_ecto?branch=master)
[![Hex.pm](https://img.shields.io/hexpm/v/file_size_ecto.svg)](https://hex.pm/packages/file_size_ecto)
Provides types for file sizes that you can use in your Ecto schemata.
This library uses [`file_size`](https://hexdocs.pm/file_size) under the hood
that brings a file size parser, formatter and allows calculation and comparison
of file sizes with different units.
## Prerequisites
* Erlang 20 or greater
* Elixir 1.8 or greater
## Installation
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `file_size_ecto` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:file_size_ecto, "~> 2.0"}
]
end
```
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at [https://hexdocs.pm/file_size_ecto](https://hexdocs.pm/file_size_ecto).
## Usage
### Without Unit
The following unit-less types are available:
* [`FileSize.Ecto.Bit`](https://hexdocs.pm/file_size_ecto/FileSize.Ecto.Bit.html)
* [`FileSize.Ecto.Byte`](https://hexdocs.pm/file_size_ecto/FileSize.Ecto.Byte.html)
Write a migration to add or update your file size field. You can use `:integer`
or `:bigint` as types. If you expect very large file sizes, `:bigint` is
recommended of course.
```elixir
defmodule MyProject.Migrations.AddFileSizeToMyTable
use Ecto.Migration
def up do
alter table(:my_table) do
add :file_size, :bigint
end
end
end
```
Update your schema:
```elixir
defmodule MySchema do
use Ecto.Schema
schema "my_table" do
# ...
field :file_size, FileSize.Ecto.Byte
end
end
```
You can store your file size like this:
```elixir
record = Repo.get(MySchema, 123)
updated_record =
record
|> Echo.Changeset.change(file_size: FileSize.new(2, :mb))
|> Repo.update!()
updated_record.file_size
# => #FileSize<"2000000 B">
```
Or, when working with user input:
```elixir
updated_record
record
|> Echo.Changeset.cast(%{file_size: "4 KiB"}, [:file_size])
|> Repo.update!()
updated_record.file_size
# => #FileSize<"4096 B">
```
Note that the file size is always converted to the base unit (bit or byte) when
storing it in the database, because no unit information is available. Read the
next section if you want to find out how to store the size unit together with
the value.
### With Unit
The following types with units are available:
* [`FileSize.Ecto.BitWithUnit`](https://hexdocs.pm/file_size_ecto/FileSize.Ecto.BitWithUnit.html)
* [`FileSize.Ecto.ByteWithUnit`](https://hexdocs.pm/file_size_ecto/FileSize.Ecto.ByteWithUnit.html)
Write a migration to add or update your file size field. The value is stored in
a `:map` field. This map contains the as bits or bytes and the unit.
```elixir
defmodule MyProject.Migrations.AddFileSizeToMyTable
use Ecto.Migration
def up do
alter table(:my_table) do
add :file_size, :map
end
end
end
```
Update your schema:
```elixir
defmodule MySchema do
use Ecto.Schema
schema "my_table" do
# ...
field :file_size, FileSize.Ecto.ByteWithUnit
end
end
```
You can store your file size like this:
```elixir
record = Repo.get(MySchema, 123)
updated_record =
record
|> Echo.Changeset.change(file_size: FileSize.new(2, :mb))
|> Repo.update!()
updated_record.file_size
# => #FileSize<"2 MB">
```
Or, when working with user input:
```elixir
updated_record
record
|> Echo.Changeset.cast(%{file_size: "4 KiB"}, [:file_size])
|> Repo.update!()
updated_record.file_size
# => #FileSize<"4 KiB">
```
## Docs
Documentation is available on [HexDocs](https://hexdocs.pm/file_size_ecto).