4

I am using acts-as-taggable-on gem

i use single field to search by tag_name and user_name

User.rb

class User < ActiveRecord::Base

  acts_as_taggable
  attr_accessor: :user_name, :age, :country, tag_list
  scope :tagged_with, lambda { |tag|
    {
      :joins => "INNER JOIN taggings ON taggings.taggable_id = user.id\
               INNER JOIN tags ON tags.id = taggings.tag_id AND taggings.taggable_type = 'User'",
      :conditions => ["tags.name = ?", tag],
      :order => 'id ASC'
    }
  }
  def self.search(search)
    if search
      where('name LIKE ?', "%#{search}%") + tagged_with(search)
    else
      scoped
    end
  end
end

But i have pagination issue while getting this as Array and i used "will_paginate/Array" in config/initializer/will_paginate.rb it doesn't work.

User controller

class UserController < ActionController::Base
  def index
    @users = User.search(params[:search]).paginate(:per_page => per_page, :page => params[:page])
  end

Console.

User.search("best") => Should search by both tag_name and user_name and return ActiveRecord result.

i want to get the result of User.search("best") union with result of tag name User.tagged_with("best")

Can you help me to add this scopes as ActiveRecord relation to use pagination without issue.

Mano
  • 979
  • 1
  • 18
  • 36
  • 1
    I think your scope can be rewritten to: `scope :tagged_with, lambda { |tag| joins(:tags).where(tags: { name: tag }).order('users.id ASC') })` – MrYoshiji Oct 21 '15 at 13:18

1 Answers1

3

I think you just need to return a chainable scope (use . instead of +):

where('name LIKE ?', "%#{search}%").tagged_with(search)

It returns an ActiveRecord::Relation instead of an Array.

If you need to perform an UNION operation, I recommend you to follow this thread: ActiveRecord Query Union.

One possible approach is to extend ActiveRecord:

module ActiveRecord::UnionScope
  def self.included(base)
    base.send(:extend, ClassMethods)
  end

  module ClassMethods
    def union_scope(*scopes)
      id_column = "#{table_name}.id"
      sub_query = scopes.map { |s| s.select(id_column).to_sql }.join(" UNION ")
      where("#{id_column} IN (#{sub_query})")
    end
  end
end 

Usage (not tested):

class User < ActiveRecord::Base
  include ActiveRecord::UnionScope

  def self.search(search)
    if search
      union_scope(where('name LIKE ?', "%#{search}%"), tagged_with(search))
    else
      scoped
    end
  end
end
Community
  • 1
  • 1
markets
  • 6,709
  • 1
  • 38
  • 48
  • Thanks for replying. i want to get the result of User.search("best") union with result of tag name User.tagged_with("best"). – Mano Oct 21 '15 at 13:42
  • Thanks for answer. Its working great from my console. Now i'm gettting this error http://stackoverflow.com/questions/33281995/mysql2-lost-connection-to-mysql-server-during-query. Kindly help. – Mano Oct 26 '15 at 06:17