Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
たのしいRuby_読書メモ

1.はじめてのRuby

Rubyの実行方法

rubyコマンドを使う方法

ruby helloruby.rb

irbコマンドを使う方法

コンソールから対話的に実行できるので、小さいコマンドを実行するときに便利

irb
print("Hello,Ruby.\n")

メソッドの呼び出し

Rubyのメソッドでは「()」を省略することができる

print "Hello,Ruby.\n"

いくつかの文字列を続けて表示したい場合は、「,」で区切る

print "Hello,", "Ruby", ".", "\n"

putsメソッド

文字列を表示するためのメソッド(Javaでいうところのprintln)
表示する文字列の最後で必ず改行する

puts "Hello,Ruby."

pメソッド

実行中のプログラムの様子を確認したいときに使う
例えば、こう書いた場合、「\n」「\t」は変換されずそのまま出力される

p "Hello\n\t,Ruby."

オブジェクトの構造をそのまま表示したい場合はppメソッドを使う
プログラムを書いている人が動作確認のためにオブジェクトを調べる場合はinspectメソッドを使う

日本語の表示

「# encoding: 文字コード」というコメントを1行目に記述することで、エンコーディングを指定できる(指定なしの場合はUTF-8)
このコメントを「マジックコメント」という

# encofing: Shift_JIS
print "いづれの御時にか、女御、更衣あまた候ひ給ひける中に、\n"
print "いとやむごとなき際にはあらぬが、すぐれて 時めき給ふありけり。\n"

実行時に「-E 文字コード」で指定することも可能

変数

文字列の中に「#{変数名}」と書くことで、文字列にデータを埋め込むことができる

puts "表面積=#{area}"

コメントを書く

コメントを表す記号は「#」を使う
行頭から始まる「=begin」と「=end」で囲まれた部分もコメントになる

制御構造

条件判断

if 〜 then 〜 end

if 条件 then
    条件が成り立ったときに実行したい処理
end

thenは省略可能。または、

if 条件 then
    条件が成り立ったときに実行したい処理
else
    条件が成り立たないときに実行したい処理
end

繰り返し

while文

doは省略可能

while 繰り返し続ける条件 do
    繰り返したい処理
end

timesメソッド

繰り返しの回数が決まっているときは「times」を使うとシンプルに書ける

繰り返す回数.times do
    繰り返したい処理
end

2.便利なオブジェクト

配列(Array)

配列を作る

names = ["小林", "林", "高野", "森岡"]

要素が決まっていない場合は、「[]」で空のオブジェクトを生成できる

names = []

配列からオブジェクトを取り出す

names[0]

すでにある配列にオブジェクトを格納する場合はこう書く

name[0] = "野尻"

配列の大きさを取得する

array.size

配列と繰り返し

配列.each do |変数|
    繰り返したい処理
end

「do 〜 end」で囲まれている部分をブロックという
eachのようなメソッドはブロック付きメソッドと呼ばれる

ハッシュ(Hash)

JavaでいうところのHashMap
keyとvalueでオブジェクトを格納できる

シンボル

Rubyがメソッドなどの名前を識別するためのラベルをオブジェクトにしたもの
先頭に「:」をつけて表現する

sym = :foo

ハッシュのキーのように、単純に「同じかどうか」を比較するような場合は、シンボルを使うことが多い

ハッシュを作る

キーとキーに対応するオブジェクトを「キー => オブジェクト」の形式で指定する

song = { :title => "Paranoid Android", :artist => "Radiohead" }

シンボルを使う場合は以下の書き方も可能

song = { title: "Paranoid Android", artist: "Radiohead" }

ハッシュの操作

オブジェクトを取り出したい場合

ハッシュ名[キー]

オブジェクトを格納したい場合

ハッシュ名[キー] = 格納したいオブジェクト

ハッシュの繰り返し

ハッシュ.each do |キーの変数, 値の変数|
    繰り返したい処理
end

正規表現

正規表現と文字列のマッチングを行うには、

/パターン/ =~ マッチングしたい文字列

と書く。マッチングが失敗した場合はnilを返す

3.コマンドを作ろう

コマンドラインからのデータの入力

コマンドラインの情報をデータとして受け取るには、「ARGV」という配列オブジェクトを使う

puts "最初の引数: #{ARGV[0]}"

ファイルからの読み込み

ファイルを読み込んで一行ずつ出力するプログラムのサンプル

filename = ARGV[0]
file = File.open(filename)
file.each_line do |line|
    print line
end
file.close

each_lineメソッドは、ファイルの各行をそれぞれ処理するメソッド

メソッドの作成

def メソッド名
    メソッドで実行したい処理
end

別のファイルを取り込む

プログラムの中でライブラリを読み込むには、requireメソッドまたはrequire_relativeメソッドを使う
Javaでいうところのimport文
ライブラリのファイル名の「.rb」は省略できる

require 使いたいライブラリのファイル名

または、

require_relative 使いたいライブラリのファイル名

requireメソッドは既存のライブラリを読み込む時に使う
require_relativeメソッドは、実行するプログラムが置かれたディレクトリを基準にしてライブラリを探す

4.オブジェクトと変数・定数

クラス

オブジェクトとクラスの対応表

  • 数値・・・Numeric
  • 文字列・・・String
  • 配列・・・Array
  • ハッシュ・・・Hash
  • 正規表現・・・Regexp
  • ファイル・・・File
  • シンボル・・・Symbol

変数

Rubyには4種類の変数があり、どの種類なのかは変数名で決まる

  • ローカル変数・・・先頭がアルファベットの小文字か「__」で始まる
  • グローバル変数・・・先頭が「$」で始まる
  • インスタンス変数・・・先頭が「@」で始まる
  • クラス変数・・・先頭が「@@」で始まる

定数

先頭がアルファベットの大文字で始まるものが定数となる

多重代入

複数の変数への代入を1つの式で一度に行うことができる

a, b, c = 1, 2, 3

配列を代入する時に左辺に複数の変数があると、自動的に配列の要素を取り出して多重代入が行われる

ary = [1, 2]
a, b = ary   # aに1、bに2が代入される

Rubyでは、変数名やメソッド名はスネークケース、クラス名やモジュール名はキャメルケースで名前づけすることが多い

5.条件判断

Rubyでの条件

文字列クラスのempty?メソッドは、その文字列の長さが0の時にtrueを、そうではない時にfalseを返す
Rubyの真偽値

  • 真・・・falseとnilを除くオブジェクト全て
  • 偽・・・falseとnil

真偽値を返すメソッドの名前は、一目でわかるように末尾に「?」をつけるルールがある

unless文

if文と反対の役割をする条件判断文

unless 条件 then
    文
end

case文

case 比較したいオブジェクト
when 値1 then
    文1
when 値2 then
    文2
when 値3 then
    文3
else
    文4
end

case文では、正規表現を用いた場合分けもできる

text.each_line do |line|
    case line
    when /^From:/i
        puts "送信者の情報を見つけました。"
    when /^To:/i
        puts "宛先の情報を見つけました。"
    when /^Subject:/i
        puts "件名の情報を見つけました。"
    when /^$/
        puts "ヘッダの解析が終了しました。"
        exit
    else
        ##読み飛ばす
    end
end

「===」は、両辺の値を比較するよりも、もう少し緩いイメージで同じかを判定する

  • 左辺が数値や文字列の場合は「==」と同じ意味をもつ
  • 正規表現の場合は、「=~」と同じようにマッチしたかどうかを判定する
  • クラスの場合は右辺がそのクラスのインスタンスかどうかを判定する

if修飾子とunless修飾子

ifやunlessは実行したい式の後ろに書くこともできる

puts "aはbよりも大きい" if a > b

2つのオブジェクトが同じかどうか(IDが同じかどうか)はequal?メソッドで判定する
オブジェクトの値が等しいかは「==」で判定する
値の比較をより厳密にしたい(ex.「0」と「0.0」を別物として取り扱いたい)場合は、eql?メソッドを使う

6.繰り返し

timesメソッド

一定の回数だけ同じ処理をさせる

繰り返したい回数.times do
    繰り返したい処理
end

または、

繰り返したい回数.times {
    繰り返したい処理
}        

ブロック変数を使うことで、繰り返し回数のインデックスを使用できる

5.times do |i|
    # do something.
end

for文

for 変数 in オブジェクト do
    繰り返したい処理
end

範囲オブジェクト(..)を使うことで、指定した回数繰り返すこともできる

for 変数 in 開始時の数値..終了時の数値 do
    繰り返したい処理
end

while文

条件が成立している間繰り返す

while 条件 do
    繰り返したい処理
end

until文

条件が成立するまで繰り返す

until 条件 do
    繰り返したい処理
end

eachメソッド

オブジェクトの集まりに対して、それを1つずつ取り出す時に使う

オブジェクト.each do |変数|
    繰り返したい処理
end

または、

オブジェクト.each { |変数|
    繰り返したい処理
}

loopメソッド

終了条件がない繰り返しのためのメソッド(必ずbreakで抜けること!)

loop do
    繰り返したい処理
end

繰り返しの制御

  • break・・・繰り返しを中断し、繰り返しの中から抜ける
  • newt・・・次の回の繰り返しに処理を移す。Javaでいうcontinue
  • redo・・・同じ条件で繰り返しをやり直す

7.メソッド

メソッドの分類

インスタンスメソッド

オブジェクトをレシーバとするメソッド

オブジェクト.メソッド名

クラスメソッド

クラスをレシーバとするメソッド。こう書いて呼び出すか、

クラス名.メソッド名

またはこう書いて呼び出す

クラス名::メソッド名

関数的メソッド

レシーバがないメソッド(ex.print、sleepなど)

メソッドの定義

def メソッド名(引数1, 引数2, ...)
    実行したい処理
end

メソッドの中でreturn文を用いることで、メソッドの戻り値を指定できる
returnは省略しても構わない
省略した場合、メソッドの中で最後に得られる値が戻り値になる

ブロックつきメソッドの定義

メソッド定義の中のyieldは、メソッドの呼び出しの際に与えられたブロックを実行する
numの値を二倍にしていき、10を超えたところでループから抜けるサンプル

def myloop
    while true
        yield
    end
end

num = 1
myloop do
    puts "num is #{num}"
    break if num > 10
    num *= 2
end

引数の数が不定なメソッド

引数の数が決められないメソッドは、「*変数名」の形式で定義することで、与えられた引数をまとめて配列として得られる

def foo(*args)
    args
end

キーワード引数

引数名と値のペアで引数を渡せ流ようになる(順番に縛られない)

def メソッド名(引数1: 引数1の値, 引数2: 引数2の値, ...)
    実行したい処理
end

デフォルト値を指定したくない場合は、「引数名:」とだけ書く
キーワード引数は通常の引数と組み合わせて使っても良い
ハッシュをキーワード引数として渡すこともできる(キーはシンボルでなければならない)

配列を引数に展開する

メソッド呼び出しの際に、「*配列」の形式で値を渡すと、配列の要素が先頭から順にメソッドの引数として渡される

def foo(a, b, c)
    a + b + c
end

args = [1, 2, 3]
p foo(*args)

8. クラスとモジュール

クラスとインスタンス

新しいオブジェクトを生成するには、各クラスのnewメソッドを使うのが一般的

ary = Array.new

オブジェクトがどのクラスに属しているのかを知るには、classメソッドを使う
あるオブジェクトがあるクラスのインスタンスかどうかを判断するには、instance_of?メソッドを使う

str = "Hello world."
p str.instance_of?(String)

継承

Rubyの全てのクラスはBasicObjectクラスのサブクラスである
BasicObjectクラスには、Rubyの世界のオブジェクトとして必要な最低限の機能が定義されている
is_a?メソッドを使うことで、継承関係を遡ってクラスに属するかどうかを調べられる

クラスを作る

class文

class クラス名
    クラスの定義
end

クラス名は必ず大文字で始めなければならない
class文の中でメソッドを定義すると、そのクラスのインスタンスメソッドになる

initializeメソッド

newメソッドによってオブジェクトを生成すると、initializeメソッドが呼ばれる
オブジェクトにとって必要な初期化の処理はここに記述する
Javaでいうところのコンストラクタ

def initialize(myname="Ruby")
    @name = myname
end

アクセスメソッド

Rubyにおけるgetterの書式

def name
    @name
end

Rubyにおけるsetterの書式

def name=(value)
    @name = value
end

「attr_〜」をインスタンスメソッドに指定すると、同名のアクセスメソッドを自動的に定義できる

  • attr_reader :name・・・getterを定義する
  • attr_writer :name・・・setterを定義する
  • attr_accessor :name・・・getterとsetterを定義する

特別な変数self

インスタンスメソッドの中で、メソッドのレシーバ自身を参照するには、selfという特別な変数を使う

クラスメソッド

クラスメソッドは、「class << クラス名 〜 end」という定義の中にインスタンスメソッドの形式で定義する

class << HelloWorld
    def hello(name)
        puts "#{name} said hello."
    end
end

クラス定義の中でクラスメソッドを追加することもできる
「class << self 〜 end」の書式で定義可能(こちらの方が一般的に使われている)

class HelloWorld
    class << self
        def hello(name)
            puts "#{name} said hello."
        end
    end
end

「def クラス名.メソッド名 〜 end」の形式で定義することもできる

def HelloWorld.hello(name)
    puts "#{name} said hello."
end

定数

クラスの持っている定数は、「::」を使ってクラス名を経由すれば、クラスの外側からも参照可能

p HelloWorld::Version

クラス変数

そのクラスの全てのインスタンスで共有できる変数のこと
「@@」で始まる変数はクラス変数となる

メソッドの呼び出しを制限する

Rubyには三種類のアクセス制限レベルが用意されている

  • public・・・メソッドをインスタンスメソッドとして使えるように公開する
  • private・・・メソッドをレシーバを指定して呼び出せないようにする
  • protected・・・メソッドを同一のクラスであればインスタンスメソッドとして使えるようにする

メソッドのアクセス制限を変更するには、これらのキーワードにメソッド名を表すシンボルを指定する

def priv
    puts "priv is a private method."
end

private : priv

何も指定せずに定義されたメソッドはpublicとなる

クラスを拡張する

継承する

継承を行うには、class文で指定するクラス名と同時にスーパークラス名を指定する

class クラス名 < スーパークラス名
    クラスの定義
end

aliasとundef

すでに存在するメソッドに別の名前を割り当てたい場合、aliasを使う

alias 別名 元の名前     # メソッド名をそのまま書いた場合
alias :別名 :元の名前   # シンボルを使った場合

定義されたメソッドをなかったことにしたい場合は、undefを使う

undef メソッド名       # メソッド名をそのまま書いた場合
undef :メソッド名      # シンボルを使った場合

特異クラス

特異クラスは英語でシングルトンクラス(singleton class)、またはアイゲンクラス(eigenclass)という

モジュール

クラス:実装と振る舞いを持った「もの」を表現する機能
モジュール:振る舞いだけをまとめる機能

  • モジュールはインスタンスを持つことができない
  • モジュールは継承できない

Mix-inによる機能の提供

モジュールをクラスに混ぜ合わせることをMix-inという
クラス定義の中でincludeを使うと、モジュールに含まれるメソッドや定数をクラスの中に取り込むことができる

名前空間の提供

名前空間とは、メソッドや定数、クラスの名前を区別して管理する単位のこと
モジュールはそれぞれは独立した名前空間を提供する
モジュールの提供するメソッド(モジュール関数)は「モジュール名.メソッド名」という形式で参照する

モジュールを作る

module モジュール名
    モジュールの定義
end

Mix-in

クラスにモジュールを取り込むには、includeメソッドを使う

Module M
    def meth
        "meth"
    end
end

class C
    include M
end

includeされているかを調べるには、include?メソッドを使う
インクルードされたモジュールは仮想的なスーパークラスとして機能する
継承関係を調べるには、ancestorsメソッドとsuperclassメソッドを使う

  • ancestors・・・継承の関係にあるクラスの一覧を取得
  • superclass・・・直接のスーパークラスを取得

Rubyは、複数のスーパークラスを持てない単純継承(単一継承)モデルを採用している
Mix-inを使うことによって、単純継承の関係を保ったまま、複数のクラスで機能を共有できる

extendメソッド

Object#extendを使うことで、モジュールで定義された全てのメソッドを特異メソッドとしてオブジェクトに追加できる
extendメソッドでは、クラスを超えて、オブジェクト単位にモジュールの異能を利用できるようになる
includeとextendの実装サンプル

module ClassMethods
    def cmethod
        "Class Method"
    end
end

module InstanceMethod
    def imethod
        "Instance Method"
    end
end

class MyClass
    extend ClassMethods
    include InstanceMethod
end

p MyClass.cmethod
p MyClass.new.imethod

ダックタイピング

「アヒルのように歩きアヒルのように鳴くものは、アヒルに違いない」
オブジェクトを特徴づけるのは実際の種類(クラスとその継承関係)ではなく、そのオブジェクトがどのように振る舞うか(どんなメソッドを持っているか)である
「実際は違うものであっても、同じ名前のメソッドを用意することによって、処理を共通化できる」というのがダックタイピングの考え方

9.演算子

論理演算子の応用

aryがnullでない時だけfirstメソッドを呼び出す、という処理がある

item = nil
if ary
    item = ary.first
end

これを「オブジェクト&.メソッド呼び出し」とすることで短く書ける
これを「安全参照演算子」や「nilチェックメソッド呼び出し」という

item = ary&.first

Rubyの演算子の多くはインスタンスメソッドとして実装されている
ユーザが新たに定義したり、再定義して意味を変えることができる

10.エラー処理と例外

例外処理

エラーメッセージの書式

ファイル名:行番号:in `メソッド名:エラーメッセージ(例外クラス名)
    from ファイル:行番号:in メソッド名
    ...

例外処理の書き方

javaでいうtry catch節

begin
    例外を発生させる可能性のある処理
rescue
    例外が起こった場合の処理
end

例外オブジェクトを手に入れたい場合は、

begin
    例外を発生させる可能性のある処理
rescue => 例外オブジェクトが代入される変数
    例外が起こった場合の処理
end

後処理

例外が起こっても起こらなくても常に実行したい処理がある場合には、ensure節に後処理を記述する
javaでいうfinally節

begin
    例外を発生させる可能性のある処理
rescue => 変数
    例外が起こった場合の処理
ensure
    例外の有無に関わらず実行される処理
end

やり直し

rescue節でretryを用いると、begin以下の処理をもう一度やり直せる

rescue修飾子

begin、rescue、endはもっと短く書くこともできる

 例外を発生させる可能性のある処理 rescue 例外が起こった場合の処理

例外処理の構文の補足

例外処理のためにメソッドの処理全体をbegin 〜 endでくくるような場合は、beginとendを省略できる

def foo
    メソッドの本体
rescue => ex
    例外処理
ensure
    後処理
end

同様にして、クラス内でもrescue節やensure節を記述できる

class Foo
    クラス定義の本体
rescue => ex
    例外処理
ensure
    後処理
end

捕捉する例外を指定する

rescue節は指定した例外クラスを捕捉するが、同時にそのサブクラスも捕捉する
どれを捕まえるかはrescue節で明示できる

begin
    例外を発生させる可能性のある処理
rescue Exception1, Exception2 => 変数
    Exception1またはException2に対する処理
rescue Exception3 => 変数
    Exception3に対する処理
rescue
    それ以外の例外が起こった場合の処理
end

例外クラス

自分で例外クラスを定義する場合は、StandardErrorクラスを継承したクラスを作成するのが一般的

例外を発生させる

自分で例外をスローするには、raiseメソッドを使う
raiseメソッドは4つの形式を持っている

  • raise メッセージ・・・指定したメッセージで、RuntimeErrorを発生させる
  • raise 例外クラス・・・指定した例外を発生させる
  • raise 例外クラス, メッセージ・・・指定したメッセージで、指定した例外を発生させる
  • raise・・・RuntimeErrorを発生させる(メッセージ指定なし)

よくあるエラーメッセージ

  • syntax error・・・プログラムの文法エラー
  • NameError・・・変数が存在しない場合のエラー
  • NoMethodError・・・メソッドが存在しない場合のエラー
  • ArgumentError・・・引数に誤りがある場合のエラー
  • TypeError・・・期待しているものとは別のクラスのオブジェクトが渡されている場合のエラー
  • LoadError・・・requireに指定したライブラリを読めなかった場合のエラー
  • [BUG]・・・Rubyや拡張ライブラリのバグによるエラー

11.ブロック

ブロックの使われ方

繰り返し

Fileクラスを使った繰り返し用メソッドいろいろ

  • each_line・・・1行ずつデータを取り出して繰り返す
  • each_char・・・1文字ずつデータを取り出して繰り返す
  • each_byte・・・1バイトずつデータを取り出して繰り返す

定型の処理を隠す

File.openメソッドにブロックを与えた場合、ブロック内の処理が終了してメソッドから抜ける前に自動的にファイルが閉じられる
File#closeメソッドの呼び出すのが不要になる
javaで言い換えるとtry with resource
具体的には、これを、

file = File.open("sample.txt")
begin
    file.each_line do |line|
        print line
    end
ensure
    file.close
end

こう書ける

File.open("sample.txt") do |file|
    file.each_line do |line|
       print line
    end
end

計算の一部を差し替える

Array#sortメソッドでは、要素の並び替えの処理はメソッド内に用意してあって、要素同士の前後関係を比較する方法だけをブロックで指定するようになっている

array.sort do |a, b|
    並び替えのルールを定義
end

<=>演算子を使うと、文字コードの値で大小比較できる
実装例はこんな感じ

array = ["Ruby", "Perl", "PHP", "Python"]
sorted = array.sort{|a, b| a <=> b }

単純に値を<=>で比較できる場合はArray#sort_byメソッドの方が効率が良い

ブロックつきメソッドを作る

def myloop
    while true
        yield
    end
end

num = 1
myloop do
    puts "num is #{num}"
    break if num > 10
    num *= 2
end

ブロック変数を渡す

block_given?は、メソッドの中で使うと、ブロック変数が渡されているか否かを判定できる

def total(from,to)
    result = 0
    from.upto(to) do |num|
        if block_given?
            result += yield(num)
        else
            result += num
        end
    end
    return result
end

ブロック変数を受け取る

yieldに引数を持たせることで、ブロック変数を受け取れる

def block_args_test
    yield(1)
end

複数持たせたい場合はこう書く

def block_args_test
    yield(1, 2, 3)
end

ブロックをオブジェクトとして受け取る

ブロックをオブジェクトとして持ち運ぶには、Procオブジェクトを使う
Procオブジェクトを作るには、Proc.newメソッドをブロックつきメソッドとして呼び出す
ブロックの手続きはProcオブジェクトに対してcallメソッドで呼び出すと実行できる

hello = Proc.new do |name|
    puts "Hello, #{name}."
end

hello.call("World")

メソッド定義の際に、最後の引数を「&引数名」の形式にすると、そのメソッドを呼び出すときに与えられたブロックは、自動的にProcオブジェクトに包まれて引数として渡される
変数名の前に「&」をつけて受け取る引数をProc引数という

def total2(from, to, &block)
    result = 0
    from.upto(to) do |num|
        if block
            result += block.call(num)
        else
            result += num
        end
    end
    return result
end

12.数値(Numeric)クラス

Numericのクラス構成

  • Integer・・・整数
    • Fixnum・・・普通の整数
    • Bignum・・・大きな整数
  • Float・・・浮動小数点数
  • Rational・・・有理数
  • Complex・・・複素数

Rationalオブジェクト

Rationalオブジェクトは「Rational(分子, 分母)」の形式で生成する
numeratorメソッドで分子を取り出す
denominatorメソッドで分母を取り出す

Complexオブジェクト

Complexオブジェクトは「Complex(実数部, 虚数部)」の形式で生成する
realメソッドで実数部を取り出す
imaginaryメソッドで虚数部を取り出す

算術演算

x.div(x)

xをyで割った商を整数で返す

x.quo(y)

xをyで割った商を返す。整数同士の場合はRationalオブジェクトを返す

x.modulo(y)

xをyで割った余りを返す

x.divmod(y)

xをyで割った時の商と余りを配列で返す

x.remainder(y)

xをyで割った余りを返す。結果の符号は「x」の符号に一致する
0による割り算はIntegerクラスではエラーとなるが、Floatクラスでは、InfinityやNaNを返すので注意

Mathモジュール

よく使う数値演算のためのメソッドはMathモジュールで提供される
JavaでいうMathクラスと同じ

数値型の変換

  • to_f・・・Integerオブジェクト -> Floatオブジェクトに変換する
  • to_i・・・Floatオブジェクト -> Integerオブジェクトに変換する
  • to_r・・・Floatオブジェクト -> Complexオブジェクトに変換する
  • to_c・・・Floatオブジェクト -> Rationalオブジェクトに変換する

文字列を数値に変換することもできる

  • round・・・小数点以下を四捨五入する
  • ceil・・・レシーバより大きくて最も小さい整数を返す
  • floor・・・レシーバより小さくて最も大きい整数を返す

乱数

乱数を得るには、Random.randメソッドを使う
乱数のタネを指定したい場合は、Random.newメソッドで乱数生成器を初期化して、Random#randを使う方法もある

r1 = Random.new(1)
r1.rand

securerandom

パスワードや暗号のキーを生成するためのライブラリ

  • SecureRandom.random_bytes・・・引数にバイト数を指定すると、その長さのランダムなバイト列を返す
  • SecureRandom.base64・・・引数に指定した文字数分だけ、英数字と記号の組み合わせを返す

数えあげ

n.times{|i| ... }

n回の繰り返しを行う

ary = []
10.times do |i|
    ary << i
end

from.upto(to){|i| ... }

fromからtoに達するまでiを1ずつ加算しながら繰り返す

from.downto(to){|i| ... }

fromからtoに達するまでiを1ずつ減算しながら繰り返す

from.step(to,step){|i| ... }

fromからtoに達するまでiにstepを足しながら繰り返す

13.配列(Array)クラス

配列の作り方

Array.newを使う

引数を指定しないでnewした場合、要素数が0の配列を作る
引数を一つ指定した場合、その引数の数だけnilが格納された配列を作る
引数を二つ指定した場合、一つ目の引数が要素数、二つ目の引数が格納される値となる

%wを使う

要素が空白を含まない配列を作る場合、%wが使える

lang = %w(Ruby Perl Python Scheme Pike REBOL)

同様にして、要素がシンボルの配列は%iで作れる

to_aメソッドを使う

各種オブジェクトに実装されているto_aメソッドで、配列に変換する

color_table = {black: "#000000", white: "#FFFFFF"}
color_table.to_a

文字列のsplitメソッドを使う

カンマや空白で区切られた文字列から、splitメソッドを使って配列を作れる

column = "a,b,c,d,e".split(',')

インデックスの使い方

要素を取り出す

  • a[n]
    • インデックスがnの要素を一つ取り出す
    • インデックスがマイナスの場合は、末尾から数える
  • a[n..m] または a[n...m]
    • 前者の場合、a[n]からa[m]の要素までを並べた新しい配列を作って返す
    • 後者の場合、a[n]からa[m-1]の要素までを並べた新しい配列を作って返す
  • a[n,len]
    • a[n]からlen個先までの要素を並べた新しい配列を返す

要素を挿入する

要素の挿入は、「0個の要素と置き換える」とみなせる
「a[n,0]」とすると、インデックスがnの要素の前に挿入できる

a.values_at(n1, n2, ...)

複数のインデックスを使って、飛び飛びに要素を参照しつつ、一つの新しい配列を作る

alpha = %w(a b c d e)
alpha.values_at(1, 3, 5)

集合としての配列

配列を集合として捉えて演算することもできる

  • 共通集合・・・ary1 & ary2
  • 和集合・・・ary1 | ary2
  • 集合の差・・・ary1 - ary2

配列を結合させるメソッドには、「|」と「+」がある
「+」を使った場合は重複が許容され、「|」を使った場合は重複が排除される

列としての配列

  • 要素を加える
    • unshift・・・先頭に要素を追加
    • push・・・末尾に要素を追加
  • 要素を取り出す
    • shift・・・先頭から要素を取り出す
    • pop・・・末尾から要素を取り出す
  • 要素を参照する
    • first・・・先頭の要素を参照する
    • last・・・末尾の要素を参照する

配列の主なメソッド

配列から要素を取り除く

a.unshift(item)

配列aの先頭に新しい要素itemを付け加える

a.push

配列aの末尾に新しい要素itemを付け加える
「a << item」とも書ける

a.concat(b)

配列aに別の配列bを連結する(破壊的メソッド)
元の配列をそのままにして連結したい場合は、「a + b」を使う

a.compact

配列aの中から要素がnilのものを取り除く
元の配列を置き換えたい場合、「a.compact!」を使う

a.delete(x)

配列aから要素xを取り除く

a.delete_at(n)

配列a[n]の要素を取り除く

a.reject{|item| ... }

配列aの各要素itemについて、ブロックを実行した結果が真だった場合、aからitemを取り除く
「a.delete_if{|item| ... }」「a.reject!{|item| ... }」も同様だが破壊的メソッド

a.slice!(n)

配列aから指定された部分を取り除き、取り除いた値を返す
「a.slice!(n..m)」「a.slice!(n, len)」を使うと複数件まとめて削除できる

a.uniq

配列aの重複する要素を削除する
「a.uniq!」は破壊的メソッド

a.shift

配列aの先頭要素を取り除き、取り除いた値を返す

a.pop

配列aの末尾要素を取り除き、取り除いた値を返す

配列の要素を置き換える

a.collect{|item| ... }

配列aの各要素itemにブロックを適用し、その結果を集めて新しい配列を作る
「a.map{|item| ... }」も同様
collect!、map!は破壊的メソッド

a.fill(value)

配列aの要素をvalueに置き換える
引数の指定の仕方によって色々できる

  • a.fill(value, begin)
  • a.fill(value, begin, len)
  • a.fill(value, n..m)

a.flatten

配列aを平坦化(配列の中に配列が入れ子になっている状況をフラットにする)
破壊的メソッドは「a.flatten!」

a.reverse

配列aの要素を逆順に並び替える
破壊的メソッドは「a.reverse」

a.sort

配列aの各要素を並び替える
並び替え方はブロック内で指定できる 破壊的メソッドは「a.sort!」

a.sort_by{|i| ... }

配列aの要素を並びかえる
ブロック内で値をセットしつつ並び替えができる

配列内の各要素を処理する

eachメソッドで要素を1ずつ得る

list = [1, 3, 5, 7, 9]
sum = 0
list.each do |elem|
    sum += elem
end

取り出した要素のインデックスも扱いたい場合は、「each_with_index」を使う

list = ["a", "b", "c", "d"]
list.each_with_index do |elem|
    print elem
end

破壊的メソッドについて

popメソッドやshiftメソッドのように、レシーバにあたるオブジェクトの値そのものを変更してしまうメソッドは、破壊的なメソッドと呼ばれる
オブジェクトの変更を禁止するには、Object#freezeを使う
これを使うとオブジェクトは凍結され、変更しようとするとエラーになる
破壊的なメソッドは、メソッド名の末尾に「!」をつけるルールになっている

14.文字列(String)クラス

文字列を作る

%Qや%qを使う

「"」や「'」を含めた文字列を作りたい場合、%Qや%qが便利

desc = %Q{Rubyの文字列には「''」も「""」も使われます}
str = %q|Ruby said, 'Hello World!'|

%Qは「""」で囲った文字列、%qは「''」で囲った文字列と同様の扱いになる

ヒアドキュメントを使う

ヒアドキュメントとは、Unixのシェルに由来する記法
「<<」を使って文字列を作る。基本文法はこう

<< "終了の記号"
置き換える文字列
終了の記号

ヒアドキュメントの記述例

10.times do |i|
    print(<<"EOB")
i: #{i}
EOB
end

インデントを揃えたい時は、「<<」の代わりに「<<-」を使う

10.times do |i|
    print(<<-"EOB")
i: #{i}
    EOB
end

「<<~」を使うと、行頭の空白が切り詰められるため、「i: #{i}」のインデントも揃えられる

10.times do |i|
    print(<<~"EOB")
        i: #{i}
    EOB
end

「``」を使う

「`コマンド`」の形式でコマンドの標準出力を受け取って、文字列オブジェクトにできる

puts `cat /etc/hosts`

文字列の長さを得る

lengthメソッドまたはsizeメソッドを使う
バイト数の長さが欲しい場合は、bytesizeメソッドを使う
文字列の長さが0であるかを調べるには、empty?メソッドを使う

文字列のインデックス

文字列中の特定位置の文字を取り出すには、配列と同様、インデックスを利用する

文字列をつなげる

新しい文字列を作るには、「+」を使う
すでにある文字列に別の文字列を繋げるには、<<メソッドかconcatメソッドを使う

文字列を分割する

特定の文字で文字列を分割するには、splitメソッドを使う

改行文字の扱い方

  • chop・・・末尾を必ず一文字削る
  • chomp・・・改行がある場合のみ削る

each_lineメソッドをつか買って、繰り返し新しい行を読み込む場合には、chomp!で破壊的に改行文字を落とすのが定石

f.each_line do |line|
    line.chomp!
    # lineを処理する
end

文字列の検索と置換

indexメソッドでは、引数に渡された文字列が含まれるかを左側から調べて返す
rindexメソッドでは、右側から調べて返す
文字列が見つかった場合は、一致した文字のインデックスを返し、見つからなければnilを返す
単純に含まれるかどうかだけなら、include?で良い

文字列と配列で共通するメソッド

s[n] = str

文字列sの一部をstrに置き換える
類似メソッドは以下の通り

  • s[n..m] = str
  • s[n, len] = str

s.slice(n)

文字列sの一部を削る
類似メソッドは以下の通り

  • s.slice(n..m)
  • s.slice(n, len)

s.delete(str)

文字列sから該当する文字列strの部分を取り除く

s.reverse

文字列sを逆順に並べ替える

その他のメソッド

s.strip

文字列sの先頭と末尾にある空白文字を剥ぎ取る

アルファベット変換メソッド各種

  • s.upcase・・・小文字を大文字に変換
  • s.downcase・・・大文字を小文字に変換
  • s.swapcase・・・大文字を小文字に、小文字を大文字に変換
  • s.capitalize・・・最初の文字を大文字に、以降の文字を小文字に変換

s.tr

文字列を置き換えるためのメソッド

"あいうえお".tr("い","イ")
"あいうえお".tr("あ〜お","ア〜オ")

日本語文字コードの変換

encodeメソッドを使うことで文字コードを変換できる
半角カナを全角カナに変換したい、といった場合はnkfライブラリが便利

15.ハッシュ(Hash)クラス

ハッシュの作り方

  • {}を使う
  • Hash.newを使う

値を取り出す・設定する

キーを指定する方法のほか、storeメソッド、fetchメソッドが使える
値の登録にはstoreメソッド、値の取り出しにはfetchメソッドを使う
キーが登録されていない場合は例外を返す

キーをまとめて取り出す

  • keys
  • each_key{|キー| ... }

値をまとめて取り出す

  • values
  • each_value{|値| ... }

[キー, 値]のペアを取り出す

  • to_a
  • each{|キー, 値|}

ハッシュのデフォルト値

Hash.newに引数を指定すると、デフォルト値として使われる
キーによって異なる値を返したい場合、同一オブジェクトが格納されることを避けたい場合はブロックを指定する
fetchメソッドの第二引数にデフォルト値を指定する�(これが一番優先度高い)

あるオブジェクトをキーや値として持つか調べる

h.key?(key)

ハッシュがあるオブジェクトをキーとして持っているかを調べる
類似メソッドは以下の通り

  • h.has_key?(key)
  • h.include?(key)
  • h.member?(key)

h.value?(value)

あるオブジェクトを値として持っているかを調べるためのメソッド
h.has_value?(value)でも同じ結果が得られる

ハッシュの大きさを調べる

h.size

ハッシュの大きさ(登録されているキーの数)を調べる
h.lengthでも可

h.empty?

大きさが0(ハッシュにキーが何も登録されていない)かどうかを調べる

キーと値を削除する

h.delete(key)

キーを指定して削除する

h.delete_if{|key, val| ... }

条件を与えて、その条件に当てはまるものだけを削除する
h.reject!{|key, val| ... }でも可

ハッシュを初期化する

h.clear

一度使ったハッシュを空にする

二つのハッシュを合わせる

二つのハッシュを組み合わせて新しいハッシュを作るには、Hash#mergeを使う

16.正規表現(Regexp)クラス

正規表現オブジェクトの作り方

  • 正規表現として扱いたいパターンを「//」で囲む
  • クラスメソッドから生成する
    • 例:re = Regexp.new("Ruby")
  • %を使った表記で作る
    • %r(パターン)
    • %r<パターン>
    • %r|パターン|
    • %r!パターン!

正規表現のパターンとマッチング

マッチしたかどうかは「=~」で判定する

正規表現 =~ 文字列

quoteメソッドを使った正規表現

メタ文字を全てエスケープしたい場合、quoteまたはescapeを使う

正規表現のオプション

  • i・・・アルファベットの大文字と小文字の違いを無視する
  • x・・・正規表現内の空白と「#」の後ろの文字を無視する
  • m・・・「.」が改行文字にもマッチするようになる

キャプチャ

正規表現でマッチした部分の一部を取り出す方法
正規表現の中の「()」で囲まれた部分にマッチした文字列を$1や$2といった形式で取り出せる

正規表現を使うメソッド

subメソッドとgsubメソッド

  • sub・・・正規表現で最初にマッチした部分を置き換える
  • gsub・・・正規表現でマッチする箇所全てを置き換える

scanメソッド

パターンにマッチした箇所を取り出す(置換はしない)

17.IOクラス

入出力の種類

標準入出力

プログラムを起動すると、下記の三つのIOオブジェクトが割り当てられる

  • 標準入力
    • データを受け取るためのIOオブジェクト
    • 組み込み変数STDINに割り当て
    • グローバル変数$stdinからも参照可能
    • キーボードからの入力をgetsメソッドなどで受け取る
  • 標準出力
    • データを出力するためのIOオブジェクト
    • 組み込み変数STDOUTに割り当て
    • グローバル変数$stdoutからも参照可能
    • puts、print、printfなどのメソッドをコンソールに出力
  • 標準エラー出力
    • 警告やエラーを出力するためのIOオブジェクト
    • 組み込み変数STDERRに割り当て
    • グローバル変数$stderrからも参照可能
    • warnなどのメソッドで警告メッセージをコンソールに出力

IOオブジェクトがコンソールに関連づけられているかはtty?メソッドで判別できる

ファイル入出力

File.open(file[, mode[, perm]][, opt])

ファイルを開いて新しいFileオブジェクトを返す
modeには、どのような目的でファイルを日落下を指定する

  • "r"・・・読み込み専用
  • "r+"・・・読み込み/書き込み用
  • "w"・・・書き込み専用。ファイルがなければ新たに作成。すでに存在する場合はファイルを空にする
  • "w+"・・・読み込み/書き込み用。そのほかは"w"と同じ
  • "a"・・・追加書き込み専用。ファイルがなければ新たに作成
  • "a+"・・・読み込み/追加書き込み用。ファイルがなければ新たに作成

permにはファイルを作成する場合のアクセス許可を指定する
optにはその他オプションを指定する

  • :mode
  • :external_encoding
  • :internal_encoding
  • :encoding
  • :textmode
  • :binmode
  • :autoclose

file.close

開いたファイルを閉じる

file.closed?

Fileオブジェクトが閉じられているかを確認する

File.read(file[, length[, offset]])

Fileオブジェクトを作らずに、ファイルからデータを読み込む
lengthには読み込むサイズを、offsetには先頭何バイト目から読み込むかを指定する

File.binread(file[, length[, offset]])

ファイルをバイナリモードで開いて読み込む

File.write(file, data[, offset])

Fileオブジェクトを作らずに、ファイルをデータに書き込む
offsetを省略した場合は、ファイルの内容を全てdataに置き換える

File.binwrite(file, data[, offset])

ファイルをバイナリモードで開いて書き込む

基本的な入出力操作

入力操作

io.gets(rs)

IOオブジェクトからデータを1行読み込む
行の区切りは引数rsに指定した文字列になる(省略した場合は「\n」で判定)

while line = io.gets
    line.chomp!
    # lineに対する操作
end

類似メソッドは以下の通り

  • io.each(rs)
  • io.each_line(rs)
  • io.readlines(rs)

io.lineno

getsメソッドやeach_lineメソッドで行単位で読み込みを行った際の行番号を取得する

io.each_char

ioから1文字ずつデータを読み込んでブロックを実行する

io.each_byte

ioから1バイトずつデータを読み込んでブロックを実行する

io.getc

ioから1文字だけ読み込む

io.ungetc(ch)

引数で指定した文字をioの入力バッファに戻す

io.getbyte

ioからデータを1バイトだけ読み込んで、バイトに対応するASCIIコードを整数オブジェクトで返す

io.ungetbyte(byte)

引数で指定した1バイトをioの入力バッファに戻す

io.read(size)

サイズを指定して読み込む

出力操作

io.puts(str0, str1, ... )

文字列の出力後に改行する

io.putc(ch)

引数で指定した文字コードに対応する文字を出力する

io.print(str0, str1, ... )

引数に指定した文字列を出力する

io.printf(fmt, arg0, arg1, ... )

書式を指定して文字列を出力する

io.write(str)

引数で指定した文字列を出力する

io << str

引数で指定した文字列を出力する
<<はレシーバ自身を戻り値とするので、

io << "foo " << "var " << "baz"

みたいな書き方もできる

ファイルポインタ

IOオブジェクトがファイルのどこを指しているかを示す情報を、ファイルポインタまたはカレントファイルオフセットという
ファイルを固定サイズのブロックの集まりとして扱う場合に便利

io.pos

現在のファイルポインタの位置を取得する
ファイルポインタの位置変更は「pos=」メソッドで可能

io.seek(offset, whence)

ファイルポインタを移動する
offsetに位置を指定し、whenceに評価方法を指定する

  • IO::SEEK_SET・・・offsetで指定した位置にポインタを移動する
  • IO::SEEK_CUR・・・offsetを現在の相対位置とみなしてポインタを移動する
  • IO::SEEK_END・・・offsetをファイルの末尾からの相対位置として指定する

io.rewind

ファイルポインタをファイルの先頭に戻す

io.truncate

ファイルの長さを、引数で指定したサイズに切り詰める

バイナリモードとテキストモード

  • テキストモード・・・改行文字の変換が有効な状態
  • バイナリモード・・・改行文字の変換が無効な状態

io.binmode

IOオブジェクトをバイナリモードに変更する

バッファリング

io.flush

出力バッファにたまっているデータを即座に出力する

io.sync

io.sync = trueに設定することで、出力の操作と実際の出力が同期するようになる

コマンドとのやりとり

Rubyのプログラム中で他のコマンドとデータをやりとりするには、IO.popenメソッドを使う

file = IO.popen("zcat #{filename}")  

openメソッドの引数にパイプ記号をつけたコマンドを渡しても、同じことができる

open("|zcat #{filename}")

open-uriライブラリ

HTTPやFTPのURLを普通のファイルのように開ける

require "open-uri"

# HTTP経由でデータを読み込む
open("http://www.ruby-lang.org/ja/") do |io|
    puts io.read
end

stringioライブラリ

IOオブジェクトの振りをするオブジェクト(テスト時等に使う)
StingIOオブジェクトへの出力は、実際にはどこにも出力されず、後からreadメソッドで読み出せる

18.FileクラスとDirクラス

Fileクラス

ファイル名を変更する

file.rename(before, after)

ファイル名を変更する
すでに存在するディレクトリにファイルを移動することもできる(なければエラーとなる)

ファイルをコピーする

File.openメソッドとwriteメソッドを組み合わせることで実現できる

def copy(from, to)
    File.open(from) do |input|
        File.open(to, "w") do |output|
            output.write(input.read)
        end
    end
end

ファイルを削除する

File.delete(file)

ファイルを削除する
「File.unlink(file)」でも削除可能

ディレクトリの操作

  • Dir.pwd・・・カレントディレクトリを取得する
  • Dir.chdir(dir)・・・カレントディレクトリを変更する

ディレクトリの内容を読む

Fileクラス同様、Dirクラスにもopenとcloseメソッドがある

  • Dir.open(path)
  • Dir.close

Dir#readメソッドを使うと、最初に開いたディレクトリに含まれるものの名前を一つずつ順に返す

def traverse(path)
    if File.directory?(path)
        dir = Dir.open(path)
        while name = dir.read
            next if name == "."  # カレントディレクトリは読み飛ばす
            next of name == ".." # 親ディレクトリも読み飛ばす
            traverse(path + "/" + name)
        end
        dir.close
    else
        process_file(path)
    end
end

Dir.globメソッドを使うと、*や?などのワイルドカードを使ってファイル名を取得できる

ディレクトリの作成と削除

  • Dir.mkdir(path)・・・ディレクトリを作成する
  • Dir.rmdir(path)・・・ディレクトリを削除する(中身は空である必要がある)

ファイルとディレクトリの属性

File.stat(path)

ファイルやディレクトリの属性を取得できる

  • File.ctime・・・ファイルを最後に参照した時刻を取得する
  • File.mtime・・・ファイルを最後に修正した時刻を取得する
  • File.atime・・・ファイルの状態を最後に変更した時刻を取得する

File.utime(atime, mtime, path)

ファイルの属性のうち、最終参照時刻(atime)と最終修正時刻(mtime)を変更する

File.chmod(mode, path)

ファイルのパーミッションを変更する
modeには新しいモードを整数値で指定する(ex.0755)

File.chown(owner, group, path)

ファイルの所有者を変更する
ownerには新しい所有者のユーザID、groupには新しいグループのIDを指定する

ファイル名の操作

File.basename(path[, suffix])

パス名のうち、一番後ろの"/"以降の部分を返す

File.basename("/usr/local/bin/ruby") #=> "ruby"

File.dirname(path)

パス名のうち、一番後ろの"/"までの部分を返す

File.dirname("/usr/local/bin/ruby") #=> "/usr/local/bin"

File.extname(path)

パス名のうち、basenameメソッドが返す部分から拡張子を取り出す
拡張子が含まれない場合は空の文字列を返す

File.split(path)

パス名をディレクトリの部分とファイルの部分に分割し、配列にして返す

File.join(name1[, name2, ... ])

引数で与えられた文字列をFile::SEPARATOR(デフォルトは"/")で連結する

File.expand_path(path[, default_dir])

相対パス名(path)を、ディレクトリ名(default_dir)に基づいて絶対パスに変換する
ディレクトリ名を指定しなかった場合は、カレントディレクトリを基準に変換する

ファイル操作関連のライブラリ

findライブラリ

ディレクトリやファイルを再帰的に処理するためのライブラリ
Find.findメソッドで、指定したディレクトリ以下の全てのファイルのパスを走査できる

Find.find(dir) do |path|
    puts path
end

tempfileライブラリ

テンポラリファイルを管理するためのライブラリ

  • Tempfile.new(basement[, tempdir])・・・テンポラリファイルを作成する
  • tempfile.close(real)・・・テンポラリファイルを閉じる。realがtrueのとき、テンポラリファイルはすぐに削除される
  • tempfile.open・・・テンポラリファイルをもう一度開く
  • tempfile.path・・・テンポラリファイルのパス名を返す

fileutilsライブラリ

ファイル操作に便利な処理を提供する

  • FileUtils.cp(from, to)・・・fromからtoへファイルをコピーする。
    • FileUtils.cp_r・・・ディレクトリを指定した場合、再帰的にコピーする
  • FileUtils.mv(from, to)・・・fromからtoへファイルを移動する
  • FileUtils.rm(path)・・・ファイルを削除する。例外発生時は処理を中断する
    • FileUtils.rm_f(path)・・・例外が発生しても処理を継続する
    • FileUtils.rm_r(path)・・・ディレクトリを指定した場合、再帰的に削除する
    • FileUtils.rm_rf(path)・・・例外が発生しても処理を継続する
  • FileUtils.compare(from, to)・・・fromとtoの内容を比較する
  • FileUtils.install(from, to[, option])・・・fromからtoへファイルをコピーする
  • FileUtils.mkdir_p(path)・・・ディレクトリを再帰的に作成する

19.エンコーディング(Encoding)クラス

スクリプトエンコーディング

スクリプト自体のエンコーディングのことを「スクリプトエンコーディング」と呼ぶ
スクリプト中の文字列や正規表現のリテラルは、スクリプトエンコーディングに従って解釈される

Encodingクラス

String#encodingメソッドを使うと、Encodingオブジェクトを返せる

Encoding.compatible?(str1, str2)

2つの文字列の互換性をチェックする
互換性がある場合は、連結した結果得られる文字列のエンコーディングを返す
互換性がない場合は、nilを返す

Encoding.default_external

デフォルトの外部エンコーディングを返す

Encoding.default_internal

デフォルトの内部エンコーディングを返す

Encoding.find(name)

エンコーディング名に対応するEncodingオブジェクトを返す

Encoding.list

Rubyがサポートしているエンコーディングの一覧を返す
Encoding.listはEncodingオブジェクトの一覧を、Encoding.name_listはエンコーディングの名前を表す文字列の一覧を返す

enc.name

Encodingオブジェクトのエンコーディング名を返す
「enc.names」を使うと、Encodingオブジェクトに与えられた名前の一覧を配列で返す

ASCII-8BITとバイト列

バイナリデータ、バイト列を表現するために「ASCII-8BIT」が用意されている
force_encodingメソッドを使うことで、エンコーディング情報を変更できる
エンコーディングが適切かは、valid_encoding?で調べられる

IOクラスとエンコーディング

外部エンコーディングと内部エンコーディング

  • 外部エンコーディング・・・入出力の対象となるエンコーディング
    • ファイル
    • コンソール
  • 内部エンコーディング・・・Rubyスクリプトの中で扱うエンコーディング

エンコーディングの設定

io.set_encoding(encoding)

"外部エンコーディング名:内部エンコーディング名"の形式でエンコードを指定できる

File.open(file, "mode:encoding")

ファイルを開く際にエンコーディングを指定できる

# 外部エンコーディングにUTF-8を指定する
File.open("foo.txt", "w:UTF-8")

# 外部エンコーディングにShift_JISを指定し、
# 内部エンコーディングにUTF-8を指定する
File.open("foo.txt", "r:Shift_JIS:UTF-8")

20.TimeクラスとDateクラス

時刻を取得する

Time.now

現在の時刻を取得する
Time.newでも取得可能

t.year、t.month、t.day

年、月、日など取得した時刻の要素を返す

Time.mktime(year[, month[, day[, hour[, min[, sec[, usec]]]]]])

指定した時刻を表すTimeオブジェクトを生成する

Time.at(epoch)

Unixシステムの基準点である「1970/1/1 00:00:00(UTC)」からの経過秒数でTimeオブジェクトを生成する

時刻のフォーマット

t.strftime(format)

時刻をフォーマットに従った文字列にする

t.rfc2822

電子メールのヘッダ情報に含まれる、Date:フィールドで使用される形式でフォーマットする

t.iso8601

ISO 8601形式(時刻の表現に関する国際標準)でフォーマットする

ローカルタイム

t.utc

Timeオブジェクトが保持しているタイムゾーンを世界協定時(UTC)に変更する
UTCからローカルタイムに変更するには、Time#localtimeメソッドを使う

文字列から時刻を取り出す

Time.parse(str)

文字列を解析し、Timeオブジェクトにして返す

Time.strptime(str, format)

「平成27年9月1日」みたいなフォーマットを解析して、Timeオブジェクトにして返す

日付を取得する

Date.todayメソッドを使うと、現在の日付を表すDateオブジェクトを取得できる
日付を指定してDateオブジェクトを生成することもできる
Timeクラスと同様、日付を構成する要素を求めることもできる

日付を計算する

Dateオブジェクト同士を引き算すると、その間の日数を得られる
引き算の結果は整数ではなく、Rationalオブジェクトとなる

  • >>演算子・・・後ろの月の同日のDateを取得できる
  • <<演算子・・・前の月の同日のDateを取得できる

日付のフォーマット

Timeクラスと同様、strftimeメソッドを使って、日付を文字列にするためのフォーマットを指定できる

文字列から日付を取り出す

文字列から日付を取り出す際には、下記のメソッドが使える

  • Date.parse
  • Date.strptime(str, format)

TimeとDateの変換

TimeオブジェクトとDateオブジェクトは、to_timeメソッドとto_dateメソッドで相互に変換できる

21.Procクラス

Procクラスとは

ブロックとして記述された手続きを持ち運ぶためのクラス
Proc.newメソッドまたは、procメソッドにブロックを指定することで生成できる

ラムダ式

Proc.newやprocとは別の書き方として、lambdaメソッドがある
違いは下記の二点

  • 引数の数のチェックが厳密になる

  • ブロックから値を返す時にreturnを使える

    def square(n) lambda do |n| return n ** 2 end end

ラムダ式は下記の構文でも作ることができる

->(ブロック変数){ 処理 }

実装例

square = ->(n){ return n ** 2 }

Procオブジェクトのように、手続きと同時に変数などの環境を保持する手続きオブジェクトを、クロージャという
クロージャを用いると、手続きとデータをオブジェクトとして扱うことができる

Procクラスのインスタンスメソッド

prc.call(args, ... )

Procオブジェクトを実行する
下記のメソッドも同様

  • prc[args, ... ]
  • prc.yield(args, ... )
  • prc.(args, ... )
  • prc === arg

prc.arity

callメソッドの引数となる、ブロック変数の数を返す

prc.parameters

ブロック変数の、より詳細な情報を返す
戻り値は[種類, 変数名]の配列をリストした配列になる

  • :opt・・・省略可能な変数
  • :req・・・必須の変数
  • :rest・・・*args形式で受け取る残りの変数
  • :key・・・キーワード引数の形式の変数
  • :keyrest・・・**args形式で受け取る残りの変数
  • :block・・・ブロック

prc.lambda?

prcがラムダ式か否かを返す

prc.source_location

prcが定義されたソースコード上の位置を返す
戻り値は[ソースファイル名, 行番号]の配列になる

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment