Skip to content

Commit

Permalink
add proper delete method for categories
Browse files Browse the repository at this point in the history
  • Loading branch information
leafo committed Jul 7, 2023
1 parent 0dd1afa commit 5413075
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 8 deletions.
13 changes: 9 additions & 4 deletions community/flows/categories.lua
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,8 @@ do
end
orphans = _accum_0
end
local archived
local to_delete = { }
local archived = { }
do
local _accum_0 = { }
local _len_0 = 1
Expand All @@ -574,15 +575,15 @@ do
repeat
local o = orphans[_index_0]
if o.topics_count > 0 then
o:update(filter_update(o, {
table.insert(archived, o)
_accum_0[_len_0] = o:update(filter_update(o, {
archived = true,
hidden = true,
parent_category_id = self.category.id,
position = Categories:next_position(self.category.id)
}))
_accum_0[_len_0] = o
else
o:delete()
table.insert(to_delete, o)
_continue_0 = true
break
end
Expand All @@ -595,6 +596,10 @@ do
end
archived = _accum_0
end
for _index_0 = 1, #to_delete do
local cat = to_delete[_index_0]
cat:delete("hard")
end
return true, archived
end),
edit_category = require_current_user(function(self, fields_list)
Expand Down
14 changes: 12 additions & 2 deletions community/flows/categories.moon
Original file line number Diff line number Diff line change
Expand Up @@ -428,19 +428,29 @@ class CategoriesFlow extends Flow
continue if existing_assigned[c.id]
c

to_delete = {}
archived = {}

-- archive the orphans that have topics, delete the empty ones
-- Note: we do this in two phases to move deeply nested categories to the
-- top before deleting empty ones, as deleting a cascades to all current children

archived = for o in *orphans
if o.topics_count > 0
table.insert archived, o
o\update filter_update o, {
archived: true
hidden: true
parent_category_id: @category.id
position: Categories\next_position @category.id
}
o
else
o\delete!
table.insert to_delete, o
continue

for cat in *to_delete
cat\delete "hard"

true, archived

-- fields_list: can contain any name from CATEGORY_VALIDATION, or "category_tags"
Expand Down
50 changes: 50 additions & 0 deletions community/models/categories.lua
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,56 @@ do
end
end
return false
end,
delete = function(self, force)
assert(force == "hard", "pass `hard` to delete category")
if not (_class_0.__parent.__base.delete(self)) then
return
end
local OrderedPaginator
OrderedPaginator = require("lapis.db.pagination").OrderedPaginator
local Topics, Subscriptions, Bans, Moderators, ActivityLogs, CategoryTags, CategoryPostLogs, CategoryGroupCategories
do
local _obj_0 = require("community.models")
Topics, Subscriptions, Bans, Moderators, ActivityLogs, CategoryTags, CategoryPostLogs, CategoryGroupCategories = _obj_0.Topics, _obj_0.Subscriptions, _obj_0.Bans, _obj_0.Moderators, _obj_0.ActivityLogs, _obj_0.CategoryTags, _obj_0.CategoryPostLogs, _obj_0.CategoryGroupCategories
end
local _list_0 = {
CategoryTags,
CategoryPostLogs,
CategoryGroupCategories
}
for _index_0 = 1, #_list_0 do
local model = _list_0[_index_0]
db.delete(model:table_name(), "category_id = ?", self.id)
end
local _list_1 = {
Moderators,
Subscriptions,
Bans,
ActivityLogs
}
for _index_0 = 1, #_list_1 do
local model = _list_1[_index_0]
db.delete(model:table_name(), db.clause({
object_type = assert(model:object_type_for_object(self)),
object_id = assert(self.id)
}))
end
local topics_pager = OrderedPaginator(Topics, {
"id"
}, db.clause({
category_id = self.id
}), {
per_page = 100
})
for topic in topics_pager:each_item() do
topic:delete("hard")
end
local _list_2 = Categories:select("where parent_category_id = ?", self.id)
for _index_0 = 1, #_list_2 do
local child = _list_2[_index_0]
child:delete("hard")
end
end
}
_base_0.__index = _base_0
Expand Down
42 changes: 42 additions & 0 deletions community/models/categories.moon
Original file line number Diff line number Diff line change
Expand Up @@ -766,3 +766,45 @@ class Categories extends Model

false


-- this cascades to all children
delete: (force) =>
assert force == "hard", "pass `hard` to delete category"

return unless super!

import OrderedPaginator from require "lapis.db.pagination"
import Topics, Subscriptions, Bans, Moderators, ActivityLogs, CategoryTags,
CategoryPostLogs, CategoryGroupCategories from require "community.models"

-- TODO: UserCategoryLastSeens -- does not have index on category_id

for model in *{
CategoryTags
CategoryPostLogs
CategoryGroupCategories
}
db.delete model\table_name!, "category_id = ?", @id

-- polymorphic references
for model in *{
Moderators
Subscriptions
Bans
ActivityLogs
}
db.delete model\table_name!, db.clause {
object_type: assert model\object_type_for_object @
object_id: assert @id
}

topics_pager = OrderedPaginator Topics, {"id"}, db.clause({
category_id: @id
}), per_page: 100

for topic in topics_pager\each_item!
topic\delete "hard"

for child in *Categories\select "where parent_category_id = ?", @id
child\delete "hard"

61 changes: 59 additions & 2 deletions spec/models/categories_spec.moon
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
db = require "lapis.db"
factory = require "spec.factory"

import assert_no_queries from require "spec.helpers"
import assert_no_queries, assert_has_queries, sorted_pairs from require "spec.helpers"

describe "models.categories", ->
sorted_pairs!

import Users from require "spec.models"
import Categories, Moderators, CategoryMembers, Bans,
CategoryGroups, CategoryGroupCategories, UserCategoryLastSeens, Topics
CategoryGroups, CategoryGroupCategories, UserCategoryLastSeens, Topics, Posts
from require "spec.community_models"

it "should create a category", ->
Expand Down Expand Up @@ -36,6 +38,61 @@ describe "models.categories", ->
"hello"
}, [t.slug for t in *category\parse_tags "hello,zone,hello,butt"]

describe "delete", ->
i = db.interpolate_query

it "does nothing without `hard`", ->
category = factory.Categories!
assert.has_error(
-> category\delete!
"pass `hard` to delete category"
)

it "deletes an empty category", ->
category = factory.Categories!
assert_has_queries {
i [[DELETE FROM "community_categories" WHERE "id" = ?]], category.id
i [[DELETE FROM "community_category_tags" WHERE category_id = ?]], category.id
i [[DELETE FROM "community_category_post_logs" WHERE category_id = ?]], category.id
i [[DELETE FROM "community_category_group_categories" WHERE category_id = ?]], category.id
i [[DELETE FROM "community_moderators" WHERE "object_id" = ? AND "object_type" = 1]], category.id
i [[DELETE FROM "community_subscriptions" WHERE "object_id" = ? AND "object_type" = 2]], category.id
i [[DELETE FROM "community_bans" WHERE "object_id" = ? AND "object_type" = 1]], category.id
i [[DELETE FROM "community_activity_logs" WHERE "object_id" = ? AND "object_type" = 3]], category.id
}, ->
category\delete "hard"

it "deletes category with topics", ->
category = factory.Categories!
topic = factory.Topics category_id: category.id

other_topic = factory.Topics!

assert_has_queries {
i [[DELETE FROM "community_categories" WHERE "id" = ?]], category.id
i [[DELETE FROM "community_topics" WHERE "id" = ? RETURNING *]], topic.id
}, ->
category\delete "hard"

assert.same 1, Topics\count!
assert.same 1, Categories\count!

it "deletes category with children", ->
category = factory.Categories!
child = factory.Categories parent_category_id: category.id
topic = factory.Topics category_id: child.id

assert_has_queries {
i [[DELETE FROM "community_categories" WHERE "id" = ?]], category.id
i [[DELETE FROM "community_categories" WHERE "id" = ?]], child.id
i [[DELETE FROM "community_topics" WHERE "id" = ? RETURNING *]], topic.id
}, ->
category\delete "hard"

assert.same 0, Topics\count!
assert.same 0, Posts\count!
assert.same 0, Categories\count!

describe "with category", ->
local category, category_user

Expand Down

0 comments on commit 5413075

Please sign in to comment.