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

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

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Q&A

1回答

4235閲覧

なぜJSON.parseが必要なのか、変数に入る値とは?

kku65614

総合スコア6

Ruby on Rails 5

Ruby on Rails 5は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

0グッド

1クリップ

投稿2017/12/17 09:03

編集2022/01/12 10:55

###前提・実現したいこと
Ruby on rails 5で書籍を読みつつ簡易掲示板を写経しています。
モデルは使わず、コントローラーとビューのみをつかっていて、データはdata.txtに保管しています。
そのときにどうしてもわからない部分があったため質問しました。

###発生している問題・エラーメッセージ
dengonban_controller.rb内の@dengon_dataというインスタンス変数があると思います。
この中には、JSON形式の投稿内容が入りますが、DengonbanControllerのindexメソッド内での@dengon_dataの挙動が理解できません。
念のためですが、挙動を確認しつつ、理解できないところをあげていきます。
※今回聞きたいところは太字にしてあります。

  1. request.post?でリクエストがPOSTかどうか判別する(今回はPOSTだったとして進めます)
  2. obj変数に、MyDataクラスでオブジェクトにした(←なぜこうするのか、理解できていない)投稿内容を入れる
  3. @dengon_dataに投稿があった時間をキーとして手順2で作ったオブジェクトを入れる
  4. data.txtに新しく投稿された内容を含めたデータを入れるために@dengon_datato_jsonでJSON形式の文字列にする
  5. File.writeを使い、data.txtの内容を更新する
  6. JSON.parse(data)でJSONを@dengon_dataに代入(なぜ@dengon_dataのままではいけないのか、理解できない)

###該当のソースコード

dengonban_controller.rb

ruby

1class DengonbanController < ApplicationController 2 layout "dengonban" 3 4 def initialize 5 super 6 7 begin 8 @dengon_data = JSON.parse(File.read("data.txt")) 9 rescue 10 @dengon_data = Hash.new 11 end 12 13 @dengon_data.each do |key, obj| 14 if Time.now.to_i - key.to_i > 24*60*60 15 @dengon_data.delete(key) 16 end 17 end 18 19 File.write("data.txt", @dengon_data.to_json) 20 21 end 22 23 def index 24 if request.post? 25 obj = MyData.new(message: params["msg"], namae: params["name"], mailaddress: params["mail"]) 26 @dengon_data[Time.now.to_i] = obj 27 data = @dengon_data.to_json 28 File.write("data.txt", data) 29 @dengon_data = JSON.parse(data) 30 end 31 end 32end 33 34class MyData 35 attr_writer(:name, :mail, :msg) 36 37 def initialize(message: msgs, namae: names, mailaddress: mails) 38 self.name = namae 39 self.mail = mailaddress 40 self.msg = message 41 end 42end

view/dengonban/index.html.erb

ruby

1<table class="form"> 2 <%= form_tag controller: "dengonban", action: "index" do %> 3 <tr> 4 <td>name:</td> 5 <td> 6 <%= text_field_tag("name") %> 7 </td> 8 </tr> 9 <tr> 10 <td>mail:</td> 11 <td> 12 <%= text_field_tag("mail") %> 13 </td> 14 </tr> 15 <tr> 16 <td>message:</td> 17 <td> 18 <%= text_area_tag("msg", "", {:size => "50x3"}) %> 19 </td> 20 </tr> 21 <tr> 22 <td></td> 23 <td> 24 <%= submit_tag("click") %> 25 </td> 26 </tr> 27 <% end %> 28</table> 29 30<table class="dengon"> 31 <tr> 32 <th style="width: 50%;">message:</th> 33 <th>name:</th> 34 <th>mail:</th> 35 <th>message:</th> 36 </tr> 37 <% @dengon_data.each do |key, obj| %> 38 <tr> 39 <td class="msg"><%= obj["msg"] %></td> 40 <td class="name"><%= obj["name"] %></td> 41 <td class="mail"><%= obj["mail"] %></td> 42 <td class="time"><%= Time.at(key.to_i) %></td> 43 </tr> 44 <% end %> 45</table>

view/layouts/dengonban.html.erb

ruby

1<!DOCTYPE html> 2<html> 3<head> 4 <title>伝言板</title> 5 <%= csrf_meta_tags %> 6 <%= stylesheet_link_tag("application", media: "all", "data-turbolinks-track": "reload") %> 7 <%= javascript_include_tag("application", "data-turbolinks-track": "reload") %> 8</head> 9<body> 10<h1 class="title">簡単伝言板</h1> 11<%= yield %> 12<div class="footer">copyright hogehoge</div> 13</body> 14</html>

routes.rb

ruby

1Rails.application.routes.draw do 2 get 'dengonban/index', to: "dengonban#index" 3 post 'dengonban/index', to: "dengonban#index" 4 5 get "helo/index", to: "helo#index" 6 post "helo/index", to: "helo#index" 7end

dengonban.scss

scss

1h1.title { 2 font-size: 20pt; 3 color: #999999; 4} 5 6.form { 7 margin: 50px 0; 8} 9 10.form tr td { 11 color: #999999; 12 padding: 0 10px; 13 font-size: 14pt; 14} 15 16th { 17 background: #999999; 18 color: #eeeeee; 19 font-size: 14pt; 20 padding: 2px; 21} 22 23.dengon tr td { 24 background-color: #eeeeee; 25 color: #666; 26 padding: 10px 5px; 27} 28 29td.msg, td.name, td.mail { 30 font-size: 12pt; 31} 32 33td.time { 34 font-size: 9pt; 35} 36 37div.footer { 38 border-style: solid; 39 border-width: 1px 0 0 0; 40 border-color: #999999; 41 margin: 50px 0 0 0; 42 padding: 3px 0 0 0; 43 color: #999999; 44 font-size: 12pt; 45 text-align: right; 46} 47

###試したこと
発生している問題・エラーメッセージの6番で言った「なぜ@dengon_dataのままではいけないのか、理解できない」について試したことがあります。
それは@dengon_data = JSON.parse(data)を削除してdata.txtに入る内容を見るというものです。その結果得られた文字列が下になります。

{1513499068=>#<MyData:0x000000000ca58c58 @name="s", @mail="s", @msg="s">}

謎の数列(恐らくタイムスタンプ)とMyDataとその後の記号、そのあとにはMyDataクラスに渡した変数の内容が入っています。
このことから、@dengon_dataに新しく入った値はJSONの形式ではないからJSON形式の文字列にしたものをJSONに戻して代入しなければならないのかなあ、と考えていますが、あまり自信がありません。

これを試した結果、JSON形式にしたり、それを文字列にしたり戻したりしていてややこしいため、何をしているのか理解しきることができないのかなと考えています。

###補足情報(言語/FW/ツール等のバージョンなど)
Ruby on rails 5

追記

書籍のソースコード

上記のソースコードは私が書籍のコードを理解するために色々な編集を加えたものでした。質問と回答の食い違いを防ぐために、追記として書籍のコードを記述させていただきます。ここに記述されていないファイルのものは、上記と同じ内容のものです。

MyDataクラスinitializeメソッドについて、後述の私が参考にしている書籍で使用されるRubyのバージョンでは警告が発生しますが、これが書籍に載っている内容であることをあらかじめご理解お願いします。
dengonban_controller.rb

Ruby

1class DengonbanController < ApplicationController 2 layout "dengonban" 3 4 def initialize 5 super 6 7 begin 8 @dengon_data = JSON.parse(File.read("data.txt")) 9 rescue 10 @dengon_data = Hash.new 11 end 12 13 @dengon_data.each do |key, obj| 14 if Time.now.to_i - key.to_i > 24*60*60 then 15 @dengon_data.delete(key) 16 end 17 end 18 19 File.write("data.txt", @dengon_data.to_json) 20 21 end 22 23 def index 24 if request.post? 25 obj = MyData.new(msg: params["msg"], name: params["name"], mail: params["mail"]) 26 @dengon_data[Time.now.to_i] = obj 27 data = @dengon_data.to_json 28 File.write("data.txt", data) 29 @dengon_data = JSON.parse(data) 30 end 31 end 32end 33 34class MyData 35 attr_accessor(:name) 36 attr_accessor(:mail) 37 attr_accessor(:msg) 38 39 def initialize msg: msg, name: name, mail: mail 40 self.name = name 41 self.mail = mail 42 self.msg = msg 43 end 44end

書籍のタイトルについて

「質問への追記・修正、ベストアンサー選択の依頼」にて質問がありました、参考にしている書籍のタイトルについてですが、私が参考にしている書籍は「Ruby on Rails 5 超入門」という書籍で、発行日が2016年12月20日のものです。

どうか、よろしくお願いします

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ockeghem

2017/12/18 06:37

書籍のタイトルを教えていただけないでしょうか?
kku65614

2017/12/18 12:59

書籍のタイトルについて、質問文に追記させていただきました。ご確認よろしくお願いします。
guest

回答1

0

全体に奇妙な印象を受けるコードです。

例えば,MyDatainitialize メソッドが

rb

1def initialize(message: msgs, namae: names, mailaddress: mails)

のようになっていますね。
仮引数の message: msgsmsgs は,キーワード引数 message のデフォルト値を与えているはずですが,msg が未定義なので,たとえば

rb

1MyData.new

とやると NameError が発生します。

また,index アクションでデータを追加するなど,Rails の流儀に反しているようです。

もし書籍にこのとおりに載っているのだとすると,あまりお手本にしないほうがよいコードではないかなあ,という印象です。

それはそれとして,index メソッドでなぜこんな回りくどいことをしているか,ですが,MyData をハッシュにしたいからかもしれません。

MyData を Rails 上で to_json して,JSON.parse すると,ハッシュになります。(一般に,オブジェクトを to_json して,それを JSON.parse しても,元には戻るとは限りません)

MyData のままだと,ビューで obj["msg"] の形で使えませんので。

それならなぜ,①最初からハッシュにしないで MyData なんか定義するのか,とか,②MyDataattr_reader を付けて obj.msg の形で使えるようにすればいいのではないか,という疑問が湧きますが,著者に聞いてみたいですね。

投稿2017/12/18 06:06

scivola

総合スコア2108

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kku65614

2017/12/18 13:04

ご回答ありがとうございます。まだ回答の内容を完全に理解しているわけではないですが(ここに少し時間がかかるかもしれません)、質問文の内容を修正したことと、回答を一度読んだことを伝えるためにコメントしました。 「該当のソースコード」のコードは私が書籍のコードを理解するために色々な編集を加えたものでしたので、質問と回答の食い違いをなくすために、追記として書籍のコードをそのまま記述させていただきました。また、追記依頼のあった書籍のタイトルについても追記しました。 大変申し訳ありませんが、以上の点について一度ご確認よろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問