Rasna Shakya
Rasna Shakya

Reputation: 557

active admin custom filter for serialized attribute

I have the following models:

Class User < ApplicationRecord
  has_one :profile
end

class Profile < ApplicationRecord
  belongs_to :user
end

I have skills column in profile which stores an array of skills. I am using rails active admin and on filtering users with skills I faced a problem which is

PG::InvalidTextRepresentation: ERROR: malformed array literal: "java"

my code for the filter is:

filter :profile_skills, label: 'Skills', as: :string

I am not getting what is the problem. please help me out

Upvotes: 3

Views: 2878

Answers (1)

Tema Bolshakov
Tema Bolshakov

Reputation: 1193

ActiveAdmin use ransack gem for filtering. The simplest way to filter by array using ransack is to define scope in model:

class Profile < ApplicationRecord
  # @!method skills_includes(skill)
  #   @param skill [String]
  #   @return [ActiveRecord::Relation<Profile>]
  scope :where_skills_contains, ->(skill) { where("skills @> ?", "{#{skill}}") }
end

Using this scope you can filter profiles by skills like this Profile. skills_include('java').

By default ransack doesn't allow to use scopes for filtering, so you have to whitelist this scope:

class Profile
  def self.ransackable_scopes(*)
    %i(where_skills_contains) 
  end
end

Now it's possible ransackable scope in a filter:

filter :where_skills_contains, label: :skills, as: :string

Note, you can't name filter (and scope) skills_contains, because it will generate completely different query to database.

> Profile.ransack(where_skills_contains: 'java').result.to_sql 
#=> SELECT "profiles".* FROM "profiles" WHERE (skills @> '{java}')
> Profile.ransack(skills_contains: 'java').result.to_sql
#=> SELECT "profiles".* FROM "profiles" WHERE ("profiles"."skills" ILIKE '{%java%}')

Upvotes: 7

Related Questions