LoginSignup
0
0

More than 1 year has passed since last update.

【Rails4.2】Postgresqlの配列リテラルを配列に変換

Posted at

背景

  • 少々古いプロジェクトでPostgresqlの配列型が使われていた。
  • ActiveRecord経由であれば取得カラムは自動で配列に変換されるが個別に変換したい場合があった

概要

  • Rails側で以下の変換を行いたい
  • 半角スペースや改行などの要エスケープ文字がある要素だけダブルクォート囲みされたりしている
  • アポストロフィーエス 's なども少々変換が必要らしい
input output
{} []
{1,2,3} [1,2,3]
{赤,青,緑} ["赤","青","緑"]
{"徳川 家康",豊臣秀吉,"織田 信長"} ["徳川 家康","豊臣秀吉","織田 信長"]

実装

モデルのconcernを追加する形にしてみた

app/models/concerns/varying_array_parsable.rb
module VaryingArrayParsable
  extend ActiveSupport::Concern

  class VaryingArrayParser
    # @see {https://github.com/rails/rails/blob/4-2-stable/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb}
    # Loads pg_array_parser if available. String parsing can be
    # performed quicker by a native extension, which will not create
    # a large amount of Ruby objects that will need to be garbage
    # collected. pg_array_parser has a C and Java extension
    begin
      require 'pg_array_parser'
      include PgArrayParser
    rescue LoadError
      require 'active_record/connection_adapters/postgresql/array_parser'
      include ActiveRecord::ConnectionAdapters::PostgreSQL::ArrayParser
    end
  end

  module ClassMethods
    private

    # @param value [String] varying arrayカラムの値
    # @return [Array] 型キャスト後の配列
    def cast_to_array(value)
      @pg_parser ||= VaryingArrayParser.new
      @pg_parser.parse_pg_array(value)
    end
  end
end

使用例

app/models/hoge.rb
class Hoge < ActiveRecord::Base
  include VaryingArrayParsable

  class << self
    # @param str [String]
    # @return [Array]
    def hogehoge(str)
      cast_to_array(str)
    end
  end
end

まとめ?

  • :smiley: pgのarray型の文字列→railsの配列 への変換ができるようになった
  • :smiley: エスケープなどの考慮もされていた
  • :thinking: postgresqlには array_to_string 関数や unnest 関数があるのでSQL側でこれを使うのもアリだった
  • :scream: もっと良い書き方がありそう。ActiveRecordにすでに実装済みのものを真似ているだけなので

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0