Ruby on Rails

Railsの文字数のバリデーション問題を解決する 改行文字が2文字と換算されてしまう場合の対処方法

投稿日:

私は「ショートショート」という短編小説の投稿サイトの運営をしているのですが、ある日ユーザーの方からこんなお問い合わせがありました。

「3000字以内で書いているのに投稿できません」と。

(ちなみにその投稿画面には、javascriptで文字数をカウントして表示しています。)

そのカウントを見る限り3000字以内であるにも関わらず、文字数オーバーのバリーデーションエラーが出てしまうようです。

 

Rails側では以下のようにvalidationを書いていました。

これは文字通り、contentは最大3000字ですよーというバリデーションです。

なので、3000字以内であれば本来エラーが出るはずはありません。

 

原因を調べてみたところ、改行文字が原因であることがわかりました。

投稿ページでは、改行をすると文字数のカウントが1増えます。(これはjavascript側の話です)

一方、Rails側では改行文字が  \r\n  となっており、それが2文字として換算されていることが分かりました。(\はバックスラッシュのことです。)

これが原因でエラーが起きてしまうことが判明したので、それに対処する方法を考えたのですが、対処方法は大きく分けて2つあるのかなと思います。

 

まず1つ目はjavascriptの方をいじる。

現在、改行されるたびに文字数カウントが1増えるようにユーザーに表示していますが、これをどうにかして2増えるようにするという方法です。

しかし、これだとユーザーからすると違和感があります。改行したら2文字増えるというのは自然ではありません。

 

なので今回はRails側で対処することにしました。すなわち、 \r\n という改行文字を一文字として換算するように変えました。

既存のバリデーションではうまく対応できそうになかったので、独自のバリデーションを作ってそれを適用させました。

ちなみに独自のバリデーションの作り方は非常に簡単です。

以下の例の上半分は既存のバリデーションを使う場合、下半分が独自のバリデーションを使う場合です。

 

独自のバリデーションの方では、contentに含まれる \r\n という改行文字を一旦aという文字に変換しています。

こうすることでもともと2文字として換算されていたものが1文字として換算されます。(aという文字を選んだ理由は特にありません。)

また、保存されるcontentの中身を直接変えるのではなく、content_for_validationという変数に入れることで、バリデーションが通った後はちゃんと元のcontent(改行文字がちゃんと入っているcontent)が保存されるようになっています。

 

これで完成です!

もちろん、このバリデーションを他のmodelでも使うよーという場合や、独自のバリデーションをいっぱい使うよーという場合には、それ用のモジュールを作ってもいいかもしれません。

 

以上でRailsで改行文字が2文字と換算されてバリデーションエラーが出た時の対処方法の説明を終わります!

-Ruby on Rails

Copyright© 京都の独学プログラマー , 2018 AllRights Reserved.