Powered by AppSignal & Oban Pro

Blog: Search

exercises/blog_search.livemd

Blog: Search

Mix.install([
  {:jason, "~> 1.4"},
  {:kino, "~> 0.8.0", override: true},
  {:youtube, github: "brooklinjazz/youtube"},
  {:hidden_cell, github: "brooklinjazz/hidden_cell"}
])

Navigation

Return Home Report An Issue

Blog: Search

You’re going to add the ability to search for blog posts to your Blog project.

The UI should look similar to the following, but does not have to match exactly as long as it has the required search functionality.

The blog page should have a text input and a search button that directs the user to http://localhost:4000/posts?title=input_string where search_string is the text inside of the form.

http://localhost:4000/posts?title=input_string should only display blogs whose title includes the search_string (case-insensitive).

Posts Context

The Posts context should be able to search for blog posts by their title. The exact interface depends on how you have implemented posts. You might consider something like the following.

Posts.list_posts(title: "My Title")

Which would return a list of blog structs that include the search string in their title (case insensitive).

[
  %Post{id: 1, title: "My Title", content: "My Example Content"},
  %Post{id: 3, title: "my title", content: "My Example Content"}
  %Post{id: 3, title: "MY TITLE", content: "My Example Content"}
]

Filter out posts that do not include the searched text in their title. posts that include the text should be found.

Consider including the following test cases.

  • Find posts that exactly match search. ("My Title" matches "My Title")
  • Find posts that partially match search. ("My Title" matches "This Includes My Title In It")
  • Find posts that match search lower case insensitive. ("My Title" matches "my title")
  • Find posts that match search capital case insensitive. ("My Title" matches "MY TITLE")
  • Do not find posts that do not match search. ("My Title" does not match "Non-matching Title")

Posts Controller

The posts controller should already display all posts when the client visits http://localhost:4000/posts.

On the same page that lists all posts, create a form with a text input and a submit button that triggers a GET request to http://localhost:4000/posts?title=search_string where search_string is the value of the text input.

The blog controller should filter the list of blogs by the title query parameter when the client visits http://localhost:4000/posts?title=search_string.

Consider including the following test cases.

Further Reading

Consider the following resource(s) to deepen your understanding of the topic.

For a deep-dive into testing, we highly recommend the excellent book Testing Elixir: Effective and Robust Testing for Elixir and its Ecosystem.

Mark As Completed

file_name = Path.basename(Regex.replace(~r/#.+/, __ENV__.file, ""), ".livemd")

save_name =
  case Path.basename(__DIR__) do
    "reading" -> "blog_search_reading"
    "exercises" -> "blog_search_exercise"
  end

progress_path = __DIR__ <> "/../progress.json"
existing_progress = File.read!(progress_path) |> Jason.decode!()

default = Map.get(existing_progress, save_name, false)

form =
  Kino.Control.form(
    [
      completed: input = Kino.Input.checkbox("Mark As Completed", default: default)
    ],
    report_changes: true
  )

Task.async(fn ->
  for %{data: %{completed: completed}} <- Kino.Control.stream(form) do
    File.write!(
      progress_path,
      Jason.encode!(Map.put(existing_progress, save_name, completed), pretty: true)
    )
  end
end)

form

Commit Your Progress

Run the following in your command line from the curriculum folder to track and save your progress in a Git commit. Ensure that you do not already have undesired or unrelated changes by running git status or by checking the source control tab in Visual Studio Code.

$ git checkout -b blog-search-exercise
$ git add .
$ git commit -m "finish blog search exercise"
$ git push origin blog-search-exercise

Create a pull request from your blog-search-exercise branch to your solutions branch. Please do not create a pull request to the DockYard Academy repository as this will spam our PR tracker.

DockYard Academy Students Only:

Notify your teacher by including @BrooklinJazz in your PR description to get feedback. You (or your teacher) may merge your PR into your solutions branch after review.

If you are interested in joining the next academy cohort, sign up here to receive more news when it is available.

Up Next

Previous Next
BookSearch: Authors Schemas and Migrations