Skip to content

Commit

Permalink
[WIP] Ticket CV2-5007: Completed basic implementation using UNION
Browse files Browse the repository at this point in the history
  • Loading branch information
caiosba committed Feb 18, 2025
1 parent 49175b4 commit 3109b2b
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 17 deletions.
19 changes: 12 additions & 7 deletions app/graph/types/team_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,10 @@ def tipline_requests(from_timestamp:, to_timestamp:)
end

field :articles, ::ArticleUnion.connection_type, null: true do
argument :article_type, GraphQL::Types::String, required: true, camelize: false
argument :article_type, GraphQL::Types::String, required: false, camelize: false

# Sort and pagination
argument :limit, GraphQL::Types::Int, required: false, default_value: 10
argument :offset, GraphQL::Types::Int, required: false, default_value: 0
argument :sort, GraphQL::Types::String, required: false, default_value: 'title'
argument :sort_type, GraphQL::Types::String, required: false, camelize: false, default_value: 'ASC'
Expand All @@ -331,13 +332,17 @@ def articles(**args)
sort = args[:sort].to_s
order = [:title, :language, :updated_at, :id].include?(sort.downcase.to_sym) ? sort.downcase.to_sym : :title
order_type = args[:sort_type].to_s.downcase.to_sym == :desc ? :desc : :asc
articles = Explainer.none
if args[:article_type] == 'explainer'
articles = object.filtered_explainers(args)
elsif args[:article_type] == 'fact-check'
articles = object.filtered_fact_checks(args)
if args[:article_type].blank?
object.filtered_articles(args, args[:limit].to_i, args[:offset].to_i, order, order_type)
else
articles = Explainer.none
if args[:article_type] == 'explainer'
articles = object.filtered_explainers(args)
elsif args[:article_type] == 'fact-check'
articles = object.filtered_fact_checks(args)
end
articles.offset(args[:offset].to_i).order(order => order_type)
end
articles.offset(args[:offset].to_i).order(order => order_type)
end

field :articles_count, GraphQL::Types::Int, null: true do
Expand Down
22 changes: 20 additions & 2 deletions app/models/team.rb
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,23 @@ def available_newsletter_header_types
available
end

def filtered_articles(filters = {}, limit = 10, offset = 0, order = 'created_at', order_type = 'DESC')
columns = [:id, :title, :language, :created_at, :updated_at]
fact_checks = self.filtered_fact_checks(filters, false).select("'FactCheck' AS type, " + columns.collect{ |column| "fact_checks.#{column}" }.join(', '))

Check warning

Code scanning / Brakeman

Possible SQL injection. Warning

Possible SQL injection.
explainers = self.filtered_explainers(filters).select("'Explainer' AS type, " + columns.collect{ |column| "explainers.#{column}" }.join(', '))

Check warning

Code scanning / Brakeman

Possible SQL injection. Warning

Possible SQL injection.

# FIXME: Make sure SQL injections are taken care off
query = <<~SQL
SELECT type, id FROM ( #{fact_checks.to_sql} UNION #{explainers.to_sql} ) AS articles
ORDER BY #{order} #{order_type} LIMIT ? OFFSET ?
SQL

results = ActiveRecord::Base.connection.exec_query(ActiveRecord::Base.sanitize_sql([query, limit, offset]))

# FIXME: Avoid N + 1 queries problem here
records = results.map{ |row| OpenStruct.new(row) }.collect{ |object| object.type.constantize.find(object.id) }
end

def filtered_explainers(filters = {})
query = self.explainers

Expand All @@ -513,8 +530,9 @@ def filtered_explainers(filters = {})
query
end

def filtered_fact_checks(filters = {})
query = FactCheck.includes(:claim_description).where('claim_descriptions.team_id' => self.id)
def filtered_fact_checks(filters = {}, include_claim_descriptions = true)
query = (include_claim_descriptions ? FactCheck.includes(:claim_description) : FactCheck.joins(:claim_description))
query = query.where('claim_descriptions.team_id' => self.id)

# Filter by standalone
query = query.left_joins(claim_description: { project_media: :media }).where('claim_descriptions.project_media_id IS NULL OR medias.type = ?', 'Blank') if filters[:standalone]
Expand Down
3 changes: 2 additions & 1 deletion lib/relay.idl
Original file line number Diff line number Diff line change
Expand Up @@ -13183,7 +13183,7 @@ type Team implements Node {
Returns the elements in the list that come after the specified cursor.
"""
after: String
article_type: String!
article_type: String

"""
Returns the elements in the list that come before the specified cursor.
Expand All @@ -13202,6 +13202,7 @@ type Team implements Node {
Returns the last _n_ elements from the list.
"""
last: Int
limit: Int = 10
offset: Int = 0
publisher_ids: [Int]
rating: [String]
Expand Down
22 changes: 15 additions & 7 deletions public/relay.json
Original file line number Diff line number Diff line change
Expand Up @@ -69221,18 +69221,26 @@
"name": "article_type",
"description": null,
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"ofType": null
}
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"defaultValue": null,
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "limit",
"description": null,
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
},
"defaultValue": "10",
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "offset",
"description": null,
Expand Down
14 changes: 14 additions & 0 deletions test/models/team_2_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1590,4 +1590,18 @@ def setup
t = create_team
assert_equal [], t.search_for_similar_articles('Test')
end

# FIXME: Test with all possible filters
test "should return all articles" do
Sidekiq::Testing.fake!
t = create_team
u = create_user
create_team_user team: t, user: u, role: 'admin'
create_fact_check title: 'Foo', user: u, claim_description: create_claim_description(project_media: create_project_media(team: t))
sleep 1
create_explainer team: t, title: 'Bar', user: u

assert_equal ['Foo'], t.filtered_articles({ user_ids: [u.id] }, 1, 0, 'created_at', 'ASC').map(&:title)
assert_equal ['Bar'], t.filtered_articles({ user_ids: [u.id] }, 1, 0, 'created_at', 'DESC').map(&:title)
end
end

0 comments on commit 3109b2b

Please sign in to comment.