LoginSignup
32

More than 5 years have passed since last update.

Ruby をざっとペロる

Last updated at Posted at 2015-04-09

a39454cc.jpg

## 2016.8.28修正中

結構ひどい間違い多い。徐々に修正していきます

環境

  • OS X Yosemite 10.10.1
  • ruby 2.2.1p85

はじめに

ruby についてざーっとまとめてみました。サンプルのコードは動かしながら書いているので動作的には大丈夫だと思いますが、1週間で纏めきるという時限付きでの投稿なので日本語がぐだぐだで説明になっていない場所もあるかもです。クリティカルにダメな表現・内容がございましたら、コメントにてご一報いただけると幸いです。
 
ってことで、ひと通りの文法をざっくりと理解するために irb というツールも利用するよ。irb はざっくり言っちゃえばターミナル等から ruby を 入力/実行 するツールだよ

irb の使い方

ターミナルで以下のように入力

$ irb

irb(main):001:0>

irb(main):001:0> 的な状態になったら、入力を待機している状態だよ

puts と p

puts メソッドは改行付きで出力するよ。System.out.println 的な役割。

p メソッドは、デバッグ用の出力メソッドだよ。より詳細な情報を出力してくれるんだ。console.log みたいなもんだね!

Hello World

以下のように、puts "Hello World" と入力するよ

irb(main):001:0> puts "Hello World"

Hello World
=> nil

ファイルの実行

ファイルは ruby ファイル名 で実行できるよ。仮に hello.rb というファイルを作って以下のように書くよ。(*このポストではファイル実行の結果をわかりやすくするために、ファイル内に標準出力するための puts だの p が呼ばれた結果に => を使うことにするよ)

puts "Hello World"

ターミナルでは以下のようにして実行するよ

$ ruby hello.rb

=> Hello World

コメント

一行コメントは # で、ブロックコメントは =begin と =end を使うよ

# 一行コメント

=begin

ぺろぺろ
ぺろりん
ぺーろぺろ

=end

変数

Ruby には 変数宣言 をするための構文がないよ。また、変数名(の一文字目)によって変数の種類が決まるよ

先頭文字 種類 デフォルト値
小文字または _ ローカル変数 参照する前に代入が必要
@ インスタンス変数 nil
@@ クラス変数 参照する前に代入が必要
$ グローバル変数 nil
大文字 定数 参照する前に代入が必要

各種変数のスコープについて

変数 説明
ローカル変数 スコープを「ブロック」、「メソッド」、「クラス・モジュール定義」各定義の終わりまでとした、一番スコープの狭い変数
インスタンス変数 特定のオブジェクトに属する変数。同じオブジェクトのメソッド間で共有。そのオブジェクトの状態を表すなどに利用
クラス変数 基本的にはクラスに属する変数。子孫クラス、それらのクラスのすべてのインスタンス間で共有される。Java や C# でいう static変数
定数 状態が変更されない変数。Java で言うと final を使った変数。C# で言うと const を使った変数。

数値

Rubyの組み込みの数値型は「整数(Integer)」オブジェクトと「浮動小数点数(Float)」オブジェクトに分類される。なので 10 はInteger(のサブクラスであるFixnumクラス)のオブジェクトで 10.5 は Float のオブジェクトだよ

i = 10
puts i.class

f = 0.1
puts f.class

=> Fixnum
=> Float

数値演算

演算 説明
加算 5 + 3 足し算。結果は 8
減算 5 - 3 引き算。結果は 2
乗算 5 * 3 掛け算。結果は 15
整数除算 5 / 3 整数での割り算。結果は 1
実数除算 5.0 / 3 実数での割り算。結果は 1.6666666666666667
べき乗 5 ** 3 5 の 3乗。結果は 125
剰余 5 % 3 5 ÷ 3 の 余り。結果は 2

インクリメント、デクリメント

Ruby には C言語系に見られる インクリメント演算子(++) や デクリメント演算子 (--) がない。ってことで「自己代入演算子」やメソッドを利用する

# 自己代入演算子の例
i = 0
i += 1

# next メソッドを利用した例
i.next

*ちなみに nextメソッド は i自体 を書き換えないよ。

i = 0
p i.next
puts i

=> 1
=> 0

代表的な自己代入演算子

演算子 意味
+= i += 1 i = i + 1
-= i -= 1 i = i - 1
*= i *= 2 i = i * 2
/= i /= 2 i = i / 2
%= i %= 2 i = i % 2
**= i **= 2 i = i ** 2

比較演算子

演算子 意味 結果
== 同値 1 == 1 true
!= 非同値 1 != 1 false
< 小なり 1 < 2 true
> 大なり 1 > 2 false
<= 小なりイコール 1 <= 2 true
>= 大なりイコール 2 >= 1 true

文字列

文字列リテラルは、二重引用符「"」または一重引用符「'」で表現したい文字列の内容を囲う。

dq = "Hello World"
puts dq

=> Hello World

sq = 'Hello World'
puts sq

=> Hello World 

バックスラッシュを使った代表的なエスケープ文字

記法 表現される文字
\t タブ
\n 改行
\s 空白
\" 二重引用符
\' 一重引用符
\\ バックスラッシュ

エスケープ文字を文字列内で使うには

エスケープ文字を文字列内で表現するためには、「"」二重引用符を利用します。

hoge = "Hello \n World"
puts hoge

=>Hello
=> World

文字列内で変数を展開するには

文字列内で変数を展開するには、「"」二重引用符を利用します。また、変数は #{変数名} で展開します。

hoge = "Hello"
puts "#{hoge} World"

=> Hello World

#{} のカッコでくくられた部分は Ruby の式として解釈される。

i = 5
puts "5x5=#{i * 5}"

=> 5x5=25

puts "#{Time.now}"

=>2015-01-01 00:0:00 +0900

バッククォート文字列

文字列をバッククォートでくくると、くくられた中身をシェルとして実行し、コマンドが出力した内容を文字列にして返す

puts `pwd`

=> /Users/chrowa3

ヒアドキュメント

puts <<EOS

    Hello
        World
            Ruby

EOS

=>  Hello
=>      World
=>          Ruby

正規表現

正規表現リテラルは / と / で囲う。例えばこんな感じ

/\d{3}-\d{4}/

これを簡単にマッチさせるなら =~ 演算子を使う

puts /\d{3}-\d{4}/ =~ "郵便番号:192-0041"

=> 5

返ってきた数値は先頭文字列を 0 としたオフセット値を返すよ。上記例だと 6文字目 からマッチしているので、5が返る。

ちなみにキャプチャはこんな感じで

if /(\d{3}-\d{4})/ =~ "郵便番号:192-0041"
    puts $1
end

=> 192-0041

マッチしなかったらnilが返ってくるよ

文字列の「部分」へのアクセス

添字を使う

s = "sos"
puts s[1]

=> o

Rubyの文字列は mutable(変更可能) なので部分的な更新も可能

s = "SOS"
s[1] = "N"
puts s

=> SNS

文字列を部分的に取得する時、インデックスに2つ目の数値を与えるとその数値分の文字をとる

str = "hoge"
p str[0,1]

=> "h"

p str[0,2]

=> "ho"

文字列結合

加算演算子 + を使う

puts "Hello" + "World"

=> HelloWorld

反復

乗算演算子で繰り返すことが可能

puts "NO!" * 3

=> NO!NO!NO!

分解

splitメソッドを使って文字列を配列に分解。引数に正規表現を渡すとそのパターンにマッチする文字列を区切り文字とし分割する。

p "a,b,c,d".split(/,/)

=> ["a","b","c","d"]

比較

文字列は比較演算子で比較できる。文字列大小関係は辞書式となるよ。

"abc" == "abc"
=> true

"a" < "b"
=> true

"a" > "b"
=> false

各種メソッド(抜粋)

# 長さを取得
"abc".length
=> 3

# クラスを取得
"abc".class
=> String

# 空かどうか
"".empty?
=> true

# 整数型へ変換
"5".to_i
=> 5

"5".to_i.class
=> Fixnum

# インデックスを取得
"abcdefg".index("c")
=> 2

# 正規表現で置換 (2015.04.10 @scivola 氏に頂いたありがたいコメントを参考に修正)
"box".gsub(/[a-z]{2}(x)/) do
    "Fi#{$1}"
end
=> Fix

# 左右の空白を取り除く
" ab c ".strip
=> "ab c"

などなど。他にもいっぱい

文字列をペロる

"ペロペロペロリン".each_char do |c|
    p c
end

=> "ペ"
=> "ロ"
=> "ペ"
=> "ロ"
=> "ペ"
=> "ロ"
=> "リ"
=> "ン"

シンボル

シンボルを理解するためには、まず文字列同士を比較する次のようなコードを見ていったほうが理解が早いかも

str1 = "a"
str2 = "a"

p str1 == str2
p str1.equal? str2

=> true # 同値
=> false # 同じオブジェクトではない

equal? は「同じオブジェクトかどうか」を調べるメソッドだよ。このコードからわかるのは、文字列は「同じ値でも同じオブジェクトとは限らない」ということ。

ただし、次のコードでは同一になる。(当たり前かw

str1 = "a"
str2 = str1

p str1 == str2
p str1.equal? str2

=> true # 同値
=> true # 同じオブジェクト

「同じオブジェクトとは限らない」ということは、オブジェクト自体の identity が違うということ。仮に object_id を見てみるとこんな感じになる。

str1 = "a"
str2 = "a"

p str1.object_id
p str2.object_id

=> 70231276141340
=> 70231276141320

僕の環境では str1 の object_id は「70231276141340」、str2 の object_id は「70231276141320」となったよ。要するにまったく別物なんだってこと。

では、シンボルではどうだろうか。シンボルは : コロンを使ってつくる。次のコードで諸々を一気に確認してみよう。

sym1 = :a
sym2 = :a

p sym1 == sym2
p sym1.equal? sym2
p sym1.object_id
p sym2.object_id

=> true
=> true
=> 702428
=> 702428

同値判定、同オブジェクトかの判定、object_id の一致を見て同じものだということがわかるよ。

ってことでシンボルは「値が同値であれば必ず同一のオブジェクト」だということがわかるよ。

まとめると

  • Rubyの内部実装では、識別子を整数で管理しており、文字列として処理(捜索)するよりも速度面で有利になる。シンボルはその内部実装のような仕組みをコード上で表現したもの。だから文字列同士の比較などよりも数値の比較になるのでよっぽど速い。見た目は文字列な整数値、的なイメージ
  • 唯一性を維持するため、シンボルは文字列と違い変更不可能(immutable)であり、同値ならば必ず同一のオブジェクトとなる。
  • これらの性質からハッシュ(連想配列)のキーなどに利用される

配列

配列のつくりかた

[]ブラケットを使う

arr = ['a','b','c']
=> ["a","b","c"]

要素の型は自由

arr = [5,'abc',{'key'=>'value'}]
=> [5, "abc", {"key" => "value"}]

当然多次元も

wey = [1,2,3]
hey = [wey,wey,wey]

p hey
=> [[1,2,3],[1,2,3],[1,2,3]]

添字参照

配列の要素は 0 から始まる番号でインデックスされています。[]ブラケットとインデックスで各要素にアクセスできます。

arr = ['a','b','c']
p arr[2]

=> "c"

インデックスを 負の数 で指定すると、配列要素の最後からの参照となる

arr = ['a','b','c']
p arr[-1]

=> "c"

インデックスは変数でもよいよ

arr = ['a','b','c']
i = 2
p arr[i]

=> "c"

インデックスに続いて、整数値を指定すると「そのインデックスからの整数値分を要素とした新しい配列を生成」するよ

arr = ['a','b','c']
p arr[1,2]

=> ["b","c"]

同じようなことを「範囲演算子」を使って実現できるよ。範囲演算子は「..」と「...」があり、たとえば 0..10 は「0から10」までを示すよ。0...10 は「0から9」までを示すよ。「含む、含まない」の違いだね。

arr = ['a','b','c']
p arr[1..2]

=> ["b","c"]

配列は参照を保持

添字での参照で返ってくる値は配列が保持している「オブジェクトへの参照」だよ。
しかし、[]ブラケットに 範囲演算子 などを指定して新たに別の配列を用意する場合はあくまでも「あらたな配列を生成」しているので、生成した配列を操作しても元となる配列には影響はありません。

arr = ['a','b','c']
newArr = arr[1..2]
newArr[0] = "hey!"

p arr
p newArr

=> ["a","b","c"]
=> ["hey!","c"]

代入

代入演算子 =(イコール)を使って代入。各要素へは[](ブラケット)へインデックスを指定するよ

arr['a','b','c']
arr[1] = 'd'
p arr

=> ["a","d","c"]

比較

配列同士を比較した場合、同一インデックスの参照先が同一の値を持っていれば true になるよ

foo = [2,3,4]
bar = [2,3,4]

p foo == bar

=> true

値の内容が一緒でも、インデックスが違えば false になるよ

foo = [2,3,4]
bar = [4,3,2]

p foo == bar

=> false

各種メソッド(抜粋)

# 前提となるサンプルの配列
arr = [5,4,3,2,2,1]

# 配列の要素数
p arr.length
p arr.size

=> 4

# 要素の参照先に指定した値を含むか
p arr.include? 3

=> true

# 配列のソート
p arr.sort

=> [2,3,3,4]

# 要素の参照先に重複した値があればそれを削除した状態の新しい配列を返す
p arr.uniq

=> [4,3,2]

# 先頭の要素を取り出す
a = arr.shift
p a
p arr

=> 4
=> [3,2,2]

# 末尾の要素を取り出す
a = arr.pop
p a
p arr

=> 2
=> [3,2]

# 末尾に要素を追加
arr.push("hoge")
p arr

=> [3,2,"hoge"]

配列をペロる

eachメソッドを使う

arr = ['a','b','c']

arr.each do |c|
    p c
end

=> "a"
=> "b"
=> "c"

do ~ end はブロックを表すよ。|と| はパラメータを渡す部分だと思ってよいよ。この each メソッドでは、arr を一つ一つ舐めていき、その一つ一つ が c に代入されていくっていうイメージ。

ハッシュ(連想配列)

ハッシュのつくりかた

{} カーリーブラケットを使う

user = { "name" => "chrowa3" , "age" => 16 }
=> {"name"=>"chrowa3", "age"=>16}

ruby 1.9 からは : コロンを使ってつくれるよ!これは嬉しい。key: valuekey:はハッシュ

user = { name: "chrowa3" , age: 16 }
=> {:name=>"chrowa3", :age=>16}

参照

ハッシュは配列のように、範囲指定などができない分単純な参照しかないよ。[]ブラケットにキーとなるオブジェクトを指定するだけだよ。

user = { "name" => "chrowa3" , "age" => 16 }
p user["name"]

=> "chrowa3"

user = { name: "chrowa3" , age: 16 }
p user[:name]

=> "chrowa3"

コロンを使った記法は、ruby 1.9 からの導入ですが、シンボルとなりうる Key と コロンとの間にスペースがあると Syntax error になるようです。

h = {a: 5}
p h

=> {:a=>5}

e = { a : 5 }
p e

=> syntax error, unexpected tSYMBEG, expecting keyword_do or '{' or '('

代入、更新

user = { name: "chrowa3" , age: 16 }
user[:name] = "PeroPero"

p user

=> {:name=>"PeroPero", :age=>16}

追加

user = { name: "chrowa3" , age: 16 }
user[:blood] = :b

p user

=> {:name=>"chrowa3", :age=>16, :blood=>:b}

比較

個人的にはこの機能結構強力だなーって思ったりします

h1 = {a:1,b:5}
h2 = {a:1,b:5}
h3 = {b:5,a:1}
h4 = {"a"=>1,"b"=>5}
p h1 == h2
p h1 == h3
p h1 == h4

=> true
=> true # 順序は関係ないってさ
=> false # シンボルと文字列は別物

キーが違ったり要素数が違えば false になるよ

各種メソッド

user = {
    name: "chrowa3",
    age: 15,
    blood: :b,
    job: "programmer",
    web: "http://webya.in"
}

p user.size

=> 5 #要素数
p user.keys

=> [:name, :age, :blood, :job, :web] # keyのみで構成された配列
p user.values

=>=> ["chrowa3", 15, :b, "programmer", "http://webya.in"] # value のみで構成された配列
p user.key?(:job)

=> true # 指定の key を含んでいるか
user.delete("age")
p user

=> {:name=>"chrowa3", :blood=>:b, :job=>"programmer", :web=>"http://webya.in"} # key age を削除
user.clear
p user

=> {} ハッシュの中身を削除

ハッシュをペロる

引数は2つの値を渡される。一つ目は Key。2つ目は Value

user.each do |key,value|
    p key.to_s + ":" + value.to_s
end

=> "name:chrowa3"
=> "age:15"
=> "blood:b"
=> "job:programmer"
=> "web:http://webya.in"

制御式

とりあえず使いそうなやつだけ書く。

if

# 構文
if 条件 then
    処理
else
    処理
end

Ruby での 真偽値

ruby での 偽 は false と nil のみ。0 や "" も true となる

イテレーターと脱出式

イテレーターには
* loop
* times
* upto

などがある。

# loop

loop do
    p "hoge"
end

p "hoge" を繰り返すよ。脱出式を使わない限り無限ループ。

# times
3.times do
    p "hoge"
end

=> "hoge"
=> "hoge"
=> "hoge"

times は内部にカウンタを引き渡してくれるよ

# times
3.times do |i|
    p "hoge" + i.to_s
end

=> "hoge0"
=> "hoge1"
=> "hoge2"

upto は オブジェクトを引数で指定した数値までカウントアップするよ。

# upto

3.upto(5) do |i|
    p i
end

=> 3
=> 4
=> 5

break

現在の繰り返し構造(while、for、loopなど)のもっとも内側から一つ外に脱出できるよ

i = 0
loop do
    i += 1
    p i
    if i == 5 then
        break
    end
end
p "complete!"

=> 1
=> 2
=> 3
=> 4
=> 5
=> "complete!"

他にも next や redo などの脱出式はあるけど割愛

例外処理

ruby での 例外処理は java に置き換えると、try が「begin」、throw が「raise」、catch が「rescue」、finaly が「ensure」となるよ。この全てを使った最小の例は以下のとおり

begin
    p "in begin"
    raise
rescue
    p "in rescue"
ensure
    p "in ensure"
end

p "end"

=> "in begin"
=> "catch"
=> "finaly"
=> "end

もういっこ例

begin
    p "in begin"
    raise Exception, "raise Exception,"
rescue Exception => e
    p "in rescue"
    p e.message
ensure
    p "in ensure"
end

p "end"

=> "in begin"
=> "in rescue"
=> "raise Exception"
=> "in ensure"
=> "end"

メソッド

定義

メソッドを定義するには def 式をつかうよ。

# 諸々省略した構文
def メソッド名
    処理
end

簡単なメソッドをつくって見よう

def m
    p "m was called to by chrowa3"
end

引数を指定してみるよ

def m name
    p "m was called to by " + name
end

引数は ,カンマ区切りで複数渡せるよ。

次に戻り値を指定してみようか。戻り値は return で指定するよ。

def m name
    return "m was called to by " + name
end

だたし、rubyでは最終的な式の結果を返すのでreturnは書かない習慣がある

def m name
    "m was called to by " + name
end

デフォルト値の指定はこんな感じ。

def m age,name = "nanashi"
    p "m was called to by " + name
    p name + " is " + age + "years old." 
end

呼び出し

メソッド名と必要な引数を指定して呼び出すよ。

def m age,name = "nanashi"
    p "m was called to by " + name + "."
    p name + " is " + age + "years old." 
end

m(5)

=> "m was called to by nanashi."
=> "nanashi is 5years old."

呼び出し時の()かっこは省略可能だよ

def m age,name = "nanashi"
    p "m was called to by " + name + "."
    p name + " is " + age + "years old." 
end

m 5

=> "m was called to by nanashi."
=> "nanashi is 5years old."

メソッドチェーンもjsばりに使えるよ

i = 12345

p i.to_s.length

=> 5

クラス

サンプルコードにモヤっとしないでね!( なんで Car クラスなんかにしちまったんだ... )

定義

class クラス名
    任意の式
end

インスタンスメソッド

クラスに def式 で定義する。

class Car
    def run
        p "Run"
    end
end

クラスメソッド

さっきの run をクラスメソッド(いわゆる static なメソッド)にするには def 式に クラス名をつける

class Car
    def Car.run
        p "Run"
    end
end

クラス名で指定するよりも self を使ったほうがちょっとエレガントよね

class Car
    def self.run
        p "Run"
    end
end

コンストラクタ

initialize という名前のメソッドを定義することにより、そのクラスをインスタンス化(new)したタイミングで呼び出され、オブジェクトの固有の状態を保持できるよ。

class Car

    def initialize carName
        @carName = carName  
    end

    def self.run
        p "Run"
    end

    def getCarName
        @carName
    end
end

この例では initialize が呼ばれた時に carName を初期化

インスタンス変数

インスタンス変数は @マークを使うよ。この例では @carName がそれにあたるよ。
また、インスタンス変数は直接アクセスが出来ないので、メソッド経由などの方法でアクセスする必要があるよ。

class Car

    def initialize carName
        @carName = carName  
    end

    def self.run
        p "Run"
    end

    def carName
        @carName
    end

    def carName=(name)
        @carName = name
    end
end

アクセサ

上記ののように単純なインスタンス変数へのアクセスならば、attr_accessorにインスタンス変数の名前をシンボルで渡してあげれば自動的に定義されるよ

class Car

    attr_accessor :carName

    def initialize(carName)
        @carName = carName
    end

    def self.run
        p "Run"
    end
end

外部から代入する必要がない場合は、attr_readerのみを使い、逆に代入だけ必要な場合はattr_writerを使いましょう

クラス変数

@@で定義するよ。これもメソッド経由などでのアクセスが必要だよ。オブジェクト間で共有されるよ。

class Car

  attr_accessor :carName

    def initialize(carName)
        @carName = carName
    end

    def self.run
        p "Run"
    end
end

myCar = Car.new('Benz')

アクセサを複数定義する場合にはカンマ区切りで列挙すればおk

new

クラスを実体化するには newメソッドを使うよ。

class Car
    ...処理
end

myCar = Car.new

new で指定したメソッドは initialize メソッドに引き渡されるよ。次の例ではこのクラスのインスタン変数 @carName に "Benz" を引き渡しているよ。

class Car
    attr_reader :carName
    def initialize carName
        @carName = carName  
    end

    def self.run
        p "Run"
    end
end

myCar = Car.new "Benz"

各呼び出し

class Car

    attr_accessor :carName

    def initialize carName
        @carName = carName  
    end

    def self.run
        p "Run"
    end
end

myCar = Car.new "Benz"

# インスタンス変数へのアクセス
p myCar.getName

=> "Benz"


# クラスメソッドを呼び出し
Car.run

=> "Run"

継承

ruby は 単一継承をサポートしています。クラス定義時、クラス名に < に続けて継承したいクラス名を指定することにより継承することになるよ。

class Vehicle
    ...処理
end

class Car < Vehicle
    ...処理
end

スーパークラスの呼び出し

super式は、親クラスの同名のメソッドを呼び出すよ。initialize メソッド内で呼べば親クラスの initilize メソッドを呼び出すよ。

class Vehicle
    attr_reader :otherName
    def initialize otherName
        @otherName = otherName
    end
end


class Car < Vehicle
    attr_reader :carName
    def initialize carName, otherName
        super otherName
        @carName = carName
    end

    def self.run
        p "Run"
    end
end

myCar = Car.new "Benz", "myBenz"
p myCar.carName
Car.run

p myCar.otherName

アクセス制限

===========2016.8.28 編集中===========

アクセス制限 説明
public どこからでも呼び出せる
protected そのクラス内とそのクラスを継承したクラスのインスタンスメソッドからの呼び出しのみ
private selfに対してしか呼び出せない

オーバーライド

クラスを継承した場合に、親クラスで定義されたメソッドと同じ名前で新しいメソッドを定義し直すことができるよ。これをオーバーライドっていうよ。
たとえば親クラスである、Vehicle に horn メソッドを追加したとしよう。

class Vehicle
    attr_reader :otherName
    def initialize otherName
        @otherName = otherName
    end
    def horn
        p "ぺっぺー"
    end
end

Vehicle を new して horn を呼べば「ぺっぺー」と表示される

v = Vehicle.new "R32"
v.horn

=> "ぺっぺー"

一方 Car クラスで horn を再定義してみるよ(注意:private なインスタンスメソッドよりも後に定義すると怒られるみたい。調査しておきます)

def horn
    "ぷっぷー"
end

.
. 省略
.

myCar.horn

=> "ぷっぷー"

ってことで、ざっペロ完了です。定数や、特異メソッド、特異クラス、ブロック、proc、yield など重要なトピックが抜けてますがそれはまた今度どこかで。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32