Ruby
まずはRubyのバージョン管理ツールrbenvをインストールするところから始まる。
homebrewで落とせる
インストールできているかどうか、テスト用のスクリプトなども用意されている。
curl -fsSL https://github.com/rbenv/rbenv-installer/raw/main/bin/rbenv-doctor | bash
インストール後はrbenv global 2.5.0などで好きなバージョンを利用することができる
pryについて
gemの一種。Rubyで最初に入っている機能のirbやLaravelのtinkerみたいなもの。 gemは有志が作ったツールみたいなもの。入れると便利
色々なオブジェクト
Stringオブジェクト
''で囲まれた文字列の変数。いきなり定義.メソッド()でそのメソッドを呼び出すこともできる
code:ruby
3 pry(main)> 'uoooo'.upcase => "UOOOO"
# 忘れた時は下記で確認できる
# 文字の連結
'あああ' << '連結'
# 変数を使う ダブルクォーテーションを利用する。
=> "に"
6 pry(main)> "1 + 1 は#{two}" => "1 + 1 はに"
# メソッドは見れる
Symbolオブジェクト
:nameなど、コロンをつけて定義する。stringと似ているが同じ場所を定義するのでメモリの効率が良いらしい
頻繁に使われるのはハッシュのキーなど。
code:ruby
23 pry(main)> { name: 'コジマ', pref: '東京都'} => {:name=>"コジマ", :pref=>"東京都"}
その他
Interger, Float, Enumerator(イーナメネーター)オブジェクトなど
code:ruby
=> Integer
27 pry(main)> (1 + 2.1).class => Float
# integerオブジェクトは、timesメソッドを利用することでenumeratorオブジェクトへと変わる 繰り返し処理ができる
# do ~ endまでの塊を、ブロックと定義する
34 pry(main)> 3.times do |i| 0
1
2
=> 3
# 別のブロックの書き方 {}で括る時はスペースを入れて使用するのが基本。
# スペース入れなくても動くけど、コーディング規約的な話
# 複数行 = do ~ end 1行 = { }と使い分けよう
35 pry(main)> 3.times { |num| puts num } 0
1
2
=> 3
Arrayオブジェクト
code:ruby
=> []
40 pry(main)> arr.push('1つ') 41 pry(main)> arr << '入れる' # %wで括ることで、クォーテーション不要で分けれる
# 大文字のWで括れば、ダブルクォーテーションのように変数を展開できる
=> 1
=> 2
# %iでシンボル配列を作れる
回す系のメソッド
code:ruby
# each
56 pry(main)> %wあ い う.each do |str| あ い う
# ifの処理例(next if : もしstr == 'b'だったらスキップ)(break if : もしstr == 'b'ならbreak)
59 pry(main)> %wa b c.each do |str| 59 pry(main)* next if str == 'b' a
c
# map
# 大文字で%w[]のスペースを定義すると文字と判断されて、「あ い う」という一つの変数扱いになってしまう
60 pry(main)> %wあ い う.map { |str| "(#{str})" } 61 pry(main)> %wあ い う.map { |str| "(#{str})" } # 途中代入 カンマ区切りで配列の値を個別に代入することができる
=> 1
=> 2
# 何もない場合はnilになる
hashオブジェクト
code:ruby
72 pry(main)> user1 = { name: '一郎' } => {:name=>"一郎"}
73 pry(main)> user2 = { id: 2, name:'次郎' } => {:id=>2, :name=>"次郎"}
=> "一郎"
=> "次郎"
# シンボルは''で呼び出せない
=> nil
77 pry(main)> user3 = { 'id'=>3, 'name'=>'三郎' } => "三郎"
# 入れ子にできる
81 pry(main)* name: '四郎', 81 pry(main)* test_results: { 81 pry(main)* scienct: 80 => {:name=>"四郎", :test_results=>{:math=>70, :scienct=>80}}
=> 70
# メソッドでkeyとvalueを確認できる
85 pry(main)> user4.values # eachもできる
89 pry(main)> user4.each do |k, v| name = 四郎
test_results = {:math=>70, :scienct=>80}
# deleteもできる
user4.delete(:test_results)
rangeオブジェクト
ある値の範囲を表すオブジェクト
code:ruby
=> 1..3
94 pry(main)> (1..3).class => Range
95 pry(main)> (1..3).to_a # ...だと最後の数字は省かれる
100 pry(main)> (1...10).to_a # アルファベットもできる
102 pry(main)> ('a'..'e').to_a # eachもできる
105 pry(main)> (1..5).each { |day| puts "#{day}日" } 1日
2日
3日
4日
5日
=> 1..5
Time, Dateオブジェクト
時間を操る
code:ruby
=> 2022-01-02 17:54:31 +0900
108 pry(main)> Time.now.zone => "JST"
# 自分で定義もできる
109 pry(main)> datetime = Time.new(2018, 1, 1, 12, 30) => 2018-01-01 12:30:00 +0900
111 pry(main)> datetime.strftime('%Y年%m月%d日 %H時%M分') => "2018年01月01日 12時30分"
# Dateオブジェクトは最初定義することができないので、requireで読み込む。
# 組み込みライブラリとその他という区分でオブジェクトは存在していて、Dateはその他。
112 pry(main)> require 'date' => true
=> Date
115 pry(main)> Date.today => #<Date: 2022-01-02 ((2459582j,0s,0n),+0s,2299161j)> # Railsではもっと使いやすいライブラリが最初から入っているからそっちを使えば良いよ
True / Falseオブジェクト
Rubyでは真偽値もオブジェクトとして取り扱う。
code:ruby
119 pry(main)> (1 != 1).class => FalseClass
120 pry(main)> (1 == 1).class => TrueClass
# nilかを判別するメソッド
=> nil
=> true
変数と定数
基本は同じ。my_nameなど小文字は変数,WEB_SITE_NAMEなど大文字は定数として定義するのが基本。
code:ruby
# 変数を変更しようとすると警告が出る
123 pry(main)> WEB_SITE_NAME = 'Udemy' => "Udemy"
124 pry(main)> WEB_SITE_NAME = 'aaa' (pry):119: warning: already initialized constant WEB_SITE_NAME
(pry):118: warning: previous definition of WEB_SITE_NAME was here
=> "aaa"
コメント
code:ruby
# コメントアウト
puts 'あああ' # これもOK
=begin
複数行の
コメントアウト
=end
# ヒアドキュメント
# 複数行の変数を扱いたい時など。あんまり使わないので使用されている時にぐぐろう
131 pry(main)> strings = <<EOS => "長い\n文章を\nかくよ\n"
132 pry(main)> puts strings 長い
文章を
かくよ
=> nil
if, unless
Rubyではnil,falseが偽として判定される
code:ruby
num = 1
if num == 1
puts '1です'
elsif num == 2
puts '2です'
else
puts 'その他です'
end
# unless
unless nil
puts '偽です'
end
# 1行でif文を書く
# ifの手前に処理を書くことで、真なら前の記述が実行される処理になる
'日本' if country == 'ja'
# 三項演算子
# 変数 = (条件式) ? 真の処理 : 偽の処理
place = country == 'ja' ? '日本' : '海外'
論理演算子を使った格納
code:ruby
val1 = nil
val2 = 100
val3 = val1 || val2 # nilでない方の値が入る
# 特殊な入れ方
=> nil
2 pry(main)> val ||= 'value' # nilの場合はここで定義した値が入る => "value"
value
=> nil
4 pry(main)> val ||= 'new value' # すでに'value'が入っているので、'new value'は入らない => "value"
value
=> nil
case文
code:ruby
value = 100
symbol = case value
when 1
:one
when 2
:two
else
:other
end
puts symbol
# rangeで書くこともできる
when 1..5
:low
...
メソッド定義
ちなみにインデントはスペース2つが基本らしい
code:ruby
def putsHello
puts 'Hello!'
end
putsHello # 定義した後に呼び出す
def putsName(name)
end
putsName('Kojina')
def putsName(name = 'Guest')
puts ...
# ラベルで引数を渡す
def hello(name: 'Guest', show: false)
end
hello(name: 'kojima')
hello(show:true, name:'sato')
# 複数の引数を取り扱う
def sum(*values)
# 配列オブジェクト.inject {|初期値, 要素| ブロック処理 }
values.inject { |total, n| total + n }
end
puts sum(1,2,3,4,5)
# "**"で、ハッシュ形式で受け取る
def some_method(**kv_values)
puts kv_values
end
some_method(param1: :aaa, param2: :bbb)
Procオブジェクト, yield
code:ruby
1 pry(main)> proc = Proc.new { puts 'hoge' } 2 pry(main)> proc.call # callメソッドで実行できる hoge
=> nil
# 外側で定義したものも呼び出せる
hoge = :hoge
proc = Proc.new { puts hoge }
proc.call
## hoge
def yield_test
yield(1, 2)
end
## ブロックを引数として渡している。
## yieldで定義したメソッドが引数として呼ばれ、a=1, b=2が入る
puts yield_test { |a, b| a + b}
# &をつけた仮引数で定義すると、ブロックオブジェクトで受け取れる
# yieldというのは、下のものを省略した書き方
def yield_test2(&proc)
proc.call(1, 2)
end
puts yield_test2 { |a,b| a + b}
def is_block
if block_given?
yield
else
puts 'ブロック未定義です'
end
end
is_block { puts 'ブロックを定義しています'}
is_block
クラス、イニシャライザ、アクセサ
code:ruby
# 定義
class User
end
class Book
# イニシャライザ(phpでいうコンストラクタ)
def initialize
puts 'イニシャライザが走っています'
end
end
Book.new # 生成したら呼ばれる
class Book
def initialize(name = '未定義')
@name = name # クラス変数
end
# 変数呼び出し用メソッド
def name
@name
end
# 変数変更用メソッド
def name=(new_name)
@name = new_name
end
end
book = Book.new
puts book.name
book.name = 'Ruby入門'
puts book.name
変数変更用のメソッドを、クラス変数分作ってたら大変
アクセサメソッドで定義すれば、両方の用途(呼び出し/変更)に使用できる
code:ruby
class Book
attr_accessor :name, :pages
attr_reader :price
attr_writer :sold
def initialize(name = '未定義')
@name = name
end
end
book = Book.new
puts book.name
クラスメソッド
code:ruby
class Foo
# self.をつけるとクラスメソッド
def self.first_method
puts 'first'
end
# 複数のものをまとめてクラスメソッドにできる。class << selfで囲む
class << self
def second_method
puts 'second'
end
def third_method
puts 'third'
end
end
end
# class名.method名で呼び出せる
Foo.first_method
Foo.second_method
Foo.third_method
# objectからは呼び出せない
Foo.new.first_method
クラス変数
code:ruby
class Num
# クラス変数
@@num = 1
def increment
@@num += 1
end
def decrement
@@num -= 1
end
def num
puts @@num
end
def self.num
puts @@num
end
end
foo = Num.new
foo.num # 1
foo.increment
foo.num# 2
bar = Num.new
bar.num # 2(foo.incrementで足された値がそのまま使われる)
bar.increment
bar.num # 3
bar.decrement
bar.num # 2
いろいろなメソッド
code:ruby
require 'date'
class User
attr_accessor :name, :birthday
def initialize(name, birthday)
@name = name
@birthday = birthday
end
# インスタンスメソッド 同じクラス内で呼び出したり、オブジェクトから呼び出せる
def display_birthday
@birthday.strftime('%Y年 %m月 %d日 ')
end
def inner_call_display_birthday
# どちらの呼び方でもOK
self.display_birthday
display_birthday
end
# private例
def call_private_name
private_name
end
# protected例
def call_protected_name
self.protected_name
protected_name # どっちでも呼べる
end
# プライベートメソッド(クラスだけで呼べるメソッド)を定義する際は、privateと書いてその下に表記する
private
def private_name
@name
end
# protectedメソッド privateとほぼ同じだけど、self.メソッド名でも呼べるようになる
protected
def protected_name
@name
end
end
birthday = Date.new(2000,1,1)
user = User.new('sato', birthday)
puts user.display_birthday
puts user.inner_call_display_birthday
puts user.private_name # プライベートメソッドは呼べない
puts user.call_private_name # これは呼べる
破壊的メソッド
!をつけたメソッド。受け取ったもの(レシーバー)の値を変更後の値にする
code:ruby
1 pry(main)> str = 'string' => "string"
=> "STRING"
3 pry(main)> puts str # そのまま string
=> nil
=> "STRING"
5 pry(main)> puts str # 変わってる STRING
=> nil
真偽値を返すメソッドは?が結構ついている
code:ruby
24 pry(main)> %wa b c.include?('c') => true
クラスの継承
Animal -> Dogなど
code:ruby
class Greeting
def hello
end
end
# Greetingの継承。(helloが使えるようになる)
class User < Greeting
def initialize(name)
@name = name
end
end
user1 = User.new('Sato')
user1.hello
user2 = User.new('Konishi')
user2.hello
オーバーライド(メソッド上書き)
code:ruby
class User < Greeting
def initialize(name)
@name = name
end
# override
def hello
puts "override!"
# 親クラスのものをオーバーライド内でも呼び出せる superだけでOK
super
end
end
モジュール
module ModuleNameで定義でき、includeで呼び出すことで利用できるようになる
code:ruby
# 定義
module SampleModule
CONST_NUM = 100
def const_num
CONST_NUM
end
end
# 通常はモジュール内の定数は、モジュール::定数としないと呼び出せないが、
puts SampleModule::CONST_NUM # 100
# includeすることで呼び出せるようになる
include SampleModule
puts const_num # メソッドとして呼び出せる
puts CONST_NUM # modle内で定義した定数としても呼び出せる
ミックスイン
クラス内でmoduleを呼び出して、クラス内で使えるようにする処理のこと
code:ruby
module SampleModule
def sum(a, b)
a + b
end
end
class Sample
include SampleModule # ミックスイン
def call_sum(a, b)
sum(a, b) # moduleのsum使用
end
end
プログラムエラーの時に処理が中断されず、別途書いた処理に従って処理が進むようにする。
外部のAPIに一時的につながらない時など、修正が自分たちでは難しい部分に使用する
code:ruby
begin # 例外が起こりそうな箇所
val = 10 / 0
puts val
rescue # 起こった場合に飛ぶ処理
puts '0で割ることはできません。'
end
例外オブジェクトを取得する
code:ruby
rescue => e
# p: オブジェクトの中身を文字で確認できるメソッド
p e
end
# ruby exception.rb
# <ZeroDivisionError: divided by 0>
# 0で割ることはできません。
例外オブジェクトの便利なメソッド
e.backtrace
どのような順序でエラーに至ったのか(行など)、教えてくれる
e.full_message
例外に関するメッセージを整形して教えてくれる(backtraceの情報、zero divisionなど)
例外によって処理を分ける
code:ruby
begin
hoge
10 / 0
# rescueの後ろに例外クラス名を書く。
rescue ZeroDivisionError => e
'0では割れません'
rescue => e
'その他エラー
end
例外が起こった場合、もう一度beginからやり直す
retryで治らない場合、無限ループになっちゃうので気を付ける
code:ruby
num = 0
begin
p 10 / num
rescue ZeroDivisionError => e
p e
num = 2
retry
end
puts '終了'
# ruby exception2.rb
# <ZeroDivisionError: divided by 0> エラーになって、num=2が入ってretry
# 5 ここは、"p 10 / num"
# 終了
例外を発生させるraise
動作確認ができる
code:ruby
begin
raise
rescue => e
p e # RuntimeError
end
raiseには任意の例外クラス名を指定できる
raise ZeroDivisionErrorなど。
独自の例外クラスを作成することもできる
元々用意されてあるクラスを継承して自作できる
code:ruby
class MyError < StandardError; end
begin
raise MyError
rescue => e
p e # <MyError: MyError>
end
例外が発生しても、しなくても走るensure
code:ruby
begin
puts 'begin'
rescue => e
p e
ensure
puts 'ensure実行!'
end