Search code examples
ruby-on-railsacts-as-taggable-onhas-scope

How to use acts-as-taggable-on with has_scope?


I'm building an API that returns a list of posts (localhost:3000/api/v1/posts):

{
  "tags": [
    {
      "id": 1,
      "name": "Tag 1"
    },
    {
      "id": 2,
      "name": "Tag 2"
    },
    …
  ],
  "posts": [
    {
      "id": 1,
      "title": "Post 1",
      "body": "Lorem ipsum dolor sit amet.",
      "tag_ids": [
        1
      ]
    },
    {
      "id": 2,
      "title": "Post 2",
      "body": "Lorem ipsum dolor sit amet.",
      "tag_ids": [
        2
      ]
    },
    …
  ]
}

These posts are tagged using the acts-as-taggable-on gem. I'd like to be able to filter them based on these tags using the has_scope gem (localhost:3000/api/v1/posts?tag_id=1):

{
  "tags": [
    {
      "id": 1,
      "name": "Tag 1"
    }
  ],
  "posts": [
    {
      "id": 1,
      "title": "Post 1",
      "body": "Lorem ipsum dolor sit amet.",
      "tag_ids": [
        1
      ]
    }
  ]
}

But I have no idea how to set a by_tag_id scope in my model since the acts-as-taggable-on documentation only explains how to find objects based on their tag names (using the tagged_with()method).

Thank you in advance for your help! ;-)

David


Solution

  • For those interested, I solved the problem like this… Here is my Post model:

    class Post < ActiveRecord::Base
      attr_accessible :title, :body, :tag_list
    
      # Alias for acts_as_taggable_on :tags
      acts_as_taggable
    
      # Named scope which returns posts whose tags have a specific ID
      scope :tagged_with_id, lambda { |tag_id| joins(:taggings).where(:taggings => {:tag_id => tag_id}) }
    end
    

    And my Posts controller:

    class PostsController < ApplicationController
      has_scope :tagged_with_id
    
      def index
        @posts = apply_scopes(Post).all
    
        render :json => @posts
      end
    end