niki12260714の日記

フリーランスのITエンジニアの呟き。

Ruby学習17日目:リクエスト情報取得、複数テーブルの処理

今日は外部に出す、取り置き依頼画面を作ります。
構成としては、「〇〇さん専用のアイテム一覧画面」→「取り置きしたいアイテム画面」→「取り置き依頼完了画面(QRコード表示)」となります。
最初にアクセスするアイテム一覧画面は、URLに、誰のアイテム画面なのかを示すパラメータを持たせます。
具体的に言うと「http://xxxx/request/(アイテム作成者を示すパラメータ)」っていう感じ。
このパラメータは、user_idにすると楽なんですけど、いたずらで「連番になっているならパラメータ書き換えて他の人の依頼画面見てみようw」ってなるのもなぁ、と思うので、ここはアイテム作成者のメールをhashで書き換えた値になっています。

さて、URLを決めたら、ルートを定義します。

get 'request/:url_txt', to: 'request#index'

 routes.rbに、上記のように記述します。
「:url_txt」というのは、controllerで受け取るための名前になります。
これにより、「http://xxx/request/********」でアクセスされたら、「requestコントローラーのindexメソッドが呼び出されます」
なので、requestコントローラーにはこんな記述をすればOK。

@url_txt = params[:url_txt]

 これで、@url_txtにrequestのスラッシュの次に書かれた値を受け取ることができます。

次はアイテムの表示です。
これにはいくつか条件が存在します。
・表示するアイテムは、パラメータで指定されたユーザが登録したアイテム
・アイテム発売の日付が本日以降であること
・アイテムの取り置き上限数が、既に取り置き予約数に達していた場合は非表示
なので、テーブルは「users」「items」「reserve_lists」の3つのテーブルが関連することになります。

普通にSELECT文発行すればこの条件を満たすアイテムを取ってくるのは簡単ですが、ちゃんとrailsのお作法に則ってやりたいので、調査開始。
まずは「itemsテーブルは、reserve_listsの数を知りたい」っていうのを実現させることにしました。


railsは名づけが重要で、ネーミングによって「このテーブルのカラムは、このテーブルに関連しているんだよ」って示すことができます。
reserve_listsにある商品IDはitem_idとすることで、itemテーブルのIDと一致することを自動解釈してくれます。
そのために、reserve_listモデルに以下の記載をします。

class ReserveList < ApplicationRecord
has_many :item
end

 has_manyとは、「自分とitemは1:nの関係にある」と宣言するもの。
他に「1:1」とか「n:m」も示すことができます。
ここを定義しておくと、なんとitemsテーブルに、やはりネーミングルールに則った名前でカラムを作っておくと、「itemsテーブルにある商品IDのデータに、reserve_listsテーブルにあるデータの数をいれる」を自動的にやってくれる!
その名前とは「(カウントしたいテーブルの名前)_count」。
型はintegerにして、defaultを0にしておくと上記の動きをしてくれます。
これをカウンターキャッシュといいます。
で、カウンターキャッシュを有効にするために、reserve_listモデルに、その旨を記載。

class ReserveList < ApplicationRecord
has_many :item, counter_cache: true
end

 これでカウンターキャッシュが有効になります。
ちなみにネーミングルールに則っていないカラムに対してカウンターキャッシュを効かせたい場合は、counter_casheに続けて、カウンターキャッシュをいれるカラム名を指定すればOK。