Skip to content

Implement a query object for tasks #34

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions