#7 リソースマスタ画面を作る(2)

投稿者: | 2021年3月21日

前回までで最初の1画面目の表示まではできるようになりました。今回は登録機能を実装していきます。

登録機能の実装

まずは画面を呼び出します。URLはroutes.rbを見て確認しましょう。まだメニューを作っていませんから、routes.rbを見に行くか、面倒であればブックマークしておきます。

振り返りがてら、画面に項目を入力して追加ボタンを押してみましょう。Controllerにはprintfデバッグの一文しかなく対応するビューも作っていませんからボタンが非活性化され、コンソールに下記のような出力が出るのみです。

コントローラの一文
    def create
        test request
    end

コンソールの出力
Processing by WResourceController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"(省略)", "waiting_resource"=>{"name"=>"りそーす", "ref"=>"びこう"}, "commit"=>"追加"}
----------------------------
/home/devuser/waiting_app/app/controllers/w_resource_controller.rb:7:in `create'
#<ActionDispatch::Request:0x00007ff93987a2a0>
----------------------------
No template found for WResourceController#create, rendering head :no_content
Completed 204 No Content in 72ms (ActiveRecord: 0.0ms)

では、ここから作っていきます。まずはコントローラです。

w_resource_controller.rb
    def create
        begin
    def create
        begin
            request_data = request[:waiting_resource]
            ActiveRecord::Base.transaction do
                WaitingResource.register( request[:waiting_resource] )
            end
            flash[:success] = "登録しました."
            redirect_to w_resource_path
        rescue => e
            obj = errorHandling(e)
            flash[:danger] = obj.to_json
            redirect_to w_resource_path
        end
    end

registerというメソッドを切っていますが、今はcreate!をよんでいるだけです。今後、登録時に一緒に行っておきたい処理があったときは「登録時に行うこと」を1つにまとめたメソッドとして育てていくつもりです。

ActiveRecord::Base.transaction…となっているのはこの範囲にトランザクションを切っているためです。この中でエラーが起きるとロールバックして元に戻します。1テーブルの更新のみであればこのような考慮は不要ですが、すぐに複数テーブルの更新が必要なアプリになってしまいます。

そのようなとき、テーブルAの更新には成功したが、Bの更新に失敗…ということはママあることなので、最初からトランザクションを切っておくほうが良いでしょう。

waiting_resource.rb
class WaitingResource < ApplicationRecord
    def self.register( request )
        self.create!(
            name: request[:name],
            ref: request[:ref]
        )
    end
    #validationはここから
    validates( :name, presence:true , length:{maximum:50} )
    validates( :ref,  presence:true , length:{maximum:50} )
end

モデル側の実装です。バリデーションもきってあります。必須で50文字もあればひとまずOKかと思います。

application_controller.rb
  def errorHandling(errorObject)
    #バリデーションエラーは特に保存する必要なし. bad request
    if errorObject.kind_of?(ActiveRecord::RecordInvalid)
      return {
        message: errorObject.message,
        status: 400
      }
    end

    #ここから先はログに保存する.ユーザには問い合わせの番号を通知する.
    logId = SecureRandom.uuid
    logger.error logId
    logger.error errorObject.class.name
    logger.error errorObject
    logger.error errorObject.backtrace.join("\n")
    return {
      message: "原因不明のエラーがあります.次のIDでお問い合わせください." + logId,
      status: 500
    }
  end

application_controllerにメソッドを1つ追加しておきます。これはエラーが発生した場合に、その情報をログに保存することと、ユーザへ返すレスポンスを何にするかを決めます。バリデーションの場合にはそのまま返しますが、それ以外のものは(現時点では)すべてログに書き込んで問い合わせ用の文字列を渡すことにします。基本的には画面キャプチャーをもらって調査するようなイメージでいます。

挙動を見てみよう

まだリスト表示機能が対応していないのでコンソール(IRB)から確認してみます。

irb(main):005:0> WaitingResource.all.pluck(:id,:name,:ref)
   (11.9ms)  SELECT "waiting_resources"."id", "waiting_resources"."name", "waiting_resources"."ref" FROM "waiting_resources"
=> [[7, "テーブル席A", "4人掛け"]]
irb(main):006:0> 

pluckで項目を選択して表示できます。

必須になっているので未入力だとこのようになります。英語メッセージのままだと何なので日本語にしましょう。

バリデーションの日本語化

2つの部分で日本語化必要です。空白だから入力してほしいという部分と、項目名です。

すでにGemファイルには下記が追加していると思いますが、設定されているか確認してください。

Gemfile
gem 'rails-i18n'

次に項目を日本語化するための設定ファイルを読み込むように指定します。

config/application.rb
module WaitingApp
  class Application < Rails::Application
#中略
    config.i18n.default_locale = :ja
    config.i18n.load_path += Dir[Rails.application.config.root.join('config', 'locales', '**', '*.yml').to_s]

#以後略
  end
end
config/locales/models/ja.yml
ja:
  activerecord:
    models: 
      waiting_resource: ウェイティングリソース
    attributes:
      waiting_resource:
        name: 名前
        ref: 備考

このファイルはインデントが重要な意味を持っているようです。インデントを間違うと読み込めなくなりますので気をつけましょう。

演習

バリデーションでエラーになったとき、「message:…」という風になっていますが、この部分を下記のように変えてみましょう。ここだけ英単語が登場するのは全体として平仄が合いません。なお、原因不明エラーの場合には、少しシステムっぽさがあってもよいので今のままにしましょう。

次回

次回は、一覧部分の表示をやっていきましょう。出来たらページネーションも含めて次回で作り切れたらと思います。