Skip to content

Instantly share code, notes, and snippets.

@raykin
Last active April 9, 2017 10:00
Show Gist options
  • Save raykin/895e8e58ba83f72efd2a to your computer and use it in GitHub Desktop.
Save raykin/895e8e58ba83f72efd2a to your computer and use it in GitHub Desktop.
Extent PG array query in Rails

In Gemfile

gem 'pg_tag', git: 'git://gist.github.com/895e8e58ba83f72efd2a.git', require: 'pg_tag'

In rails model file

has_pg_tag **** # your col name
class Array
# Give %w[a b]
# Return "'{a, b}'"
#
def to_pg_array_string
"'{#{join(', ')}}'"
end
# Give %w[a b]
# Return "ARRAY['a', 'b']"
#
def to_pg_array_text
"ARRAY#{to_s}"
end
alias_method :to_pg_array_integer, :to_pg_array_text
end
Gem::Specification.new do |s|
s.name = 'pg_tag'
s.version = '0.0.1'
s.platform = Gem::Platform::RUBY
s.author = 'Raykin'
s.email = 'raykincoldxiao@gmail.com'
s.summary = 'Easy query and update pg array column in rails'
s.description = 'Same as Summary'
s.files = ['pg_tag.rb']
s.require_path = '.'
end
require 'array'
require 'active_support/concern'
module PgTag
def self.build_pg_string
Proc.new do |ele, col_type|
case ele
when String, Numeric
matchs = [ele]
when Array
matchs = ele
else
matchs = ele.to_a
end
matchs.send "to_pg_array_#{col_type}"
end
end
extend ActiveSupport::Concern
module ClassMethods
def has_pg_tag(*names, col_type: :string)
names.each do |name|
define_singleton_method "#{name}_contain" do |match_value|
pg_array = PgTag.build_pg_string.call(match_value, col_type)
where("#{name} @> #{pg_array}")
end
define_singleton_method "#{name}_overlap" do |match_value|
pg_array = PgTag.build_pg_string.call(match_value, col_type)
where("#{name} && #{pg_array}")
end
define_method "add_#{name}" do |value|
new_value = send(name).clone.push(value)
send("#{name}=", new_value)
end
end
end # END has_pg_tag
end
end
ActiveRecord::Base.send :include, PgTag
require 'minitest/autorun'
require 'active_record/railtie'
require 'pg_tag'
class PgTagTest < Minitest::Test
def setup
@str = "abc"
@array = %w[1 2 3]
end
def test_str_to_pg_array
assert_equal "'{abc}'", PgTag.build_pg_string.call(@str, 'string')
end
def test_array_to_pg_array
assert_equal("ARRAY[\"1\", \"2\", \"3\"]",
PgTag.build_pg_string.call(@array, 'text'))
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment