mrkamel/search_cop

Support for PostgreSQL ENUM

Opened this issue · 3 comments

Great gem, @mrkamel!

One small thing: Support for PostgreSQL enums would be great. Currently, it fails with a NameError. Example:

CREATE TYPE public.person_gender AS ENUM (
    'male',
    'female'
);

CREATE TABLE public.people (
    id bigint NOT NULL,
    name character varying,
    gender public.person_gender
);
class Person < ApplicationRecord
  include SearchCop

  enum gender: {
    male: 'male',
    female: 'female'
  }

  search_scope :search do
    attributes :gender, :name
  end
end

Person.search("gender:male")
=> NameError: Uninitialized constant SearchCopGrammar::Attributes::Enum

Maybe this code (placed in an initializer) can be used as a workaround:

module SearchCopGrammar
  module Attributes
    class Enum < Base
      def matches(value)
        eq value
      end
    end
  end
end

module SearchCop
  module Visitors
    class Visitor
      def visit_enum(attribute)
        "CAST(#{quote_table_name attribute.table_alias}.#{quote_column_name attribute.column_name} AS VARCHAR)"
      end

      alias visit_SearchCopGrammar_Attributes_Enum visit_enum
    end
  end
end

hi, thanks for opening this.
Actually, i want to stay as database agnostic as possible.
But more importantly, it's currently not possible to add database specific attributes.
While postgres and mysql have an ENUM which works in a very similar way, sqlite doesn't have one afaik, and if they add one, it could probably work differently.

Looks like you can use Custom Operators for this

enum gender: {
  male: 0,
  female: 1,
}

search_scope :search do
  attributes :gender

  generator :match_gender_enum do |column_name, raw_value|
    gender_int = genders[raw_value]
    "#{column_name} = #{gender_int}"
  end
end

Book.search(gender: {match_gender_enum: "male"})