モデルの中の要素をランダムに表示したい(2)

前回の続き、

まずは、前回に引き続きjavaに result を渡す方法を調べる

ruby javascript 変数 受け渡し」で検索

https://qiita.com/Kohei_Kishimoto0214/items/d919b00d75dec0699cf0

こちらの通りにやってみることに

 

①viewに変数を埋め込む

サンプルのコードがhaml記法になっているからhtmlに直してと書いてある

haml記法を調べて、直してみる

https://qiita.com/49497974m/items/d94245a12db4f60b7a11

%input{name: "result", type: "hidden", value: @results, class: 'result' }/
<input name= "result", type= "hidden", value: @results, class='result' >

上から下に変更してみる

とりあえず表示はされている。

 

javascriptに読み込ませる

result = $('.result').val();

これで@resultを読めているらしい

それで

result = result.shuffle

を続けて入力してみるが

文法エラーは起きないけど、シャッフルもされていない。

そこで、追加したものをコメントアウトして動作を確認していったら、

どうやら、上の二つのどちらかが仕事をしていなそう。

よって、resultに中身が入っていないか、shuffleメソッドがjavaで使えないかだと思われる。

まずはresultの中身を確認する

consoleを開いたら

shuffle.js:5 Uncaught ReferenceError: $ is not defined
at HTMLAnchorElement.<anonymous> (shuffle.js:5)

とある。

これは5行目がおかしいということだろうから5行目を確認。

result = $('.result').val();

5行目は上記。

https://www.genius-web.co.jp/blog/web-programming/points-to-check-on-javascript-errors.html

こちらのサイトによれば、変数名「:$」が読み込めない。という状況になっているそう。

jQueryを使って読み込んでいるとのことなので、

jQuery記述の仕方を確認してみる。

 

そもそもjQueryがなんだかわかっていなかった

yarn add jquery

まずは導入

config/webpack/environment.js
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
const { environment } = require('@rails/webpacker')
const webpack = require('webpack')

environment.plugins.prepend('Provide',
  new webpack.ProvidePlugin({
    $: 'jquery',
    jQuery: 'jquery',
    jquery: 'jquery',
  })
)

module.exports = environment
app/javascript/packs/application.js
1
2
3
4
5
6
7
8
9
// 省略

require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")
require('jquery')

// 省略

と導入したら先程のエラーは吐かなくなった。

 

ただページ更新はうまくいったが

シャッフルはできない。

またresultが入っていないのか

console.log(result)

をしてみるが、何も出てこない

今の記述に

window.location.reload();

が入っているから、更新されてログが残っていないよう

一旦コメントアウトする。

それでも何も出てこない。

 

切り口が思いつかないので、また少し検索してみる

https://techacademy.jp/magazine/9444#sec2

何やら配列はいじれないと書いてある。

違う切り口にしてみようか

 

https://qiita.com/mosa_siru/items/e69eee47a183b13cfb62

こちらのサイトにある Gon gem というのを使ってみる

ただ、使用例がないので、どのように適用したものか

そこで、リンク先にいってみる

http://railscasts.com/episodes/324-passing-data-to-javascript?language=ja&view=asciicast

 

このサイトの最初に

ここでおこないたいのは、JavaScriptの機能を使って商品データを取得して表示する処理です。そのためにはアプリケーションからクライアントで実行されているJavaScriptに情報を渡す必要があります。

とある。これはやりたいことと似通っている。

gonの説明を読む限り、コントローラーを

ントローラアクションのgonオブジェクトに変数を設定します。

/app/controllers/products_controller.rb
class ProductsController < ApplicationController
  def index
    gon.products = Product.limit(10)
  end
end

とあるので、

def search
@results = @p.result.includes(:category)
gon.products = @results
end

としてみる。

そして

console.log(gon.products);

とすると

  1. (19) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
    1. length19

これは・・・できているのでは!

ようやく進んだので、とても嬉しい。

 

次はこの検索結果をクリックしたら並び順をshuffleする

Viewでやっていたようにとりあえずやってみる

gon.products.shuffle;
console.log(gon.products);

当然のごとくできない。

よって、

javascriptで配列の並びをランダムに置き換わるものがないかを検索する。

https://www.sejuku.net/blog/62904

キーを使ったsort()を使えば、id順に並び替えるはできそう。

後から使うが、今はランダムに置き換わる方針を探す

 

http://bashalog.c-brains.jp/14/03/05-100000.php

こちらにランダムで並び替える記述があるので使わさせていただく

  1. (19) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
    1. length19

並び変わっている!

 

お次は、この並び変わったやつをviewファイルに戻す

クリックしたら

「gon.products」の中身は変わっているが、

今、viewファイルにあるのは「@result」。

 

ただ、今はreloadを最後にして表示し直している。

(「gon.products」の中身を「@result」に入れられたとして)

そうすると

javaでいじった変数を渡す

②reloadして表示し直す

③渡された@resultはコントローラーの処理に従って元のid順に戻る。

となってしまう。

 

よって、データを挿入していくパターンならできるか、

表示されているのを全部削除して、

今得た、「gon.products」の中身を並べる記述をjava上で行うのはどうだろうか。

 

もしくは

今はid順に並んでいるのが表示されているので、

クリックしたらそれが隠されて、

ランダムなやつが表示されるようになるとかはどうか

 

とりあえず表示できるようにしてみる。https://tech-master.s3.amazonaws.com/uploads/curriculums//b10b4adeebb73bd73cc0ff2797b09ebd.png

こんな感じで「ランダムで並び替え」を押したら

現状並んでいる、id順の検索結果を潰せるように潰せるようにできないか

 

(現状、ランダムかそうでないかだけなのでこれが実装できればこれでいいのだろうが、将来的には複数条件でソート可能にしたい。

RubyonRails:検索条件を引き継いで検索結果のソート順を変更する - Madogiwa Blog

こんな感じの表示にしたい。ただ、今回はjsの経験を積むためにも表示非表示でできないかを試してみる)

 

f:id:mst_kb:20210506191159j:plain

こんなイメージ

とりあえずdivの記述はできた。

次は記述を行なっていく。