Skip to content

Commit

Permalink
Added Basic Actions for ChartMeta
Browse files Browse the repository at this point in the history
- added changesets, queries, actions
- wrote tests for actions

Updates #264
  • Loading branch information
Vince Forgione committed Apr 4, 2018
1 parent df54ba6 commit 62347a3
Show file tree
Hide file tree
Showing 5 changed files with 229 additions and 0 deletions.
54 changes: 54 additions & 0 deletions lib/plenario/actions/chart_meta_actions.ex
@@ -0,0 +1,54 @@
defmodule Plenario.Actions.ChartMetaActions do
alias Plenario.Repo

alias Plenario.Schemas.{
Meta,
DataSetField,
VirtualPointField,
VirtualDateField,
ChartMeta
}

alias Plenario.Changesets.ChartMetaChangesets

alias Plenario.Queries.ChartMetaQueries

@type ok_cm :: {:ok, ChartMeta.t} | {:error, Ecto.Changeset.t}

@spec new() :: Ecto.Changeset.t
def new, do: ChartMetaChangesets.new()

@spec create(meta :: Meta.t | integer, name :: String.t, description :: String.t, timestamp_field :: String.t, location_field :: String.t, data_field :: list(String.t), data_agg_func :: String.t) :: ok_cm
def create(%Meta{} = meta, name, description, timestamp_field, location_field, data_fields, data_agg_func),
do: create(meta.id, name, description, timestamp_field, location_field, data_fields, data_agg_func)
def create(meta, name, description, timestamp_field, location_field, data_fields, data_agg_func) do
%{
meta_id: meta,
name: name,
description: description,
timestamp_field: timestamp_field,
location_field: location_field,
data_fields: data_fields,
data_agg_func: data_agg_func
}
|> ChartMetaChangesets.create()
|> Repo.insert()
end

@spec edit(instance :: ChartMeta.t) :: Ecto.Changeset.t
def edit(instance), do: ChartMetaChangesets.update(instance)

@spec update(instance :: ChartMeta.t, opts :: Keyword.t) :: ok_cm
def update(instance, opts \\ []) do
params = Enum.into(opts, %{})
ChartMetaChangesets.update(instance, params)
|> Repo.update()
end

@spec list(opts :: Keyword.t) :: list(ChartMeta)
def list(opts \\ []) do
ChartMetaQueries.list()
|> ChartMetaQueries.handle_opts(opts)
|> Repo.all()
end
end
58 changes: 58 additions & 0 deletions lib/plenario/changesets/chart_meta_changesets.ex
@@ -0,0 +1,58 @@
defmodule Plenario.Changesets.ChartMetaChangesets do
import Ecto.Changeset

alias Plenario.Schemas.ChartMeta

@type create_params :: %{
name: String.t,
description: String.t,
timestamp_field: String.t,
location_field: String.t,
data_fields: list(String.t),
data_agg_func: String.t,
meta_id: integer
}

@type update_params :: %{
name: String.t,
description: String.t,
timestamp_field: String.t,
location_field: String.t,
data_fields: list(String.t),
data_agg_func: String.t
}

@required_keys [:name, :timestamp_field, :location_field, :data_fields, :data_agg_func, :meta_id]

@create_keys [:name, :description, :timestamp_field, :location_field, :data_fields, :data_agg_func, :meta_id]

@update_keys [:name, :description, :timestamp_field, :location_field, :data_fields, :data_agg_func]

@spec new() :: Ecto.Changeset.t
def new, do: %ChartMeta{} |> cast(%{}, @create_keys)

@spec create(params :: create_params) :: Ecto.Changeset.t
def create(params) do
%ChartMeta{}
|> cast(params, @create_keys)
|> validate_required(@required_keys)
|> cast_assoc(:meta)
|> validate_data_agg_func()
end

@spec update(instance :: ChartMeta.t, params :: update_params) :: Ecto.Changeset.t
def update(instance, params \\ %{}) do
instance
|> cast(params, @update_keys)
|> validate_required(@required_keys)
|> validate_data_agg_func()
end

defp validate_data_agg_func(%Ecto.Changeset{valid?: true, changes: %{data_agg_func: func}} = changeset) do
case Enum.member?(ChartMeta.get_data_agg_func_values(), func) do
true -> changeset
false -> add_error(changeset, :data_agg_func, "Not a valid aggregate function")
end
end
defp validate_data_agg_func(changeset), do: changeset
end
22 changes: 22 additions & 0 deletions lib/plenario/queries/chart_meta_queries.ex
@@ -0,0 +1,22 @@
defmodule Plenario.Queries.ChartMetaQueries do
import Ecto.Query

alias Plenario.Schemas.{Meta, ChartMeta}

alias Plenario.Queries.{Utils, ChartMetaQueries}

def list, do: (from cm in ChartMeta)

def for_meta(query, %Meta{id: id}), do: for_meta(query, id)
def for_meta(query, id), do: from q in query, where: q.meta_id == ^id

def handle_opts(query, opts \\ []) do
defaults = [
for_meta: :dont_use_me
]
opts = Keyword.merge(defaults, opts)

query
|> Utils.filter_compose(opts[:for_meta], ChartMetaQueries, :for_meta)
end
end
17 changes: 17 additions & 0 deletions lib/plenario/schemas/chart_meta.ex
Expand Up @@ -9,6 +9,16 @@ defmodule Plenario.Schemas.ChartMeta do

alias Plenario.Schemas.ChartMeta

@data_agg_func_values ["avg", "sum", "min", "max", "count"]

@data_agg_func_choices [
Average: "avg",
Sum: "sum",
Minimum: "min",
Maximum: "max",
Count: "count"
]

schema "chart_metas" do
field :name, :string
field :description, :string
Expand All @@ -21,6 +31,7 @@ defmodule Plenario.Schemas.ChartMeta do
belongs_to :meta, Plenario.Schemas.Meta
end

@spec get_field_choices(meta_id :: ChartMeta | integer) :: list(String.t)
def get_field_choices(%ChartMeta{meta_id: meta_id}), do: get_field_choices(meta_id)
def get_field_choices(meta_id) do
fields = DataSetFieldActions.list(for_meta: meta_id)
Expand Down Expand Up @@ -48,4 +59,10 @@ defmodule Plenario.Schemas.ChartMeta do

reg_fields ++ jsonb_fields
end

@spec get_data_agg_func_values() :: list(String.t)
def get_data_agg_func_values(), do: @data_agg_func_values

@spec get_data_agg_func_choices() :: Keyword.t
def get_data_agg_func_choices(), do: @data_agg_func_choices
end
78 changes: 78 additions & 0 deletions test/plenario/chart_meta_actions_test.exs
@@ -0,0 +1,78 @@
defmodule Plenario.Testing.ChartMetaActionsTest do
use Plenario.Testing.DataCase

alias Plenario.Repo

alias Plenario.Actions.{
DataSetActions,
DataSetFieldActions,
UniqueConstraintActions,
VirtualPointFieldActions,
ChartMetaActions
}

setup %{meta: meta} do
{:ok, pk} = DataSetFieldActions.create(meta, "node_id", "text")
{:ok, lat} = DataSetFieldActions.create(meta, "latitude", "float")
{:ok, lon} = DataSetFieldActions.create(meta, "longitude", "float")
{:ok, ts} = DataSetFieldActions.create(meta, "timestamp", "timestamptz")
{:ok, _} = DataSetFieldActions.create(meta, "observations", "jsonb")
{:ok, vp} = VirtualPointFieldActions.create(meta, lat.id, lon.id)
{:ok, _} = UniqueConstraintActions.create(meta, [pk.id, ts.id])

:ok = DataSetActions.up!(meta)

insert = """
INSERT INTO "#{meta.table_name}"
(node_id, timestamp, longitude, latitude, observations)
VALUES
('001', '2018-01-01 00:00:00+00:00', -87.71, 42.1, '{"BMP180": {"temperature": -1.65}, "HTU21D": {"humidity": 71.94, "temperature": -0.78}, "TSYS01": {"temperature": -1.1}}'),
('001', '2018-01-01 00:00:30+00:00', -87.71, 42.1, '{"BMP180": {"temperature": -1.65}, "HTU21D": {"temperature": -0.78}, "TSYS01": {"temperature": -1.1}}'),
('002', '2018-01-01 00:00:00+00:00', -87.72, 42.1, '{"BMP180": {"temperature": -1.65}, "HTU21D": {"humidity": 71.94, "temperature": -0.78}}'),
('003', '2018-01-01 00:00:00+00:00', -87.73, 42.1, '{"BMP180": {"temperature": -1.65}, "HTU21D": {"humidity": 71.94, "temperature": -0.78}, "TSYS01": {"temperature": -1.1}}'),
('004', '2018-01-01 00:00:00+00:00', -87.74, 42.1, '{"BMP180": {"temperature": -1.65}, "HTU21D": {"humidity": 71.94, "temperature": -0.78}, "TSYS01": {"temperature": -1.1}}'),
('005', '2018-01-01 00:00:00+00:00', -87.75, 42.1, '{"bananas": 1}')
;
"""
{:ok, _} = Ecto.Adapters.SQL.query(Repo, insert)

{:ok, [meta: meta, vp: vp]}
end

test :new do
changeset = ChartMetaActions.new()
refute changeset.action
end

test :create, %{meta: meta, vp: vp} do
{:ok, _} = ChartMetaActions.create(
meta, "name", "description", "timestamp", vp.name,
["observations.BMP180.temperature"], "avg")
end

test :edit, %{meta: meta, vp: vp} do
{:ok, cm} = ChartMetaActions.create(
meta, "name", "description", "timestamp", vp.name,
["observations.BMP180.temperature"], "avg")

changeset = ChartMetaActions.edit(cm)
refute changeset.action
end

test :update, %{meta: meta, vp: vp} do
{:ok, cm} = ChartMetaActions.create(
meta, "name", "description", "timestamp", vp.name,
["observations.BMP180.temperature"], "avg")

{:ok, cm} = ChartMetaActions.update(cm, name: "something else")
assert cm.name == "something else"
end

test :list, %{meta: meta, vp: vp} do
{:ok, cm} = ChartMetaActions.create(
meta, "name", "description", "timestamp", vp.name,
["observations.BMP180.temperature"], "avg")

assert ChartMetaActions.list(for_meta: meta) == [cm]
end
end

0 comments on commit 62347a3

Please sign in to comment.