Edited at

PHPer向けのRuby入門

More than 3 years have passed since last update.


はじめに


  • この記事はRubyの書き方・読み方を最低限説明するために作成されたものである。


  • PHPがある程度普通に触れている人向けに、Rubyではどう書く?みたいなところが中心


  • Rubyの環境は既に整ってる前提


基本思想


PHPは関数が基本


  • 例えばある配列から先頭の要素を取り出す時

$a = array(1,2,3);

$first = array_shift($a);
var_dump($first);
var_dump($a);



  • array_shiftという関数に引数を渡すことで任意の処理を行う。


Rubyはオブジェクトが基本


  • 同様に配列から先頭の要素を取り出す時

a = [1,2,3]

first = a.shift
p first
p a

Arrayオブジェクトashiftメソッドで先頭の要素を取り出す。

これがPHPRubyの基本思想の違いである。


まず先に出力方法


  • 基本的な出力形式を押さえておく。


  • PHPでいう「困ったらダンプしてみる」というのはRubyでも通用するのでpメソッドを覚えておくと何かと便利。

  • コメント文は#

PHP
Ruby

echo('hoge');
print 'hoge'

echo("hoge¥n");
puts 'hoge'

var_dump('hoge');
p 'hoge'

//コメント文
#コメント文


実際に出力してみよう

コンソールでirbと打つとインタラクティブシェルが起動する。まずはファイルを作成せずにシェルで挙動を確認しましょう。

PHP
Ruby

php -a
irb


演習問題1

インタラクティブシェルでprint, puts, pの出力を試してみましょう。


拡張子と実行方法

プログラムファイルの拡張子は.rb、実行はrubyコマンド

PHP
Ruby

.php
.rb

php hoge.php
ruby hoge.rb


hoge.php

<?php

$a = 'hoge';
var_dump($a);


hoge.rb

a = 'hoge'

p a



  • <?php等の開始タブが不要

  • 変数に$不要

  • 行末にセミコロン不要(つけても良い)

  • カッコの省略可(つけても良い)


演習問題2

実際に上記ファイルを作って実行してみましょう。


ループ


loop.php

<?php

for($i=0; $i<10; $i++){
echo($i."\n");
}


loop.rb

for i in 0...10 do

p i
end

ここで覚えて欲しいのは0...10の範囲オブジェクト

0..10だと10を含む、0...10だと10を含まない。

またPHPで中括弧で囲んでいる部分はそのままRubyではdo ~ endで置き換えることができる。

ちなみに上記のfor文はほぼ使わない。

私も久しぶりに使うにあたってドキュメントを参照しながらでないと書けなかった(汗

上記の例でいうと範囲オブジェクトに対してeachメソッドを使って


loop2.rb

(0...10).each do |i|

p i
end

こんな感じに書くのが自然である。

もっと言うと基本は配列等のオブジェクトに対してループを回すことが大半である(PHPでいうところのforeachと同義)

そのあたりは次の配列の項で触れる。


演習問題3

1から100までの偶数を出力して下さい。


配列


array.php

<?php

$a = array('Hello', 'new', 'world');
foreach($a as $value){
var_dump($value);
}


array.rb

a = ['Hello', 'new', 'world']

a.each do |value|
p value
end

これが前項で述べていたオブジェクト(この場合には配列)に対してeachでループを回している様子である。foreachだと思えば馴染みやすいかと思う。

Arrayオブジェクトに色々なメソッドがあるので適宜使って欲しい。


http://ref.xaio.jp/ruby/classes/array


PHP
Ruby

sort($a)
a.sort

empty($a)
a.empty?

array_unique($a)
a.uniq

count($a)
a.count

ここで出てきたのでついでに紹介するがRubyではメソッド名に!?が使用できる。

自由に命名に使って良いが慣習として



  • true or falsebooleanを返すメソッドには末尾に?

  • 対象のオブジェクトに対して破壊的なメソッドには末尾に!を使う。

例えばarray.uniqarray.uniq!という元の配列を上書き(破壊)してしまうものも存在する。


演習問題4

次の処理のPHPRubyに書き換えてみましょう。


example4.php

<?php

// カンマ区切りの文字列を配列に格納
$string = 'Hello, new, world';
$array = explode(', ', $string);
print_r($array);

// 配列の各要素をカンマ区切りの文字列に変換
$convert_string = implode(', ', $array);
print_r($convert_string);

// カンマ区切りの文字列をコロン区切りの文字列にする
print_r(str_replace(',', ':', $convert_string));



条件分岐


if.php

<?php

$a = 'hoge';
if($a === 'hoge'){
echo("true\n");
}


if.rb

a = 'hoge'

if a == 'hoge'
p 'true'
end

特に難しいことはない。


  • カッコの省略

  • 中括弧がthen ~ end (thenは省略可)


  • ==PHP===と同じく厳密比較

Rubyならではの書き方を以下に記載する。


unless


unless.php

<?php

$a = 'hoge';
if($a !== 'moge'){
echo('true');
}


unless.rb

a = 'hoge'

unless a == 'moge'
p 'true'
end

unlessとは簡単に言えば!==と同義である。

簡単に否定の比較ができるので割と重宝する。

!よりも見落としにくい。


elsif


else.php

<?php

$a = 'hoge';
if($a === 'moge'){
echo('moge');
} else if($a === 'hoge'){
echo('hoge');
} else{
echo('else');
}


else.rb

a = 'hoge'

if a == 'moge'
p 'moge'
elsif a == 'hoge'
p 'hoge'
else
p 'else'
end

else ifでもelseifでもなくelsifなので注意


後置if


back_if.rb

a = 'hoge'

p 'true' if a == 'hoge'
p 'true' unless a == 'moge'

個人的にRubyが好きな理由の1つ

条件式を後ろに配置できる。

ものによっては1行でまとまって非常にスッキリするのでオススメ

英語の文法としても自然(と思う)

PHPにはないのでPHP版は割愛


演習問題5

1から30の間でFizzBuzzRubyで実装してみましょう。

FizzBuzzとは3の倍数でFizz, 5の倍数でBuzz, 15の倍数でFizzBuzz, それ以外の時は数値を出すプログラム問題のことである。


ハッシュ(連想配列)


hash.php

<?php

$a = array('key1' => 'value1', 'key2' => 'value2');
print_r($a);

foreach($a as $key => $value){
echo("$key, $value\n");
}

echo($a['key2']."\n");



hash.rb

a = {'key1' => 'value1', 'key2' => 'value2'}

p a

a.each do |key, value|
puts key + ', ' + value
end

puts a['key2']


ハッシュとは簡単に言うとPHPでいうところの連想配列である。

キーとそれに対応する値を保持する形

これも連想配列を理解していれば特に難しいことはない。

リテラルが中括弧を使用する点に注意


演習問題6

'key1' => 1この形で10まであるハッシュをループで生成して下さい。

生成したハッシュに対して、値が5以上であるもののkey値を出力して下さい。

Hint: キャスト

PHP
Ruby

(int)'5'
'5'.to_i

(string)5
5.to_s


関数


function.php

<?php

function add($a, $b){
$sum = $a + $b;
return $sum;
}

$result = add(1, 2);
var_dump($result);



function.rb

def add(a, b)

sum = a + b
return sum
end

sum = add(1, 2)
puts sum


PHPfunctiondefに置き換えればほぼそのまま流用できる。

ただRubyでは上記のような書き方は普通しない。

通常は以下のような書き方になる。


function2.rb

def add a, b

a + b
end

puts add(1, 2)


Rubyではreturnを省略することができる。

省略した場合は関数内で最後に評価された値が自動で返る(この場合はa+bの結果)

ここはRubyのソースを読む上で勘違いしやすいところなので注意。


演習問題7

引数: array

戻値: hash

配列を渡したらその中に入っている数値を全て足した結果を返す関数を作成して下さい。

配列の中が全て整数でなければ加算できないのでsuccessにfalseを入れて返して下さい。

例:

[1,2,3,4,5,6,7,8,9,10] >> {'success' => true, 'value' => 55}

[1,2,3,'a',5,6,'b',8,9,10] >> {'success' => false, 'value' => nil}

Hint: nil

nilとはPHPでいうところのNULLと同義である。

PHP
Ruby

NULL
nil

is_null(NULL)
nil.nil?


例外処理


exception.php

<?php

try {
$a = 'moge';
if($a === 'hoge'){
echo("hoge\n");
} else {
throw new Exception('exception occur');
}

echo('finish');
} catch(Exception $e){
var_dump($e->getMessage());
}



exception.rb

begin

a = 'moge'
if a == 'hoge'
puts a
else
raise 'exception occur'
end
rescue => message
puts message
end

PHPtry-catchRubyではbegin-rescue-endに置き換わる。

また、例外を発生させる方法はthrowraiseに置き換える。


クラス


class.php

<?php

class ParentClass
{
public function sayHello(){
echo("Hello!\n");
}
}

class ChildClass extends ParentClass
{
}

$a = new ParentClass();
$a->sayHello();

$b = new ChildClass();
$b->sayHello();



class.rb

class ParentClass

public
def sayHello
puts 'Hello'
end
end

class ChildClass < ParentClass
end

a = ParentClass.new
a.sayHello

b = ChildClass.new
b.sayHello


簡単に違いを表す

PHP
Ruby

extends
<

new Class
Class.new

$a->hoge()
a.hoge

また、PHPではメソッド1つ1つにpublic, protected, privateをつけるのに対し、Rubyでは宣言箇所以下ではそのアクセス権に絞られる。

以下の例で言うとa,b,cpublic, d,eprotected, fprivateとなる。

class hoge

public
a
b
c
protected
d
e
private
f
end


演習問題8

上記の例にChildClassを継承したGrandChildClassを追加して下さい。

GrandChildClassではsayHelloメソッドに引数で文字列を渡すとその人に対してHelloするようにメソッドを拡張して下さい。

例: c.sayHello('yamamoto') >> 'Hello! yamamoto!'


ブロック

ブロックに関してはPHPに置き換えるのが難しいため割愛

こちらの記事が大変参考になるので気になる人はこちら


http://qiita.com/kidach1/items/15cfee9ec66804c3afd2



おわりに

これでRubyの基本的な書き方は押さえられました。

次回はRailsにスポットを当てる予定です。


Appendix

演習問題の解答例を載せておきます。

解き方は1通りではないし私の解答がイケてない可能性もあるのであくまで例ということで。


演習問題3の解答例


example3.rb

(1..50).each do |i|

p i * 2
end

# 条件文を使った方法はこっち
#(1..100).each do |i|
# p i if i % 2 == 0
#end



演習問題4の解答例


example4.rb

string = 'Hello, new, world'

array = string.split(', ')
p array

convert_string = array.join(', ');
p convert_string

p convert_string.gsub(',', ':');



演習問題5の解答例


example5.rb

(1..30).each do |i|

print 'Fizz' if i%3 == 0
print 'Buzz' if i%5 == 0
print i unless (i%3 == 0 || i%5 == 0)
puts
end


演習問題6の解答例


example6.rb

a = {}

1.upto 10 do |i|
a['key'+i.to_s] = i
end
p a

a.each do |key, value|
p key if value >= 5
end



演習問題7の解答例


example7.rb

def add_all target_array

# 全て数値かチェック
success = number_check(target_array)
result_hash = {'success' => success}
if success
result_hash['value'] = target_array.inject { |sum, n| sum + n }
else
result_hash['value'] = nil
end
result_hash

end

def number_check target_array
target_array.each do |i|
return false unless i.kind_of?(Numeric)
end
true
end

target_array = [1,2,3,4,5,6,7,8,9,10]
p add_all(target_array)

target_array = [1,2,3,'a',5,6,'b',8,9,10]
p add_all(target_array)



演習問題8の解答例


example8.rb

class ParentClass

public
def sayHello
puts 'Hello'
end
end

class ChildClass < ParentClass
end

class GrandChildClass < ChildClass
public
def sayHello(name)
puts 'Hello! ' + name + '!'
end
end

a = ParentClass.new
a.sayHello

b = ChildClass.new
b.sayHello

c = GrandChildClass.new
c.sayHello('yamamoto')