20201024のRubyに関する記事は26件です。

[Ruby] each_with_index と each.with_indexの違いを考えた

この記事ではmacOS Catalina10.15.6にインストールしたRuby 2.6.5を使っています。
2つの違いを区別するためにまとめてみました。

each_with_index

  • each_with_indexと2つの値をブロック変数に渡すことで、配列の要素の数だけ繰り返し処理その要素が何番目のものか表すことができます。
fruits = ["apple", "banana", "peach"]

fruits.each_with_index do |fruit, index|
  puts "#{index}番目のフルーツは#{fruit}です。"
end

結果

ただ、このままだと「0番目のフルーツはappleです。」となってしまいますね。

0番目のフルーツはappleです。
1番目のフルーツはbananaです。
2番目のフルーツはpeachです。

each.with_index

  • indexの引数に1を入れました。
  • すると、要素に割り振られる番号が1からスタートになります。
fruits.each.with_index(1) do |fruit, index|
  puts "#{index}番目のフルーツは#{fruit}です。"
end

結果

この通り、きれいに1から順番が始まっていますね。

1番目のフルーツはappleです。
2番目のフルーツはbananaです。
3番目のフルーツはpeachです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

データベースに登録するときにエラーメッセージを表示させたい

はじめに

 テストコードを書いていて、エラーメッセージを表示させるようにしたときに、わからなかったことなので、記録として残しておく。

エラーメッセージの表示方法

viewディレクトリに

_error_messages.html.erb
<% if model.errors.any? %>
  <div id="error_explanation" class="alert alert-danger">
    <ul>
      <% model.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
    </ul>
  </div>
<% end %>

を作成し、renderメソッドで呼び出すようにする。
1行目のmodelは、今回データベースに何かを登録する場面を想定しているため。

呼び出す側のコード

<%= render 'error_messages', model: f.object %>

ファイルの位置によって、shared/error_messagesのように指定してあげる必要がある。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerを組み込むために参考にした記事

参考にした記事

DockerをMacにインストールする
https://qiita.com/kurkuru/items/127fa99ef5b2f0288b81

はじめてのDocker 導入から開発の流れまで
https://qiita.com/m-dove/items/173d08a5d8d910e10283

最初はわからなさすぎたのでYouTubeなども見ましたー。

もう環境構築で悩まない!Dockerを使ってRails環境構築!
https://www.youtube.com/watch?v=BZS8AHF3TTo&t=503s

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RubyのDateクラスを使った曜日の出力

Dateクラスとは

Rubyの標準ライブラリの機能です。

Dateクラスを使うには以下一文を記述します。

require "date"

次に、Dateクラスを用いて

「今日の曜日」を取得する場合は以下のように記述します。

day = Date.today.wday

wdayは曜日を0(日曜日)から6(土曜日)の整数で取得することができるDateクラスに用意されているメソッドです。

例えば、木曜日なら 4 が出力されるわけですね!

どうすれば、「今日は木曜日です」と出力されるか考えてみました。

require "date"

day = Date.today.wday

if day == 0
  puts "今日は日曜日"
elsif day == 1
  puts "今日は月曜日"
elsif day == 2
  puts "今日は火曜日"
elsif day == 3
  puts "今日は水曜日"
elsif day == 4
  puts "今日は木曜日"
elsif day == 5
  puts "今日は金曜だ!!!"
else
  puts "今日は土曜日"
end

If文が長いので、リファクタリングできそうですね。

出力されるのが数字というのがポイントで、

配列を使用して出力される数字を添字に代入すれば上記と同じ結果が得られそうです。

require "date"

day = Date.today.wday
days = ["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"]


  puts "今日は#{days[day]}"


コンパクトにまとまりました。

If文を使うなら、特定の曜日でコメントを変える時に使うという方がいいですね。

まだまだ、コードを短くする記述ができないのでやりながら覚えていきたいと思います!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

即時に更新されるチャット機能(Action Cableの実装)

即時に更新されるチャットアプリ

  • Action Cableを用いた、リアルタイムチャットアプリを作成する

まとめてコードずらりします⬇︎

ターミナル
% cd projects
% rails _6.0.0_ new mini_talk_app -d mysql
% cd mini_talk_app
% rails db:create
ターミナル
% rails g controller messages new
% rails g model message text:text
% rails db:migrate
app/config/routes.rb
Rails.application.routes.draw do
  root 'messages#new'
  resources :messages, only: [:create]
end
app/controllers/messages_controller.rb
class MessagesController < ApplicationController
  def new
    @messages = Message.all
    @message = Message.new
  end

  def create
    @message = Message.new(text: params[:message][:text])
  end
end
app/views/messages/new.html.erb
<h3>mini_talk_app</h3>
<%= form_with model: @message do |f| %>
  <%= f.text_field :text %>
  <%= f.submit '送信' %>
<% end %>
<div id='messages'>
  <% @messages.reverse_each do |message| %>
    <p><%= message.text %></p>
  <% end %>
</div>

この時点で下記のようになっているはず

d6806db02ad04b485928bbd124c73f1a.png

Action Cableの実装(先ほどの続き)

ターミナル
% rails g channel message
app/channel/message_channel.rb
class MessageChannel < ApplicationCable::Channel
  def subscribed
    stream_from "message_channel"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end
end
app/controller/messages_controller.rb
class MessagesController < ApplicationController
  def new
    @messages = Message.all
    @message = Message.new
  end

  def create
    @message = Message.new(text: params[:message][:text])
    if @message.save
      ActionCable.server.broadcast 'message_channel', content: @message
    end
  end
end
app/javascript/channels/message_channel.js
import consumer from "./consumer"

consumer.subscriptions.create("MessageChannel", {
  connected() {
    // Called when the subscription is ready for use on the server
  },

  disconnected() {
    // Called when the subscription has been terminated by the server
  },

  received(data) {
    const html = `<p>${data.content.text}</p>`;
    const messages = document.getElementById('messages');
    const newMessage = document.getElementById('message_text');
    messages.insertAdjacentHTML('afterbegin', html);
    newMessage.value='';
  }
});

現場からは以上です!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

配列の掛け算について

rubyの問題でつまづいた箇所があるので記録として残しておきます。

問題内容をざっくり説明すると以下のとおりです。
・2つの数字が文字列として入力される("a b")・
最終的それぞれを2倍した数字を出したい

誤答
num = gets.split.map(&:to_i)
puts num * 2

1.splitメソッドで値を分割して配列に文字列の値を入れます。
2.map(&:to_i)で配列の値を数字に変換して配列を作成する。(map(&:to_i)に関しては以下の記事が大変わかりやすく、参考にさせていただきました。)
https://a-records.info/ruby-map-ampersand-colon-to_i/

3.配列の要素に対して*2を行う。

結果は以下のとおりになりました。

num = gets.split.map(&:to_i) // 5 10と入力する
puts num * 2
出力結果 => 5 10 5 10

なぜ@map(&:to_i)で数値に変換しているのに5 10が2回繰り返されているのかわからずにいました。

結論

・配列に対して掛け算を行うと同じ要素を繰り返した新しい配列が作られる。
各要素に対してではなく配列自体に*2を行っていたため要素が繰り返されていました。(わかってから見直すとそりゃそうだと思いますね...)

num = gets.split.map(&:to_i)
num.each {|n| puts n * 2}

eachで各要素に処理を行うことで解決しました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails学習 1日目その2

Ruby on Rails5速習実践ガイド chapter2

2-6-1-1 Railsアプリケーションを新規作成する

$ rails new scaffold_app -d postgresql

rails new:Railsの新規ファイル作成
scaffold_app:ファイル名
-d postgresql:SQLの指定(-dはpostgreSQL用ですよという意味)

2-6-1-2 ユーザー管理機能のひな形を作る

$ bin/rails generate scaffold user name:string address:string age:integer

bin/rails:
scaffold:アプリを作る上での作業をまとめて簡単にしてくれるツール
user:モデル名(userモデル)
name:string address:string age:integer:3つの情報をテーブルに入れテーブルを作成。

Column YAMLの基本

YAMLは構造化されたデータを表現するためのフォーマット。

animal: &animal
 cat: 'ネコ'
 dog: 'イヌ'

animal_shop_1:
  <<: *animal
  hamster: 'ハムスター'

animal_shop_2:
  <<: *animal
  parrot: 'オウム'

animalを&animalとしておく
つまり&animal= cat: 'ネコ' dog: 'イヌ'となる

animal_shop_1は
<<: *animal
hamster: 'ハムスター'

つまり
 &animalとhamster: 'ハムスター'
cat: 'ネコ' dog: 'イヌ' hamster: 'ハムスター'となる

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

rails学習 1日目

Ruby on Rails5速習実践ガイドchapter1

1-1-6 クラスとインスタンス(p.6)

・クラスとインスタンスの関係
クラスは親でインスタンスは子の関係になっており、クラスの中にたくさんのインスタンスが存在している。
Untitled-2.jpg
例を出すと人間という大枠(クラス)の中にAさん(インスタンス)Bさん(インスタンス)Cさん(インスタンス)Dさん(インスタンス)が存在しているということになる。

1-2-5 ローカル変数とインスタンス変数の違い

種類 特徴
ローカル変数 その場限りの一時的な変数。定義したメソッド内でしか使うことができない
インスタンス変数 オブジェクトの保有する変数。インスタンス内で定義するとそのインスタンスないのどのメソッドにも利用できる

例)

class MyClass
 def method_1
  @number=100
 end

 def method_2
  @number  #他のメソッド(method_1)で定義した@numberを別のメソッド(method_2)で利用できる
 end
end

1-2-7 ゲッターやセッターを簡単に定義する(attr_accessor)の使い方

@nameなどのインスタンス変数をちゃんと使おうとすると次の2つを実行しなければならない。
1.作成した情報の名前(name)を@nameに代入して使えるようにするためのメソッドを定義する
2.@nameを表示させるためのnameメソッドを定義する

class User
 def name=(name) #1.
  @name = name
 end

 def name #2.
  @name 
 end

ここまで来て初めて@nameを使えるメソッドが完成する。
...しかしめんどくさい。

class User
 attr_accessor :name
end

attr_accessorを使うことによって一気にすっきりとした。

1-2-8 住んでいる場所やEメールアドレスを持たせる(attr_accessorの具体的な使い方)

attr_accessorには様々な属性をつけることができる

class User
 atte_accessor :name, :address, :email
end

それぞれの属性を使いたい時は以下のようにする

user = User.new
user.name = "小田井優"
user.address = "東京"

def profile  #名前と出身を表示させるメソッドを作った
 "#{name}(#{address})"
end

user.profile #userの名前と出身をまとめて表示するprofileメソッドを実行した
=> "小田井優(東京)"

nameやaddressを使ってuserの情報を記入、呼び出しできる。

1-3-4-2 当てはまらない場合に分岐するunless (unlessの使い方)

ifは条件の結果が真だった時に処理を実行するがunlessは条件の結果が偽のときに処理を実行する。
(ifの逆の処理をする)

1-3-4-3 後置if

普段のifが後ろについた形。
else等はつけることができず1行だけに作用するif

puts 'おはようございます' if true  #出力される

puts 'お疲れ様でした' if false  #出力されない

上のコードは「もし結果がtrueならばputsを出力する」になる
結果はtrueなので「おはようございます」が出力される

1-3-6 ハッシュ

普通の配列だと欲しいの値を出そうと思ったら番号(何番目か)を指定しなければならない。
これは配列の情報が多くなればなるほど不可能になっていく。
そこでハッシュを使い、値それぞれにあだ名(キー)みたいなものをつけていく。
そうすることであだ名を入力すれば自動的にそれに紐づいた値が出てくる。

 jinnkou ={ tokyo: 13636222, kanagawa: 9145572 }
         #{あだ名(キー):東京の人口,あだ名(キー):神奈川の人口}

puts jinnkou[:tokyo]
=> 13636222

[]の中には:を入れてあだ名(キー)をいれる

1-4-1 initialize

Rubyで「〇〇.new」を実行する時は必ず〇〇のクラスの中のinitializeが実行される。
テーブルのカラムに対応する値を入れれるようにする
例えばname,address,emailカラムがあるUserテーブルに新しい情報を入れる時、
initialize(name, address, email)と書くと、「カッコの中の1番目が名前、2番目が住所、3番目がメアドに対応させるよ」といった操作をする

class User #User.newのときにinitializeが使える
 def initialize(name, address, email)
   @name = name
   @address = address
   @email = email
 end
end
user = User.new("大場寧子","東京都","nil")
                 # ||       ||      ||
  #initialize(  name   ,address, email)

1-4-2 メソッドの呼び出しに制限をかける(private)

セキュリティ面により誰もがメソッドを使えると個人情報の流失等の問題になってしまうためprivateメソッドを使って外からメソッドを使えないようにする。

1-5-2 モジュールによる共通化(Mix-in)

規模の小さいメソッド(処理が一つだけだったり処理自体が簡単だったり)をモジュールとしてひとかたまりにし、様々なクラスで使えるようにする。

#価格についてまとめたモジュール
module PriceHolder
 def total_price
  price*Tax.rate
 end
end

class Product
 include PriceHolder
 attr_accessor :price
end

class OrderedItem
 include PriceHolder
 attr_accessor :unit_price, :volume

#税抜き単価*数量
 def price
  unit_price*volume
 end
end

価格に消費税率をかけて戻り値を出す処理をPriceHolderモジュールとして、そのPriceHolderモジュールをそれぞれのクラスに使っている。モジュールを使う時はincludeを使う。

1-7-1 nilガード

number ||=10

もしもnumberがあればnumberを使い、なければnumberに10を代入したnumberが使われる。

1-7-2 ぼっち演算子 &.

例えばUserテーブルはあるがobject.nameとコードを打っても、まずobjectテーブルがないのでエラーが表示される。しかしぼっち演算子object&.nameを使うとテーブルがない場合はエラーではなくnilを戻り値として返すようになる。

1-7-3 %記法

ary1 = ['apple', 'banana' ,'orange']
# %記法を使うと
ary1 = %w[apple banana orange]

%記法を使うと’’などが省略できる。

1-7-4 配列の各要素から特定の属性だけを取り出す(mapメソッド)

class User
 attr_accessor :name, :address
end

user1 = User.new(name:'大場寧子', address:'東京都')
user2 = User.new(name:'小芝美由紀', address:'千葉県')
user3 = User.new(name:'小田井優', address:'神奈川県')

users = [user1,user2.user3]

この時、それぞれのuserの名前だけの配列が欲しい場合は、mapメソッドを使い

names = users.map(&:name)
=>["大場寧子","小芝美由紀","小田井優"]

このように 元の配列.map(&:欲しい情報) とすると欲しい情報だけの配列ができる。

その他勉強になったことメモ

1.require:ソースコード(ここではuser.rb)を読み込む時に使う

> require './user.rb'

2.returnを使うタイミング

メソッドを実行した時に返ってくる値のことを「返り値」という。基本的にメソッドは実行されると何かしらの返り値をくれるが、返り値をくれるのはメソッドが全て実行し切った時になる。メソッドの途中で返り値が欲しい場合はreturnを使い返り値を取得する。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Font awesomeを使用したアイコンの入れ方

はじめに

ウェブページ内にメニューバーやFacebook、instagram、twitterなどのアイコンを入れたいと思った時にFont awesomeが使える。

Font awesomeとは

無料で使えるウェブフォントアイコンである。

サイト:Font awesome

使い方

Gemfileにfont-awesome-sassを追加し、bundle installする。

Gemfile
gem 'font-awesome-sass' #追加しbundle install後、サーバーを立ち上げ直す

bundle install後、サーバーを立ち上げ直し、
application.scssファイルにfont-awesome-sprocketsとfont-awesomeを追加。
読み込む順番が異なるとアイコンが読み込まれないので注意が必要。

app/assets/stylesheets/application.scss
@import "font-awesome-sprockets";
@import "font-awesome";

ビューに欲しいアイコン(今回は、class="fas fa-bars"のfasとfa-以降の部分barsを使用)を入力する。
iconはfont-awesome-sassのgemのヘルパーメソッド。

app/views/chats/index.html.haml
= icon('fas', 'bars')

スクリーンショット 2020-10-24 19.07.02.png

これで、ウェブページにFont awesomeのアイコンを入れることができる

参考サイト
Font awesome Github
pikawaka font-awesome-sass

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RailsにVue.jsを導入する

備忘録

今回はrailsで開発中のアプリにVue.jsを導入したので備忘録として記録します。
初めてrailsでVue.jsを使う人の助けになればと思います。
また、初心者のため間違いなどあればご指摘お願いします!
ruby 2.6.5
Rails 6.0.3.3

ステップ1webpackerのインストール

インストール済みの方はスキップして下さい
Gemgile内に記述

gem "webpacker", github: "rails/webpacker”

記述できたらbundle installしましょう。

インストールできたらターミナルで以下を実行

$ bin/rails webpacker:install

これでwebpackerのインストールが完了

ステップ2 Vue.jsのインストール

ターミナルで以下コマンドを入力

$ rails webpacker:install:vue

これでVue.jsに必要なファイルなどが作成されました。

ステップ3 Vue.jsの読み込み

app/views/layouts配下のapplication.html.erbファイルに以下を記述

 <%= javascript_pack_tag "hello_vue" %>

正常に読み込まれると写真のようにviewに表示されます。
https://gyazo.com/57e56686d2113920659f3dc9410f3a15

最後に

以上でrailsでVue.jsを導入する事ができました!
比較的に簡単に導入する事ができるのでよければ使ってみて下さい!
何か間違えなどあればご教授下さい!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】video_tagで動画が再生されない

Railsのvideo_tagを使用した実装

Railsで画像を表示させる時はimage_tagを使用しますが、動画を再生したい時にはvideo_tagを使用します。
ところがどっこい動画が再生されないのはどうしてなのでしょう!
ちなみにRailsの公式ドキュメントは以下です。

Rails公式ドキュメント【video_tag】

再生されない記述

<% @posts.each do |post| %>
 <%= video_tag(post.movie, size: "500x300", autoplay: true) %>
<% end %>

postsテーブルのmovieカラムからデータをとってきています。
動画サイズを500×300に指定、autoplay: trueとすることで自動再生されるはず、、、されません。

原因とコード追加

Rails公式ドキュメントを見てもらえればわかる通り、mutedというオプションがあります。
デフォルトだとmuted: folseとなっており、音声再生が行われる状態になっています。
自動で音声などが再生され始めるとユーザーにとって負担となるため、Chromeではautoplaymutedがどちらも有効になっていないと自動再生されないようです。
mutedを追加した記述が以下です。

<% @posts.each do |post| %>
 <%= video_tag(post.movie, size: "500x300", autoplay: true, muted: true) %>
<% end %>

おわりに

読んでいただきありがとうございました。
どなたかの動画再生で役に立てば幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails]Active Storageの使用方法

はじめに

Active Storageを使うと、画像などのファイルのアップロードを簡単にするメソッドが使用できたり、画像を保存するテーブルを簡単に作成できます。

目次

  1. 画像加工ツールの導入
  2. Active Storageのインストール
  3. 画像の保存方法
  4. 画像の表示

1. 画像加工ツールの導入

まず画像加工に必要な画像変換ツールと、これをRailsから使えるようにするためのgemを導入します。
ImageMagicはコマンドラインから画像の作成やサイズ変更、保存形式などの変更ができます。
以下のコマンドを実行します。

ターミナル
brew install imagemagick

ImageMagicはgemではないのでRubyやRailsで扱うには、MiniMagickというgemを導入する必要があります。
MiniMagicはImageMagicをRubyで扱えるようにするためのgemです。
次に画像サイズの変更をするためのgemをインストールします。
ImageProcessingはMiniMagicではできない、画像サイズを調整する機能を提供するgemです。
以下のようにgemfileの一番下に追記します。
その後、コマンドでbundle installを実行します。

gemfile
gem 'mini_magick'
gem 'image_processing', '~> 1.2'

2. Active Storageのインストール

ターミナルで以下を実行します。

ターミナル
rails active_storage:install

Active Storageに関連したマイグレーションが作成されるので、続けて以下を実行します。

ターミナル
rails db:migrate

3. 画像の保存方法

Active Storageのテーブルに画像を保存するために、アソシエーションの定義とimageカラムの保存の許可を設定します。
今回はhas_one_attachedメソッドを使って、一つの画像ファイルを添付できるようにしました。

app/models/post.rb
class Post < ApplicationRecord
  ~~
  has_one_attached :image
  ~~
end

これでpostsテーブルに画像ファイルの紐付けができました。
このとき、postsテーブルにカラムを追加する必要はありません。

次にストロングパラメーターにimageを追加し、画像ファイルの保存を許可します。

app/controllers/posts_controller.rb
class PostsController < ApplicationController
  ~~
  def post_params
    params.require(:post).permit(:name, :image, :price, :evaluation, :description, :category_id, :shop_name).merge(user_id: current_user.id)
  end
  ~~
end

4. 画像の表示

Railsのヘルパーメソッドであるimage_tagメソッドを用いて画像を表示します。

<%= image_tag post.image, class: "post-img" %>

attached?メソッドを使うことで画像が存在しないときのエラーを防ぐことができます。

<%= image_tag @post.image ,class:"user-box-img" if @post.image.attached? %>

上記のように記述することで画像が存在する場合のみimage_tagが読み込まれます。

Active Storageを導入している場合、variantメソッドを用いることができます。
variantメソッドを使用することで、画像ファイルの表示サイズを指定することができます。

<%= image_tag post.image.variant(resize: '500x500'), class: "post-img" %>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【rails】センテンス集

ヘルパーメソッド

ビューファイルではヘルパーメソッドを使用することができました。これまでに登場した「form_with」や「link_to」などもヘルパーメソッドであり、あらかじめ定義されている処理です。これらのヘルパーメソッドは、HTMLの要素が戻り値となっています。より詳しく言うと、文字列としてHTMLの要素が戻り値となる、ということです。

モジュール

モジュールとは、Rubyにおける「インスタンスを生成できないクラス」のようなもののことです。
下記のように定義します。

module Sample1
 class Test
 end
end

module Sample2
 class Test
 end
end

Sample1::Test
Sample2::Test

クラスとモジュールの使い分けとして、具体的なオブジェクトを生成したい場合(インスタンスを生成したい場合)はクラスを使用し、処理だけ(メソッドなど)が必要な場合はモジュールを使用するという認識で構いません。

Helper

Helperとは、ヘルパーメソッドを作成できるモジュールです。
app/helpers配下に用意されており、application_helper.rbや、各コントローラーに対応したhelperのファイルに処理を記述することでヘルパーメソッドとして使用できます。実際には〇〇Helperという形で定義されます。

module ApplicationHelper
  def sample
    # sampleというヘルパーメソッドです
  end
end

このようにApplicationHelper内へメソッドとして定義すると、下記のようにビューファイルで使用できます。

<%= sample %>

ビューファイルへRubyの処理をたくさん記述してしまった場合や、繰り返し同じ処理を記述する場合は、可読性が落ちてしまうのでヘルパーメソッドとして切り出しましょう。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

フォーム入力の結果を表示する方法

はじめて記事を書かせていただきます
プログラミングの学習をはじめて、1ヶ月の初心者です

ruby on railsでfurimaアプリを作成しています
ユーザー登録をして、商品を出品し、他のユーザーが購入すると、取引が完了する流れです

現段階の仕様では、ユーザーの出品商品の入力が終わると、topページに移動するようにしています

def create
  @item = Item.new(item_params)
  if @item.valid?
     @item.save
     return redirect_to root_path #topページに戻る
  else
    render :new
  end
end

*itemsテーブルに出品商品の情報が登録されます

ここで「商品の出品が完了しました」と表示されるページを追加し、topページへクリックで戻るようにする方法を検討しています

  • コントローラーに、パスを記述する方法でやってみる

まず、結果表示のHTML文書を作成(kanryouとする)
routesファイルに記述

resources :items  do
  resources :orders, only: [:index, :create]
  member do
    get 'kanryou'
  end
end

コントローラーに記述

def create
  @item = Item.new(item_params)
  if @item.valid?
     @item.save
     return redirect_to kanryou_item_path(@item.id)
  else
     render :new
  end
end

以上でうまくいきました

参考にさせていただきました
https://qiita.com/imayasu/items/19f43a5726ed2170f611

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

さまざまなマイグレーション操作を使いこなす

マイグレーションの適用を理解しよう

1.「マイグレーション」ファイルを作成し、RubyでDBの構造(スキーマ)を変更するコードを記述
2.作成した「マイグレーション」ファイルをrails db:migrateコマンドを使ってデータベースに適用する(migrateする)。

$ rails db:migrate

マイグレーションファイルの更新・変更・削除はコマンドを実行しないと適用されない。

マイグレーションの上げ下げ

マイグレーションを適用する = 上げ
適用を取り消す = 下げ

schema.rb

Railsは現在のデータベース構造をdb/schema.rbに自動出力します。
マイグレーションのを適用したり外したりすると自動的に出力され、また

db:schema.rb:dump

で手動出力する事も可能

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby on Rails】javascriptのお手軽スクロールアニメーション(ScrollReveal.js使用)

目標

scroll.gif

開発環境

ruby 2.5.7
Rails 5.2.4.3
OS: macOS Catalina

ScrollReveal.jsとは

https://scrollrevealjs.org/
こちらが公式サイトにはなります。
ScrollReveal is a JavaScript library for easily animating elements as they enter/leave the viewport.
ScrollRevealは、要素がビューポートに出入りするときに要素を簡単にアニメーション化するためのJavaScriptライブラリです。
※google翻訳

流れ

1 ScrollReveal.jsを導入する
2 viewの編集
3 jsファイルの編集

ScrollReveal.jsを導入する

①CDNで読み込む場合(おすすめ)
application.html.erbのhead内に
<script src="https://unpkg.com/scrollreveal">
この一行を追加し、ScrollReveal.jsを使用できるようにします。

app/views/layouts/application.html.erb
<head>
  <title>Ddtt</title>
  <%= csrf_meta_tags %>
  <%= csp_meta_tag %>

  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  <script src="https://unpkg.com/scrollreveal"></script>
</head>

②ファイルをダウンロードする場合
https://github.com/jlmakes/scrollreveal
こちらからzipファイルダウンロードするし、中にある「scrollreveal.min.js」を
app/assets/javascripts内に保存します。
その後、<script src="/js/scrollreveal.min.js"></script>
こちらをhead内または表示ファイルの一番上に追加してください。

view,CSSの編集

説明のため、html内にcssを記述します。

app/views/homes/top.html.erb
<div class="page">
  <span>スクロールしてください</span>
</div>

<div class="page">
  <div class="box"></div>
</div>

<style>
.page {
  position: relative;
  height: 100vh;
}
.box {
  width: 500px;
  height: 200px;
  background-color: red;
}
</style>

jsファイルの編集

こちらが基本の形。

app/asstes/javascripts/application.js
$(function(){
  ScrollReveal().reveal('.box');
});

基本形だとこのようになります。
画面収録 2020-10-23 20.11.11.mov.gif
gif画像にした分表示がかなり早くなっていますが、
ご覧の通りあまりアニメーションがあるかどうかは確認しにくいです。
したがってオプションを付けていきます。

目標にある動画の記述。

app/asstes/javascripts/application.js
$(function(){
  ScrollReveal().reveal('.box', { 
    duration: 2000, 
    scale: 4,
    reset: false
  });
});

このようにオプションを追加することも可能です。
今回使用したオプションは

  • duration:アニメーションの完了にかかる時間
  • scale:表示される前の要素のサイズ
  • reset:viewportを離れる時に初期化された位置に戻る要素を有効/無効にする

その他にも様々なオプションが用意されているため、
興味のある方は公式サイトをご覧ください。
https://scrollrevealjs.org/api/delay.html

まとめ

ほとんどの有名サイトにはなにかしらのアニメーションが付与されており、
今から作成する場合は必須になっていると思います。
ただし、上記を活用すれば数分で導入できるのでおすすめです」。

またtwitterではQiitaにはアップしていない技術や考え方もアップしていますので、
よければフォローして頂けると嬉しいです。
詳しくはこちら https://twitter.com/japwork

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

初投稿です。

ブログがわりに始めようかなと思っております。

最近はアプリで英語の勉強をしています。

https://eigomonogatari.com/

今日はこんなところで。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rails 投稿とユーザーの紐付け

はじめに

今、メモアプリを開発をしています。
全てのメモの一覧が表示されてしまうのですが、どうにか
メモ一覧ページにログインユーザーのメモのみの一覧を表示したいです。

今回はそれについて学習していきます。

メモとユーザーの紐付け

まず、各投稿が誰がしたのかを判別するためにnotesテーブル(投稿系のテーブル)に、user_idというカラムをたす。

class CreateNotes < ActiveRecord::Migration[5.2]
  def change
    create_table :notes do |t|
      t.text :title
      t.integer :user_id
      t.integer :category_id
      t.text :explanation

      t.timestamps
    end
  end
end
$ rails db:migrate:reset

メモに投稿したユーザーのidを保存

投稿を保存する際に、先ほど追加したuser_idカラムにも情報を入れる。
buildメソッドについて

notes.controller.rb
def create
    @note = current_user.notes.build(note_params)
    @note.save
    redirect_to notes_path
  end

メモ一覧ページにユーザーの投稿をのみを表示する。

 <div class='container'>
   <div class='row'>
    <h2>メモ一覧</h2>
    <table class='table'>
      <thead>
        <tr>
          <th>タイトル</th>
          <th>カテゴリー</th>
        </tr>
      </thead>
      <tbody>

        <% @notes.each do |note| %>
        <% if user_signed_in? && current_user.id == note.user_id %>   #ここを追加
        <tr>
          <td>
            <%= link_to note_path(note) do %>
              <%= note.title %>
            <% end %>
          </td>
          <td><%= note.category.name %></td>
        </tr>
        <% end %>
        <% end %>
      </tbody>
    </table>
   </div>
 </div>

メモ一覧のeach文(繰り返し)の中に記述。

<% if user_signed_in? && current_user.id == note.user_id %> 

この記述でログインしているユーザなのか?とログインユーザーのidとメモを投稿したユーザのidが同じか見ている。

trueなら表示される!
これで大丈夫だと思います!

最後に

説明が分かりにくいと思いますが何かの参考になれば幸いです。
また、間違っているところがあればご教授いただけるとありがたいです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ruby buildメソッド

buildメソッド

親モデルに属する子モデルのインスタンスを新たに生成したい場合に使うメソッド。
(親モデルと子モデルは、アソシエーション設定あり)
外部キーに値が入った状態でインスタンスが生成できる。

ユーザーに紐づくメモインスタンスを生成したい場合
※UserモデルとNoteモデルは、1対多のアソシエーションを設定しているとします。

note.controller.rb
 @note = current_user.notes.build(note_params)  ## 親モデル.子モデル.buildという形式

生成されるコメントインスタンスの中身
*pry-byebugで@noteインスタンスの中身を確認

 @note
 id: nil,
 title: "aaa",
 user_id: 2,
 category_id: 1,
 explanation: "ppppp",
 created_at: nil,
 updated_at: nil 

user_idに値が入っています。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Ruby on Rails】Formオブジェクト(ActiveModel)のエラーメッセージを日本語化する方法

本記事の概要

・Formオブジェクトのバリデーションエラーが日本語にならない問題に悩んだので、備忘録として残しておきます。
・+α余談としてActiveRecordとActiveModelの違いについて少し触れました。

開発環境

Mac OS Catalina 10.15.4
ruby 2.6系
rails 6.0系

前提条件

gem 'rails-i18n'を導入してデフォルトの言語設定はすでに日本語にしています。
また、configのlocalsディレクトリにja.ymlファイルを作成済みです。

エラーメッセージを日本語化できなかった原因とその対策

結論から言うと、今回作成したFormオブジェクトはinclude ActiveModel:Modelによってactivemodelを継承したモデルであったにも関わらず
activerecordを継承したモデルとして日本語化を行おうとしたのが問題だったよう。

<誤っていたコードの記述>

ja.yml
ja:
  activerecord:
    models:
      detail: 詳細情報
      posts_tag: 投稿 
    attributes:
      user:
        name: 名前
      detail:
        age: 年齢
        pr: PR
        area_id: 居住地
        occupation_id: 職業
        interest_id: 興味
      posts_tag: 
        title: タイトル
        content: 概要
        name: タグ

<正しいコードの記述>

ja.yml
ja:
  activerecord:
    models:
      detail: 詳細情報
    attributes:
      user:
        name: 名前
      detail:
        age: 年齢
        pr: PR
        area_id: 居住地
        occupation_id: 職業
        interest_id: 興味

  activemodel:
    models:
      posts_tag: 投稿 
    attributes:
      posts_tag: 
        title: タイトル
        content: 概要
        name: タグ

余談

ちなみに、rails g modelで生成するデフォルトモデルが継承しているActiveRecordとActiveModelの違いは、DBとのやり取りが可能か否かにあります。

前者は、可能なのでモデル名.findなどですでに保存してあるデータを引っ張ってこられますが、後者のActiveModelは通常findメソッドは使えません。

他にも、バリデーションにおける`validates uniqueness: true等も、DBに保存されているデータを参照して一意性かどうか判断するので、ActiveModelで記述することはできません。

そんな感じで便利な一方、割とActiveModelはややこしいですね...
なにはともあれ、最後までお読み頂きありがとうございました!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

"data" クラスの使用

概要

・日付に関する複雑な概念を簡単に使用できる様にしたもの
・日付や時刻を出力できる

準備

・requireメソッドで外部からdateクラスを呼び出す

require"date"

todayメソッド

・dateクラスで良く使われるメソッド
・自動的に”今日の”日付を算出し出力してくれる

require"date"
day = Date.today
#dayという変数に代入する

puts day

#結果 
2020-10-24

wdayメソッド

・曜日を日曜日か土曜日の順に1〜6の整数として出力できる。
 日曜日=0
 月曜日=1
 火曜日=2
 水曜日=3
 木曜日=4
 金曜日=5
 土曜日=6

require"date"
day = Date.today.wday

puts day

#結果(日曜日の場合)

備考

 (例)
 日曜日と土曜日は 『今日は○○曜日。休みです』 と出力し
 その他の曜日は 『今日は○○曜日。仕事です』 と出力する

※間違っている箇所や,こうした方が良いなどありましたらよろしくお願い致します

require"date"
day = Date.today.wday
wday = ["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"]

if day == 6 or 0
  puts "今日は#{wday[day]}。休みです!!"

else 
  puts "今日は#{wday[day]}。仕事です"

end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dateクラスの使用

概要

・日付に関する複雑な概念を簡単に使用できる様にしたもの
・日付や時刻を出力できる

準備

・requireメソッドで外部からdateクラスを呼び出す

require "date"

todayメソッド

・dateクラスで良く使われるメソッド
・自動的に”今日の”日付を算出し出力してくれる

require "date"
day = Date.today
#dayという変数に代入する

puts day

#結果 
2020-10-24

wdayメソッド

・曜日を日曜日か土曜日の順に1〜6の整数として出力できる。
 日曜日=0
 月曜日=1
 火曜日=2
 水曜日=3
 木曜日=4
 金曜日=5
 土曜日=6

require "date"
day = Date.today.wday

puts day

#結果(日曜日の場合)

備考

 (例)
 日曜日と土曜日は 『今日は○○曜日。休みです』 と出力し
 その他の曜日は 『今日は○○曜日。仕事です』 と出力する

※間違っている箇所や,こうした方が良いなどありましたらよろしくお願い致します

require"date"
day = Date.today.wday
wday = ["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"]

if day == 6 or 0
  puts "今日は#{wday[day]}。休みです!!"

else 
  puts "今日は#{wday[day]}。仕事です"

end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

普段 Ruby を使ってない人が Ruby の環境を構築する

内容

普段 Ruby を使っていない人向けに Ruby の環境を構築するまでの工程を書く。Ruby プログラムを書く予定はないが、Ruby 製のアプリケーションを利用するために、 Ruby 環境を構築する必要があったのだが、検索しても分かりにくい記事やら明らかに内容が非 Ruby 書いてる人から見ても変なのばっかヒットするので、自分で書く。私は専門家でもなんでもないので、書いた内容の正しさは保証しません。

Ruby を使っている人が全然書いてくれない前提条件

本当の専門家はおそらくみんな知っているのだろうが、検索でヒットしないのが悲しい。

  1. OS に含まれるインタープリタ型プログラミング言語のインスタンス A と開発に使うインスタンス B が同じ A = B だと、B をカスタマイズすると A を含む OS が壊れるので、A ≠ B となるように B を別に用意するのが現代では一般的である。
  2. macOS(やその他多くの Unix-like システム) は Ruby を含む。
  3. rbenv が Ruby に対して前提条件1を実現するために存在する。
  4. Ruby のパッケージ(部品化された Ruby で書かれたプログラム)は gem と呼ばれている。
  5. gem を取り扱うプログラムの名前とコマンド名は gem である。
  6. gem にはそのまま gem 名のコマンドとして呼び出し可能なものがある。
  7. プログラム gem はパッケージ管理ソフトとしては(おそらく)機能が不十分である(と考えられている)。
  8. プログラム gem を補完し、パッケージ管理ソフトとするプログラム Bundler が存在する。
  9. Bundler は bundle という名前の gem であり、呼び出し可能である。
  10. コマンド bundle を実行すると現在のディレクトリ下の Gemfile という名前のテキストファイルの指示に従って様々な gem をインストールし、Ruby 環境を構成する。
  11. Ruby アプリケーションは1つの gem として提供される(ものもある)。
  12. 高度な Ruby アプリケーションは複数の Ruby アプリケーションの連携で構成される。
  13. 高度な Ruby アプリケーションを真面目に取り扱うならば、bundler を利用するのが自然である。

やること

前提条件を考えると、gem で提供される Ruby アプリケーションを真面目に使うには、

  • Ruby
  • rbenv
  • gem
  • bundler

を利用する必要があることが分かる。私は Fish Shell を使っているので、bash や Zsh 利用者とは異なる部分が含まれる。

  1. rbenv を Homebrew を通してインストールし、Fish 上で機能するように rbenv に指示された通りに謎の設定コマンドを Fish の設定ファイルに記述する。
  2. 最新の Ruby インスタンスをインストールする。
  3. インストールした Ruby インスタンスをシェルが呼び出す Ruby インスタンスに指定する。
  4. Ruby インスタンスに bundler をインストールする。
  5. やんなきゃ動かない謎のコマンドを実行する。
#! /usr/bin/env fish

brew install rbenv
echo "status --is-interactive; and source (rbenv init -|psub)" >> $HOME/.config/fish/config.fish
rbenv install 2.7.2
rbenv global 2.7.2
gem install bundler
rbenv rehash

rbenv rehash は必要なのだが、なぜ必要なのかは理解していない。

Ruby アプリケーションのインストール

  1. 私は Asciidoctor で図形を楽に入れられるようにする Asciidoctor Diagram を利用したい。
  2. 私は私のユーザースペース全体でこのアプリケーションが機能すればいいので、ホームディレクトリ以下に ファイル Gemfile を作成し、そこに、gem の設定を記述し、bundler を動かす。
  3. やんなきゃ動かない謎のコマンドを実行する。
#! /usr/bin/env fish

echo "\
source 'https://rubygems.org'
gem 'asciidoctor'
gem 'asciidoctor-diagram'
" > $HOME/Gemfile
bundle
rbenv rehash

こちらも同様に rbenv rehash が必要なのだが、なぜ必要なのかは理解していない。

あとがき

ただアプリケーションが動くようになった過程を書いただけなので、詳しい方の補足・訂正・批判を待っています。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

数値について

数値

数値は、数を表現する値です。文字列とは異なり、計算などを
行うことができます。

数値は文字列とは違って、ダブルクォーテーション"
シングルクォーテーション'も必要ありません。
以下は数値を使った数の表し方の例です。

【例】Rubyファイル
# 整数
10

# 負の値
-10

# 小数
3.14

数をダブルクオーテーションで囲むと数値ではなく文字列として扱われてしまいます。
プログラミングでは文字列の"10"と数値の10は別物です。数値は計算ができますが、文字列は計算ができません。

irbで以下のコードを実行してみましょう

irbでRubyの数値を記述し、実行してみましょう。

irb
# 数値を書いてエンターキーで実行
irb(main):001:0> 12345

# 続けてこのように表示されれば成功
=> 12345

まとめ

数値とは、数を表現する値のこと。

以上。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【RSpec】コントローラーのインスタンス変数をテストで使いたいとき【assignsは非推奨】

Rails 5 から assigns(assert_templateも)が非推奨になりました。
一応、コントローラーテスト自身はdeprecatedになっていないのでassignsは使えるのですが、rails-controller-testingというgemをインストールする必要があります。

しかし、これはあくまでも既存のプロジェクトに対する救済策で、新規のプロジェクトでassignsを使うことは推奨できません。(ぶっちゃけ理由はわからないです。わかる方いれば教えて下さい :pray: )

代わりに、

controller.instance_variable_get("@hoge")

というのを使うことでインスタンス変数を取得することができます。

コード例

最近書いたパスワードリセット処理のテストを一部抜粋してきました。

password_resets_request_spec.rb
RSpec.describe 'PasswordResets', type: :request do
  let(:user) { create(:user) }

 describe 'パスワードリセット編集画面へのアクセス' do
    context '不正なメールアドレスだったとき' do
      it 'userはパスワード再設定ページへリダイレクトされること' do
        post password_resets_path, params: { password_reset: { email: user.email } }
        user = controller.instance_variable_get('@user')
        get edit_password_reset_path(user.reset_token, email: '')
        expect(flash[:danger]).to be_truthy
        follow_redirect!
        expect(request.fullpath).to eq '/password_resets/new'
      end
    end

↑のコードではreset_token属性にアクセスしたかったので、そのためにcreateアクションの@userというインスタンス変数を取得しているといった感じです。

最後まで読んでいただきありがとうございます!

最近個人開発のアプリのデプロイに必死で、少し短いです :pray:
デプロイ完了したら、また記事をがっつり書いてこうと思ってます!!よろしくお願いいたします。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Rubyで外部APIのOpenWeatherMapを使用して天気予報を表示

アプリ説明

Rubyで翌日の天気予報を表示するプログラムです。
外部APIでOpenWeatherMapを使用します。

開発環境

ruby:2.6.6
外部API:OpenWeatherMap

完成イメージ

wf.gif

操作の流れ
  1. アプリのルートディレクトリでruby execution.rbを実行。
  2. 都道府県が一覧表示される。
  3. 都道府県の番号を入力。
  4. 翌日の天気予報を、3時間毎に区切り、一覧表示される。

ディレクトリ構成図

wf.png

事前準備でOpenWeatherMapのAPIキーが必要

このプログラムを作成するにあたり、OpenWeatherMapAPIキーが必要になります。

  1. OpenWeatherMapのホームページからアカウント登録をします。
  2. 登録したメールアドレス宛にメールが送信されます。
  3. 受信したメール本文内にAPIキーが記載されていますので、こちらを利用します。

有料プランもありますが、無料で利用することができます。
今回作成するプログラムのような、5日以内の天気情報を取得する場合は無料枠で使用できます。

環境変数にAPIキーを格納

セキリュティ対策のため、外部から参照できない環境変数にAPIキーを格納しておく。

操作方法
ターミナル
vim ~/.zshrc

インサートモードにし、下記を追加。

.zshrc
export WEATHER_API_KEY="APIキーを入力"

:wqで保存終了し、下記を実行し設定を反映させる。

ターミナル
source ~/.zshrc

コード内でAPIキーを使用できるようにする

config.rbファイルを作成し下記を追加。

config.rb
WEATHER_API_KEY = ENV["WEATHER_API_KEY"]

今回は定数に代入して使用する形をとります。
これでWEATHER_API_KEYという定数名でAPIキーを使用することができる。

都道府県一覧のCSVファイルを作成し、読み込む

prefectures.csvファイルを作成し、下記の都道府県一覧を追加。

prefectures.csv
prefecture,english
北海道,Hokkaido
青森県,Aomori-ken
岩手県,Iwate-ken
宮城県,Miyagi-ken
秋田県,Akita-ken
山形県,Yamagata-ken
福島県,Fukushima-ken
茨城県,Ibaraki-ken
栃木県,Tochigi-ken
群馬県,Gunma-ken
埼玉県,Saitama-ken
千葉県,Chiba-ken
東京都,Tokyo
神奈川県,Kanagawa-ken
新潟県,Niigata-ken
富山県,Toyama-ken
石川県,Ishikawa-ken
福井県,Fukui-ken
山梨県,Yamanashi-ken
長野県,Nagano-ken
岐阜県,Gifu-ken
静岡県,Shizuoka-ken
愛知県,Aichi-ken
三重県,Mie-ken
滋賀県,Shiga-ken
京都府,Kyoto Prefecture
大阪府,Osaka-fu
兵庫県,hyogo
奈良県,Nara-ken
和歌山県,Wakayama-ken
鳥取県,Tottori-ken
島根県,Shimane-ken
岡山県,Okayama-ken
広島県,Hiroshima-ken
山口県,Yamaguchi-ken
徳島県,Tokushima-ken
香川県,Kagawa-ken
愛媛県,Ehime-ken
高知県,Kochi Prefecture
福岡県,Fukuoka-ken
佐賀県,Saga-ken
長崎県,Nagasaki-ken
熊本県,Kumamoto-ken
大分県,Oita Prefecture
宮崎県,Miyazaki-ken
鹿児島県,Kagoshima-ken
沖縄県,Okinawa-ken

CSVファイルの読み込み

execution.rbを作成し、下記を追加。

execution.rb
require "csv"

prefectures = CSV.read("./prefectures.csv", headers: true)

WeatherInfoクラスを作成

weather_info.rbを作成し、クラスを定義。

weather_info.rb
class WeatherInfo
  def initialize(prefectures)
    @prefectures = prefectures
  end
end

execution.rbWeatherInfoクラスからインスタンスを作成しCSVデータを渡す

execution.rb
require "csv"

prefectures = CSV.read("./prefectures.csv", headers: true)

#--------- 下記を追加 ---------

weather_info = WeatherInfo.new(prefectures)

#----------- ここまで -----------

都道府県一覧を表示し番号選択できるメソッドを定義

WeatherInfoクラスに、都道府県を一覧表示し番号選択できるselect_prefectureメソッドを定義。

weather_info.rb
class WeatherInfo
  def initialize(prefectures)
    @prefectures = prefectures
  end

  #--------- 下記を追加 ---------

  def select_prefecture
    puts <<~TEXT
            ☀~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~☀
            ☁                              ☁
            ☂        明日の天気予報        ☂
            ☆                              ☆
            ☀~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~☀

          TEXT

    # 都道府県一覧をインデックス番号付きで一覧出力
    @prefectures.each.with_index(1) do |prefecture, i|
      puts "#{i.to_s.rjust(2)}. #{prefecture["prefecture"]}"
    end
    puts <<~TEXT

            明日の天気情報を3時間毎に表示します。
            都道府県の番号を入力してください。
          TEXT
    while true
      input = gets.to_i
      # 正しいリスト番号が入力されればメソッドを抜ける
      if input.between?(1, @prefectures.count)
        return @prefectures[input - 1]
      else
        # リスト番号以外が入力されればエラー表示し再ループ
        puts <<~TEXT
                --------------------------------------------
                error : 表示の番号のみを入力してください。
                --------------------------------------------
              TEXT
      end
    end
  end

  #----------- ここまで -----------

end
  • 表示される都道府県一覧のインデックス番号の桁数が違う場合、縦方向に揃わなくなります。縦方向に揃えるためにto_sで文字列に変換してrjust(2)を使用しています。
  • インデックス番号以外が入力された場合はエラー文を表示してループさせるようにしています。

execution.rbselect_prefectureメソッドを実行

execution.rbに上記で定義したselect_prefectureメソッドを実行する。
また、weather_info.rbを読み込んでおく。

execution.rb
require "csv"

#--------- 下記を追加 ---------

require_relative "weather_info"

#----------- ここまで -----------

prefectures = CSV.read("./prefectures.csv", headers: true)
weather_info = WeatherInfo.new(prefectures)

#--------- 下記を追加 ---------

prefecture = weather_info.select_prefecture

#----------- ここまで -----------

OpenWeatherMapから天気情報を取得

外部APIのOpenWeatherMapから天気情報を取得します。
weather_info.rbget_weather_forecastメソッドを定義。

weather_info.rb
class WeatherInfo
  #----------*** 略 ***---------
  def select_prefecture
    #--------*** 略 ***---------
  end

  #--------- 下記を追加 ---------

  def get_weather_forecast(prefecture)
    # 外部API「OpenWeatherMap」から天気情報を取得
    response = open("http://api.openweathermap.org/data/2.5/forecast" + "?q=#{prefecture["english"]}&appid=#{WEATHER_API_KEY}&units=metric&lang=ja")
    # 取得したデータをJSONとして解析
    data = JSON.parse(response.read)
    # JSONデータ内の一部の情報のみ取得しハッシュ化
    datas = { list: data["list"], prefecture_name: data["city"]["name"] }
  end

  #----------- ここまで -----------
end
openメソッドでURLを指定し、天気情報を取得します。
  • http://api.openweathermap.org/data/2.5/forecast → 3時間ごとの天気予報を5日分取得できる
  • ?q= → CSVデータの英語化した都市名が入る
  • &appid= → APIキーが入る
  • &units=metric → データ形式の単位を指定
  • &lang= → 言語を日本語に指定

各パラメータやJSONデータの中身について、詳しくはこちらで確認できます。

execution.rbget_weather_forecastメソッドを実行

execution.rbに、上記で定義したget_weather_forecastメソッドを実行する。
また、config.rbファイル、jsonライブラリ、open-uriライブラリ を読み込んでおく。

execution.rb
require "csv"
require_relative "weather_info"

#--------- 下記を追加 ---------

require_relative "config"
require "json"
require "open-uri"

#----------- ここまで -----------

prefectures = CSV.read("./prefectures.csv", headers: true)
weather_info = WeatherInfo.new(prefectures)
prefecture = weather_info.select_prefecture

#--------- 下記を追加 ---------

datas = weather_info.get_weather_forecast(prefecture)

#----------- ここまで -----------

翌日の天気情報を一覧表示する

取得した天気情報を一覧表示するdisplay_weather_forecastメソッドを定義。

weather_info.rb
class WeatherInfo
  #----------*** 略 ***---------
  def select_prefecture
    #--------*** 略 ***---------
  end

  def get_weather_forecast(prefecture)
    #--------*** 略 ***---------
  end

  #--------- 下記を追加 ---------

  def display_weather_forecast(weathers)
    # 曜日を日本語表示できるようにしておく
    wd = ["日", "月", "火", "水", "木", "金", "土"]
    # 翌日
    tomorrow = Date.today + 1
    puts <<~TEXT


           ☀~~☆~~☁~~☂~~☀~~☆~~☁~~☂~~☀~~☆~~☁~~☂

              #{weathers[:prefecture_name]}#{tomorrow.strftime("%m/%d(#{wd[tomorrow.wday]})")}の天気予報   

           ☀~~☆~~☁~~☂~~☀~~☆~~☁~~☂~~☀~~☆~~☁~~☂

         TEXT
    weathers[:list].each do |weather|
      # DateTime型に変換
      date_and_time = DateTime.parse(weather["dt_txt"])
      # 比較用にDate型も用意
      date = Date.parse(weather["dt_txt"])
      # 翌日の情報だけに限定して一覧表示
      if date == tomorrow
        puts <<~TEXT
               ---------------------------
               #{date_and_time.strftime("%p%H時頃")}
               天気:#{weather["weather"][0]["description"]}
               気温:#{weather["main"]["temp"]}℃
               ---------------------------
             TEXT
      end
    end
  end

  #----------- ここまで -----------

end

execution.rbdisplay_weather_forecastメソッドを実行

execution.rbに上記で定義したdisplay_weather_forecastメソッドを実行する。
また、dateライブラリ を読み込んでおく。

execution.rb
require "csv"
require_relative "weather_info"
require_relative "config"
require "json"
require "open-uri"

#--------- 下記を追加 ---------

require "date"

#----------- ここまで -----------

prefectures = CSV.read("./prefectures.csv", headers: true)
weather_info = WeatherInfo.new(prefectures)
prefecture = weather_info.select_prefecture
datas = weather_info.get_weather_forecast(prefecture)

#--------- 下記を追加 ---------

weather_info.display_weather_forecast(datas)

#----------- ここまで -----------


これで完成したので、あとは

ターミナル
ruby execution.rb

を実行すれば、完成イメージの通りに動きます。

ソースコード

https://github.com/keisuke-333/Weather_Forecast

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む