今日はテックアカデミーの講師とのビデオ通話面談で様々な疑問を解消できたので、それをまとめています。
皆さんに役立つ記事にはなってないかもしれませんが、トピックは豊富です!
自分が後から見直したり、同じよう悩みを抱えているプログラミング初心者の参考になるコードを探す時に使えれば幸いです。
レスポンスのJSON形式にカラがあってエラーになる問題
Yahoo MAP APIにリクエストを投げて、JSON形式でデータを取ってきたら、中にNULLの項目があるときがあって、それを扱おうとするとエラーが出てしまう。
これをどうやって回避すればよいかを聞きました。
まず私がやってるのはこのようにしてJSON形式のレスポンスを取得します。
yquery_enc = URI.encode yquery #日本語を%のUTF-8の形にエンコード uri = URI.parse(yquery_enc) json = Net::HTTP.get(uri) @results = JSON.parse(json) #配列形式に変換 @features = @results['Feature'] #Feature配下の配列のみとりだす。これで店舗一覧がとれる。
レスポンスコードの一覧はYahooのページを確認。
レスポンスコード
最後の文で@features配列から1個1個とりだしています。Yahoo地図APIから取得した店舗情報がJSON形式からハッシュに変換して入っています。
ここからshopのインスタンスを生成していく実装です。
@features.each_with_index do |feature,i| @shops[i] = Shop.new( name: feature['Name'], y_id: feature['Id'], y_gid: feature['Gid'], y_uid: uid, #feature['Property']['Uid'], y_ido: ido, #feature['Geometry']['Coordinates'].split(",")[1], y_keido: keido, #feature['Geometry']['Coordinates'].split(",")[0], y_address: address, #feature['Property']['Address'], y_moyorieki: eki, #feature['Property']['Station'][0]['Railway'] + " " + feature['Property']['Station'][0]['Name']+"駅 徒歩" + feature['Property']['Station'][0]['Time'] + "分" y_leadimage: image_url #feature['Property']['LeadImage'] ) end
こんな風にしてやりました。ところがfeature[‘Property’]やfeature[‘Property’][‘Station’]がカラだと、Railsでエラーが出てしまいます。
エラーを回避するにはどうすればよいか検討しました。
私が導き出した答えは
feature[‘Property’].present?
で、カラかどうかをチェックしてカラだったら
uid = nil
カラじゃなかったら値をそのまま入れる
uid = feature[‘Property’][‘Uid’]
ということをやりました。問題は、これ全部の項目やんの?(; ・`ω・´)
てことなんです。
なのでいま以下のようなプログラミングコードを書いています。
@features.each_with_index do |feature,i| #@features配列から1個1個とりだしてshopのインスタンスを生成していく unless feature['Property'].present? #propertyがカラなら uid = nil address = nil image_url = nil else #propertyがあるなら uid = feature['Property']['Uid'] address = feature['Property']['Address'] image_url = feature['Property']['LeadImage'] #なかのstationがあるかチェック unless feature['Property']['Station'][0].present? #nil.['Railway']とやるとエラーでるからチェックしないといけない #stationがカラなら eki = nil else #stationがあるなら eki = feature['Property']['Station'][0]['Railway'] + " " + feature['Property']['Station'][0]['Name']+"駅 徒歩" + feature['Property']['Station'][0]['Time'] + "分" end end unless feature['Geometry'].present? #Geometryがカラなら ido = nil keido = nil else #Geometryがあるなら unless feature['Geometry']['Coordinates'].present? #Coordinatesがカラなら ido = nil keido = nil else ido = feature['Geometry']['Coordinates'].split(",")[1] keido = feature['Geometry']['Coordinates'].split(",")[0] end end

例えば
hash = { address: { city: :sapporo } } こういうのがあったときに
データはhash[:address][:city] でsapporoがとれる
そういうときは
hash[:address] && hash[:address][:city]
とやれば、adoressがないときは、後ろを実行しない。これを活用できる。
あとはdigメソッド
hash.dig(:address, :city)
これだと、キーがnilであってもエラーがおきません。
とは言え今回はRailsでもそんなに手短かにもならない感じですね。

indexアクションで生成したインスタンスを持ち回りたい
shop#indexアクション → shops/index.html.erb → shop#newアクション へインスタンスを持っていきたい。
けど、Railsでもこれが出来ないので解決策を探しています。
indexアクションで作った変数やインスタンスは@を付けてあげればVIEW(index.html.erb)に持っていけます。
持っていったインスタンスは1個1個展開して、
newアクションへのクエリ文でパラメータを全部URLの後ろにつなげることをやってみました。
<%= link_to 'ニューに飛ぶ', new_shop_path(shop, name: shop.name, address: shop.address), class: %>
これをするとURLが
http://sample/?name=デニーズ新宿店&address=東京都新宿区ほげほげほげほげ1-2-3&eki=都営新宿線/JR線/地下鉄副都心線 新宿駅徒歩3分・・・・
みたいになります。
#newアクション側で送られてきた上記のURLからパラメータを取得します。そのコードは以下のとおり。
hash = {} request.query_parameters.each do |key, value| hash[key] = value.to_s puts hash[key]

URLの文字数は2048文字までだしオーバーする可能性もあります。それに見た目もスマートじゃないんですけど。Railsなら簡単に出来る方法ってないでしょうか?

クッキーにセッション情報をうめこんでいることはご存知でしょうか。これを活用できます。
クッキーに店舗情報を入れて持ち回ればよいですね。
他にはサーバー側にセッション情報をもたせることもできます。
キーだけクライアントがもってて、サーバー側がキーを元に店舗情報を復元するようなイメージもできますね。
ということでした。セッションを学び直すのは大変なので、取り敢えず今できてる方法で進めてみることにしました。
コントローラーで作ったハッシュがビュー側に来ない問題
先程のコントローラー側でハッシュを作っています。
@hash = {} request.query_parameters.each do |key, value| @hash[key] = value.to_s puts @hash[key] end
@をつければビュー側で展開できるので以下のようにしていますが、なぜか取り出しができません。
<p><%= @hash[:name] %></p>
これで取り出しができると思ったのですが。。

ビュー側では、@hash[‘name’]で表示ができますよ。
全項目修正するのが大変であれば以下のメソッドをコントローラーで使ってみましょう。
@hash.symbolize_keys!
これでハッシュのKEYをシンボルに変更してくれます。便利なメソッドですね。
フォームで入力しない項目もcreateアクションに送信したい
店舗への口コミ投稿フォームでは、
<%= form_for @kuchikomi |f| %>
このように@kuchikomiでモデルを渡して口コミ情報を記入してもらっています。
ところがフォームで渡したいのは口コミ情報以外にもあって、それをどうやって渡せばよいか探しています。

<% @hash.each do |key, value| %> <%= hidden_field_tag "shop[#{key}]", value %> <% end %>
こんな形ですね。
これで
indexアクション→index.html.erb→newアクション→new.html.erb→createアクション
とデータを持ち回る事ができるようになりました。
さらに発展して以下のようにできました。これはアクション側で@shopインスタンスを生成して、それをビュー側でhiddenタグに入れるやり方です。
<% @shop.attributes.each do |key, value| %> <%= hidden_field_tag "shop[#{key}]", value %> <% end %>
index.html.erb→newアクションのときは、GETメソッドでURLの後ろにクエリをつなげて。
new.html.erb→createアクションのときはPOSTメソッド(formタグ)の中にhiddenタグで埋めてあげて。
なんだか自分が書くとややこしくなってる気がするけど。。
今日は非常に密度の濃い30分となりました。かなり前進した気がします!