When `acts-as-taggable-on`'s `.tagged_with()` is used with `any: true`,
the gem will use `SELECT *` regardless of any previous (or following) requests
of selecting a limited amount of columns.
Given that the `articles` table has [73 columns](https://dev.to/admin/blazer/queries/314-number-of-columns-in-all-tables)
that will amount to wasted RAM memory for columns we don't need.
By "unscoping" any previous `select()` we can optimize used memory.
Before:
```ruby
[24] pry(main)> Article.tagged_with([:ruby], any: true).select(:id, :name).to_sql
=> "SELECT \"articles\".*, \"articles\".\"id\", \"name\" FROM \"articles\" WHERE EXISTS (SELECT * FROM \"taggings\" WHERE \"taggings\".\"taggable_id\" = \"articles\".\"id\" AND \"taggings\".\"taggable_type\" = 'Article' AND \"taggings\".\"tag_id\" IN (SELECT \"tags\".\"id\" FROM \"tags\" WHERE (\"tags\".\"name\" LIKE 'ruby' ESCAPE '!')))"
```
Note, how the SQL query is `articles.*, articles.column_a`
After:
[25] pry(main)> Article.tagged_with([:ruby], any: true).unscope(:select).select(:id, :name).to_sql
=> "SELECT \"articles\".\"id\", \"name\" FROM \"articles\" WHERE EXISTS (SELECT * FROM \"taggings\" WHERE \"taggings\".\"taggable_id\" = \"articles\".\"id\" AND \"taggings\".\"taggable_type\" = 'Article' AND \"taggings\".\"tag_id\" IN (SELECT \"tags\".\"id\" FROM \"tags\" WHERE (\"tags\".\"name\" LIKE 'ruby' ESCAPE '!')))"
```
`articles.*` is gone :-)
- https://github.com/mbleigh/acts-as-taggable-on/issues/936
- 47da5036de/lib/acts_as_taggable_on/taggable/tagged_with_query/any_tags_query.rb (L2-L8)
53 lines
1.5 KiB
Ruby
53 lines
1.5 KiB
Ruby
module Articles
|
|
class SuggestStickies
|
|
SUGGESTION_TAGS = %w[career productivity discuss explainlikeimfive].freeze
|
|
|
|
def self.call(article)
|
|
new(article).call
|
|
end
|
|
|
|
def initialize(article)
|
|
@article = article
|
|
@reaction_count_num = Rails.env.production? ? 15 : -1
|
|
@comment_count_num = Rails.env.production? ? 7 : -2
|
|
end
|
|
|
|
def call
|
|
(tag_articles.load + more_articles).sample(3)
|
|
end
|
|
|
|
private
|
|
|
|
attr_accessor :article, :reaction_count_num, :comment_count_num
|
|
|
|
def tag_articles
|
|
article_tags = article.cached_tag_list_array - ["discuss"]
|
|
|
|
Article
|
|
.published
|
|
.tagged_with(article_tags, any: true).unscope(:select)
|
|
.limited_column_select
|
|
.where("public_reactions_count > ? OR comments_count > ?", reaction_count_num, comment_count_num)
|
|
.where.not(id: article.id)
|
|
.where.not(user_id: article.user_id)
|
|
.where("featured_number > ?", 5.days.ago.to_i)
|
|
.order(Arel.sql("RANDOM()"))
|
|
.limit(3)
|
|
end
|
|
|
|
def more_articles
|
|
return [] if tag_articles.size > 6
|
|
|
|
Article
|
|
.published
|
|
.tagged_with(SUGGESTION_TAGS, any: true).unscope(:select)
|
|
.limited_column_select
|
|
.where("comments_count > ?", comment_count_num)
|
|
.where.not(id: article.id)
|
|
.where.not(user_id: article.user_id)
|
|
.where("featured_number > ?", 5.days.ago.to_i)
|
|
.order(Arel.sql("RANDOM()"))
|
|
.limit(10 - tag_articles.size)
|
|
end
|
|
end
|
|
end
|