Skip to content

Commit 2ed8c23

Browse files
author
Igor Barchenkov
committed
Initial commit
0 parents  commit 2ed8c23

File tree

16 files changed

+316
-0
lines changed

16 files changed

+316
-0
lines changed

.formatter.exs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Used by "mix format"
2+
[
3+
inputs: ["mix.exs", "{config,lib,test}/**/*.{ex,exs}"]
4+
]

.gitignore

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# The directory Mix will write compiled artifacts to.
2+
/_build/
3+
4+
# If you run "mix test --cover", coverage assets end up here.
5+
/cover/
6+
7+
# The directory Mix downloads your dependencies sources to.
8+
/deps/
9+
10+
# Where 3rd-party dependencies like ExDoc output generated docs.
11+
/doc/
12+
13+
# Ignore .fetch files in case you like to edit your project deps locally.
14+
/.fetch
15+
16+
# If the VM crashes, it generates a dump, let's ignore it too.
17+
erl_crash.dump
18+
19+
# Also ignore archive artifacts (built via "mix archive.build").
20+
*.ez
21+
22+
# Ignore package tarball (built via "mix hex.build").
23+
cubecto-*.tar
24+

README.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Cubecto
2+
3+
Cubecto adds a [`Postgrex.Extension`][1] and [`Ecto.Type`][2] definitions
4+
for the datatypes defined in the [`cube`][3] PostgreSQL module.
5+
6+
## Installation
7+
8+
**Add the package to your Mixfile**
9+
10+
```elixir
11+
defp deps do
12+
[{:cubecto, "~> 0.1.0"}]
13+
end
14+
```
15+
16+
17+
**Add Cubecto.Extension to the Postgrex types file somewhere in lib/my_app/**
18+
19+
```elixir
20+
Postgrex.Types.define(
21+
MyApp.PostgrexTypes,
22+
[Cubecto.Extension] ++ Ecto.Adapters.Postgres.extensions()
23+
)
24+
```
25+
26+
**Configure Repo to use custom Postgrex types in config/config.exs**
27+
28+
```elixir
29+
config :my_app, MyApp.Repo,
30+
types: MyApp.PostgrexTypes
31+
```
32+
33+
**Create the cube extension in the database**
34+
35+
```elixir
36+
defmodule MyApp.Repo.Migrations.CreateCubeExtension do
37+
use Ecto.Migration
38+
39+
def change do
40+
execute(
41+
"CREATE EXTENSION IF NOT EXISTS cube",
42+
"DROP EXTENSION IF EXISTS cube"
43+
)
44+
end
45+
end
46+
```
47+
48+
## Usage
49+
50+
**Add a column with the cube datatype to a table**
51+
52+
```elixir
53+
defmodule MyApp.Repo.Migrations.CreateUser do
54+
use Ecto.Migration
55+
56+
def change do
57+
create table("users") do
58+
add :cube, :cube
59+
# other fields
60+
end
61+
end
62+
end
63+
```
64+
65+
**Use Cubecto.Type for the cube field in an Ecto.Schema module**
66+
67+
```elixir
68+
defmodule MyApp.Accounts.User do
69+
use Ecto.Schema
70+
71+
schema "users" do
72+
field :cube, Cubecto.Type
73+
# other fields
74+
end
75+
end
76+
```
77+
78+
[1]: http://hexdocs.pm/postgrex/Postgrex.Extension.html
79+
[2]: http://hexdocs.pm/ecto/Ecto.Type.html
80+
[3]: https://www.postgresql.org/docs/current/static/cube.html

config/config.exs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
use Mix.Config
2+
3+
import_config "#{Mix.env}.exs"

config/dev.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
use Mix.Config

config/prod.exs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
use Mix.Config

config/test.exs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
use Mix.Config
2+
3+
config :cubecto, Cubecto.Test.Repo,
4+
database: "cubecto_test",
5+
username: "postgres",
6+
password: "postgres",
7+
hostname: "localhost",
8+
adapter: Ecto.Adapters.Postgres,
9+
types: Cubecto.Test.PostgrexTypes
10+
11+
config :logger, level: :warn

lib/cubecto/extension.ex

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
defmodule Cubecto.Extension do
2+
@moduledoc false
3+
@behaviour Postgrex.Extension
4+
5+
@impl true
6+
def init(opts) do
7+
Keyword.get(opts, :decode_copy, :copy)
8+
end
9+
10+
@impl true
11+
def matching(_), do: [type: "cube"]
12+
13+
@impl true
14+
def format(_), do: :text
15+
16+
@impl true
17+
def encode(_) do
18+
quote do
19+
bin when is_binary(bin) ->
20+
[<<byte_size(bin)::signed-size(32)>> | bin]
21+
end
22+
end
23+
24+
@impl true
25+
def decode(:reference) do
26+
quote do
27+
<<len::signed-size(32), bin::binary-size(len)>> ->
28+
bin
29+
end
30+
end
31+
32+
def decode(:copy) do
33+
quote do
34+
<<len::signed-size(32), bin::binary-size(len)>> ->
35+
:binary.copy(bin)
36+
end
37+
end
38+
end

lib/cubecto/type.ex

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
defmodule Cubecto.Type do
2+
@moduledoc false
3+
@behaviour Ecto.Type
4+
5+
@impl true
6+
def type, do: :cube
7+
8+
@impl true
9+
def cast(list) when is_list(list) do
10+
{:ok, list}
11+
end
12+
13+
def cast(_), do: :error
14+
15+
@impl true
16+
def load(string) do
17+
list =
18+
string
19+
|> String.trim_leading("(")
20+
|> String.trim_trailing(")")
21+
|> String.split(", ")
22+
|> Enum.map(&parse_value/1)
23+
24+
{:ok, list}
25+
end
26+
27+
@impl true
28+
def dump(list) when is_list(list) do
29+
list =
30+
list
31+
|> Enum.map(&to_string/1)
32+
|> Enum.join(", ")
33+
34+
{:ok, list}
35+
end
36+
37+
def dump(_), do: :error
38+
39+
defp parse_value(val) do
40+
{float, _} = Float.parse(val)
41+
int = trunc(float)
42+
if float == int, do: int, else: float
43+
end
44+
end

mix.exs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
defmodule Cubecto.MixProject do
2+
use Mix.Project
3+
4+
def project do
5+
[
6+
app: :cubecto,
7+
version: "0.1.0",
8+
elixir: "~> 1.5",
9+
start_permanent: Mix.env() == :prod,
10+
elixirc_paths: elixirc_paths(Mix.env()),
11+
deps: deps(),
12+
docs: docs()
13+
]
14+
end
15+
16+
# Run "mix help compile.app" to learn about applications.
17+
def application do
18+
[
19+
extra_applications: [:logger]
20+
]
21+
end
22+
23+
defp elixirc_paths(:test), do: ["lib", "test/support"]
24+
defp elixirc_paths(_), do: ["lib"]
25+
26+
# Run "mix help deps" to learn about dependencies.
27+
defp deps do
28+
[
29+
{:postgrex, ">= 0.13.2"},
30+
{:ecto, ">= 2.1.0"},
31+
{:ex_doc, "~> 0.18.0", only: :dev, runtime: false}
32+
]
33+
end
34+
35+
defp docs do
36+
[
37+
main: "readme",
38+
extras: extras()
39+
]
40+
end
41+
42+
defp extras do
43+
[
44+
"README.md"
45+
]
46+
end
47+
end

0 commit comments

Comments
 (0)