From 5d5662c281ebd10ec15f898c3fa5898137fbfa34 Mon Sep 17 00:00:00 2001 From: Osama Sayed Date: Sun, 24 Mar 2024 00:08:42 +0200 Subject: [PATCH 1/2] [QDC] Add filter by range API --- app/controllers/api/qdc/verses_controller.rb | 4 ++ app/finders/qdc/verse_finder.rb | 45 ++++++++++++++------ app/lib/quran_utils/verse_key.rb | 25 +++++++++++ config/routes/api/qdc.rb | 1 + 4 files changed, 62 insertions(+), 13 deletions(-) create mode 100644 app/lib/quran_utils/verse_key.rb diff --git a/app/controllers/api/qdc/verses_controller.rb b/app/controllers/api/qdc/verses_controller.rb index 2f65489c..91d221bc 100644 --- a/app/controllers/api/qdc/verses_controller.rb +++ b/app/controllers/api/qdc/verses_controller.rb @@ -4,6 +4,10 @@ module Api::Qdc class VersesController < Api::V4::VersesController before_action :init_presenter + def by_range + render partial: 'verses' + end + protected def init_presenter @presenter = Qdc::VersesPresenter.new(params, action_name) diff --git a/app/finders/qdc/verse_finder.rb b/app/finders/qdc/verse_finder.rb index 77a74165..5c033cf6 100644 --- a/app/finders/qdc/verse_finder.rb +++ b/app/finders/qdc/verse_finder.rb @@ -77,16 +77,21 @@ def fix_verses_order(verses) end def fetch_verses_range(filter, mushaf: nil, words: false) - # both from and to could be ayah key or ayah ID(not ayah number) - params[:from] = get_ayah_id(params[:from]) - params[:to] = get_ayah_id(params[:to]) - - if 'by_page' == filter - @results = fetch_by_page(mushaf: mushaf, words: words) - elsif 'by_juz' == filter - @results = fetch_by_juz(mushaf: mushaf) + if 'by_range' == filter + @results = fetch_by_range else - @results = send("fetch_#{filter}") + # TODO: we need to validate from and to before passing it to get_ayah_id. Currently "from"=>"testFrom:1", "to"=>"testTo:5" gets converted to "from"=>6231, "to"=>6235. {@see fetch_by_range} + # both from and to could be ayah key or ayah ID(not ayah number) + params[:from] = get_ayah_id(params[:from]) + params[:to] = get_ayah_id(params[:to]) + + if 'by_page' == filter + @results = fetch_by_page(mushaf: mushaf, words: words) + elsif 'by_juz' == filter + @results = fetch_by_juz(mushaf: mushaf) + else + @results = send("fetch_#{filter}") + end end end @@ -210,10 +215,24 @@ def fetch_by_ruku end def fetch_by_range + # 1. make sure both from and to are present + raise(RestApi::RecordNotFound.new("From and to must be present.")) unless params[:from] && params[:to] + from_range = QuranUtils::VerseKey.new(params[:from]) + from_verse_key_data = from_range.process_verse_key + to_range = QuranUtils::VerseKey.new(params[:to]) + to_verse_key_data = to_range.process_verse_key + # 2. make sure from and to are in the format of 'chapter:verse' e.g. don't accept from=test&to=anotherTest + raise(RestApi::RecordNotFound.new("Verse key contains invalid data")) if from_verse_key_data.empty? || to_verse_key_data.empty? + # 3. make sure from and to have both chapter and verse. e.g. don't allow testFrom:1&to=testTo:5 + raise(RestApi::RecordNotFound.new("Verse key contains invalid data")) unless from_verse_key_data.all? && to_verse_key_data.all? + params[:from] = get_ayah_id(params[:from]) + params[:to] = get_ayah_id(params[:to]) + # 4. make sure from and to Ids are not nil. Either can be nil if the verse key contains out of range values e.g. 1:8 or 500:1 + raise(RestApi::RecordNotFound.new("Verse key contains out of range values")) if params[:from].nil? || params[:to].nil? + # 5. make sure from is smaller than to. An invalid range e.g. from=1:7&to=1:4 + raise(RestApi::RecordNotFound.new("From should be smaller than to")) if params[:from] > params[:to] from, to = get_ayah_range_to_load(params[:from], params[:to]) - - @results = rescope_verses('verse_index') - .where('verses.verse_index >= ? AND verses.verse_index <= ?', from, to) + @results = rescope_verses('verse_index').where('verses.verse_index >= ? AND verses.verse_index <= ?', from, to) end def load_words(word_translation_lang, mushaf) @@ -309,4 +328,4 @@ def load_verse_to(default_to) default_to end end -end \ No newline at end of file +end diff --git a/app/lib/quran_utils/verse_key.rb b/app/lib/quran_utils/verse_key.rb new file mode 100644 index 00000000..8a12c8ef --- /dev/null +++ b/app/lib/quran_utils/verse_key.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module QuranUtils + class VerseKey + include QuranUtils::StrongMemoize + VERSE_KEY_REGEX = /(?\d+):?(?\d+)?/ + + def initialize(verse_key) + @verse_key = verse_key + end + + def process_verse_key + strong_memoize :process_verse_key do + match = @verse_key.match(VERSE_KEY_REGEX) + + return [] if match.nil? + + chapter = match[:chapter] + verse = match[:verse] + + [chapter, verse] + end + end + end +end diff --git a/config/routes/api/qdc.rb b/config/routes/api/qdc.rb index 3d17c579..1c44a052 100644 --- a/config/routes/api/qdc.rb +++ b/config/routes/api/qdc.rb @@ -72,6 +72,7 @@ get 'by_hizb/:hizb_number', action: 'by_hizb' get 'by_ruku/:ruku_number', action: 'by_ruku' get 'by_key/:verse_key', action: 'by_key' + get 'by_range', action: 'by_range' get :filter From 6b287be128d8942c024767a76fdc5f76ca80635d Mon Sep 17 00:00:00 2001 From: Osama Sayed Date: Sun, 24 Mar 2024 01:36:56 +0200 Subject: [PATCH 2/2] [QDC] Add look_up for ranges --- app/presenters/qdc/mushaf_page_presenter.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/presenters/qdc/mushaf_page_presenter.rb b/app/presenters/qdc/mushaf_page_presenter.rb index a5f4a9bc..c451b9e4 100644 --- a/app/presenters/qdc/mushaf_page_presenter.rb +++ b/app/presenters/qdc/mushaf_page_presenter.rb @@ -96,10 +96,12 @@ def look_up_filter 'by_hizb' elsif params[:ruku_number].present? 'ruku_number' + elsif params[:from].present? && params[:to].present? + 'by_range' else raise_404 "Look up filter is invalid, please provide a valid filter(chapter_number, juz_number, page_number, manzil_number, rub_el_hizb_number, hizb_number, ruku_number)" end end end end -end \ No newline at end of file +end