質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.08%

ハッシュからのkey, valueの取り出し順が異なる

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 172

t.togashi

score 22

前提・実現したいこと

Ruby on Railsで残業時間を管理するシステムを作っています。
このシステムにおいて、月毎の残業合計時間を集計し、時系列でグラフとして表示しています。

該当のソースコード

overtime.rb

class Overtime < ApplicationRecord
 (略)
 def self.monthly_chart_data(userid)
    # {[2019, 4]=>○○○○, [2019, 5]=>○○○○, …} を生成
    year_and_month_minute_data = Overtime.where(user_id: userid).group("extract(year from date)").group("extract(month from date)").sum(:work_time_minute)
    monthly_hour_data = {}
    year_and_month_minute_data.each do |key, value|
      monthly_hour_data["#{key[0].floor}#{key[1].floor}月"] = value / 60
    end
    monthly_hour_data
  end
  (略)
end

users_controller.rb

class UsersController < ApplicationController
  (略)
  def show
    @user = User.find(params[:id])
    gon.monthly_chart_data = Overtime.monthly_chart_data(params[:id])
  end
  (略)
end

発生している問題・エラーメッセージ

users showアクションに対応するviewにて、ブラウザの検証機能を利用し、controller から受け取った gon.monthly_chart_data の内容を確認すると、
開発環境においては、 
window.gon={};gon.monthly_chart_data={"2019年4月":35,"2019年5月":45,"2019年6月":22,"2019年7月":51,"2019年8月":43,"2019年9月":41,"2019年10月":50,"2019年11月":49,"2019年12月":24,"2020年1月":36,"2020年2月":31,"2020年3月":36,"2020年4月":25};
というように意図通り時間順になっているのですが、
本番環境においては、 
window.gon={};gon.monthly_chart_data={"2020年1月":14,"2019年8月":34,"2019年12月":31,"2019年7月":28,"2019年4月":12,"2020年2月":31,"2019年11月":36,"2019年5月":8,"2019年10月":27,"2019年6月":11,"2019年9月":26,"2020年4月":12,"2020年3月":26};
と、開発環境と異なり、時間順になっていません。
(それぞれの月に対応する時間数は、seed.dataの投入時にランダムに決定されるため、開発環境と本番環境とで同一にはなりません。)
このデータで時系列のグラフにする際、ハッシュの中身が開発環境のように時間順になっていると大変都合が良いです。
ついてはお手数ですが、
(1)なぜこのようにハッシュ内の順番に差異が生じるのか
(2)本番環境のハッシュ内の順番を開発環境と同様に時間順にする方法
をそれぞれご教示いただきたいです。

補足情報(FW/ツールのバージョンなど)

開発環境 MySQL
本番環境 PostgreSQL

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • asahina1979

    2020/04/12 23:15

    hashの順がランダムアクセスなのでは?

    キャンセル

  • no1knows

    2020/04/13 01:18

    質問とは全く関係ないですが、開発環境と本番環境が異なるDBなのは凄いリスクだと思いますが・・・

    キャンセル

回答 1

checkベストアンサー

0

ハッシュの中身が開発環境のように時間順になっていると大変都合が良いです。

そもそも論として、JavaScriptの世界では、ハッシュの順番は尊重される保証がありません(いちおう、順序はES2020で固定されるに至りましたが、ユーザーが完全対応したブラウザを使っているとも限りません)。

JavaScriptレベルで対応したいなら、JavaScript側でソートをかけることになります。もしくはRubyから渡す時点で、順番を決め打ちできるように配列としておくかです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/04/13 11:14 編集

    現実問題としては(JavaScriptに追加された時点で順番保障のあった新しいメソッドを使う場合以外は)「キーの順が保証されない」という前提でプログラミングをするのが安全です。

    キャンセル

  • 2020/04/13 11:15

    Objectのキー順序はこのように複雑な事情を抱えているのに対して、Mapは「追加順」になると明記されています(ただし、直接JSONに書くことはできませんので、配列などを介する必要があります)。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.08%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る