提升你代码质量的10个Ruby小技巧

www345 9年前


Ruby 中有很多你可能并不知道,但实际上非常实用的小技巧。下面笔者就结合自身经验,向大家分享一些。

1.构造Hash

你可以用一个列表一系列的值构造 Hash 通过 Hash[...] 方法,它将会像下面的方式创建一个 Hash:

Hash['key1', 'value1', 'key2', 'value2']  # => {"key1" => "value1", "key2" => "value"}

2.Lambda字面量->

定义一个 lambda 可以使用在 Rails 中也用的比较流行的 -> 字面量,它可以很容易的定义一个 lambda 对象

a = -> {1 + 1}  a.call  # => 2  a = ->(arg) {arg + 1} # 含参  a.call(2) # 传递参数  # => 3

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}]

4.操作单个对象和数组用同样的方式

有时你可能会先给出一个选项去接受单个对象或者一个数组对象,而不是最后去检查你接受到对象的类型,这时你可以用 [*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]

5. ||= 操作符号

利用 ||= 操作符能写出很简洁的代码

它实际上和下面的表示方式相同:

a || a = b # 正确

大多数人都认为它和下面的表示方式一样,但实际不是:

a = a || b # 错误

因为如果 a 已经存在,第二种方法的表示就是再给 a 进行分配赋值,但这样其实是没有意义的。

6.强制的哈希参数

这个是在 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]

7.生成字符或者字符数组

你可能想要生成一个数字列表或者把所有的字符放入一个数组,你可以用 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]

8. Tap

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 方法引入被调用的对象到代码块中并最后返回它。

9.Hash 默认的值

默认的,当我们试图接受一个在 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"

10. here 文档

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