LoginSignup
0
0

More than 1 year has passed since last update.

[rails 初心者]同率順位を踏まえたランキング機能(修正版)

Last updated at Posted at 2022-11-01

初めに

前回作成したランキング機能にて、1点だけ動作不備が見つかりました。
今回はそのバグを解消する記事になります。
(因みに前回の記事をまだ読んでいないという方は、前提条件のところにリンクがあるので
よかったら読んでみて下さい!!)

前提条件

前回までの記事が一通り終了していること(因みに次の3つです)
レビューの基本 = 評価関係の処理についてまとめた記事です
レビュー機能+@(応用) = 「評価点の平均値化」と「その平均値順に並び替え」を行いました
ランキング機能の追加 = 同率順位を考慮したランキング機能を実装しました。

リンクはこちら

[rails初心者]複数権限でのログインを使ったレビューサイトの作成(基本)
[rails初心者]複数権限でのログインを使ったレビューサイトの作成(応用)
[rails 初心者]同率順位を踏まえたランキング機能

バグについて

まだ一度も評価されたことのない業者がランキングに反映されていませんでした。

主なやること

・コントローラの編集(配列に配列を追加)

開発環境

・rails 6.1.7
・ruby 3.1.2
・raty 3.1.1
・jquery 3.6.1
・bootstrap 4.5

コントローラの記述

配列に配列を追加

早速ですが、修正版を載せたいと思います。

app/controllers/平均値を表示したいファイルに関係するコントローラ
  def アクション名
    same_rate = 0
    rank = 1
    #最低一回は評価されたことのあるtraderのデータを取得
    reviews = Review.group(:trader_id).order('avg(star) desc').pluck(:trader_id)
    traders = Trader.find(reviews)
    #一度も評価されたことがないtraderのデータを取得
    not_traders = Trader.where.not(id: Review.group(:trader_id).order('avg(star) desc').pluck(:trader_id))
    not_traders.each {|trader|  traders.push(trader)}

    traders = traders.map.with_index(1) do |trader, i|
      if i == 1 #ランキング処理の一番最初だけ以下の処理
        same_rate = trader.review_average #一番最初だけ「same_rate」に値が入っていないので、先に値を入れる
      end
      if trader.review_average != same_rate #同率順位がない場合以下の処理
        rank = i #同率が無いので、順位を更新
        same_rate = trader.review_average #「same_rate」に現在の値を代入 → 次の値と比べる用として運用するイメージ
        {trader: trader, index: rank } #[trader = trader]という配列と[index = rank]という配列それぞれをセットにしている
      else #同率順位がある場合以下の処理
        same_rate = trader.review_average
        {trader: trader, index: rank }
      end
    end

  @traders = Kaminari.paginate_array(traders).page(params[:page]).per(5)
  #Kaminari.paginate_array → pageメソッドを配列(Rubyの型)に対して用いる場合に必要な記述

こんな感じのプログラムに書き換えると、無事不具合を解消することができました!!

これだけだと何がどうのように変わったのか分かり辛いので、
まずは前回から変わった点について解説したいと思います。

修正点1

変数のtradersの文章が長かったので3分割にしました。
※今回の不具合解消には関係ない部分ですが、変更したので一応 (´゚д゚`)カンケイナインカイ

具体的には次の箇所です(さっきのコントローラの記述から持ってきています)

変更箇所
    reviews = Review.group(:trader_id).order('avg(star) desc').pluck(:trader_id)
        #評価点の平均値算出と並び替えを行う

    traders = Trader.find(reviews)
        #さっき定義したreviewsをtraderに紐づけする

    traders = traders.map.with_index(1) do |trader, i|
        #さっきの配列(traders)とランキング化するにあたって使う配列(with_index)を一つにまとめる

これについては前回の記事で解説しているので、詳しい説明は割愛させていただきます。

ポイント:前回の書き方だと長い文章になってしまったので、3分割にした

修正点2

二つ目の修正点はズバリ・・・「取得されていないtraderの情報を取得する」ことです
先程のプログラミングで言うと、次の部分です

変更箇所
    #一度も評価されたことがないtraderのデータを取得
    not_traders = Trader.where.not(id: Review.group(:trader_id).order('avg(star) desc').pluck(:trader_id))

ポイント①where.notにより取得されていないデータを参照することが可能になる
ポイント②where.not(id:と宣言することで、取得されていないtrader.idを検索ワードとして設定している
ポイント③Review.group以下略は、情報が取得済みのtrader側と同じ働きをする

修正点3

続いての修正点は、配列と配列を合わせることです。
これも先程のプログラミングで使って説明します。

変更箇所
    not_traders.each {|trader|  traders.push(trader)}

ポイント①pushメソッドを使うことで配列と配列を合わせることができる
ポイント②not_traders.each{}ではnot_tradersで取得した配列をもとに{}内の処理を一通り実行する
ポイント③|trader|not_tradersで取得したtrader情報を一つづつ参照する
ポイント④traders.push(trader)評価されたことのある方の業者達(traders)と評価されたことのない業者(trader)をpushする
ポイント⑤traders.push(trader)(trader)は、厳密に言えば|trader|で参照された業者情報が入る

これだけだと「(。´・ω・)ん?」※これ自分ですw
となるので、分かりやすく図解したいと思います。

まず今回の不具合の内容は「まだ一度も評価されたことのない業者がランキング表示されていない」ことでした
つまり「評価されたことのある業者達(配列1)」+「一度も評価されていない業者達(配列2)」を処理してしまえばいいことになります。

ではこれを踏まえたうえで、実際に行った処理についてです。
簡単にまとめると
次の画像の赤枠部分を配列1(traders)配列2(trader)としました。

qiita用2.png

つまり、traders.push(trader)について、こんな感じにイメージできればOKです。

traders部分=レビューされたことがある業者の変数(厳密には業者情報とランキングの情報の二つ)
trader部分=レビューされたことがない業者の変数(こちらは業者情報のみ)

完成イメージ

以上で、平均点0.0の業者がランキングに反映されるようになりました
qiita用3.png

さいごに

 今回の作業は、どちらかというと応用になるランキング機能の修正でした。量は少ないですが、難しく感じた部分がたくさんありました。

 例えばオブジェクト指向を考える時、どの情報が足りないのかを真っ先に把握すればいいところ、先にpushについて探してしまったり。。。ランキングの配列について考えた際には、結果的には前の順位(評価されたことのある業者の順位)を継承するためnot_tradersでは作成しませんでしたが、作業の序盤ではランキング用の配列をnot_tradersにも作ろうとしました。その結果頭が混乱する状況に陥ってしまったことも(-_-;)

 このように順番がバラバラによって2度手間3度手間に合った場面がありました。エラーや不具合を修正する際は、一つ一つの問題を根気強く紐解いていく忍耐力も必要だということでしょう(多分)

 自走力をつけるためにもこう言った目に見えないスキル?をレベルアップしていきたいと思います(^^ゞ

今回も最後まで読んでいただきありがとうございました。!!
※まだ学習中の身なので理解不足・誤りがあったらコメント頂けますと幸いです。m(__)m<ヨロシクオネガイシマス

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0