ActiveRecord validates로 표시되는 오류 메시지의 형식 변경

무엇이 곤란한가?



ActiveRecord validates에서 오류가 발생했을 때 표시되는 메시지를 %{attribute}%{message}가 아닌 형식으로 만들고 싶습니다.
예를 들어, User.name의 validates 오류로 この名前は1文字以上入力してください。 같은 오류 메시지를 표시하고 싶습니다.
또한, 그 포맷을 적용하는 스코프를 한정하고 싶다.

validates 오류 메시지를 변경하려면



0. 샘플 앱 개요



이번 환경은 ruby:2.5.2, rails:6.0.0입니다.

User 모델이 있는 앱을 준비합니다.
$ rails new validation_message_sample
$ rails g model user name:string
name를 validation으로 설정합니다.
class User < ApplicationRecord
  validates :name, presence: true
end

이 상태에서 validation 에러를 발생시키면 에러 메세지는 이렇게 됩니다.
$ rails c
Running via Spring preloader in process 27748
Loading development environment (Rails 6.0.0)
irb(main):001:0> user = User.new
   (2.0ms)  SELECT sqlite_version(*)
=> #<User id: nil, name: nil, created_at: nil, updated_at: nil>
irb(main):002:0> user.valid?
=> false
irb(main):003:0> user.errors.full_messages
=> ["Name can't be blank"]

이것을 この名前は1文字以上入力してください。로 변경합니다.

1. attribute명을 일본어로 한다



먼저 Name로 표시된 부분을 名前로 변경합니다.

이것은 rails-i18n라는 gem을 사용합니다.
Gemfile에 다음을 추가하여 bundle install를 실행합니다.

Gemfile
gem 'rails-i18n`

그런 다음 config/application.rb에 i18n 설정을 추가합니다.

config/application.rb

module ValidationMessageSample
  class Application < Rails::Application
    config.load_defaults 6.0

    # 下の2行を追加する
    config.i18n.default_locale = :ja
    config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.yml').to_s]
  end
end
config/local/models/ja.yml 파일을 만들고 수정할 속성 이름을 정의합니다.

config/local/models/en.yml
ja:
  activerecord:
    models:
      user: ユーザー
    attributes:
      user:
        name: 名前

이 상태에서 실행하면 다음과 같이 됩니다.
$ rails c
Running via Spring preloader in process 28562
Loading development environment (Rails 6.0.0)
irb(main):001:0> user = User.new
   (3.0ms)  SELECT sqlite_version(*)
=> #<User id: nil, name: nil, created_at: nil, updated_at: nil>
irb(main):002:0> user.valid?
=> false
irb(main):003:0> user.errors.full_messages
=> ["名前を入力してください"]

attribute 이름이 名前입니다.
그런 다음 기본 메시지도 일본어가되었습니다.

2. :message 이용하기


:message 옵션을 사용하여 메시지를 변경할 수 있습니다.
자세한 내용은 Rails Guide을 참조하십시오.
class User < ApplicationRecord
  validates :name, presence: { message: 'は1文字以上入力してください。' }
end

실행하면 이렇게 되었습니다.
$ rails c
Running via Spring preloader in process 29059
Loading development environment (Rails 6.0.0)
irb(main):001:0> user = User.new
   (1.5ms)  SELECT sqlite_version(*)
=> #<User id: nil, name: nil, created_at: nil, updated_at: nil>
irb(main):002:0> user.valid?
=> false
irb(main):003:0> user.errors.full_messages
=> ["名前は1文字以上入力してください。"]

attribute 이름 앞에 この 라는 문자열을 표시하려고 합니다.

app/models/user.rb
class User < ApplicationRecord
  validates :name, presence: { message: "この%{attribute}は1文字以上入力してください。" }
end

실행해 보겠습니다.
$ rails c
Running via Spring preloader in process 29190
Loading development environment (Rails 6.0.0)
irb(main):001:0> user = User.new
   (1.6ms)  SELECT sqlite_version(*)
=> #<User id: nil, name: nil, created_at: nil, updated_at: nil>
irb(main):002:0> user.valid?
=> false
irb(main):003:0> user.errors.full_messages
=> ["名前この名前は1文字以上入力してください。"]

흠, 머리에도 attribute 이름이 붙어 버립니다.
이는 오류 메시지의 기본 형식이 %{attribute}%{message}이기 때문입니다.

3. 커스텀 메소드 이용하기



맞춤 메소드을 사용하여 오류 메시지를 변경합니다.
errors.add(:カスタムメソッド名, エラーメッセージ) 로 에러 메세지를 추가할 수 있습니다만, 결국 커스텀 메소드명이 문두에 표시되어 버리므로, :base 를 이용하기로 합니다.
코드는 다음과 같습니다.

app/models/user.rb
class User < ApplicationRecord
  validate :name_presence

  private

  def name_presence
    return if name.present?

    errors.add(:base, "この名前は1文字以上入力してください.")
  end
end

실행하면 이렇게 됩니다.
$ rails c
Running via Spring preloader in process 33134
Loading development environment (Rails 6.0.0)
irb(main):001:0> user = User.new
   (2.5ms)  SELECT sqlite_version(*)
=> #<User id: nil, name: nil, created_at: nil, updated_at: nil>
irb(main):002:0> user.valid?
=> false
irb(main):003:0> user.errors.full_messages
=> ["この名前は1文字以上入力してください."]

확실히 의도대로 오류 메시지를 변경할 수있었습니다.

그러나, attribute명을 일부러 베타 치고 버리고 있어 DRY가 아니고, 본래의 :base의 용도가 아니기 때문에, 그다지 좋은 해가 아니라고 생각합니다.

4. 오류 메시지의 형식 변경



이 기사에 따르면 Rails6.0.0에서 오류 메시지의 형식을 범위를 제한하여 변경할 수 있습니다.

범위를 제한하기 위해 다음 설정을 추가합니다.
require_relative 'boot'

require 'rails/all'

Bundler.require(*Rails.groups)

module ValidationMessageSample
  class Application < Rails::Application
    config.load_defaults 6.0

    config.i18n.default_locale = :ja
    config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.yml').to_s]
    config.active_model.i18n_customize_full_message = true  # この行を追加
  end
end

config.active_model.i18n_customize_full_message는 기본값이 false이므로 이 설정을 수행하지 않으면 작동하지 않습니다. (이것을 깨닫지 않고 빠졌습니다 ...)

오류 메시지의 형식을 다음과 같이 설정합니다.

config/local/models/en.yml
ja:
  activerecord:
    models:
      user: ユーザー
    attributes:
      user:
        name: 名前
    errors:
      models:
        user:
          attributes:
            name:
              format: '%{message}'
              blank: この%{attribute}は1文字以上入力してください。

덧붙여서 User 모델은 아래와 같습니다.

app/models/user.rb
class User < ApplicationRecord
  validates :name, presence: true
end

실행하면 이렇게 됩니다.
$ rails c
Running via Spring preloader in process 34119
Loading development environment (Rails 6.0.0)
irb(main):001:0> user = User.new
   (2.4ms)  SELECT sqlite_version(*)
=> #<User id: nil, name: nil, created_at: nil, updated_at: nil>
irb(main):002:0> user.valid?
=> false
irb(main):003:0> user.errors.full_messages
=> ["この名前は1文字以上入力してください。"]

마침내 목표를 달성하는 구현에 도달 할 수있었습니다

일단 샘플 코드를 GitHub에 넣습니다.

참고문헌



htps : // 코 m / 우신 지 / ms / 242bf 84df7 a5 a 67d5b
htps : // 코 m / 스케타 / ms / 5 아 f12 아 cd88 에 bc8 아 2 아 1 아 5

좋은 웹페이지 즐겨찾기