Skip to content

Commit

Permalink
remove status schema from project completely #89 #94 (comment) #93
Browse files Browse the repository at this point in the history
  • Loading branch information
nelsonic committed Jul 14, 2022
1 parent b35ca04 commit d5ca2ec
Show file tree
Hide file tree
Showing 15 changed files with 99 additions and 369 deletions.
106 changes: 10 additions & 96 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ of the **@dwyl App**
- [_Explanation_ of the Schemas](#explanation-of-the-schemas)
- [`person`](#person)
- [`item`](#item)
- [`status`](#status)
- [`timer`](#timer)
- [2.1 Run Tests!](#21-run-tests)
- [3. Input Items!](#3-input-items)
Expand Down Expand Up @@ -626,9 +625,8 @@ Run the following
commands:

```sh
mix phx.gen.schema Status status text:string status_code:integer
mix phx.gen.schema Person people givenName:binary auth_provider:string key_id:integer status_code:integer picture:binary locale:string
mix phx.gen.schema Item items text:string person_id:references:people status:references:status
mix phx.gen.schema Item items text:string person_id:references:people status_code:integer
mix phx.gen.schema Timer timers item_id:references:items start:naive_datetime end:naive_datetime person_id:references:people
```

Expand All @@ -637,7 +635,7 @@ we have the following database
[Entity Relationship Diagram](https://en.wikipedia.org/wiki/Entity%E2%80%93relationship_model)
(ERD):

![mvp-erd-without-associations](https://user-images.githubusercontent.com/194400/177014286-cefc55e8-510f-44dd-befb-59f6e3315fd7.png)
![mvp-erd-without-associations](https://user-images.githubusercontent.com/194400/178869576-c6aff9d7-1bc3-43ff-80ac-71b3e86363dd.png)

<!-- probably not needed ...
> **Note**: We used
Expand All @@ -648,8 +646,8 @@ generator which creates a _lot_ of
[boilerplate code](https://github.com/dwyl/app-mvp-phoenix/issues/89#issuecomment-1167548207).
-->

In this step we created **4 database tables**;
`items`, `people`, `status` and `timers`.
In this step we created **3 database tables**;
`items`, `people` and `timers`.
Let's run through them.

### _Explanation_ of the Schemas
Expand All @@ -671,7 +669,10 @@ The `person` _using_ the App
used to encrypt personal data (NOT the key itself!)
see:
[dwyl/phoenix-ecto-**encryption**-**example**](https://github.com/dwyl/phoenix-ecto-encryption-example)
+ `status_id`: `Int` (**FK** `status.id`) - e.g: "0: unverified, 1: verified", etc.
+ `status_code`: `Integer` - e.g: "0: unverified, 1: verified", etc.
For the list of available statuses,
please see:
[github.com/dwyl/statuses](https://github.com/dwyl/statuses)

#### `item`

Expand All @@ -685,72 +686,11 @@ for what we are building later on.
+ `inserted_at`: `Timestamp` - created/managed by `Phoenix`
+ `updated_at`: `Timestamp`
+ `text`: `Binary` (_encrypted_) - the free text you want to capture.
+ `person_id`: `Int`
([**FK**](https://en.wikipedia.org/wiki/Foreign_key)
+ `person_id`: `Integer`
`person.id` the "owner" of the `item`)
+ `status_id`: `Int` (**FK** `status.id`) the `status` of the `item`
+ `status_code`: `Integer` the `status` of the `item`
e.g: "in progress"

#### `status`

The `status` of an `item` or `person`.

+ `id`: `Int`
+ `inserted_at`: `Timestamp`
+ `updated_at`: `Timestamp`
+ `person_id`: `Int` (**FK** `person.id` - the person
who defined/updated the status)
+ `text`: `String` - examples:
+ "unverified" - for a person that has not verified their email address
+ "verified" - for a person who's identity has been verified.
+ "open"
+ "in_progress"
+ "complete"
+ [etc.](https://github.com/dwyl/checklist/pull/3/files#diff-597edb4596faa11c05c29c0d3a8cf94a)

`status` is _deliberately_ both versatile and limited.
We want to be able to apply a _single_ `status`
to a `person` or `item` at any given time.
i.e. an `item` cannot be `status` `"active"` and `"done"`
at the same time.

<!--
We _could_ have just used `tags` for everything,
e.g. (SQL pseudocode)
```sql
SELECT * FROM items
JOIN items_tags ON
item_tags.item_id = item.id
JOIN tags on
item_tags.tag_id = tags.id
WHERE
item.person_id = 42
AND
tags.text = 'open';
```
However we _prefer_ to have `status`
_distinct_ from `tags`
because we feel it makes it
easier to reason about.
e.g:
```sql
SELECT * FROM items WHERE person_id = 4 AND status_id = 1; -- i.e. 'open'
```
No join required.
The `status_id = 1`
is defined by the App
so can be hard-coded.
-->

> **Note**: the plural form of "status" is "status":
https://english.stackexchange.com/questions/877/plural-form-of-status


#### `timer`

A `timer` is attached to an `item`
Expand All @@ -773,32 +713,6 @@ been taken.

<br />

<!--
#### Schema Notes
If naming things is
[hard](https://martinfowler.com/bliki/TwoHardThings.html),
choosing names for schemas/fields is **_extra_ hard_**,
because once **APIs** are defined
it can be a _mission_ to modify them
because **_changing_ APIs "_breaks_" _everything_**!
We have been thinking about,
researching and iterating on this idea for a _long_ time.
Our _hope_ is that it will be obvious to everyone _why_
a certain database table is named the way it is,
but if not,
[please open an issue/question](https://github.com/nelsonic/time-mvp-phoenix/issues)
to seek clarification.
<sup>1</sup> We are using the `default` Phoenix auto-incrementing `id`
for all `id` fields in this MVP. When we _need_ to make the App "offline first"
we will transition to a Globally Unique [ContentID](https://github.com/dwyl/cid)
-->

<br />


### 2.1 Run Tests!

Once we've created the required schemas,
Expand Down
16 changes: 0 additions & 16 deletions lib/app/ecto_atom.ex

This file was deleted.

33 changes: 13 additions & 20 deletions lib/app/item.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ defmodule App.Item do

schema "items" do
field :text, :string

belongs_to :status, App.Status, on_replace: :nilify
belongs_to :person, App.Person
field :status_code, :integer
field :person_id, :integer

timestamps()
end

@doc false
def changeset(item, attrs) do
item
|> cast(attrs, [:text])
|> cast(attrs, [:text, :status_code, :person_id])
|> validate_required([:text])
end

Expand All @@ -32,11 +32,9 @@ defmodule App.Item do
{:error, %Ecto.Changeset{}}
"""
def create_item(attrs \\ %{}, person, status) do
def create_item(attrs) do
%Item{}
|> changeset(attrs)
|> put_assoc(:person, person)
|> put_assoc(:status, status)
|> Repo.insert()
end

Expand All @@ -54,7 +52,7 @@ defmodule App.Item do
** (Ecto.NoResultsError)
"""
def get_item!(id), do: Repo.get!(Item, id) |> Repo.preload(:status)
def get_item!(id), do: Repo.get!(Item, id)

@doc """
Returns the list of items where the status is different to "deleted"
Expand All @@ -66,13 +64,10 @@ defmodule App.Item do
"""
def list_items do
query =
from i in Item,
join: s in assoc(i, :status),
where: s.text != :deleted,
preload: [status: s]

Repo.all(query)
Item
|> order_by(desc: :inserted_at)
|> where([a], is_nil(a.status_code) or a.status_code != 6)
|> Repo.all()
end

@doc """
Expand All @@ -93,11 +88,9 @@ defmodule App.Item do
|> Repo.update()
end

def update_status(%Item{} = item, status) do
item
|> Repo.preload(:status)
|> Ecto.Changeset.change()
|> put_assoc(:status, status)
def delete_item(id) do
get_item!(id)
|> Item.changeset(%{status_code: 6})
|> Repo.update()
end
end
12 changes: 5 additions & 7 deletions lib/app/person.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ defmodule App.Person do
field :key_id, :integer
field :locale, :string
field :picture, Fields.Encrypted

belongs_to :status, App.Status
field :status_code, :integer

timestamps()
end
Expand All @@ -24,18 +23,17 @@ defmodule App.Person do
:auth_provider,
:key_id,
:picture,
:locale
:locale,
:status_code
])
|> validate_required([:givenName, :auth_provider])
end

def create(attrs, status) do
def create(attrs) do
%Person{}
|> Repo.preload(:status)
|> changeset(attrs)
|> put_assoc(:status, status)
|> Repo.insert!()
end

def get_person!(id), do: Repo.get!(__MODULE__, id)
# def get_person!(id), do: Repo.get!(__MODULE__, id)
end
43 changes: 0 additions & 43 deletions lib/app/status.ex

This file was deleted.

23 changes: 6 additions & 17 deletions lib/app_web/live/app_live.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
defmodule AppWeb.AppLive do
use AppWeb, :live_view
alias App.{Item, Person, Status, Timer}
alias App.{Item, Timer}

@topic "live"

Expand All @@ -15,9 +15,7 @@ defmodule AppWeb.AppLive do

@impl true
def handle_event("create", %{"text" => text}, socket) do
person = Person.get_person!(1)
status = Status.get_by_text!(:uncategorized)
Item.create_item(%{text: text}, person, status)
Item.create_item(%{text: text, person_id: 1, status_code: 2})

socket =
assign(socket, items: Item.list_items(), active: %Item{}, timer: %Timer{})
Expand All @@ -29,15 +27,10 @@ defmodule AppWeb.AppLive do
@impl true
def handle_event("toggle", data, socket) do
# Toggle the status of the item between 3 (:active) and 4 (:done)
status =
if Map.has_key?(data, "value") do
Status.get_by_text!(:done)
else
Status.get_by_text!(:active)
end
status = if Map.has_key?(data, "value"), do: 4, else: 3

item = Item.get_item!(Map.get(data, "id"))
Item.update_status(item, status)
Item.update_item(item, %{status_code: status})

socket =
assign(socket, items: Item.list_items(), active: %Item{}, timer: %Timer{})
Expand All @@ -48,9 +41,7 @@ defmodule AppWeb.AppLive do

@impl true
def handle_event("delete", %{"id" => item_id}, socket) do
deleted_status = Status.get_by_text!(:deleted)
item = Item.get_item!(item_id)
Item.update_status(item, deleted_status)
Item.delete_item(item_id)

socket =
assign(socket, items: Item.list_items(), active: %Item{}, timer: %Timer{})
Expand All @@ -72,8 +63,6 @@ defmodule AppWeb.AppLive do
start: NaiveDateTime.utc_now()
})

# IO.inspect(timer)

socket =
assign(socket, items: Item.list_items(), active: %Item{}, timer: timer)

Expand Down Expand Up @@ -119,7 +108,7 @@ defmodule AppWeb.AppLive do
end

# helper function that checks for status 4 (:done)
def done?(item), do: item.status.text == :done
def done?(item), do: item.status_code == 4

def started?(item, timer) do
# IO.inspect(item, label: "item")
Expand Down
Loading

0 comments on commit d5ca2ec

Please sign in to comment.