Skip to content

Instantly share code, notes, and snippets.

@sunaot
Last active April 4, 2017 11:04
Show Gist options
  • Save sunaot/148ff114b3c882cfc4ed to your computer and use it in GitHub Desktop.
Save sunaot/148ff114b3c882cfc4ed to your computer and use it in GitHub Desktop.
さらっと読んで Ruby がわかった気になれるプログラミング言語 Ruby のかんたんな紹介

Ruby+Rails を始めるのにこの辺をおさえておくといいのでは。 というのを書いていきます。

リソース

Ruby

Rails

初めての Ruby を 3 分で。

インストール

rbenv+ruby-build でインストールがおすすめ

REPL

$ irb

とすると REPL が開くので、試してみるのが早いはず。

配列とハッシュ

配列

array = [ 'this', 'is', 'array', 'object' ]
p array       #=> ["this", "is", "array", "object"]
puts array[0] #=> this

array[4] = '!'
p array       #=> ["this", "is", "array", "object", "!"]

Ruby の配列は tuple のようにいろいろな型の要素を持つことができます。

[ 'string', 10, :symbol, ['array in array'], { hash: :in_array } ]

ハッシュ

hash = { 'this' => 'is', hash: 'object' }
p hash            #=> {"this"=>"is", :hash=>"object"}
puts hash['this'] #=> is
puts hash[:hash]  #=> object

hash['!'] = '?'
p hash            #=> {"this"=>"is", :hash=>"object", "!"=>"?"}

ハッシュのキーをシンボルにする場合は、以下のような書き方ができ、

call_method(with: params)

これは

call_method({ :with => params })

と等価です (ハッシュのキーがシンボルの場合のハッシュリテラルの記法と、最後のパラメータがハッシュの場合は {} のリテラルの表記を省略可能なことを利用した書き方)。

Ruby でプログラミングする最初の一歩は Array クラスと Hash クラスのメソッドを理解すること。

Array や Hash は Enumerable を mix-in (実装継承) しているため、Enumerable module のメソッドを呼び出すこともできます。 慣れてきたら、Enumerable を使いこなせるようにリファレンスマニュアルを眺めてみましょう。

emails = User.where('age > ?', 20).reject {|user| user.name == 'sunaot' }.map {|user| user.email }

ハッシュや Array に対して期待する操作については大体メソッドが用意されていると思って間違いないと思います。 まずはリファレンスマニュアルを眺めてやりたいことを実現できる抽象化されたメソッドがないか探してみましょう。 とくにイテレータは非常に強力にサポートされており、上記の reject のようにブロックをわたしてやることで reject 条件をクロージャでカスタマイズするような柔軟な呼出しが可能です。

数値

3 / 2   #=> 1
3.0 / 2 #=> 1.5
3 / 2.0 #=> 1.5

任意の位置に桁区切りが入れられます。数値型の中の _ は見た目以上の意味は持ちません。

3 + 1_000 #=> 1003

文字列

文字列リテラル

'fixed string'

text = 'quote'
"double #{ text } string" #=> double quote string

`echo executable`

%Q| double quote string |
 %| double quote string |
%q| single quote string |

puts <<HEREDOC
hello, world!
HEREDOC

文字列操作も Ruby の得意分野です。やりたいことは大体メソッドがあるはずなので探してみてください。

正規表現リテラル

/this is regexp/

Ruby の M17N

Ruby 2.0 以降、未指定の場合の script encoding がデフォルト UTF-8 になったため、マジックコメント (shebang の下の conding: utf-8) は不要となりました。マジックコメントは指定せず、スクリプトは UTF-8 で保存してください。

UTF-8 ではないエンコーディングを扱う場合、プログラム内に取込む入力の境界と出力の境界で適切に encode/decode します。

force_encoding は「実態はわからないが、そのようにみなす」というものなので、お世話にならないようなつくりのプログラムを書き、出会うことのないようにしましょう。IO から入力されるエンコーディングがわかっているなら、その入力ストリームにたいしてエンコーディング情報を指定することができます。くわしくは、IO のリファレンスマニュアルを読む。

シンボルリテラル

:this_is_symbol

シンボルはインスタンスが一意に特定できる文字列オブジェクトです。通常、Ruby の文字列は同じ値の文字列でも個別にインスタンスが違います。

'hello'.object_id #=> 70365954987520
'hello'.object_id #=> 70365954972240

'hello' ==  'hello'     #=> true  同値性の検査 String#==
'hello' === 'hello'     #=> true  同値性の検査 String#===
'hello'.eql?('hello')   #=> true  同値性の検査 String#eql?
'hello'.equal?('hello') #=> false 同一性の検査 Object#equal?

シンボルは同じ値であれば、プログラム中で一つしかインスタンスが生成されないことが保証されています。

:hello.object_id #=> 515368
:hello.object_id #=> 515368

:hello.equal?(:hello) #=> true

メソッド名のような唯一であることを表現したい場合に使いますが、どーしてもシンボルじゃないといけない機会はそれほどなく、実際は表記上の見た目の使い分けがされていることが多いです。

シンボルと文字列は別のものとして扱われるので、パラメータとしてシンボルを期待するのか文字列を期待するのか両方を許容して value.to_s とキャストするのかというあたりは気をつけることが多いです。

# 共存可能
{ 'hello' => 1, :hello => 2 }

'hello'      == :hello      #=> false
'hello'.to_s == :hello.to_s #=> true

入出力

IO class や File class を見てみてください。

open('filename') do |file|
  file.readlines.map {|line| line + '!!!' }
end
# ファイルの close はブロックを抜けるときに保証されている

モジュールとクラス

Ruby はいくつかのルールによって最小限の記述でセマンティックを表現しています。

# namespace は module を使ってつくっていきます
# namespace を TopLevel::NextLevel と重ねることもできますが
# 定義済の module ではない場合はエラーとなるので、
# 最初の定義ではひとつずつネストを深くしていきます
module TopLevelName
  class ClassName
    # 大文字で始まる名前は定数となります。メソッドの中ではリテラルとしては定義できません (裏口はある)
    CONSTANT_NAME = 'const'

    # @@ を二つつけるとクラス変数です。同一クラスのインスタンス間で共有されます
    @@class_variable = 'this is class variable'

    # クラスコンテキストの特異変数
    @on_class_context = 'class context'

    # class のコンストラクタは initialize という名前でつくります。
    # ClassName.new(args) されたときに initialize(args) が呼ばれます。
    def initialize
      # インスタンスコンテキストで宣言された @ 付変数はインスタンス変数となります
      # インスタンス内でメソッドをまたいで共有されます
      @instance_variable = ':-)'
    end

    # def とスネークケースの命名でインスタンスメソッドを定義します
    # 引数にはデフォルトを指定できます
    # 末尾の引数は複数の値を array でまとめて受けることができ、可変長引数に使われます
    def method_name(val = 'default', *args)
      # メソッドからの復帰は return を使います
      return :ok
    end

    # 呼出しの多くの場合と同様に、メソッド定義の引数の () は省略できます
    # デフォルトを指定しない引数は必須の引数としてシグネチャがあわない場合に ArgumentError を起こします
    # &付でブロックを受け、another_method(val) {|item| item.succ } のような記法を受け付けるメソッドを定義できます
    def another_method val, &block
      block.call(val) unless block.nil?
    end

    # self. とつけることでクラスメソッドを定義できます
    # クラスメソッドは、ClassName.class_method と呼び出します
    # この中はクラスコンテキストになります
    def self.class_method
      puts @on_class_context # 見える. 一方、@instance_variable は見えない
    end

    private
    # private 宣言した以降のメソッドはプライベートメソッドとなり、
    # 同一インスタンス内からのみ呼出しが可能になります
    # 外部からの呼出しは NoMethodError となります
    def private_method
    end

    # デストラクタ
    # ないです。GC のタイミングで走る機構など言語レベルではありますが、
    # それよりも open のような execute around method pattern などで
    # 事後処理を保証するほうがよいでしょう
    # 実装は begin ensure の制御構造を使ってかんたんに行えます
  end
end

くわしくはリファレンスマニュアルを参照。

ん、グローバル変数?

$global_var

です。まず、見ないので唯一この説明の中でぐぐって調べました。

継承と Mix-in

  • 継承
    • 継承は単一継承です
    • 多重継承できないことの力の弱さは Mix-in が補います
    • 結果として、Ruby では概念の親子関係を表現するためだけに継承を使い、実装の共有は Mix-in で実現するという設計ができます
  • Mix-in
    • Ruby の module は namespace をつくる役割と、Mix-in による実装継承を行うための module を定義する役割のふたつを兼任しています

Matz による Mix-in の解説

ポリモーフィズムとダックタイピング

Ruby は動的型言語なので、Java のようなポリモーフィズムのための型の継承によるインターフェイスの保証というのが必要ありません。 これも継承の利用を少なくおさえている理由のひとつです。 interface 継承で型としてポリモーフィズムを保証するかわりに、Ruby では DuckTyping といわれるインスタンス重視のアプローチをとっています。 これはそのときに呼ばれたメソッドのシグネチャに対してインスタンスが振る舞えるなら、その型は問わないという呼出しメソッドごとのシグネチャだけを対象とした最小限の契約です。 (Perl もそうですね)

制御構造

その他の、条件分岐や繰り返し、例外についてはリファレンスマニュアルを参照。

注意点としては、Ruby では通常繰り返しの制御構造はほぼ使いません。 90% 以上が Array や Hash に対するメソッド呼出しでのイテレーションでまかなえるからです。 Array, Hash, Enumerable を使ったプログラミングに慣れましょう。

もっと Ruby を知りたい!

それパーフェクト Ruby に書いてるよ!

落ち穂拾い

特異クラス

Ruby のコードを読んでいると

class Hoge
  class << self
    def hello
      puts 'hello'
    end
  end
end

って出てきてびびるんだが、これはなんの暗号ですか?

続きはこちら。

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