變數
以此例為例子
class Var
def print
puts $hh
end
$hh = "hh"
end
t = Var.new
t.print
替換以下變數
$name
: 全域變數. 結果: 正常
@name
: 實例變數, 作用僅限於 self 指示的物件. 結果: 相當於輸出 nil, 什麼東沒有
@@name
: 類別變數, 在 class 內使用, 如果另個物件繼承它的物件, 也可以使用 @@name
. 結果: 正常
name
: 區域變數 (小寫字母或底線開頭, 初始化前並沒有 nil 值). 結果: undefined local variable or method hh'
Name
: 常數 (大寫開頭, 不可重覆定義). 結果: 正常
結論 : 定義在 class 內的變數必須是 全域, 類別或常數
宣告
陣列
%w(i1 b2 c3 j4) # ["i1", "b2", "c3", "j4"]
arr = { # {:A => 1, :B => 2 }
'A' : 1,
'B' : 2,
}
基本 class 觀念
class Foo
def instance_method # instance method (可以用 self 取 instance 的值)
'instance_method 要先 new 才能使用'
end
def self.class_method # class method (無法用 self 取內部的值)
'slef.class_method 不能 new, 可直接使用'
end
def call_method
inside_method
end
protected
def inside_method
'Call 內部的 inside_method 不需加 `self.` prefix'
end
end
a = Foo.new
puts a.instance_method # instance_method 要先 new 才能使用
puts Foo.class_method # slef.class_method 不能 new, 可直接使用
puts a.call_method # Call 內部的 inside_method 不需加 `self.` prefix
判斷
0 及 empty 都是 TRUE, 只有 false 與 nil 才是 FALSE
是否為數值
9.9.integer?
數值是否在範圍裡面
(11..15).include? 15
15.between?(11, 15)
檔案相關
Check directory in existence, Create folder
require 'fileutils'
if File.directory?('/tmp/layer1')
puts "Folder exist !"
else
puts "Create folder ..."
FileUtils.mkpath('/tmp/layer1/layer2')
end
Check if a file exists
File.exist?('/tmp/ruby_test/send/sorry.mp3')
Getting path from full file path
2.0.0-p247 :001 > File.dirname("/tmp/ruby_test/send/qq.php")
=> "/tmp/ruby_test/send"
Getting filename from path
2.0.0-p247 :003 > File.basename("/tmp/ruby_test/send/qq.php")
=> "qq.php"
Integer & Float
小數第一位四捨五入
a = 633.633
a.round(1) # 633.6
次方
2 ** 3
絕對值
-5.abs # 5
取最近的整數/四捨五入
5.6.round # 6
取整數/無條件捨去
9.9.floor # 9
取整數/無條件進位
2312.22.ceil # 2313
下一個數
2.next # 3
二元運算
n & num
n | num
n ^ num (XOR)
n << num (向左位移)
n >> num (向右位移)
Rand
rand(1..10)
[true, false].sample
亂數
SecureRandom.random_number(99999999999) # 9997979524
建立 UUID
require 'securerandom' # 原生
SecureRandom.hex(20) # ac5d23f916dd83dcc495dc5f0b8b602942b635fa 長度會是你傳值的 2 倍
SecureRandom.base64(20) # WcLJKJzgibphbiXHKIeCsP8jtN8=
SecureRandom : This library is an interface for secure random number generator which is suitable for generating session key in HTTP cookies
字串處理
gsub
"hello".gsub(/[aeiou]/, '*') # "h*ll*"
"hello".gsub(/([aeiou])/, '<\1>') # "h<e>ll<o>"
"hello".gsub(/./) {|s| s.ord.to_s + ' '} # "104 101 108 108 111 "
"hello".gsub(/(?<foo>[aeiou])/, '{\k<foo>}') # "h{e}ll{o}"
'hello'.gsub(/[eo]/, 'e' => 3, 'o' => '*') # "h3ll*"
split
'C3-0803986E423F0C66DA56'.split('-') # ["C3", "0803986E423F0C66DA56"]
last word
'example'.last # e
取固定位置及長度的字串
a = "1234567890"
a[1..3] # 234
Hash
key 是否存在
genders.has_key?(:male)
value 是否存在
genders.value?(2)
刪除某個 key
a.delete('es')
刪除某個 value
hash.delete_if{|_,v| v == "2"}
Reverse key <-> value
Hash[h.to_a.collect(&:reverse)]
Find value and return key
h.key(value) # return key
Get all keys from Hash
h.keys
Sort
hash = {f: 4, a: 2, r: 1 }
hash.sort # => [[:a, 2], [:f, 4], [:r, 1]] # 這不是我們要的結果
hash.sort.to_h # => {:a=>2, :f=>4, :r=>1} , 這才是
兩個 hash 合併另種寫法
a = {"zh"=>1, "es"=>5}
b = {"zh"=>1, "qq"=>5}
a.merge(b) # {"zh"=>1, "es"=>5, "qq"=>5}
# 這個範例可以看的出它只比對 key,如果 key 一樣值不一樣,則會被後者的值覆蓋
a = {"zh"=>1, "es"=>5}
b = {"zh"=>1, "es"=>7}
a.merge(b) # {"zh"=>1, "es"=>7}
只取得 hash 裡面某些 key -> value
{a: 1, b: 2, c: 3, d: 4 }.slice(:a, :b)
{:a=>1, :b=>2}
定義 hash parameters
def instance_method(hash = {})
Call : a.instance_method aa: 'aa', bb: 'bb'
hash key 使用 integer 時注意 :
hash = {1: 'one'} # will not work
hash = {1 => 'one'} # will work
Array
是否為 array
array.is_a?(Array)
去除相同的值 :
[2,4,2,5,1].uniq # => [2, 4, 5, 1]
Array to Hash
a = ['apple', 'banana', 'mongo']
c = Hash[a.map { |e| [e.to_sym, e + ' !'] }]
=> {:apple=>"apple !", :banana=>"banana !", :mongo=>"mongo !"}
a = [["Bob", 1], ["Jex", 2], ["Jxx", 3]]
Hash[a.map { |e| [e[0].to_sym, e[1]]}
=> {:Bob=>1, :Jex=>2, :Jxx=>3}
刪除 each 判斷
a.delete_if { |x| x >= 3 }
a.delete_if do |v|
if v >= 3
true # Make sure the if statement returns true, so it gets marked for deletion
end
end
array’s value to symbol
array.map { |x| x.to_sym }
或
array.map &:to_sym
值是否存在
a = [1,2,3]
a.include?(2)
多項是否存在, 只要其中一項存在就是 true
([2, 6, 13, 99, 27] & [5,6]).any?
找出值旳 index
array.find_index(90)
兩個 array 合併
a.zip(s).flatten.compact
或
s.inject(a, :<<)
add
會改變原值
a.push("d", "e", "f")
a << 'x'
不會改變原值
a + [3]
delete
會改變原值
a = [2,4,6,3,8]
a.delete(3)
不會改變原值
a - [3]
remove duplicate elements
array = array.uniq
join array (無值就 delete value)
my_array.delete_if(&:empty?).join(',')
ordre ASC
my_array.sort
order DESC
my_array.sort.reverse
order 某個欄位
my_array.sort_by &:lastname
associations 關聯,如果想刪除其中某一筆
items.each do |i|
if i.product.nil?
needed_remove << i # 先放進待刪除區
end
end
items - needed_remove
# 以下看起來會 work ,但實際上最後的 items 還是跟原始的一樣,也就是 delete 沒有在原本的 items 移除該項目
items.each do |i|
if i.product.nil?
items.delete(i)
end
end
items
insert 一筆到最前面
[1,3,6].unshift(5) # [5, 1, 3, 6]
Data process for Array or Hash
Extract columns from an array of objects and make them an array
cats.each(&:name)
cat_names = cats.map(&:name) # 相當於 each cat.name
cats.each do |cat| cat.name end
cats.each {|cat| cat.name }
only preserve specific columns from an array of objects and make them an array
example
[{id: 1, name: 'xxx', ….}, {id: 2, name: 'ccc', ….}]
=>
[{id: 1, name: 'xxx'}, {id: 2, name: 'ccc'}]
code
@rooms.map { |room| [room.id, room.plan] }
only preserve specific columns from objects of a hash by key
example
{
"AAA": [{id: 1, name: 'one', age: 25}, {id:2, name: 'one', age: 25}],
"BBB": [{id: 3, name: 'three', age: 30}, {id:4, name: 'three', age: 30}]
}
=>
{
"AAA": [{id: 1}, {id:2}],
"BBB": [{id: 3}, {id:4}]
}
code
h.transform_values { |arr| arr.map { |room| {id: room.id} } }
Count items for each key of a hash
example
{"AAA": [RoomA, RoomB], "BBB": [RoomA]}
=>
{"AAA": 2, "BBB": 1}
code
data.transform_values { |value| value.size }
json
string to json
JSON.parse(params[:JSONData])
Call Dynamic method name
Sometimes you might need a dynamic method, you can use send
send
def test
puts 'test~'
end
send('test')
前面也可以接 instance 以及可以多個 method 一起執行
User.send('smart').send('honest') # 等於 User.smart.honest
傳遞參數
User.send('smart', iq: 130)
只 call public method
User.public_send(:name, "Jex")
method call
程式碼比較多而且不能串多個 method
> a = "my_string"
> meth = a.method("size")
> meth.call() # call the size method
=> 9
型態
Print variable type
3.class
=> Fixnum
3.class.superclass
=> Integer
加密
Digest::SHA256.digest 'message' # "\xABS\n\x13\xE4Y\x14\x98+y\xF9\xB7\xE3\xFB\xA9\x94\xCF\xD1\xF3\xFB\"\xF7\x1C\xEA\x1A\xFB\xF0+F\fm\x1D"
Digest::SHA256.hexdigest('message') # ab530a13e45914982b79f9b7e3fba994cfd1f3fb22f71cea1afbf02b460c6d1d
Symbol
%Y
: 2017
%C
: 20 (year / 100)
%y
: 17 (year % 100)
%B
: January
%b
: Jan 也等於 %h
%m
: 01..12 with zero-padding
%_m
: 1
..12 with blank-padding
%-m
: 1..12 without balnk-padding
%d
: 01..31 with zero-padding
%e
: 1
..31 with blank-padding
%-d
: 1..31 without balnk-padding
%j
: 001..336 day of the year
%H
: 00..23 with zero-padding
%k
: 0
..23 with blank-padding
%I
: 01..12 with zero-padding
%l
: 1
..12 with blank-padding
%P
: am / pm
%p
: AM / PM
%M
: 00..59 minute
%S
: 00..59 second
%L
: 000..999 millisecond
%N
= 9 digits nanosecond
%3N
= 3 digits millisecond
%6N
= 6 digits microsecond
%9N
= 9 digits nanosecond
%12N
= 12 digits picosecond
%z
: +0900
%:z
: +09:00
%::z
: +09:00:00
%:::z
: +09:30:30
%Z
: CST time zone abbreviation name
%A
: Sunday
%^A
: SUNDAY
%a
: Sun
%^a
: SUN
%u
: 1..7 day of the week (monday is 1)
%w
: 0..6 day of the week (sunday is 0)
%G
: 2016 the week-based year
%g
: 16 the last 2 digits of the week-based year
%V
: 52 Week number of the week-based year
%U
: 00..53 week number of the year. starts with sunday
%W
: 00..53 starts with mondy
%s
: 1483249934 timestamp, number of seconds since 1970-01-01 00:00:00 UTC
%n
: \n
%c
: Sun Jan 1 13:54:29 2017
date and time (%a %b %e %T %Y)
%D
= %x
: 01/01/17
Date (%m/%d/%y)
%F
: 2017-01-01
The ISO 8601 date format (%Y-%m-%d)
%v
: 1-JAN-2017
VMS date (%e-%b-%Y)
%r
: 01:56:03 PM
12-hour time (%I:%M:%S %p)
%R
: 13:56
24-hour time (%H:%M)
%T
= %X
: 13:55:44
24-hour time (%H:%M:%S)
語法
Time.now # 2016-04-07 11:04:09 +0800
Time.now.getutc # 2016-04-07 03:05:00 UTC
Time.now.strftime('%F %T') # 2015-08-10 21:02:04
Time.now.strftime('%F %R') # 2015-09-21 01:04
Time.now.strftime("%Y-%m-%d %H:%M:%S") # 2015-08-10 21:01:06
Time.now.in_time_zone # Tue, 22 Sep 2015 09:27:56 CST +08:00 如果 config 有設定 timezone
Time.now.to_i # 1483249426 (timestamp)
將 String
轉回 Time
Time.parse("2015-09-21 12:00")
或
"2015-09-21 12:00".to_time
2 天前 (rails)
2.days.ago
2 天後 (rails)
2.days.since
現在 DateTime 減 5 天
Post.find(12).update(created_at: Time.now.strftime('%F %R').to_time - 5.days)
5 天後
Date.today + 5
Date.today + 5.days
10.days.from_now
date 相減
require 'date'
> now = Date.today
> before = Date.today + 2.days
> difference_in_days = (before - now).to_i
-----
start_date = Date.parse "2012-03-02 14:46:21 +0100"
end_date = Date.parse "2012-04-02 14:46:21 +0200"
(end_date - start_date).to_i
Add time to date
d = Date.new(2012, 8, 29)
t = Time.now
dt = DateTime.new(d.year, d.month, d.day, t.hour, t.min, t.sec, t.zone)
或
Date.new(2015, 2, 10).to_datetime + Time.parse("16:30").seconds_since_midnight.seconds
Today
Date.today
Year
Time.now.year
顯示時間語意
# console 要引入 include ActionView::Helpers::DateHelper
time_ago_in_words(3.minutes.from_now) # => 3 minutes
time_ago_in_words(Time.now - 15.hours) # => 15 hours
time_ago_in_words(Time.now) # => less than a minute
from_time = Time.now - 3.days - 14.minutes - 25.seconds # => 3 days
distance_of_time_in_words('2015-09-16'.to_date, Date.today) # => 不到 1 分鐘
yield
example
class TT
attr_accessor :name
def initialize(name)
@name = name
end
end
def test(tt)
qq(tt) do |c|
puts 'c'
tt.name = '456'
puts 'd'
end
end
def qq(tt)
puts 'a'
puts tt.name
yield tt
puts 'yield'
puts tt.name
puts 'b'
end
tt = TT.new('123')
test(tt)
result
a
123
c
d
yield
456
b
Progress bar
簡易
10.times{|i| STDOUT.write "\r#{i}"; sleep 1}
1~100%
progress = 'Progress [ '
1000.times do |i|
j = i + 1
if j % 10 == 0
# 將 = 加到 progress string
progress << "="
# 將游標移到這行的最前面
print "\r"
# 取代目前這一行, 並輸出進度
print progress + " #{j / 10} % ]"
# flush buffer 立即顯示
$stdout.flush
sleep 0.05
end
end
puts "\nDone!"
Rake
Rake 是像 C 語言的 Make 工具, 但是用 Ruby 寫的, 主要是用來執行預先寫好的腳本語言
依不同環境跑 tasks
lib/tasks/tasks.rake :
namespace :tasks do
namespace :create do
desc "Create all survey templates"
task :all => [:task1, :task2]
desc "desc1"
task :task1 => :environment do
Rails.logger.info(1)
end
desc "desc2"
task :task2 => :environment do
end
end
end
lib/tasks/dev.rake :
namespace :dev do
desc "Rebuild system"
task :build => ["tmp:clear", "log:clear", "db:drop", "db:create", "db:migrate"]
task :rebuild => [ "dev:build", "db:seed" ]
end
rake dev:build
: 重建一個乾淨的環境
rake dev:rebuild
: 跑完 dev:build
再跑 db:seed
ref: 參考這裡