1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
|
---
language: ruby
filename: learnruby.rb
contributors:
- ["David Underwood", "http://theflyingdeveloper.com"]
- ["Joel Walden", "http://joelwalden.net"]
- ["Luke Holder", "http://twitter.com/lukeholder"]
- ["Tristan Hume", "http://thume.ca/"]
- ["Nick LaMuro", "https://github.com/NickLaMuro"]
- ["Marcos Brizeno", "http://www.about.me/marcosbrizeno"]
- ["Ariel Krakowski", "http://www.learneroo.com"]
- ["Dzianis Dashkevich", "https://github.com/dskecse"]
- ["Levi Bostian", "https://github.com/levibostian"]
- ["Rahil Momin", "https://github.com/iamrahil"]
- ["Vinh Nguyen", "http://rubydaily.net"]
---
```ruby
# Đây là một comment
=begin
Đây là một comment nhiều dòng
Không ai dùng cách này
Bạn không nên dùng
=end
# Đầu tiên và quan trọng nhất: Mọi thứ là đối tượng.
# Các con số là các đối tượng.
3.class #=> Fixnum
3.to_s #=> "3"
# Một vài bài toán số học căn bản
1 + 1 #=> 2
8 - 1 #=> 7
10 * 2 #=> 20
35 / 5 #=> 7
2**5 #=> 32
# Số học vừa là các cú pháp thân thiện cho việc gọi
# một hàm trên một đối tượng
1.+(3) #=> 4
10.* 5 #=> 50
# Các giá trị đặc biệt là các đối tượng
nil # Ở đây không có gì để xem
true # luôn đúng
false # luôn sai
nil.class #=> Lớp Nil
true.class #=> Lớp True
false.class #=> Lớp False
# So sánh bằng
1 == 1 #=> true
2 == 1 #=> false
# So sánh không bằng
1 != 1 #=> false
2 != 1 #=> true
# Ngoài chính false, thì nil là một giá trị khác của false
!nil #=> true
!false #=> true
!0 #=> false
# Các loại so sánh khác
1 < 10 #=> true
1 > 10 #=> false
2 <= 2 #=> true
2 >= 2 #=> true
# Các toán tử logic
true && false #=> false
true || false #=> true
!true #=> false
# Có các cách khác của các toán tử logic với mức thấp hơn
# Chúng được sử dụng như các cấu trúc điều khiển luồng nối các mệnh đề
# với nhau cho đến khi một trong số chúng trả về đúng hoặc sai.
# `do_something_else` chỉ được gọi nếu như hàm `do_something` thành công.
do_something() and do_something_else()
# `log_error` chỉ được gọi nếu hàm `do_something` không thành công.
do_something() or log_error()
# Các chuỗi là các đối tượng
'I am a string'.class #=> String
"I am a string too".class #=> String
placeholder = 'use string interpolation'
"I can #{placeholder} when using double quoted strings"
#=> "I can use string interpolation when using double quoted strings"
# Nên đưa các chuỗi vào trong dấu nháy đơn
# Ngoài ra dấu nháy kép được sử dụng trong tính toán.
# Nối các chuỗi, nhưng không nối với các số.
'hello ' + 'world' #=> "hello world"
'hello ' + 3 #=> TypeError: can't convert Fixnum into String
'hello ' + 3.to_s #=> "hello 3"
# Xuất ra ngoài màn hình
puts "I'm printing!"
# Các biến
x = 25 #=> 25
x #=> 25
# Chú ý về việc gán các giá trị được trả về vào biến.
# Điều này có nghĩa là bạn có thể gán nhiều biến.
x = y = 10 #=> 10
x #=> 10
y #=> 10
# Theo quy ước, dùng snake_case cho các tên của biến.
snake_case = true
# Dùng để mô tả tên các biến
path_to_project_root = '/good/name/'
path = '/bad/name/'
# Ký tự (là các đối tượng)
# Các ký tự là bất biến, như các biến hằng số chỉ đến các số nguyên.
# Chúng thường xuyên được sử dụng thay cho các chuỗi để chuyển đổi các giá
# trị hiệu quả.
:pending.class #=> Symbol
status = :pending
status == :pending #=> true
status == 'pending' #=> false
status == :approved #=> false
# Các mảng
# Đây là một mảng
array = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5]
# Các mảng có thể chứa nhiều phần tử khác nhau
[1, 'hello', false] #=> [1, "hello", false]
# Có thể truy cập các giá trị của mảng thông qua các chỉ mục
array[0] #=> 1
array[12] #=> nil
# Giống như số học, sử dụng [biến] là một cú pháp thông dụng
array.[] 0 #=> 1
array.[] 12 #=> nil
# Lấy phần tử cuối cùng
array[-1] #=> 5
# Bắt đầu từ chỉ mục và số phần tử cần lấy
array[2, 3] #=> [3, 4, 5]
# Đảo ngược một mảng
a=[1,2,3]
a.reverse! #=> [3,2,1]
# Lấy một khoảng
array[1..3] #=> [2, 3, 4]
# Thêm phần tử vào mảng bằng cách này
array << 6 #=> [1, 2, 3, 4, 5, 6]
# Hoặc cách này
array.push(6) #=> [1, 2, 3, 4, 5, 6]
# Kiểm tra phần tử có tồn tại trong mảng
array.include?(1) #=> true
# Băm là phần chính của Ruby với các cặp khoá/giá trị
# Băm được biểu thị bằng dấu ngoặc nhọn:
hash = { 'color' => 'green', 'number' => 5 }
hash.keys #=> ['color', 'number']
# Băm có thể được truy cập nhanh chóng thông qua khoá
hash['color'] #=> 'green'
hash['number'] #=> 5
# Khoá không tồn tại sẽ trả về nil
hash['nothing here'] #=> nil
# Kể từ Ruby bản 1.9, đây là một cú pháp đặc biệt, sử dụng symbol như khoá
new_hash = { defcon: 3, action: true }
new_hash.keys #=> [:defcon, :action]
# Kiểm tra khoá hoặc giá trị có tồn tại hay không
new_hash.has_key?(:defcon) #=> true
new_hash.has_value?(3) #=> true
# Mẹo: Cả Mảng và Băm đều là Enumberable
# Chúng cùng chia sẻ rất nhiều phương thức hữu ích như each, map, count...
# Cấu trúc điều khiển
if true
'if statement'
elsif false
'else if, optional'
else
'else, also optional'
end
for counter in 1..5
puts "iteration #{counter}"
end
#=> iteration 1
#=> iteration 2
#=> iteration 3
#=> iteration 4
#=> iteration 5
# TUY NHIÊN, không ai sử dụng vòng lặp for.
# Thay vào đó, ban nên dùng phương thức "each" và truyền vào đó một khối.
# Một khối là một loạt các mã mà bạn có thể truyền
# cho một phương thức giống như each.
# Nó tương tự với lambda, các hàm ẩn danh hoặc closures trong các ngôn ngữ
# lập trình khác.
#
# Phương thức "each" cho một khoản sẽ chạy qua từng phần tử của khoảng đó.
# Khối được truyền vào là một số đếm như là tham số.
# Gọi một method "each" với một khối sẽ trông như thế này:
(1..5).each do |counter|
puts "iteration #{counter}"
end
#=> iteration 1
#=> iteration 2
#=> iteration 3
#=> iteration 4
#=> iteration 5
# Bạn cũng có thể bao khối trong các dấu ngoặc nhọn.
(1..5).each { |counter| puts "iteration #{counter}" }
# Các nội dung của cấu trúc dữ liệu cũng có thể được lặp bằng each.
array.each do |element|
puts "#{element} is part of the array"
end
hash.each do |key, value|
puts "#{key} is #{value}"
end
counter = 1
while counter <= 5 do
puts "iteration #{counter}"
counter += 1
end
#=> iteration 1
#=> iteration 2
#=> iteration 3
#=> iteration 4
#=> iteration 5
grade = 'B'
case grade
when 'A'
puts 'Way to go kiddo'
when 'B'
puts 'Better luck next time'
when 'C'
puts 'You can do better'
when 'D'
puts 'Scraping through'
when 'F'
puts 'You failed!'
else
puts 'Alternative grading system, eh?'
end
#=> "Better luck next time"
# Cases cũng được dùng cho các dãy
grade = 82
case grade
when 90..100
puts 'Hooray!'
when 80...90
puts 'OK job'
else
puts 'You failed!'
end
#=> "OK job"
# Xử lý ngoại lệ:
begin
# Code ở đây có thể sẽ đưa ra một ngoại lệ.
raise NoMemoryError, 'You ran out of memory.'
rescue NoMemoryError => exception_variable
puts 'NoMemoryError was raised', exception_variable
rescue RuntimeError => other_exception_variable
puts 'RuntimeError was raised now'
else
puts 'This runs if no exceptions were thrown at all'
ensure
puts 'This code always runs no matter what'
end
# Hàm
def double(x)
x * 2
end
# Hàm (và tất cả các khối) được mặc định giá trị trả về ở mệnh đề cuối.
double(2) #=> 4
# Dấu ngoặc là một tuỳ chọn cho một kết quả rõ ràng.
double 3 #=> 6
double double 3 #=> 12
def sum(x, y)
x + y
end
# Các đối số được chia cắt bởi dấu phẩy.
sum 3, 4 #=> 7
sum sum(3, 4), 5 #=> 12
# yield
# Tất cả các hàm có thể có một tham số tuỳ chọn.
# Nó có thể được gọi với từ khóa "yield".
def surround
puts '{'
yield
puts '}'
end
surround { puts 'hello world' }
# {
# hello world
# }
# Bạn có thể truyền một khối đến một hàm
# Dấu "&" được đánh dấu đến một khối
def guests(&block)
block.call 'some_argument'
end
# Bạn có thể truyền một danh sách các tham số, nó sẽ được chuyển thành mảng.
# Thông qua việc sử dụng dấu *.
def guests(*array)
array.each { |guest| puts guest }
end
# Định nghĩ một lớp thông qua từ khoá class.
class Human
# Một biến class. Nó được chia sẽ cho tất cả các instance của lớp này.
@@species = 'H. sapiens'
# Các khởi tạo căn bản
def initialize(name, age = 0)
# Gán đối số đến biến instance "name"
@name = name
# Nếu không có age, sẽ lấy giá trị mặc định trong danh sách đối số.
@age = age
end
# Hàm nhập giá trị căn bản
def name=(name)
@name = name
end
# Hàm lấy giá trị căn bản
def name
@name
end
# Các hàm trên có thể được gọn lại bằng cách dùng hàm attr_accessor
attr_accessor :name
# Các hàm nhận/lấy cũng có thể được tạo riêng như sau:
attr_reader :name
attr_writer :name
# Một hàm lớp dùng self để phân biệt với hàm instance.
# Nó chỉ có thể được gọi trên lớp.
def self.say(msg)
puts msg
end
def species
@@species
end
end
# Khởi tạo một lớp
jim = Human.new('Jim Halpert')
dwight = Human.new('Dwight K. Schrute')
# Hãy gọi một cặp các hàm.
jim.species #=> "H. sapiens"
jim.name #=> "Jim Halpert"
jim.name = "Jim Halpert II" #=> "Jim Halpert II"
jim.name #=> "Jim Halpert II"
dwight.species #=> "H. sapiens"
dwight.name #=> "Dwight K. Schrute"
# Gọi một hàm lớp
Human.say('Hi') #=> "Hi"
# Phạm vi của biến được định nghĩa bởi cách chúng ta đặt tên cho chúng.
# Các biến bắt đầu với dấu $ là biến toàn cục.
$var = "I'm a global var"
defined? $var #=> "global-variable"
# Các biến bắt đầu với dấu @ là biến phạm vi.
@var = "I'm an instance var"
defined? @var #=> "instance-variable"
# Các biến bắt đầu với dấu @@ có pham vi là trong một lớp.
@@var = "I'm a class var"
defined? @@var #=> "class variable"
# Các biến bắt đầu với ký tự viết hoa là biến hằng.
Var = "I'm a constant"
defined? Var #=> "constant"
# Lớp cũng là một đối tượng trong Ruby. Bởi vậy lớp có các biến instance.
# Biến lớp được chia sẽ trong lớp và các lớp kế thừa nó.
# Lớp cơ sở
class Human
@@foo = 0
def self.foo
@@foo
end
def self.foo=(value)
@@foo = value
end
end
# Lớp kế thừa
class Worker < Human
end
Human.foo # 0
Worker.foo # 0
Human.foo = 2 # 2
Worker.foo # 2
# Các biến lớp instance không được chia sẽ trong lớp kế thừa.
class Human
@bar = 0
def self.bar
@bar
end
def self.bar=(value)
@bar = value
end
end
class Doctor < Human
end
Human.bar # 0
Doctor.bar # nil
module ModuleExample
def foo
'foo'
end
end
# Include một module sẽ đưa các hàm của module thành instances của lớp.
# Extend một module sẽ đưa các hàm của module thành các biến của lớp.
class Person
include ModuleExample
end
class Book
extend ModuleExample
end
Person.foo # => NoMethodError: undefined method `foo' for Person:Class
Person.new.foo # => 'foo'
Book.foo # => 'foo'
Book.new.foo # => NoMethodError: undefined method `foo'
# Hàm hồi quy được thực hiện khi include và extend một module.
module ConcernExample
def self.included(base)
base.extend(ClassMethods)
base.send(:include, InstanceMethods)
end
module ClassMethods
def bar
'bar'
end
end
module InstanceMethods
def qux
'qux'
end
end
end
class Something
include ConcernExample
end
Something.bar # => 'bar'
Something.qux # => NoMethodError: undefined method `qux'
Something.new.bar # => NoMethodError: undefined method `bar'
Something.new.qux # => 'qux'
```
## Các nguồn tham khảo thêm.
- [Learn Ruby by Example with Challenges](http://www.learneroo.com/modules/61/nodes/338) - A variant of this reference with in-browser challenges.
- [Official Documentation](http://www.ruby-doc.org/core-2.1.1/)
- [Ruby from other languages](https://www.ruby-lang.org/en/documentation/ruby-from-other-languages/)
- [Programming Ruby](http://www.amazon.com/Programming-Ruby-1-9-2-0-Programmers/dp/1937785491/) - An older [free edition](http://ruby-doc.com/docs/ProgrammingRuby/) is available online.
- [Ruby Style Guide](https://github.com/bbatsov/ruby-style-guide) - A community-driven Ruby coding style guide.
|