複数のインスタンス変数をjson形式に変換する方法を✅

「13時間」MVP完成までに残された可処分時間。思いの外技術的負債が多くて無理なんじゃないかと焦っていることスバルです。

今回は複数のインスタンス変数をjson形式に変換してVueファイルで使う方法を✅していきます。

コントローラーにSQLをいっぱい書いてしまいfatになることってよくありますよね。僕もそうなりかけたので、うまい具合にmodelに切り出してfat controllerを防いでいきたいと思います。

 

「modelで作成したscopeをcontrollerに呼び出し、jsonに変えてから、vueで使いたい。」

これを実現していきたいと思います。以下いきなり独り言モードに入りますが、嫌いにならないでください。

scopeを作成

「Alcoholモデルのalcohol_percentageの値が7以下、7以上それぞれランダムで5つ取り出す」

これを実現するスコープは以下の通り。

class Alcohol < ApplicationRecord
  scope :random_weak, -> { where('alcohol_percentage < ?', 7).sample(5) }

  scope :random_strong, -> { where('alcohol_percentage > ?', 7).sample(5) }
end

controllerで呼び出す。

モデルファイルで定義したスコープはコントローラーにそのまま呼び出すことができる。一覧表示を担うindexアクションに記載する。N + 1問題は無視。

module Api
  module V1
    class AlcoholsController < ApplicationController

      def index
        @weak_alcohols = Alcohol.all.random_weak
            render json: @weak_alcohols
      end

    end
  end
end

複数のインスタンス変数をjsonに変える

モデルで作成したscope二つをコントローラーで使用したい。

respond_toを使って繰り返し処理を行うと複数のインスタンスjsonに変換することができる。

module Api
  module V1
    class AlcoholsController < ApplicationController
      def new
        Alcohol.new
      end

      def index
        @weak_alcohols = Alcohol.all.random_weak.sort do |a, b|
          b[:alcohol_percentage] <=> a[:alcohol_percentage]
        end
        @strong_alcohols = Alcohol.all.random_strong.sort do |a, b|
          a[:alcohol_percentage] <=> b[:alcohol_percentage]
        end
        respond_to do |format|
          format.json do
            render json: { weak_alcohols: @weak_alcohols,
                           strong_alcohols: @strong_alcohols }
          end
        end
      end
    end
  end
end
Alcohol.all.random_weak.sort do |a, b|
          b[:alcohol_percentage] <=> a[:alcohol_percentage]
        end

この部分で、random_weakで取得したAlcoholデータをソートしている。

スコープを使わない状態に戻したら下記のようになる。長い。

Alcohol.all.where('alcohol_percentage < ?', 7).sample(5).sort do |a, b|
       b[:alcohol_percentage] <=> a[:alcohol_percentage]
end

vueで呼び出す

サーバーに保存されているデータは、axiosを使い、apiを叩いて持ってくる。


<template>
	<div>
		{{ alcoholAll }} #...3
	</div>
	<h1 class="text-center" style="font-size: 50px">
	      酩酊に向けた酒ケジュール
	    </h1>
</template>

import axios from '../plugins/axios';
export default {
  data: function () {
    return {
      alcohols: [],#...1
}
}
mounted() {
    axios.get('/alcohols').then((alcoholResponse) => (this.alcohols = alcoholResponse.data)); #...2
  },
computed: {
alcoholAll (){ #...3
  const alcoholAll = this.alcohols["weak_alcohols"];
  return alcoholAll;
},
}
}
  1. data()に、apiを叩いて持ってきたデータを格納するためのalcoholsを用意している。
  2. mountedは、DOM構築後に発火するライフサイクルフック。非同期処理はDOM構築前にやっても変わらないため、サーバーにアクセスする負担軽減のためにcreatedフックで行われることが推奨されているみたい。
  3. computedにデータを返すメソッドを記述することで、リアクティブにデータを表示することができる。定義したメソッドは、双方向バインディング( {{}}で囲まれている部分。)を使うことで、HTMLに表示することができる。

結果

こんな感じで「Alcoholモデルのalcohol_percentageの値が7以下、7以上それぞれランダムで5つ取り出す」を実現することができた。

Image from Gyazo

今日の酒ケジュール

今日はバイト先の飲みに参加します。

できれば今日までにアプリを完成させて、この飲み会に向けた酒ケジュールを作りたかったのですが叶わず、、

ちなみに今日のスタンスは、「ほろ酔い」です。

酒ケジュールは以下の通り

1 ビール 2 ハイボール3 ハイボール 4 レモンサワー

これでバッチリほろ酔いになれます。それでは、楽しい週末を。

rails 昇順、降順の並び替え - Qiita

jbuilderの使い方辞典〜メソッドの文法と使い方

Ruby on Rails - Render JSON for multiple models

Rubyのsortとsort_byを理解してマルチソートをしよう - Qiita