Skip to content

Implement a query object for tasks #34

@biggujo

Description

@biggujo

Set of methods:

  • sort by name (ascending, descending);
  • sort by deadline (ascending, descending);
  • filter by actual status: only completed/only in progress/only overdue tasks (it means deadline has passed, but the task is still in progress);
  • filter by date range (e.g. tasks between 2024-03-02 12:00 and 2024-04-05 12:00);
  • pagination

Hint: dates can be compared as plain strings (e.g. of a query: "deadline >= 2024-03-02 12:00 and deadline <= 2024-04-05 12:00")

Steps to implement:

  • create folder backend/query;
  • create file backend/query/tasks_query.py;
  • implement a class TasksQuery:
    • constructor accepts an object of initial scope of data;
    • methods (better to make private, but not essential):
      • like in Rails last homework

How to use this class:

  • in tasks_controller.py in def index() write something like this (it is not tested to work, though):
def index():
  user_id = session.get("id")
  if user_id is None:
      return {'message': 'Unauthorized'}, 401

  parameters = request.args
  initial_scope = Task.query_user_tasks(user_id).all()

  query_object = new TasksQuery(initial_scope) # idk if it works. It is just a pseudocode
  scoped_data = query_object.call(parameters)

  return jsonify(json_list=[i.serialize for i in scoped_data])

How to test:

Authorisation request:
Image

Create tasks request:
Image

Update task:
Image

Main request to test queries:
Image


Example of Query Object class in Rails:

# frozen_string_literal: true

class ServiceSubcategoryQuery
  attr_accessor :initial_scope

  def initialize(initial_scope)
    @initial_scope = initial_scope
  end

  def call(params)
    scoped = @initial_scope

    scoped = filter_by_name(scoped, params)
    scoped = filter_by_domain(scoped, params)
    sort_by_categories_amount(scoped, params)
  end

  private

  def filter_by_name(scoped, params)
    query = params[:query]

    scoped.where("categoryname ILIKE ?", "%#{query}%")
  end

  def filter_by_domain(scoped, params)
    domain = params[:domain]

    is_domain_empty = domain == "" || domain.nil?

    return scoped if is_domain_empty

    scoped.where(servicedomain_id: domain.to_i)
  end

  def sort_by_categories_amount(scoped, params)
    sort_order = params[:sort_by_services_amount] == "ascending" ? "ASC" : "DESC"

    scoped.left_joins(:services)
          .group("servicesubcategories.id")
          .order("COUNT(services.id) #{sort_order}")
  end
end

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions