Fix OR condition in public taggings

In SQL, conditions like:

```
tag_id IN (x) AND taggable_type='Debate' OR taggable_type='Proposal'
```

Don't work as intended; we need to write:

```
tag_id IN (x) AND (taggable_type='Debate' OR taggable_type='Proposal')
```

Due to this bug, we were returning taggings for proposals without
intending to do so.

Since the code was very hard to read, we're also simplifying it.
This commit is contained in:
Javi Martín
2021-09-19 02:01:26 +02:00
parent effd646e54
commit 2e863fdc51
2 changed files with 29 additions and 9 deletions

View File

@@ -4,12 +4,10 @@ module ActsAsTaggableOn
after_destroy :touch_taggable, :decrement_tag_custom_counter
scope :public_for_api, -> do
where(%{taggings.tag_id in (?) and
(taggings.taggable_type = 'Debate' and taggings.taggable_id in (?)) or
(taggings.taggable_type = 'Proposal' and taggings.taggable_id in (?))},
Tag.where("kind IS NULL or kind = ?", "category").pluck(:id),
Debate.public_for_api.pluck(:id),
Proposal.public_for_api.pluck(:id))
where(
tag: Tag.where(kind: [nil, "category"]),
taggable: [Debate.public_for_api, Proposal.public_for_api]
)
end
def touch_taggable
@@ -35,9 +33,10 @@ module ActsAsTaggableOn
include Graphqlable
scope :public_for_api, -> do
where("(tags.kind IS NULL or tags.kind = ?) and tags.id in (?)",
"category",
Tagging.public_for_api.distinct.pluck("taggings.tag_id"))
where(
kind: [nil, "category"],
id: Tagging.public_for_api.distinct.pluck(:tag_id)
)
end
include PgSearch::Model

View File

@@ -0,0 +1,21 @@
require "rails_helper"
describe Tagging do
describe ".public_for_api" do
it "returns taggings for debates and proposals" do
create(:tag, name: "Health", kind: nil)
debate = create(:debate, tag_list: "Health")
proposal = create(:proposal, tag_list: "Health")
expect(Tagging.public_for_api.map(&:taggable)).to match_array [debate, proposal]
end
it "does not return taggings for other tag kinds" do
create(:tag, name: "Health", kind: "custom")
create(:debate, tag_list: "Health")
create(:proposal, tag_list: "Health")
expect(Tagging.public_for_api.map(&:taggable)).to be_empty
end
end
end