Commit eebc6b8badbdc7a85d499ba521a8a7aaad0b738f
Committed by
Larissa Reis
1 parent
97e657da
Exists in
master
and in
22 other branches
tags: migration to fix tags case differences
Whenever you have 2 or more tags with the same name but different cases, ActsAsTaggableOn returns an empty list of objects tagged with either of the tags. To solve this problem, we must not have tags with different cases stored. Performance was my primal concern on this migration since we have instances that have over 130k tags registered. So I decided to convert every tag to lower case. This is the fastest way I could conceive this migration and still it might take a lot of time. Here is basic resume of what it basically does: x: number of new downcased tags created. y: number of oddcased tags. z: number of tags 1. Find all tags do not have a downcased form already created - [1 fast select query]. 2. Create a downcased version of the above queries - [x slow update queries but n is usually low because a minority of tags have odd case and all different cases of a single word generate only 1 query]. 3. Update taggings relations based on new ids - [1 slow update and 2 join queries]. 4. Updates the taggings_count of every tag - [1 slow update with z fast selects] 5. Delete all unused tags tags - [1 slow delete query]. Signed-off-by: Larissa Reis <larissa@colivre.coop.br>
Showing
1 changed file
with
19 additions
and
0 deletions
Show diff stats
... | ... | @@ -0,0 +1,19 @@ |
1 | +class FixTagsCaseDifferences < ActiveRecord::Migration | |
2 | + def up | |
3 | + tags = ActsAsTaggableOn::Tag.joins('LEFT JOIN tags as b on LOWER(tags.name) = b.name').where('b.id is null') | |
4 | + tags.find_each do |tag| | |
5 | + unless ActsAsTaggableOn::Tag.exists?(:name => tag.name.mb_chars.downcase) | |
6 | + ActsAsTaggableOn::Tag.create(:name => tag.name.mb_chars.downcase) | |
7 | + end | |
8 | + end | |
9 | + | |
10 | + execute("UPDATE taggings SET tag_id = new.id FROM taggings AS t INNER JOIN tags AS old ON t.tag_id = old.id INNER JOIN tags AS new ON LOWER(old.name) = new.name WHERE old.id != new.id AND taggings.id = t.id") | |
11 | + | |
12 | + execute("UPDATE tags SET taggings_count = (SELECT COUNT(*) FROM taggings WHERE taggings.tag_id = tags.id)") | |
13 | + execute("DELETE FROM tags WHERE taggings_count = 0") | |
14 | + end | |
15 | + | |
16 | + def down | |
17 | + say 'This migration is irreversible.' | |
18 | + end | |
19 | +end | ... | ... |