mbleigh / acts-as-taggable-on

A tagging plugin for Rails applications that allows for custom tagging along dynamic contexts.
http://mbleigh.lighthouseapp.com/projects/10116-acts-as-taggable-on
MIT License
4.96k stars 1.19k forks source link

N+1 SQL query problem with serialization due to tag_list #1029

Open lukes opened 3 years ago

lukes commented 3 years ago

Hi!

The use of attribute for tag_list appears to be responsible for an N+1 SQL query problem when taggable records are serialized.

Example:

MyTaggableModel.all.as_json 
# => Observe the N+1 problem calls to `ActsAsTaggableOn::Tagging` and `ActsAsTaggableOn::Tag`

This is due to the attribute's inclusion in #serializable_hash:

MyTaggableModel.new.serializable_hash # => `Hash` includes "tag_list" key

Our workaround, because we do not need tag_list to be serialized is to always exclude: it:

MyTaggableModel.all.as_json(exclude: :tag_list)

But this is a gotcha if we ever serialize a collection of records that are taggable, and forget to do this.

ggladden commented 2 years ago

I ran into this same issue when fragment caching taggable records. I overrode the serializable_hash method on models using acts-as-taggable as a workaround.

private

def serializable_hash
  self.attributes.reject{ |k, v| k == 'tag_list' }
end

Wondering if there is a better solution?

rieg-ec commented 1 year ago

I'm having the same issue, it isn't a nice default i guess, it should be opt-in

neco3s commented 1 year ago

I personally use serizlizer to do the handling with the following code. I would be happy if this information is useful to anyone!

class Model < ApplicationRecord
   acts_as_taggable
end

class ModelSerializer < ApplicationSerializer
  attributes :tag_list,

  has_many :tags

  # delegate :tag_list, to: :object

  def tag_list
    object.tags.pluck(:name)
  end
end