質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.77%

【Rails】フォーム入力後エラー画面になるもののバリデーション突破して、ひらがなが登録できてしまう問題

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 611

Romay

score 25

前提・実現したいこと

Ruby 2.4.5
Rails 4.2.8
本番環境:heroku postgreSQL
開発環境:mySQL

ユーザーがユーザ情報編集のためフォームを入力後、送信するも、バリデーションに引っかかってエラー画面に移る。
しかし、もう一度ユーザー編集画面に戻ると、バリデーションをかけているはずなのに登録できてしまっている。

上記が現状発生している問題です。

以下フロー

  1. users/edit.html.erbでユーザーが情報を編集(friendly_id(ユーザーがURLを決定できるGem)を編集し英数字で文字列を決定)
    2. ユーザーが英数字ではなく、ひらがな(例:あいうえお)を入力し送信
  2. エラー画面に遷移
    4 送信したひらがなをfriendly_idに当てはめて(例:http://localhost:3000/users/あいうえお)アクセスすると、アクセスできてしまう。(つまりひらがな「あいうえお」がfriendly_idにupdateされている)

発生している問題・エラーメッセージ

ローカル環境では、This page isn’t working というエラー
Herokuでは、Application error An error occurred in the application and your page could not be served. If you are the application owner, check your logs for details. You can do this from the Heroku CLI with the command
というエラー

該当のソースコード

ユーザ情報編集画面
users/edit.html.erb

<%= form_for @user do |f| %>
  <div class="modal-body">
  <div class="error-message"></div>
  <label>
    <span class="btn">アイコン画像
      <%= f.file_field :avatar ,:style=>"display:none;" , id: 'avatar_img' %>
    </span>
    <div class="image-edit">
      <img id="avatar_img_prev" src="#" class='hidden'  />
      <%= image_tag(@user.avatar(:medium), :size => "70x70", :class => " avatar_present_img") %>
    </div>
  </label>
  <ul style="list-style: none; padding-left: 0;">
    <li><i class="fa fa-user"></i> ユーザー名<%= f.text_field :nickname, placeholder: "ニックネーム", :required => true %></li>
    <li><i class="fa fa-link"></i> URL (3~20文字英数字)<%= f.text_field :friendly_url, placeholder: "URLを設定(英数字3-20文字)" , :required => true %></li>
    <li><i class="fa fa-twitter"></i> Twitter<%= f.text_field :twitter, placeholder: "@以下だけを入力" %></li>
    <li><i class="fa fa-instagram"></i> Instagram<%= f.text_field :instagram, placeholder: "@以下だけを入力" %></li>
    <li><i class="fa fa-comment"></i> プロフィール<%= f.text_area :description, placeholder: "100文字以内で入力"  %></li>
  </ul>
 </div>
 <div class="modal-footer">
   <%= f.submit "完了", class: "btn" %>
 </div>
<% end %>


ユーザーモデル
バリデーションの設定で、英数字のみに限定
user.rb

#friendly_url
  include FriendlyId
  friendly_id :friendly_url

  validates :friendly_url, length: { in: 3..20 },
                          uniqueness: true, #一意性
                          format: { with: /\A[\w@-]*[A-Za-z][\w@-]*\z/ }, #英数字のみ
                          on: :friendly_url_user #登録時に入力必要なし

friendly_idに関するmigrationファイル

class AddFriendlyUrlToUsers < ActiveRecord::Migration
  def change
    add_column :users, :friendly_url, :string

    add_index :users, :friendly_url, :unique => true
  end
end

コントローラー該当部
user_controller.rb

def update
    @user = User.friendly.find(params[:id])
    @user.update(update_params)
    if @user.valid?
      flash[:notice] = "更新しました"
      if @user.friendly_url
        redirect_to "/#{@user.friendly_url}"
      else
        redirect_to :user and return
      end
    else
      if @user.friendly_url?
      render :error
      else
        render :error
      end
    end
  end

  private

  def update_params
    params.require(:user).permit(:nickname, :password, :password_confirmation, :current_password, :avatar, :description, :twitter, :instagram, :friendly_url)
  end

  def correct_user
    user = User.friendly.find(params[:id])
    if current_user != user
      redirect_to root_path
    end
  end

試したこと

実際に、データベースに保存されてしまっているため、モデルのみだけではなくデータベースにもバリデーションをかけるのが必要なのでは...?と考えています。
しかし、送信後Railsのエラー画面になるのではなく、エラーメッセージを表示するもしくは、指定したページに飛ばすようにしたいと考えています。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

on: :friendly_url_user #登録時に入力必要なし

にてバリデート実行タイミングを明示しているため

    @user.update(update_params)
    if @user.valid?

では、検証を実行していません。(むしろエラーになっているのが不思議です。)

onにより、検証の実行を問うよりもallow_nilallow_blankにて空白や無入力を許可した方がよいでしょう

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/20 09:51

    回答ありがとうございます。ユーザー登録時には、friendly_urlを設定しない仕様のため'on'を使っていたのですが、空白や無入力を許可した状態で常にこのバリデーションをかけるのが良いということでしょうか。

    キャンセル

  • 2019/04/20 10:38

    「登録時以外は検証する。」というのを徹底するのならonによって制御してもいいですが
    実際、提示されたupdateでは検証されていないようです。

    「登録時には入力しない」と「未入力を許可」の間にある違いが無視できるのならば
    (つまりは、未入力の更新や登録→解除を許可できる)のならば、そちらの方がよいでしょう。

    キャンセル

  • 2019/04/23 15:18

    allow_nilで処理することにしました。回答いただきありがとうございました!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.77%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • トップ
  • Rubyに関する質問
  • 【Rails】フォーム入力後エラー画面になるもののバリデーション突破して、ひらがなが登録できてしまう問題