ActiveRecordでpostgresqlのjson typeのバリデーションを行う
ActiveRecordは4.2以降でPostgreSQLのJSON型をサポートしています。
# == Schema Information
#
# Table name: hoges
#
# id :integer not null, primary key
# name :string
# options :json
#
class Hoge < ActiveRecord::Base
end
このHogeモデルのoptions
にJSON形式の文字列を渡すと正しく保存されるのですが、もしJSON形式でない文字列が渡ると、値にnilが設定されただけで何もエラーが起きませんでした。
バリデーションをしようにも、不正なJSON文字列を渡した時点で既にnil
になってしまうため、困ってしまいました。
pryを使って調べたところ、不正なJSON文字列は、options_before_type_cast
という属性に保存されていました。今回はこれを使って、JsonTypeValidator
を作ってみました。
JsonTypeValidatorの定義
class JsonTypeValidator < ActiveModel::EachValidator
def initialize(options)
options.reverse_merge!(:message => :invalid)
super(options)
end
def validate_each(record, attribute, value)
value = record.try(:"#{attribute}_before_type_cast")
value = value.strip if value.is_a?(String)
return true if value.blank?
if value.is_a? String
ActiveSupport::JSON.decode(value)
else
true
end
rescue JSON::ParserError => exception
record.errors.add(attribute, options[:message], exception_message: exception.message)
end
end
指定されたattribute
に該当するbefore_type_cast
の値を取得し、それが文字列であれば、JSON.decode
を実行しています。パースに失敗したらエラーの原因をexception_message
に渡しています。基本的には、エラーメッセージは:invalid
で不正なデータとして扱っています。
使い方
config/application.rb
で読み込むように設定します。
config.autoload_paths += %W(#{config.root}/lib/validators)
次に、Modelに定義します。
# == Schema Information
#
# Table name: hoges
#
# id :integer not null, primary key
# name :string
# options :json
#
class Hoge < ActiveRecord::Base
validates :options, json_type: true
end
これで、不正なJSON文字列が渡った場合はエラーになるようになりました。
gistで公開しています
今回のコードはgistでも公開しています。
https://gist.github.com/patorash/8f79c1dc9e271132a2152808b1bce477
また、以下のURLを参考にしました。
このURLは、カラムが文字列型でJSONを保存する場合の方法だったので、カラムの型がJSON型の場合はうまくいきませんでしたが、とても参考になりました。
参考にしたURL:
- http://stackoverflow.com/questions/6594257/how-to-validate-if-a-string-is-json-in-a-rails-model
- https://gist.github.com/joost/7ee5fbcc40e377369351
Author And Source
この問題について(ActiveRecordでpostgresqlのjson typeのバリデーションを行う), 我々は、より多くの情報をここで見つけました https://qiita.com/patorash/items/cb65ce658890da2cf56a著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .