[RUBY] L'API Rails empêche boolean d'être casté arbitrairement et a passé la validation

un événement

Lors de la création et de la mise à jour d'une colonne de type booléen avec l'API Rails, je souhaite lire des types autres que booléen

$ rails -v
Rails 6.0.3.2
$ rails g model Post body:text opened:boolean

app/models/post.rb


class Post < ApplicationRecord
  validates :opened, inclusion: { in: [true, false]}
end

Si vous faites cela, vous devriez pouvoir tout lire sauf le booléen ...

$ curl localhost:3000/posts -X POST -H "Content-Type: application/json" -d '{"body": "hoge", "opened": "moge"}'
{"status":"success","data":{"id":1,"body":"hoge","opened":true,"created_at":"2020-08-16T01:31:14.277Z","updated_at":"2020-08-16T01:31:14.277Z"}}

Spécifiez "moge" pour la colonne ouverte de booléen

Attente: comme il n'est pas booléen, il sera joué avec une erreur Condition réelle: cast à vrai et enregistré sans erreur

$ curl localhost:3000/posts -X POST -H "Content-Type: application/json" -d '{"body": "hoge", "opened": "0"}'
{"status":"SUCCESS","data":{"id":2,"body":"hoge","opened":false,"created_at":"2020-08-16T01:31:28.498Z","updated_at":"2020-08-16T01:31:28.498Z"}}

Attente: comme il n'est pas booléen, il sera joué avec une erreur Condition réelle: Cast en faux et enregistré sans erreur

Apparemment, il semble que la valeur sera transmise à l'état de distribution

Contre-mesures

Faire une validation personnalisée

app/validators/boolean_validator.rb


class BooleanValidator < ActiveModel::EachValidator
  def validate_each(record, attr, _value)
    before_value = record.send("#{attr}_before_type_cast")
    record.errors.add(attr, "is invalid") unless %w[true false].include?(before_value.to_s.downcase)
  end
end

app/models/post.rb


class Post < ApplicationRecord
  validates :opened, boolean: true
end

résultat

$ curl localhost:3000/posts -X POST -H "Content-Type: application/json" -d '{"body": "hoge", "opened": "moge"}' 
{"status":"error","data":{"opened":["is invalid"]}}
$ curl localhost:3000/posts -X POST -H "Content-Type: application/json" -d '{"body": "hoge", "opened": "0"}' 
{"status":"error","data":{"opened":["is invalid"]}}
$ curl localhost:3000/posts -X POST -H "Content-Type: application/json" -d '{"body": "hoge", "opened": "true"}'
{"status":"success","data":{"id":3,"body":"hoge","opened":true,"created_at":"2020-08-16T02:25:18.211Z","updated_at":"2020-08-16T02:25:18.211Z"}}
$ curl localhost:3000/posts -X POST -H "Content-Type: application/json" -d '{"body": "hoge", "opened": "false"}'
{"status":"success","data":{"id":4,"body":"hoge","opened":false,"created_at":"2020-08-16T02:25:30.700Z","updated_at":"2020-08-16T02:25:30.700Z"}}

Comme prévu, tous sauf vrai et faux sont maintenant joués

référence

Comment valider une colonne de type booléen dans Rails et la renvoyer comme une erreur si le type est différent Si vous l'implémentez avec l'URL ci-dessus, il sera pris dans rubocop de différentes manières, donc j'écris cet article

Recommended Posts

L'API Rails empêche boolean d'être casté arbitrairement et a passé la validation
[Rails] [jQuery] Empêche le bouton d'envoi d'être enfoncé jusqu'à ce que le formulaire soit rempli et sélectionné.
[Rails] Paramètres de validation et localisation en japonais