[RAILS] Option to specify validation execution timing [on:]

Introduction / Situation when an error occurs

Rails is implementing something like a calendar app (bookmark of travel). Specify the date, details, members (using devise's user registration function), Register your travel page.

Participating users (users) of the travel page (trips) As shown in the figure below, an intermediate table called trip_users is associated with many-to-many associations.

スクリーンショット 2020-11-15 16 14 29

If you fill in the required items and register On the trips table スクリーンショット 2020-11-15 16 19 20

In the trip_users table スクリーンショット 2020-11-15 16 21 03

It will be saved like this.

However, as we proceed with the implementation ...

スクリーンショット 2020-11-15 16 03 24

With an error I've never seen, I suddenly became unable to register my travel page.

Development environment

Ruby 2.6.5 Rails 6.0.3.4 MySQL Visual Studio Code (GoogleChrome)

Consideration and verification of the cause

I confirmed the create process in binding.pry.

[1] pry(#<TripsController>)> trip_params
=> <ActionController::Parameters {
(Omission)

 "user_ids"=>["", "2", "3", "4", "5", "6", "1"]} permitted: true>
[2] pry(#<TripsController>)> @trip = Trip.new(trip_params)
(Omission)

[3] pry(#<TripsController>)> @trip.valid?
=> false
[4] pry(#<TripsController>)> @trip.errors.full_messages
=> ["Participating members are invalid values"]

Participating users are sent with ids stored in user_ids in params. On the other hand, it seems that it is said to be an "illegal value". What went wrong when it wasn't wrong at all a while ago ...

When I remember what I did recently, I wondered if there was any error in my mind ...

"By the way, I didn't write the alphanumeric mixed validation of the password ~"

I suddenly found a description that I remembered and wrote.

user.rb


class User < ApplicationRecord
 (Omission)

  PASSWORD_REGEX = /\A(?=.*?[a-z])(?=.*?\d)[a-z\d]+\z/i.freeze #Alphanumeric mixed regular expression
  validates :password, format: { with: PASSWORD_REGEX, message: 'Please include both letters and numbers' }
end

I tried commenting it out ... and it's back! It seems that this was the cause ...

Apparently, the alphanumeric mixed validation set in the password when registering a new user was activated when the other model with which it was associated was generated. it seems like. It is probable that he was also playing "Please mix alphanumeric characters!" For user_ids, which is data with only numbers. There is such a rare case ...

Then, is it possible to apply that ** validation only to user registration **? As a result of investigation ...

[Official] Rails documentation / validates

スクリーンショット 2020-11-15 16 29 30

This seems to be usable!

result

You can specify the timing of validation execution with the : on option. This time, we want to execute password validation only when registering as a user, so write on:: create.

↓ Modified User model

user.rb


class User < ApplicationRecord
 (Omission)

  PASSWORD_REGEX = /\A(?=.*?[a-z])(?=.*?\d)[a-z\d]+\z/i.freeze #Alphanumeric mixed regular expression
  validates :password, format: { with: PASSWORD_REGEX, message: 'Please include both letters and numbers' }, on: :create
end

This leaves the password validation, The travel page registration function is back as before!

At the end / impression

It took me a while to find the causative description. I also learned the importance of committing to beans so that I can go back in case of an error ...

This is a poor article for beginners, but I hope it will be of some help to you. Thank you for reading to the end.

Reference article

[Official / Rails Guide] Active Record Validation [Official] Rails documentation / validates [Qiita] Switch validation to be executed at save time depending on the situation [Qiita] Rails | Specify validation timing using on option

Recommended Posts

Option to specify validation execution timing [on:]
[Validation] rails How to specify after today's date
Install MySQL 5.6 on CentOS6 [How to specify the version]