在 Ruby 中有很多你可能并不知道,但实际上非常实用的小技巧。下面笔者就结合自身经验,向大家分享一些。
你可以用一个列表一系列的值构造 Hash 通过 Hash[...] 方法,它将会像下面的方式创建一个 Hash:
Hash['key1', 'value1', 'key2', 'value2'] # => {"key1" => "value1", "key2" => "value"}
定义一个 lambda 可以使用在 Rails 中也用的比较流行的 -> 字面量,它可以很容易的定义一个 lambda 对象
a = -> {1 + 1} a.call # => 2 a = ->(arg) {arg + 1} # 含参 a.call(2) # 传递参数 # => 3
双星在 Ruby 中是一个小魔法,来看看下面的方法:
def my_method(a, *b, **c) end
a是一个常规的参数,b将会得到第一个参数后面的所有参数并把他们放入一个数组中, **c将会得到传人方法的任何格式为key: value的参数。
来看看下面的例子: 一个参数
my_method(1) # => [1, [], {}]
超过一个参数
my_method(1, 2, 3, 4) # => [1, [2, 3, 4], {}]
超过一个参数 + hash-style 参数
my_method(1, 2, 3, 4, a: 1, b: 2) # => [1, [2, 3, 4], {:a => 1, :b => 2}]
有时你可能会先给出一个选项去接受单个对象或者一个数组对象,而不是最后去检查你接受到对象的类型,这时你可以用 [*type]或者 Array(type)
我们先设置两个变量,第一个是单对象,第二个是数字数组:
obj = 1 obj_arr = [1, 2, 3]
在下面的例子,通过任何被给定的对象用 [*...] 去循环:
[*obj].each { |s| s } # => [1] [*obj_arr].each { |s| s } # => [1, 2, 3]
和上面效果一样,这次用 Array(...):
Array(stuff).each { |s| s } # => [1] Array(stuff_arr).each { |s| s } # => [1, 2, 3]
利用 ||= 操作符能写出很简洁的代码
它实际上和下面的表示方式相同:
a || a = b # 正确
大多数人都认为它和下面的表示方式一样,但实际不是:
a = a || b # 错误
因为如果 a 已经存在,第二种方法的表示就是再给 a 进行分配赋值,但这样其实是没有意义的。
这个是在 Ruby 2.0 被引进的,你可以在定义方法时指定接受的参数为 hash 类型,像这样:
def my_method({}) end
你可以指定想要接受值的键,或者为键指定一个默认的值。下面的 a 和 b 是指定要接受值的键:
def my_method(a:, b:, c: 'default') return a, b, c end
我们不给 b 传值来调用它,这时会报错:
my_method(a: 1) # => ArgumentError: missing keyword: b
由于 c 有一个默认的值,我们可以仅仅只给 a 和 b 传值:
my_method(a: 1, b: 2) # => [1, 2, "default"]
或者是给所有键传值:
my_method(a: 1, b: 2, c: 3) # => [1, 2, 3]
我们大多时候的做法是直接传入一个 hash,这样的做法只是看起来更明显,就像下面的方式:
hash = { a: 1, b: 2, c: 3 } my_method(hash) # => [1, 2, 3]
你可能想要生成一个数字列表或者把所有的字符放入一个数组,你可以用 Ruby 的 range 去做这样的事。
A到Z:
('a'..'z').to_a # => ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
1到10:
(1..10).to_a # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
tap 是一个很好的小方法去提高代码的可读性,我们拿下面的类作为例子:
class User attr_accessor :a, :b, :c end
现在去实例化一个对象并为对象的属性去赋值,你可能会这么做:
def my_method o = User.new o.a = 1 o.b = 2 o.c = 3 o end
或者你可以用tap使用下面的方式去做:
def my_method User.new.tap do |o| o.a = 1 o.b = 2 o.c = 3 end end
基本上,tap 方法引入被调用的对象到代码块中并最后返回它。
默认的,当我们试图接受一个在 hash 中未定义的值,你将会得到 nil。但你可以改变这个结果在进行初始化时。 (提示:一般不要这样做除非你知道自己在干什么)
在第一个例子中,我们定义了一个默认的值为0,所以当我们 a[:a] 时会得到 0 而不是 nil:
a = Hash.new(0) a[:a] # => 0
我们能够传入任何形式类型到 Hash 初始函数中:
a = Hash.new({}) a[:a] # => {}
或者是一个字符串:
a = Hash.new('lolcat') a[:a] # => "lolcat"
here 文档有一个缺点就是它会影响代码流畅和缩进问题,由于 HERE 会缩进两格,但有时为了最后内容连续性,你可能会把每行内容都靠左写,像这样:
def my_method <<-HERE Ruby stricks Interesting Right HERE end
这有一个技巧可以避免它,通过用 gsub 方法加一个正则表达式。你可以自动的去除前面的空格,这样你就能保持缩进。
def my_method <<-HERE.gsub(/^/s+/, '') Ruby stricks Interesting Right HERE end