Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails "acts-as-taggable-on": how to add tag *objects* to taggables, not by name

In a data importer, I have code which is attempting to add a bunch of ActsAsTaggableOn::Tag objects to a taggable's tag list:

    existing_item = FeedItem.where(url: item[:url]).first

    if existing_item.nil?
      new_item = FeedItem.new

      new_item.attributes = item.except(:id, :feeds)

      new_item.feeds = Feed.where(id: feeds_old_to_new(item_feeds, feeds))
      new_item.tag_list.add(
          ActsAsTaggableOn::Tag.where(id: tags_old_to_new(item[:tags], tags)))

      new_item.save!
   else
      # ... merge imported record with existing item ...
   end

This doesn't work, because tag_list.add takes a list of tag names, not tag objects. Is there any way to add tag objects? I can't find anything in the acts-as-taggable-on documentation, and its code is much too magic for me to understand (for instance, Tag::concat doesn't appear to mutate self!)

I could map the tags to their names, but then acts-as-taggable-on would run name canonicalization that is appropriate for user input but not for bulk data import, so I don't want to do that.

like image 269
zwol Avatar asked Dec 10 '17 15:12

zwol


1 Answers

The gem is really just adding this for you:

has_many :taggings
has_many :tags, through: :taggings

(It's a little more complicated to support multiple kinds of tags, but the details are pretty simple.)

So you can use those associations just like any other. In your case it'd be something like:

ActsAsTaggableOn::Tag.where(id: tags_old_to_new(item[:tags], tags))).each do | t|
  new_item.tags << t
end
like image 157
Paul A Jungwirth Avatar answered Oct 26 '22 07:10

Paul A Jungwirth