11

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.

zwol
  • 135,547
  • 38
  • 252
  • 361

1 Answers1

3

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
Paul A Jungwirth
  • 23,504
  • 14
  • 74
  • 93
  • I have a distinct recollection of doing something that led me to believe that `FeedItem` objects do not _have_ a `tags` property. There are some weird things in [the definition of `FeedItem`](https://github.com/berkmancenter/tagteam/blob/master/app/models/feed_item.rb) - look specifically at what it's doing with `:tag_context_hierarchy`. Can you offer any additional advice on what might need to be changed in your answer to cope with that? – zwol Jan 23 '18 at 14:56
  • It has a simple [`acts_as_taggable` declaration](https://github.com/berkmancenter/tagteam/blob/master/app/models/feed_item.rb#L24). I don't see anything in `tag_context_hierarchy` to change that. You can see that [it even uses the `tags` association itself](https://github.com/berkmancenter/tagteam/blob/master/app/models/feed_item.rb#L185-L189). – Paul A Jungwirth Jan 23 '18 at 16:45
  • Hmm, OK. That's enough information that I can believe this _ought_ to work. I timed the bounty badly; I won't be able to test this for another month or so. I'm going to go ahead and give the bounty to you, but not accept the answer until I've actually tested it. – zwol Jan 23 '18 at 17:06
  • For the record, [this is the weird thing I was concerned about](https://github.com/berkmancenter/tagteam/blob/master/app/models/feed_item.rb#L59). – zwol Jan 23 '18 at 17:07
  • I don't think you need to be concerned about that. `acts_as_api` controls how instances are serialized to JSON when rendering an HTTP response, but it doesn't replace the `tags` method. (Right? I haven't used it, but I glanced at its docs.) – Paul A Jungwirth Jan 23 '18 at 17:20
  • Your guess is probably better than mine - I don't even really speak Ruby. In retrospect, attempting to build on this particular Rails app may have been a mistake. – zwol Jan 23 '18 at 17:58