Rubyを学ぶ

はじめに

Rubyについて学ぶことにしたのでその記録です。

最初にざっくりとProgateで基礎をさらった後にチェリー本を読んでみたいと思います。

✅ゴール
・Rubyの理解を深める

※Windows環境になります。

✅参考

書籍:プロを目指す人のためのRuby入門 ※Ruby2.4を対象

Q. チェリー本の学習時にサポートが切れたRuby 2.4を使ってもいいの?

Progate:Ruby学習コース

環境構築

Progate:Rubyの開発環境を用意しよう!(Windows用)

上記参考に構築しようとしたところ、以前どうやらRubyはインストールしていました。笑

何もわからずにRailsやっていたときのものですね。。。笑

> ruby -v
ruby 2.4.9p362 (2019-10-02 revision 67824) [x64-mingw32]

ってことでさっそく使ってみます。

index.rbを作成

puts "Hello, world!!"
puts 1 + 2

実行

> ruby index.rb
Hello, world!!
3

※追記

Qiita:Windowsでrubyをはじめよう

irbで日本語入力できないエラーが出たのでインストールしなおしました。

こちらのサイトにて僕はRuby+Devkit 2.6.6-1 (x64) 入れました。

環境変数に追加されていることを確認。

コマンド実行で動作確認◎

> ruby -v
ruby 2.6.6p146 (2020-03-31 revision 67876) [x64-mingw32]
> irb
irb(main):001:0> a = "こんにちは"                                                                                       => "こんにちは"

✅irbを活用したターミナルでの操作

> irb
irb(main):001:0> a = "hello world"
=> "hello world" 
irb(main):002:0> a
=> "hello world"

※irbでは変数名を打ち込むだけで内容が表示され、putsメソッドが必要ない。

基礎

ProgateⅠ

✅基本的な出力

# 基本
puts "Hello, world!!" + "こんにちは!!"
puts 1 + 2

✅変数を扱った出力

# 変数
message = "こんにちは、"
name = "John" # ←変数
puts message + name # 「こんにちは、John」が出力
number1 = 1
number2 = 2
number1 = 3 # 「1」を「3」に上書き
number2 += 2 # number2の「2」に「2」を加算
puts number1 + number2 # 「7」が出力
puts "こんにちは、#{name}さん" #「こんにちは、Johnさん」が出力
puts 'こんにちは、#{name}さん' # シングルクォーテーションだと変数展開されない

ダブルクォーテーションと#{}で変数展開。JSだと$なのでそこだけ注意!

✅条件分岐

# 条件分岐
score = 90
puts score > 80 #「true」が出力
puts score > 95 #「false」が出力
if score == 100
  puts "満点です!すごい!!"
elsif score > 80
  puts "よくできました"
else
  puts "がんばりましょう" 
end
# 「よくできました」が出力

🙄elsifのスペルだけ注意ですかね!

ProgateⅡ

✅配列

names = ["sato","saito","suzuki"]
puts names # sato saito suzuki と改行されて出力
puts names[0] # sato が出力
puts "こんにちは、#{names[0]}さん" # 「こんにちは、satoさん」と出力

✅繰り返し処理

each文を用いる。「配列.each do |変数名|」と書く。

# 繰り返し処理
names = ["sato","saito","suzuki"]
names.each do |name|
  puts "名前は#{name}です"
end
#名前はsatoです 名前はsaitoです 名前はsuzukiです と改行されて出力

🙄JS学んでいた身からすると|変数名|とendを必ず書くってのが独特な書き方ですね!

✅ハッシュオブジェクト

オブジェクトを複数補完できるオブジェクト。

それぞれの値にキーと呼ばれる名前をつけて管理。

シンボル:文字を「”」や「’」で囲む代わりに、先頭に「:」をつけた書き方

# ハッシュ それぞれの値にキーと呼ばれる名前をつけて管理
user = {"name" => "sato", "age" => 27}
puts user["name"] # 「sato」と出力
user["age"] = 28
puts user["age"] # 「28」と出力
user["gender"] = "male" # ハッシュの追加
puts user["gender"] # 「male」と出力
puts user[:gender] # 「male」と出力されない!!
user[:test] = "test"
puts user[:test] # 「test」と出力

# ハッシュの省略記法
symbol = {name: "saito", age: 21} 
puts symbol[:name] # 「saito」と出力

🙄ハッシュは呼び出しに[]を用いなければいけないのがポイントですね。:の位置も定義時と呼び出し時で逆転するという。。。

🙄user.nameなどと書きそうになるのも注意。

要素がハッシュの配列

users = [
  {"name" => "sato", "age" => 27},
  {"name" => "saito", "age" => 25},
  {"name" => "suzuki", "age" => 23},
]

puts users[1]["name"] # 「saito」と出力

users.each do |user|
  puts user["name"] # 「sato」「saito」「suzuki」と出力
end

✅メソッド

「def メソッド名」と「end」の間にまとめたい処理を記載。

def introduce
  puts "こんばんは"
  puts "まさるです"
end
introduce

実行

> ruby method.rb
こんばんは
まさるです

引数活用

def introduce(name, age, food)
  puts "こんばんは#{name}です"
  puts "年齢は#{age}です"
  puts "好きな食べ物はは#{food}です"
end
introduce("まさる", 27, "ラーメン")

実行

> ruby method.rb
こんばんはまさるです
年齢は27です
好きな食べ物ははラーメンです

📝メソッドの注意点

・メソッドに引数を設けた場合は、呼び出し時に引数を設けないとエラーになる

・メソッド内で使える引数と定義した引数はメソッドの外(スコープ外)では使えない。

・returnが実行された後の処理は実行されない

・真偽値を返すメソッドは末尾に「?」をつける慣習がある。

def number?(n)
  return n < 5
end

puts number?(3) # 「true」が出力

・キーワード引数を用いることで呼び出し側で引数を明示することも可能※「:」が必須。

def introduce(name:)
  puts "hello"
  puts "my name is #{name}"
end

introduce(name: "sato")

※以下ProgateⅣの内容

✅クラス

※クラスを使うとJSでいうオブジェクト.プロパティ的な書き方ができる。これはハッシュの呼び出し方とこんがらがるので要注意!!

🙄RubyはJSに比べクラスを多用するのかもしれない。。。

「class クラス名」で定義。

設計図のことをクラス、「もの」のことをインスタンスと呼ぶ。
インスタンス変数は、「attr_accessor :変数名」で定義。

インスタンス生成は「インスタンス(変数名)=クラス名.new」として、変数に代入。
インスタンス変数は「インスタンス.インスタンス変数名 = 値」で代入。

class Menu
  attr_accessor :name
  attr_accessor :price 
end

menu1 = Menu.new
menu1.name = "すし"

puts menu1 # 「#<Menu:0x00000000052a1d90>」と出力※毎回変動!!
puts menu1.name # 「すし」と出力

クラスで定義したメソッド(インスタンスメソッド)は「インスタンス.メソッド名」で呼び出し。

class Menu
  attr_accessor :name
  attr_accessor :price 
  def show
    puts "this is menu"
  end
end

menu1 = Menu.new
menu1.show # 「this is menu」と出力

インスタンスメソッドの中では「self.変数名」でインスタンス変数を扱える。

※selfは呼び出したインスタンス自身が代入されている

class Menu
  attr_accessor :food

  def show
    puts "this is #{self.food}"
  end
end

menu = Menu.new
menu.food = "sushi"
menu.show # 「this is sushi」と出力

🙄selfを用いることで、クラスの外で代入した変数の値をクラス内のメソッドから呼び出すことができてますね!!

showメソッドを以下のように変更してself変数を出力するとインスタンス自身が出力されるのがわかります。

def show
  puts self # 「#<Menu:0x0000000005111980>」と出力
end

initializeメソッドでインスタンス生成直後に処理を実行できる。

class Menu
  attr_accessor :food
  attr_accessor :price

  def initialize(food:, price:)
    self.food = food
    self.price = price
  end
end

menu = Menu.new(food: "sushi",price: 200)
puts menu.food # 「sushi」と出力

🙄initializeメソッドの引数にnewメソッドの引数が代入→インスタンスの初期値を設定できる感じですね!インスタンス生成してから代入する記述をしないで済むので楽ですね。

✅ファイル分割

requireを用いる

menu.rb

class Menu
  attr_accessor :food
  attr_accessor :price

  def initialize(food:, price:)
    self.food = food
    self.price = price
  end
end

index.rb

require "./menu"

menu1 = Menu.new(food: "pizza", price: 300)
puts menu1.food # 「pizza」と出力

繰り返し処理で番号付ける

require "./menu"

menu1 = Menu.new(food: "pizza", price: 300)
menu2 = Menu.new(food: "sushi", price: 200)
menu3 = Menu.new(food: "curry", price: 100)

menus = [menu1, menu2, menu3]
index = 0

menus.each do |menu|
  puts "#{index}. #{menu.info}"
  index += 1
end

出力

0. pizza 300円
1. sushi 200円
2. curry 100円

✅入力の受け取り

gets.chompを用いる

puts "What's your favorite food?"
choice = gets.chomp
puts "My favorite food is #{choice}"

コンソール※sushiは入力内容

What's your favorite food?
sushi
My favorite food is sushi

gets.chomp.to_i」とすることで、入力された内容を数値に変換

puts "何個買いましたか?"
choice = gets.chomp.to_i
puts "合計#{300 * choice}円です"

コンソール

何個買いましたか?
3
合計900円です

ProgateⅤの内容

✅継承

class 新しいクラス名 < 元となるクラス名」とすることで他のクラスを継承して、新しいクラスを定義

※前述のmenu.rbを利用

class Menu
  attr_accessor :food
  attr_accessor :price

  def initialize(food:, price:)
    self.food = food
    self.price = price
  end

  def info
    return "#{self.food} #{self.price}円"
  end
end

proto.rb

require "./menu"

class Food < Menu
  def show
    puts "prototype"
  end
end

food = Food.new(food: "curry", price: 100)
food.show # 「prototype」と出力
puts food.info # 「curry 100円」と出力

オーバーライド:親クラスにあるメソッドと同じ名前のメソッドを子クラスで定義すると、メソッドを上書き可能。

Foodクラスに独自のメソッドを追加&親クラスのメソッド上書き

require "./menu"

class Food < Menu
  attr_accessor :calorie
  def calorie_info
    puts calorie
  end
  def info
    puts "edit"
  end
end

food = Food.new(food: "curry", price: 100)
food.calorie = "200kcal"
food.calorie_info # 「200kcal」と出力
food.info # 「edit」と出力

オーバーライドしたメソッドの中で「super」とすることで、親クラスの同名のメソッドを呼び出すことも可能。

require "./menu"

class Food < Menu
  attr_accessor :calorie
  def initialize(food:, price:, calorie:)
    super(food: food, price: price)
    self.calorie = calorie
  end
  def calorie_info
    puts calorie
  end
end

food = Food.new(food: "curry", price: 100, calorie: "200kcal")
puts food.calorie # 「200kcal」と出力
puts food.food # 「curry」と出力

✅組み込みオブジェクト

Dateクラス

date.rb

require "date"

date1 = Date.new(2020,7,6)
puts date1 # 「2020-07-06」と出力

date2 = Date.today
puts date2 # 「2020-07-05」と出力

todayメソッドなどクラスに対して呼び出すメソッドをクラスメソッドと呼ぶ。

📝sunday?メソッドで日曜日かどうかの真偽値を返す。

※上記のような組み込みオブジェクトをクラス内のメソッド定義に活用して応用できる。

FizzBuzz

※後程追記

組込系メソッド

✅to_sメソッド 参考

文字列以外のオブジェクトを文字列に変換するメソッド

✅classメソッド

クラス名を確認することができる。

a = 15
puts a.class # Integer
b = "string"
puts b.class # String
c = [1,2,3]
puts c.class # Array
d = {a: "A", b: "B",c: "C"}
puts d.class # Hash

その他抑えておきたい部分

・セミコロンがない

・nullを「nil」で表現する

・変数名のルール

①2語以上を組み合わせた変数名を付けるときはアンダーバー(_)を用いる慣習がある。
②キャメルケースは使わない。
③数字から始まる変数名は使えない。

user_name
userName # これ使わない!!
123number # エラーになる

・ダブルクォートの特徴(※シングルクォートの違い)

①\nを改行として扱う
②#{}式展開できる。
③改行文字や式展開を打ち消したい場合手前にバックスラッシュ\n

👉どちらを使うべきか好み。ダブルクォートを使う必然性がない場合はシングルクォートを使うという規約を設けているチームもあるらしい。

・%記法

「%q! !」でシングルクォート

「%Q! !」もしくは「%! !」でダブルクォート

※?など任意の記号を区切り文字として使うことも可能。

puts %Q!test! # 「test」と出力
puts %q!改行
できる!

・ヒアドキュメント

Sinatra使ってみる編

✅導入

公式:Sinatra 始めよう

Rubyの学習をするにせよ、HTMLに記述して簡易的なWebページを生成しながら勉強したいなと思い調べる。

ERBというRubyのライブラリを使うことで簡単に埋め込みができる。

【Ruby】HTMLに埋め込んでみる&メソッドの返り値は何?

どうやらerbというライブラリは必須っぽい。(railsでも見かけたことある!)

Railsぐらいに重量級のフレームワークが必要でないのなら、Sinatraというごく薄いフレームワークがあります。

RailsもSinatraも、Rackという枠組みに乗っかっていますので、サーバとしてはPassenger、Puma、Unicorn、Thin、ローカルテスト用のWebrickなど、いろいろ使えます。

今時Railsを使わずにRubyでそこそこのWebサイト作るにはどうすればいいですか?

SinatraがRailsより軽量らしい。

ってことで内部的な部分もこっちの方が掴みやすいかもと思い試してみました。

✅とりあえず使う

①インストール

gem install sinatra

②myapp.rbを作成

# myapp.rb
require 'sinatra'

get '/' do
  'Hello world!'
end

③実行

> ruby myapp.rb
[2020-07-01 11:26:40] INFO WEBrick 1.4.2
[2020-07-01 11:26:40] INFO ruby 2.6.6 (2020-03-31) [x64-mingw32]
== Sinatra (v2.0.8.1) has taken the stage on 4567 for development with backup from WEBrick
[2020-07-01 11:26:40] INFO WEBrick::HTTPServer#start: pid=8248 port=4567

④確認

http://localhost:4567/へアクセス

🙄簡単すぎる!!笑

⑤ルーティング

get '/test' do
  a = "test"
  "Hello world!#{a}"
end

🙄こんなわかりやすすぎていいの??って感じです。

✅HTMLを使う

利用可能なテンプレートは公式見ると、haml、erb、Sassなど。と書いてありましたが、HTMLを使う方法を調べたらあったので試しました。

参考:【Sinatra】静的ファイルを表示する

public配下はurlの「/」以下にマッピングされる。コンフリクト時はpublicが優先。

①public/index.htmlの作成

<html>

<head>
  <meta charset="UTF-8">
  <base href="/">
  <title>sinatra1_study</title>
  <link rel="stylesheet" href="/css/test.css" type="text/css">
</head>

<body>
  <h1>public/index.html</h1>
  <p>Hello, Sinatra</p>
</body>

</html>

②確認

http://localhost:4567/index.htmlへアクセス

🙄簡単すぎてショック!!

※以下はエラーでした。

public/top/index.htmlを作成し、http://localhost:4567/topへアクセス

🙄どうやらindex.htmlをデフォで読み込んでくれるわけではないみたいですね!

✅リロード処理

Qiita:SinatraでとりあえずWebアプリを立ち上げてみる

Sinatra面白いので、上記の記事参考に更に深掘りしてみます。

①bundlerを使用するため、Gemfile作成

bundle init

②Gemfileの編集

gem 'sinatra'

③インストール

bundle i

④ファイル生成

※既に作成済みの上記ファイルを活用します

⑤起動

> bundle exec ruby myapp.rb

bundleを使用している場合はコマンドの頭にbundle execを付ける模様。

⑥リロード処理

gemfileに追記

gem 'sinatra-contrib'

インストール

bundle i

myapp.rbを編集

# myapp.rb
require 'sinatra'
require 'sinatra/reloader' # 追記

get '/' do
  a = "hello"
  reload = "fine"
  "Hello world! #{reload}"
end

実行

> bundle exec ruby myapp.rb

確認

✅erb活用

上記リロード処理実装時と同様の記事を参考にします。

テンプレートはviewsディレクトリ下に配置で「/」にマッピング。

①myapp.rbに追記

get '/erb_template' do
  erb :erb_template_page
end

②ディレクトリとファイルを作成

mkdir views
touch views/erb_template_page.erb

③erb_template_page.erbを編集

<%= Time.now %>

④確認

http://localhost:4567/erb_template

🙄やっとRubyのコードを使ってページ描画できました!!

ついでにerbの拡張機能も追加しました◎

ERBに関して

上記でSinatra使っていて気になったので調べました。

Qiita:Railsに入る前にしっておきたいERBとActiveRecordのこと

✅ERB(Embedded Ruby)とは

これを使うことで、ファイルの任意の個所でRubyのコードを実行することが可能。

erb.rbを作成

require "erb"

erb = ERB.new("Hello erb")
puts erb.result

実行

> ruby erb.rb
Hello erb

Rubyコードを書いてみる

require "erb"

erb = ERB.new('はじめての <%= "erb".upcase %>の実行')
puts erb.result

実行

ruby erb_run.rb
#=> はじめてのERBの実行

🙄<% %>のerb部分が無事反映されているのでerb使えてますね◎

index.htmlの作成

<html>
  <head>
  </head>
  <body>
    <h1>はじめてのERB</h1>
    <h2><%= "erb".upcase %>を実行する</h2>
    <% 1.upto(3) do |num| %>
      <p><%= num %></p>
    <% end %>
  </body>
</html>

html_run.erbを作成

# erb の読み込み
require "erb"

# index.html の中身を文字列で取得する
index_html = File.read("index.html")

# ERB実行
erb = ERB.new(index_html)
puts erb.result

実行

> ruby html_run.rb
<html>
  <head>
  </head>
  <body>
    <h1>はじめてのERB</h1>
    <h2>ERBを実行する</h2>
      <p>1</p>
      <p>2</p>
      <p>3</p>
  </body>
</html>

✅ActiveRecordとは

Railsに標準で入っているGem。DBとの接続から値の取得を行なってくれるORM(DBとRubyのオブジェクトの橋渡しをしてくれる仕組み)。

🙄LaravelのEloquent然りFWでは当たり前にありますね!

※ここは一旦ステイします。

躓いた点

✅irbで日本語入力できない

アンインストールすべしっぽいですね。

おわりに

JavaScriptで素のコードはだいぶ慣れたと思ったが、RubyはRubyで書き方が独特で慣れるまでもう少し時間がかかりそうです。頑張ろう!!

備忘録

・キーワード引数がまだピンと来ていない

✅uru

Qiita:Windowsにuruを入れてrubyのバージョン管理をする

uruを入れたのち、7Zipという拡張子を扱うために7-Zipをインストール。

パスの通し方はこの記事が参考になりました。

PowerShellの管理者実行してuru_rt.exeがあるフォルダへ移動し以下実行。

uru_rt admin install

するとuru.batとuru.ps1が作成される。

※パスの通し方の復習とRuby2.6の導入でirbの正常起動ができたので導入途中でステイしました。

コメントを残す