diff --git a/app/queries/applications_index_query.rb b/app/queries/applications_index_query.rb new file mode 100644 index 00000000..bb2638ff --- /dev/null +++ b/app/queries/applications_index_query.rb @@ -0,0 +1,33 @@ +class ApplicationsIndexQuery + delegate :to_sql, to: :query + + def execute + ApplicationRecord.connection.execute(to_sql) + end + + def query + @query ||= applications + .project(projection) + .order(applications[:created_at].asc) + end + + def projection + [ + applications[:id], + row_number.as("application_index"), + ] + end + + def row_number + Arel::Nodes::Over.new( + Arel::Nodes::NamedFunction.new("ROW_NUMBER", []), + Arel.sql("(ORDER BY created_at ASC)"), + ) + end + +private + + def applications + Application.arel_table + end +end diff --git a/app/queries/find_application_index_query.rb b/app/queries/find_application_index_query.rb new file mode 100644 index 00000000..551c6f16 --- /dev/null +++ b/app/queries/find_application_index_query.rb @@ -0,0 +1,37 @@ +class FindApplicationIndexQuery + delegate :to_sql, to: :query + attr_reader :application_id + + def initialize(application_id:) + @application_id = application_id + end + + def execute + ApplicationRecord.connection.execute(to_sql) + end + + def query + @query ||= manager + .project(projection) + .from(from_clause) + .where(where_clause) + end + + def projection + [Arel.star] + end + + def from_clause + ApplicationsIndexQuery.new.query.as("list") + end + + def where_clause + Arel.sql("list.id").eq(application_id) + end + +private + + def manager + @manager ||= Arel::SelectManager.new(Arel::Table.engine) + end +end diff --git a/spec/queries/applications_index_query_spec.rb b/spec/queries/applications_index_query_spec.rb new file mode 100644 index 00000000..dda743be --- /dev/null +++ b/spec/queries/applications_index_query_spec.rb @@ -0,0 +1,12 @@ +require "rails_helper" + +RSpec.describe ApplicationsIndexQuery, type: :model do + subject(:sql) { described_class.new.to_sql } + + describe "#to_sql" do + it { expect(sql).to include("SELECT") } + it { expect(sql).to include('"applications"."id"') } + it { expect(sql).to include("ROW_NUMBER() OVER (ORDER BY created_at ASC) AS application_index") } + it { expect(sql).to include('FROM "applications"') } + end +end diff --git a/spec/queries/find_application_index_query_spec.rb b/spec/queries/find_application_index_query_spec.rb new file mode 100644 index 00000000..7de40a1c --- /dev/null +++ b/spec/queries/find_application_index_query_spec.rb @@ -0,0 +1,14 @@ +require "rails_helper" + +RSpec.describe FindApplicationIndexQuery, type: :model do + subject(:sql) { described_class.new(application_id: application.id).to_sql } + + let(:application) { create(:application) } + let(:subquery) { ApplicationsIndexQuery.new.to_sql } + + describe "#to_sql" do + it { expect(sql).to include("SELECT *") } + it { expect(sql).to include("FROM (#{subquery}) list") } + it { expect(sql).to include("WHERE list.id = #{application.id}") } + end +end