Create Schemas
As outlined in
tidy#1,
our goal is to allow people
wanting to help tidy
the house,
to create the records.
Object
Schema
An object
will have the following fields:
name
- the name of theobject
you need help withdesc
- brief description of theobject
including any salient features.color
- astring
for main color of theobject
e.g. "green"person_id
- theid
of theperson
who created theobject
record.owner_id
-id
of theperson
who owns theobject
location
- astring
describing where theobject
belongs.status
- aint
representing the currentstatus
of theobject
record.
Note: we will need to map out the
statuses
required for this App and add them to our list.
Using the
mix phx.gen.live
command,
we can create the object
schema and LiveView
pages,
run:
mix phx.gen.live Objects Object objects name:binary desc:binary color:binary person_id:integer owner_id:integer location:binary status:integer
You should expect to see output similar to the following:
* creating lib/tidy_web/live/object_live/show.ex
* creating lib/tidy_web/live/object_live/index.ex
* creating lib/tidy_web/live/object_live/form_component.ex
* creating lib/tidy_web/live/object_live/index.html.heex
* creating lib/tidy_web/live/object_live/show.html.heex
* creating test/tidy_web/live/object_live_test.exs
* creating lib/tidy/objects/object.ex
* creating priv/repo/migrations/20231004034411_create_objects.exs
* creating lib/tidy/objects.ex
* injecting lib/tidy/objects.ex
* creating test/tidy/objects_test.exs
* injecting test/tidy/objects_test.exs
* creating test/support/fixtures/objects_fixtures.ex
* injecting test/support/fixtures/objects_fixtures.ex
Add the live routes to your browser scope in lib/tidy_web/router.ex:
live "/objects", ObjectLive.Index, :index
live "/objects/new", ObjectLive.Index, :new
live "/objects/:id/edit", ObjectLive.Index, :edit
live "/objects/:id", ObjectLive.Show, :show
live "/objects/:id/show/edit", ObjectLive.Show, :edit
Remember to update your repository by running migrations:
$ mix ecto.migrate
Those are a lot of new files. 😬
We will go through each file
in the next page
and update as needed.
For now we need to follow the instructions
and add the new routes to the router.ex
.
With the new lines added e.g: router.ex
If we re-run the tests with coverage checking:
mix c
We see the following output:
...................
Finished in 0.2 seconds (0.08s async, 0.1s sync)
19 tests, 0 failures
Randomized with seed 121378
----------------
COV FILE LINES RELEVANT MISSED
100.0% lib/tidy.ex 9 0 0
100.0% lib/tidy/objects.ex 104 6 0
100.0% lib/tidy/objects/object.ex 23 2 0
100.0% lib/tidy/repo.ex 5 0 0
100.0% lib/tidy_web.ex 111 2 0
100.0% lib/tidy_web/components/layouts.ex 5 0 0
100.0% lib/tidy_web/controllers/error_html.ex 19 1 0
100.0% lib/tidy_web/controllers/error_json.ex 15 1 0
100.0% lib/tidy_web/controllers/page_controller 9 1 0
100.0% lib/tidy_web/controllers/page_html.ex 5 0 0
100.0% lib/tidy_web/endpoint.ex 47 0 0
94.1% lib/tidy_web/live/object_live/form_compo 96 34 2
100.0% lib/tidy_web/live/object_live/index.ex 47 10 0
100.0% lib/tidy_web/live/object_live/show.ex 21 5 0
100.0% lib/tidy_web/router.ex 35 7 0
[TOTAL] 97.1%
----------------
FAILED: Expected minimum coverage of 100%, got 97.1%.
The lib/tidy_web/live/object_live/form_component.ex
has a few lines that are not reached by the default tests:
Both of these functions are defp
i.e. "private".
So we cannot simply invoke them in a unit test
to exercise the error handling.
We have several options for dealing with these untested lines:
- Ignore them - the easiest/fastest
- Convert them from
defp
todef
and test (invoke) them directly - Construct elaborate tests with bad data to trigger the errors ...
In our case we know that we won't be using these functions when we build our custom interface, so we're just going to ignore the untested lines, for now.
E.g:
lib/tidy_web/live/object_live/form_component.ex
Ref:
tidy#1
Now re-running the tests with coverage mix c
we get:
Finished in 0.2 seconds (0.05s async, 0.1s sync)
19 tests, 0 failures
Randomized with seed 729041
----------------
COV FILE LINES RELEVANT MISSED
100.0% lib/tidy.ex 9 0 0
100.0% lib/tidy/objects.ex 104 6 0
100.0% lib/tidy/objects/object.ex 23 2 0
100.0% lib/tidy/repo.ex 5 0 0
100.0% lib/tidy_web.ex 111 2 0
100.0% lib/tidy_web/components/layouts.ex 5 0 0
100.0% lib/tidy_web/controllers/error_html.ex 19 1 0
100.0% lib/tidy_web/controllers/error_json.ex 15 1 0
100.0% lib/tidy_web/controllers/page_controller 9 1 0
100.0% lib/tidy_web/controllers/page_html.ex 5 0 0
100.0% lib/tidy_web/endpoint.ex 47 0 0
100.0% lib/tidy_web/live/object_live/form_compo 98 32 0
100.0% lib/tidy_web/live/object_live/index.ex 47 10 0
100.0% lib/tidy_web/live/object_live/show.ex 21 5 0
100.0% lib/tidy_web/router.ex 34 7 0
[TOTAL] 100.0%
----------------
With that out of the way,
let's proceed to defining the images
schema.
images
An object
can have one or more images
.
These are used identify and categorize the object
.
obj_id
- theid
of theobject
theimage
belongs to.person_id
-id
of theperson
who uploaded theimage
.url
- theURL
of theimage
that was uploaded toS3
In the case of images we don't want any "pages"
to be created, we just want the schema
,
so we use the
mix phx.gen.schema
command:
mix phx.gen.schema Image images obj_id:integer person_id:integer url:binary
Output should be similar to:
* creating lib/tidy/image.ex
* creating priv/repo/migrations/20231004055222_create_images.exs
Remember to update your repository by running migrations:
$ mix ecto.migrate
This is a far more manageable 2 files.
But in this case the tests are not generated.
So if we run mix c
we get:
19 tests, 0 failures
Randomized with seed 852972
----------------
COV FILE LINES RELEVANT MISSED
100.0% lib/tidy.ex 9 0 0
0.0% lib/tidy/image.ex 19 2 2
100.0% lib/tidy/objects.ex 104 6 0
... etc.
[TOTAL] 97.1%
----------------
FAILED: Expected minimum coverage of 100%, got 97.1%.
Where the
lib/tidy/image.ex
file has 0%
coverage.
This is easy to fix.
Test images
Schema
Create a file with the path:
test/tidy/image_test.exs
and add the following test to it:
defmodule TidyWeb.ImageTest do
use Tidy.DataCase
alias Tidy.Image
describe "images" do
@valid_image %{obj_id: 1, person_id: 1, url: "https://imgur.com/gallery/odNLFdO"}
test "create_image/1 with valid data creates an image" do
assert {:ok, %Image{} = image} = Image.create_image(@valid_image)
assert image.url == @valid_image.url
end
end
end
With that test in place, we can now re-run mix c
and see that we're back up to 100%
coverage:
20 tests, 0 failures
Randomized with seed 236415
----------------
COV FILE LINES RELEVANT MISSED
100.0% lib/tidy.ex 9 0 0
100.0% lib/tidy/image.ex 39 3 0
100.0% lib/tidy/objects.ex 104 6 0
...
etc.
[TOTAL] 100.0%
# ----------------
Time for the comments
schema!
comments
An object
can have one ore more comments
associated with it.
This allows people
to discuss the object
in a conversational style
similar to what they are already used to
from using Instant Messaging.
The data/fields we need to store for each comment
are:
obj_id
- theid
of theobject
thecomment
belongs to.person_id
-id
of theperson
commenter.text
- thestring
of their comment.
Again using the
mix phx.gen.schema
command:
mix phx.gen.schema Comment comments obj_id:integer person_id:integer text:binary
Output should be similar to:
* creating lib/tidy/comment.ex
* creating priv/repo/migrations/20231004142856_create_comments.exs
Remember to update your repository by running migrations:
$ mix ecto.migrate
Same as with the images
above, no tests are created,
so if we run mix c
we get:
20 tests, 0 failures
Randomized with seed 986302
----------------
COV FILE LINES RELEVANT MISSED
100.0% lib/tidy.ex 9 0 0
0.0% lib/tidy/comment.ex 19 2 2
100.0% lib/tidy/image.ex 39 3 0
100.0% lib/tidy/objects.ex 104 6 0
... etc.
[TOTAL] 97.2%
----------------
FAILED: Expected minimum coverage of 100%, got 97.2%.
Test comment
Schema
Create a file with the path:
test/tidy/comment_test.exs
and add the following test to it:
defmodule TidyWeb.CommentTest do
use Tidy.DataCase
alias Tidy.Comment
describe "comments" do
@valid_attrs %{obj_id: 1, person_id: 1, text: "Candles on the kitchen counter"}
test "create_comment/1 with valid data creates an comment" do
assert {:ok, %Comment{} = com} = Comment.create_comment(@valid_attrs)
assert com.text == @valid_attrs.text
end
end
end
With that test in place, we can now re-run mix c
and see that we're back up to 100%
coverage:
20 tests, 0 failures
Randomized with seed 236415
----------------
COV FILE LINES RELEVANT MISSED
100.0% lib/tidy.ex 9 0 0
100.0% lib/tidy/comment.ex 40 3 0
100.0% lib/tidy/image.ex 39 3 0
100.0% lib/tidy/objects.ex 104 6 0
...
etc.
[TOTAL] 100.0%
# ----------------
With all the schemas & functions tested, we can now move on to the interface! 🪄