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 theobjectyou need help withdesc- brief description of theobjectincluding any salient features.color- astringfor main color of theobjecte.g. "green"person_id- theidof thepersonwho created theobjectrecord.owner_id-idof thepersonwho owns theobjectlocation- astringdescribing where theobjectbelongs.status- aintrepresenting the currentstatusof theobjectrecord.
Note: we will need to map out the
statusesrequired 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
defptodefand 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- theidof theobjecttheimagebelongs to.person_id-idof thepersonwho uploaded theimage.url- theURLof theimagethat 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- theidof theobjectthecommentbelongs to.person_id-idof thepersoncommenter.text- thestringof 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! 🪄