Edited at

Road to ruby silver (part2)

More than 1 year has passed since last update.

This is just some note for who want to get Ruby Silver certification. :)

Part 1


2.3. String (文字列)

a = "abcd"

p a → "abcd"
b = "ab""cd"
p b → "abcd"
b = "ab" 'cd'
p b → "abcd"

a = 1

p "a = #{a}"
→ a = 1
p 'a = #{a}'
→ a = \#{a}

"100".to_i → 100

"1.9".to_f → 1.9
"10a5".to_i → 10
"10a5".to_f → 10.0
"1.9".to_i → 1
"1.9.a".to_f → 1.9
"1.9.9".to_f → 1.9


Use \ notation

Content
Means

\x
?

\n
new line

\r
?

\f
?

\a
bell

\s
?

\nnn
Octor notation (n: 0 ~ 7)

\xnn
Hexa notation (n: 0-9, a-f)

\C-x
Control + x (x is ASCII chacter)

\M-x
Meta + x (x is ASCII chacter)

\M-\C-x
Meta + Control + x (x is ASCII chacter)

"\101" → "A" (in octal)

"\x41" → "A" (in hexa)


Different between p, puts, print

2.3.0 :035 > p "a\b"

"a\b"
=> "a\b"

2.3.0 :036 > print "a\nb"
a
b => nil

2.3.0 :037 > puts "a\nb"
a
b
=> nil


Here document

2.3.0 :037 > a = 1

2.3.0 :038 > query = <<-SQL
2.3.0 :039"> SELECT * FROM users where id = #{a};
2.3.0 :040"> SQL
=> "SELECT * FROM users where id = 1;\n"
2.3.0 :041 >
2.3.0 :042 > puts query
SELECT * FROM users where id = 1;
=> nil
2.3.0 :043 > p query
"SELECT * FROM users where id = 1;\n"

Different betwwen double quotes and single quotes is explained in here too.

2.3.0 :009 > a = 1

2.3.0 :010 > query = <<-'SQL'
2.3.0 :011'> SELECT * FROM users
2.3.0 :012'> where id = #{a};
2.3.0 :013'> SQL
=> "SELECT * FROM users\nwhere id = \#{a};\n"
2.3.0 :014 > puts query
SELECT * FROM users
where id = #{a};
=> nil

2.3.0 :015 > query = <<-"SQL"
2.3.0 :016"> SELECT * FROM users
2.3.0 :017"> where id = #{a};
2.3.0 :018"> SQL
=> "SELECT * FROM users\nwhere id = 1;\n"
2.3.0 :019 > puts query
SELECT * FROM users
where id = 1;
=> nil


Percent notation

2.3.0 :028 > a = %*abcdef*

=> "abcdef"
2.3.0 :029 > p a
"abcdef"
=> "abcdef

2.3.0 :026 > a = %*"abcdef"*
=> "\"abcdef\""
2.3.0 :027 > p a
"\"abcdef\""
=> "\"abcdef\""

2.3.0 :035 > a = %[abcdef]

=> "abcdef"
2.3.0 :036 > p a
"abcdef"
=> "abcdef"

2.3.0 :037 > a = %["abcdef"]
=> "\"abcdef\""
2.3.0 :038 > p a
"\"abcdef\""
=> "\"abcdef\""

All percent notation formats:

Format
The value will be generated
Example

%
Double quote
(1)

%Q
Double quote
(2)

%q
Single quote
(3)

%s
Symbol
(4)

%W
Array
(5)

%w
Array (Same with %W)
(6)

%s
Export command
(7)

%r
Regular expression
(8)

a = 1


2.3.0 :056 > test = %*"#{a}"*
=> "\"1\""
2.3.0 :057 > p test
"\"1\""

2.3.0 :058 > test = %*'#{a}'*
=> "'1'"
2.3.0 :059 > p test
"'1'"


2.3.0 :060 > test = %Q!#{a}!
=> "1"
2.3.0 :061 > p test
"1"

2.3.0 :064 > test = %Q!'#{a}'!
=> "'1'"
2.3.0 :065 > p test
"'1'"


2.3.0 :066 > test = %q!'#{a}'!
=> "'\#{a}'"
2.3.0 :067 > p test
"'\#{a}'"

2.3.0 :068 > test = %q!"#{a}"!
=> "\"\#{a}\""
2.3.0 :069 > p test
"\"\#{a}\""


2.3.0 :070 > test = %s!"#{a}"!
=> :"\"\#{a}\""
2.3.0 :071 > p test
:"\"\#{a}\""


2.3.0 :074 > test = %W('a' "b" 'c' "d")
=> ["'a'", "\"b\"", "'c'", "\"d\""]


2.3.0 :075 > test = %w('a' "b" 'c' "d")
=> ["'a'", "\"b\"", "'c'", "\"d\""]


2.3.0 :084 > %x*ls*
=> "chapter3.md\n"
(Run ls command and print the output)


2.3.0 :086 > %r*(a-9)+*
=> /(a-9)+/


Operater

2.3.0 :087 > a = "ru" + "by"

=> "ruby"
2.3.0 :088 > a * 3
=> "rubyrubyruby"
2.3.0 :089 > 3 * a
TypeError: String can't be coerced into Fixnum

2.3.0 :090 > a = "ru"
=> "ru"
2.3.0 :091 > a << "by"
=> "ruby"
2.3.0 :092 > p a
"ruby"

Comparison

"a" < "b" → true

"ab" < "ac" → true
"ab" < "abc" → true
"Ab" == "Ab" → true
"Ab" <=> "Ab" → 0

Length and size of string

NOTE: There are some differents between different encoding

"abcdef".length → 6

"日本語".encoding → #<Encoding:UTF-8>
"日本語".length → 3


Print with format: sprintf

Same with printf of C language

# Radices format

sprintf("result: %#b", 12) → "result: 0b1100" (binary)
sprintf("result: %#o", 12) → "result: 014" (octor)
sprintf("result: %#x", 12) → "result: 0xC" (hexa)
sprintf("result: %#X", 12) → "result: 0xC" (Hexa)

# Number of digits
sprintf("result: %02d", 1) → "result: 01"
sprintf("result: %02d", 123) → "result: 123"
sprintf("result: %05.5f", 123.2345678) → "result: 123.23457" → rounded

Other way: use % symbol

"result: %#b" % 12  → "result: 0b1100"

"result: %05.5f" % 123.2345678 → "result: 123.23457" → rounded


2.4. Symbol


Generation ways:

foo1 = :"foo1"  → :foo1

foo2 = :"#{foo1}foo2" → :foo1foo2
foo3 = :'foo3' → foo3
foo4 = :foo4 → foo4
foo5 = :"foo1 foo2" → :"foo1 foo2"
foo6 = %s*foo6* → :foo6
foo7 = "foo7".to_sym → :foo7


Different between symbol and string

"foo1".object_id → 70300729983460 # 1st time

"foo1".object_id → 70300733581760 # 2nd time
→ Always create new string object after called string

"foo1" == "foo1" → true
"foo1".equal? "foo1" → false

:foo1.object_id → 1154268 # 1st time
:foo1.object_id → 1154268 # 2nd time
→ Create symbol object only 1 time

:foo1 == :foo1 → true
:foo1.equal? :foo1 → true

eql?

"foo1".eql? "foo1" → true

1.0 == 1 → true
(1.0).eql? 1 → false
(1.0).eql? 1.0 → true

"foo1".equal? "foo1" → false
(1.0).equal? 1 → false
(1.0).equal? 1.0 → true


2.5. Variables and value of its

v1 = "test"

v2 = v1

v1.equal? v2 → true

v1 += "test 2"
p v1 → "testtest 2"
p v2 → "test"

Parameter's value in function


def func v1
v1.object_id
end

v1 = "test"
v1.object_id → 70300726236340
func v1 → 70300726236340


def func v1
p v1.object_id
v1 += "test 2"
v1.object_id
end

v1 = "test"
v1.object_id → 70300737948960
func v1 → 70300726215520
v1 → "test"

Destruction method sample

v1 = "test1"

v2 = v1
v1.chop
p v1 → "test1"
p v2 → "test1"

v1.chop!
p v1 → "test"
p v2 → "test"


2.6. Array (配列)


array = Array.new(2){|index| index + 1}
→ [1, 2]


array = Array.new(2, "a")
→ ["a", "a"]
array[0].object_id → 70300726074660
array[1].object_id → 70300726074660
array[0].replace("b")
p a
→ ["b", "b"]


array = ["a", "a"]
array[0].object_id → 70300725957160
array[1].object_id → 70300725957140
array[0].replace("b")
p array
→ ["b", "a"]


Subscript operator(添字演算子)


array = [1, 2, 3, 4]
array[-1] → 4
array[3] → 4
array[-4] → 1
array[0] → 1


array = [0, 1, 2, 3, 4, 5]
array1 = array[2, 3] # 2: from_index, 3: length of new array
→ [2, 3, 4]
p array
→ [0, 1, 2, 3, 4, 5]
p array1
→ [2, 3, 4]


a = [0, 1, 2, 3, 4]
a[1, 3] = "a" # 1: from_index, 3: number of elements will be earsed
p a
→ [0, "a", 4]


a = [0, 1, 2, 3, 4]
a[1, 3] = ["a", "b"]
p a
→ [0, "a", "b", 4]


a = [0, 1, 2, 3, 4]
a[1, 3] = "a", "b", "c", "d", "e"
p a
→ [0, "a", "b", "c", "d", "e", 4]


Some ways to set value


2.3.0 :197 > a, b, c = 1, 2, 3
=> [1, 2, 3]
2.3.0 :198 > a
=> 1
2.3.0 :199 > b
=> 2
2.3.0 :200 > c
=> 3


2.3.0 :201 > def foo
2.3.0 :202?> return 1, 2, 3
2.3.0 :203?> end
=> :foo
2.3.0 :205 > a, b, c = foo
=> [1, 2, 3]
2.3.0 :206 > a
=> 1
2.3.0 :207 > b
=> 2
2.3.0 :208 > c
=> 3
2.3.0 :209 > a, b, c, d = foo
=> [1, 2, 3]
2.3.0 :210 > d


2.3.0 :211 > a, b, c = [1, 2, 3]
=> [1, 2, 3]
2.3.0 :212 > a
=> 1
2.3.0 :213 > b
=> 2
2.3.0 :214 > c
=> 3

2.3.0 :215 > (a, b), c = [1, 2], 3
=> [[1, 2], 3]
2.3.0 :216 > a
=> 1
2.3.0 :217 > b
=> 2
2.3.0 :218 > c
=> 3


2.3.0 :219 > a = 1, 2, 3
=> [1, 2, 3]
2.3.0 :220 > a
=> [1, 2, 3]


2.3.0 :221 > a, *b = 1, 2, 3, 4
=> [1, 2, 3, 4]
2.3.0 :222 > a
=> 1
2.3.0 :223 > b
=> [2, 3, 4]

2.3.0 :224 > a, *b, c = 1, 2, 3, 4
=> [1, 2, 3, 4]
2.3.0 :225 > a
=> 1
2.3.0 :226 > b
=> [2, 3]
2.3.0 :227 > c
=> 4

a, *b, *c = 1, 2, 3, 4, 5, 6
→ SyntaxError


def foo1 a, *b
foo2 *b
end

def foo2 c, *d
d
end

foo1(1, 2, 3) → [3]
foo1(1, 2, 3, 4) → [3, 4]


Operate with array

a = [1, 1, 2, 2]

b = [2, 2, 3, 4]


a & b → [2]
a | b → [1, 2, 3, 4]
b | a → [2, 3, 4, 1]


a + b → [1, 1, 2, 2, 2, 2, 3, 4]
b + a → [2, 2, 3, 4, 1, 1, 2, 2]
a - b → [1, 1]
b - a → [3, 4]

a - [1] → [2, 2]


[1, 2] * 3 → [1, 2, 1, 2, 1, 2]
[1, 2, 3] * "/" → "1/2/3"
[1, 2, 3].join("/") → "1/2/3"


for and each


for i in [1, 2, 3]
p i
end
→ ok


for i, j in [[1, 2], [3, 4]]
p i+ j
end

→ ok


for i in [1, 2, 3]
bar = i
end
p bar
→ 3


[1, 2, 3].each do |i|
bar = i
end
p bar
→ NameError


2.7. Hash


2.3.0 :005 > hash = Hash.new(4) # 4 is default value
=> {}
2.3.0 :006 > hash
=> {}
2.3.0 :007 > hash[:test]
=> 4
2.3.0 :008 > hash[:test1]
=> 4

2.3.0 :012 > a = Hash[:test1, 1, :test2, 2]
=> {:test1=>1, :test2=>2}1, 1, :test2, 2]


def foo a, b, c, d
c
end

foo(1, 2, foo1: 1, foo2: 1)
→ ArgumentError: wrong number of arguments (given 3, expected 4)

foo(1, 2, {foo1: 1, foo2: 2}, "d")
→ {:foo1 => 1, :foo2 => 2}


2.8. Range


(1..5).include? 3 → true
(1..5).include? 6 → false
(1..5).include? 5 → true
(1...5).include? 5 → false
(1...5).include? 1 → true


(1..5) == 3 → false
(1..5) === 3 → true
(1..5) === 5 → true
(1..5) === 6 → false
(1...5) === 5 → false
(1...5) === 1 → true


a = "abcdef"
a[1] → "b"
a[1..2] → "bc"
a[1..2] → "b"


case


case condition
when value1
...
when value2
...
else
...
end


case condition
when value1 then; <<command>>
when value2 then; <<command>>
else <<command>>
end

Sample:

case 7
when 1..5 then; p 1
when 5..10 then; p 2
end
→ 2


while, until


while <<condition>> do
...
end


begin
...
end while <<condition>>

Sample:

i = 0
begin
p i
i += 1
end while(1..4) === i


until <<condition>> do
...
end


2.9. RegularExpression (正規表現)


/Ruby/ → /Ruby/
%r(Ruby) → /Ruby/
Regexp.new "Ruby" → /Ruby/


/Ruby/ === "I love Ruby"
→ true
"I love Ruby" === /Ruby/
→ false


/Ruby/ =~ "Version of Ruby: 2.3"
→ 11
"Version of Ruby: 2.3" =~ /Ruby/
→ 11

$` → "Version of "
$& → "Ruby"
$' → ": 2.3"


2.10. Output command (コマンド出力)

`date`

%x(date)


2.11. Block and Proc


Block

def func x

x + yield
end

func(3){ 2 }
→ 5

func(3)
→ LocalJumpError: no block given (yield)

def func x
x
end

func(3) {2}
→ 3

def func y

y + yield
end

func(1){x = 2}

p x
→ NameError: undefined local variable or method `x'

x = 2
func(1){x += 2} → 5

x → 4

def func a, b

a + yield(b, 3)
end

func(1, 2){|x, y| x + y}
→ 6

def func

return 1 if block_given?
0
end

func(){} → 1
func → 0


Proc

Block become object → proc

proc = Proc.new{|x| p x}

proc.call(1)
→ 1


  • Use proc in block

def func x

x + yield
end

proc = Proc.new{2}
func(2, &proc)
→ 4


  • Use block in proc

def func x, &proc

x + proc.call
end

func(1){2}
→ 3


  • lambda

lmd = lambda{|x| p x}

lmd.call(3)
→ 3

★ Different between lambda and proc


def func
proc = Proc.new{return 1}
proc.call
2 # do not run to here
end

func → 1

def func2
lmd = lambda{return 1}
lmd.call
2 # run to here
end

func2 → 2


p1 = Proc.new{|x, y| y}
p p1.call(1)
→ nil

l1 = lambda{|x, y| y}
p l1.call(1)
→ ArgumentError


Some method using block


  • each

  • each_with_index

  • each_key


  • upto, downto

  • times


Thread

t = Thread.new do

p "start"
sleep 5
p "end"
end

p "wait"
t.join

3.times do |i|

Thread.start(i) do |index|
p "Thread-#{index} start"
end
end


2.12. Loop break systax (脱出構文)


  • next

  • redo


2.13. Exception

raise ArgumentError, "message"

→ ArgumentError: message

raise ArgumentError.new, "message"
→ ArgumentError: message

err = ArgumentError.new("message")
raise err
→ ArgumentError: message

raise "message"
→ RuntimeError: message


  • Catch exception


begin
1 / 0
1
rescue
0
end

→ 0


b2.3.0 :141 > begin
2.3.0 :142 > p 1
2.3.0 :143?> rescue
2.3.0 :144?> p 0
2.3.0 :145?> else
2.3.0 :146 > p 2
2.3.0 :147?> ensure
2.3.0 :148 > p 3
2.3.0 :149?> end
1
2
3
=> 2


1 / 0 rescue p 1
→ 1

2.3.0 :151 > begin

2.3.0 :152 > 1 / 0
2.3.0 :153?> rescue ZeroDivisionError
2.3.0 :154?> p $!.class
2.3.0 :155?> raise
2.3.0 :156?> end
ZeroDivisionError
ZeroDivisionError: divided by 0

a = 0

begin
b = 1 / a
rescue ZeroDivisionError
a += 1
retry
ensure
p b
end

=> 1


Exception class structure


  • Exception


    • ScriptError

    • SyntaxError

    • SignalException

    • StandardError

    • ArgumentError

    • RuntimeError

    • NameError


      • NoMethodError



    • ZeroDivisionError




Catch, throw

def foo

throw :exit
end

catch(:exit) {
a = 5
foo
a = 3 → this is not executed
}

p a
→ NameError: undefined local variable or method `a'