Toptal Developers的Ruby最佳实践和技巧

Share

这个资源包含了由Toptal网络成员提供的Ruby最佳实践和Ruby技巧的集合.

这个资源包含了由Toptal网络成员提供的Ruby最佳实践和Ruby技巧的集合. As such, 本页将定期更新,以包含更多的信息,并涵盖新兴的Ruby技术. 这是一个社区驱动的项目, 所以我们也鼓励你们做出贡献, 我们期待着你们的反馈.

Ruby是一种独特的语言,充满了奇怪的语法和语义,有时看起来有点神奇. 而Ruby经常被建立在它之上的某个web开发框架所掩盖, 该语言本身是通用的,非常适合各种各样的应用程序. Great Ruby developers 可以使用Ruby构建任何东西,从web应用程序的后台到计算机上的命令行实用程序. The language is dynamic, reflective, and object oriented, 但是开发人员仍然需要经验才能驾驭它们的真正力量. 我们最好的建议和实践就是试图填补这一空白.

Check out the Toptal resource pages 以获取有关Ruby的更多信息. There is a Ruby hiring guide, Ruby job description, and Ruby interview questions.

如何访问数据后的'__END__'块?

In Ruby, the __END__ 关键字用于告诉解析器停止执行源文件. 它通常用于存储不需要内联的代码片段和关于脚本的注释, 以及将诸如许可证文件之类的文档附加到源代码文件的末尾.

后文件的内容 __END__ 关键字可通过名为 DATA. 它包含了之后的所有内容 __END__ 在那个Ruby脚本文件中.

How can this be useful? Let’s try it out. 在下面的示例中,我将在需要处理文本数据的快速脚本中使用它, rather than piping to STDIN.

DATA.each_line.map(&:chomp).each do |url|
    `open "#{url}"`
end

__END__
http://140v.ngskmc-eis.net/
140v.ngskmc-eis.net/ruby/tips-and-practices

Not that useful? Ok, 假设你有一堆CSV数据,你只需要其中的一列, 你想要使用CSV数据 DATA 拉出你想要的字段:

require "csv"

CSV.解析(DATA, headers: true).each do |row|
  puts "#{row['Name']} => #{row['URL']}" 
end

__END__
Id,Name,URL
1,Eqbal,http://140v.ngskmc-eis.net/resume/eqbal-quran
2,迭戈,http://http: / / 140v.ngskmc-eis.net/resume/diego-ballona

This is pretty cool. Still don’t believe me? 考虑最后一个例子. 假设你只想使用DATA来包含ERB模板:

require 'erb'

number = rand(100)
erb = ERB.new(DATA.read)
puts erb.result()

__END__
Here is a randon number: <%= number %>.

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

从Toptal获取最新的开发人员更新.

订阅意味着同意我们的 privacy policy

Write Readable Code.

如果我们考虑代码的可读性, 代码可维护性和代码效率, 在Ruby代码中可读性是最重要的.

如果你有一个选择,在写你的代码聪明, short, 也许更快的代码相对于更长的但可读的代码, go for readability. Ruby使得编写糟糕的代码变得很容易,以至于人们都不敢碰它. 同时,Ruby还可以让您编写漂亮而简洁的代码.

一旦您开始使用Ruby,这可能会让您感到困惑. 但是,当你花更多的时间阅读不同的Ruby库和其他开发人员的代码时,你将开始在Ruby专家的代码中看到一些模式. 向最好的人学习,开始编写更好、更易读的代码.

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

如何检验一组非常大的数

假设您需要在Ruby中测试一组非常大的数字,甚至是无穷大. 最好的方法是什么? You can use Range 对象作为无限惰性列表.

您只需要在使用诸如 #select,因为你可能会以while的无限循环结束 #select 不断检查每一个数字,因为它永远不会达到无穷大.

在这种情况下,您可以使用 Enumerable#lazy 方法创建惰性枚举数,然后使用 #first 方法从该列表中获取一定数量的项.

下面的例子说明了如何做到这一点:

infinity = 1.0 / 0

(1..infinity).include?(100_000_000)  #=> true
(1..infinity).include?(-100_000_000) #=> false
(100_000_000..infinity).step(100_000_000).take(2) #=> [100000000.0, 200000000.0]

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

避免使用' before_action '来设置变量:使用Memoized Finder来代替

The before_action 过滤器已用于使控制器DRY. 为了干爽而牺牲了清晰. Don’t get me wrong, DRY is a great concept, 但当它将Rails控制器变成一个复杂的谜题时就不是了!

注意:这是一个很好的技巧,即使它与Rails的默认控制器约定相冲突.

一个简单的解决方案是使用记忆查找器(||=).

Before

before_action: set_contest

def index
	@entries = @contest.entries
end

private

def set_contest
    @contest = Contest.找到(params [: contest_id])
end

After

def index
	@entries = contest.entries
end

private

def contest
    @_contest ||= Contest.找到(params [: contest_id])
end

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

Russell Colin Allen

自由Ruby开发人员

United States

Russell是一个非常热情和积极的软件开发人员,他喜欢创建创新和可扩展的web和桌面应用程序. 他参与了许多开源项目,并为自己适应不同技术和堆栈的能力感到自豪. Russell期待着用他的技能和专业知识帮助别人实现他们的目标.

Show More

为什么' Enumerable '方法优于' For '和' While '循环?

许多Ruby开发人员使用 For and While loops. 使用可枚举方法是更好的做法,例如: #each, #map, #select, #inject, #reject and #detect 而是迭代数组或对象. 更不用说使用了 #each 被认为是Ruby更习惯的用法.

让我们用一个例子来说明这一点:

loop1 = []
loop2 = []

Arr = ["top", "tal", "ent"]

for c in arr
  loop2 << c
end

这是更习惯的ruby代码
arr.each do |c|
  loop1 << c 
end

最后,这种方法使代码更具可读性,并且更易于理解 Ruby way.

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

使用Ruby交互优化你的Ruby文档

Ruby Interactive, or ri for short, 是一个导航文档和显示Ruby类信息的工具, 就像忍者一样. It is a companion to RDoc文件系统.

如果您以规定的RDoc格式在程序文件中放入注释, RDoc将扫描您的文件, extract those comments, 明智地组织它们, 最后将基于它们创建格式良好的文档.

所以为什么要用它呢? 首先,它已经安装了Ruby. 使用Ruby Interactive,您可以脱机访问所有文档和Ruby信息, 而且比通过谷歌搜索文档更快更好. 最重要的是,它看起来更像 Ruby way.

让我们看看这在几个例子中是如何工作的:

#类方法查找
数组#max #实例方法查找

$ ri Enumerable.each
Enumerable.每个都没找到,也许你的意思是:

Enumerable#each_cons
Enumerable#each_entry
Enumerable#each_slice
可列举的# each_with_index
可列举的# each_with_object

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

如何创建一个哈希值列表

在Ruby中,有一种简单的方法可以从列表中创建散列:

  a = %w{ T O P T A L }      
  Hash[*a] #=>  {"T"=>"O", "P"=>"T", "A"=>"L"}
  Hash[ [["dev","eqbal"], ["skil","ruby"] ]] #=> {"dev"=>"eqbal", "skil"=>"ruby"}

让我们考虑更多现实生活中的例子,让我们想象一下下面的场景,您刚刚收集了一些数据. 收集的数据采用表格格式并进行组织,因此一个数组表示列标题, 另一个数组的数组表示行值.

columns = ["Name", "technology", "availability"]

rows = [ 
  [“Eki”,“ruby”,真], 
  ["Dave", "angular",假的], 
  ["Aamir", "cpp", false]
]

columns数组保存列名. 这些将是最终哈希的键. rows数组是数组的数组,保存实际的表格数据. The objective, once again, 是否最终得到一个哈希数组,其中每个哈希的键将是列名, and value as row.

# The hard way 
results = []

for i in (0...rows.length)  
  h = {}
  for j in (0...columns.length)    
    H[列[j]] =行[i][j]    
  end
  results << h
end

results # =>  [{"Name"=>"Eki", "technology"=>"ruby", "availability"=>true}, {"Name"=>"Dave", "technology"=>"angular", "availability"=>false}, {"Name"=>"Aamir", "technology"=>"cpp", "availability"=>false}]

# Easier way 

correlated = rows.map{|r| Hash[ columns.zip(r) ] }

The Array#zip 方法将两个数组“压缩”到一起, 创建数组的数组, 每个数组在相同的索引持有两个组件数组的元素.

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

把常量放在一个地方.

在应用程序执行期间不更改的数据称为常量. 这些信息包括应用程序的名称、管理员电子邮件和标语. Ruby的最佳实践是将所有常量保存在一个文件中. By using this convention, 项目中的所有开发人员都确切地知道在哪里寻找常量,并可以快速进行更改. 一个示例文件看起来像这样:

# File config/settings.rb

ADMIN_EMAIL = 'eqbal@toptalcom'
ADMIN_PASS = 'my_awesome@pass'

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

为什么要避免使用“nil”??

What is nil? It is an instance of NilClass 和一种特殊的Ruby singleton. So NilClass is a class and nil 是该类的唯一实例吗.

>> nil.class
=> NilClass
>> nil.singleton_class
=> NilClass

问题是,当我们使用 nil 它会越来越容易治疗 nil 不是一个简单的物体. 例如,常用的用法是 nil 对消息的发送者来说意味着没有结果. 考虑下面的例子:

class Toptaller
  attr_reader :name

  def self.find(id)
    return nil if id == ''
    new(id)
  end

  def initialize(name)
    @name = name
  end
end

Toptaller.find('Eqbal') #=> #
Toptaller.find('')      #=> nil

Toptaller.find 的实例 Toptaller,但是当它接收到一个空字符串 id it returns nil.

假设我们要查找 Toptallers with id = [' equal ', ', 'diego']:

toptallers = ids.map {|id| Toptaller.find(id)}

toptallers.each {|top| puts top.name}
=> eqbal
=> NoMethodError: undefined method `name' for nil:NilClass

What to do now? Good idea is to use Null Object Pattern instead.

class Toptaller
  attr_reader :name

  def self.find(id)
    return nil if id == ''
    new(id)
  end

  def initialize(name)
    @name = name
  end

  def self.get_toptaller(name)
    case name
    when nil
      NilToptaller.new
    else
      Toptaller.find(name)
    end
  end
end

names = [" equal ", nil, "Diego"]

class NilToptaller
  def name
    "No name."
  end
end

toptallers = names.map {|n| Toptaller.get_toptaller(n).name}
["Eqbal", "No name.", "Diego"]

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

为什么要对共享库进行美化?

因为您经常使用Ruby并开发应用程序, 您将开始使用越来越多的组件, 比如快速RESTful api或任何其他框架. 在这种情况下,您需要考虑分离责任和业务逻辑. 例如,如果您正在使用Ruby on Rails,则应该开始使用 ActiveRecord 并将所有rake任务保持在Rails之外.

现在假设您想创建一个新的restful API Grape,但你不想以复制模型结束. What can you do?

一种方法是将模型和核心任务移动到 Gem 所以它可以解耦并在任何地方使用. Another way is to use Git Submodules. 因为现在将一些通用代码封装到Gems中被认为是一种很好的实践, 在本文中,我们将继续使用Gems.

You can use Bundler 用命令启动一个新的Gem: bundle gem core. Bundler将生成如下所示的基本文件结构:

├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── core.gemspec
└── lib
    ├── core
    │   └── version.rb
    └── core.rb

这些文件包含大部分业务逻辑, 我们需要将它们移动到一个单独的Gem中,以便它们可以在Rails应用程序之外使用:

  • Move your db folder to the gem: Mv /path_to_rails/db /path_to_gem
  • Move your tests folder to the gem: Mv /path_to_rails/spec /path_to_gem
  • Move your lib/tasks 到gem的根路径: Mv /path_to_rails/lib/tasks /path_to_gem . xml
  • Move your models to lib folder in the gem Mv /path_to_rails/app/models /path_to_gem/lib/gem_name/
  • Move config folder Mv /path_to_rails/config /path_to_gem/
  • Update your Gemfile accordingly
  • Modify the Rakefile 使用ActiveRecord Rake任务,类似于:
require 'rake'
require 'active_record'

包括ActiveRecord::任务
DatabaseTasks.database_configuration = YAML::load(文件.open('./config/database.yml'))
DatabaseTasks.db_dir = 'db'
DatabaseTasks.create_current (ENV [' RACK_ENV '])

That’s it. 现在,在您的Grape API项目中,您可以像这样将Gem包含在Gemfile中 git: /path/to/my/ Gem, and you are all done.

请注意,我们在这个例子中使用了Ruby on Rails, 但逻辑和文件结构可以应用于任何Ruby框架.

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

什么是符号垃圾收集器?

Ruby 2.2. 引入了一个重要的新特性,符号垃圾收集器(GC). Why is this big? 在此特性之前,在Ruby 2之前的旧Ruby版本中.2、象征永存.

让我们通过下面的例子来看看它是什么意思:

# Ruby 2.1
before = Symbol.all_symbols.size
100_000.times do |i|
  "toptaller_#{i}".to_sym
end
GC.start
after = Symbol.all_symbols.size
puts after - before
# => 100001

# Ruby 2.2
before = Symbol.all_symbols.size
100_000.times do |i|
  "toptaller#{i}".to_sym
end
GC.start
after = Symbol.all_symbols.size
puts after - before
# => 1

Just make sure to use any Ruby implementation > 2.2.0来获得这个可爱的新功能.

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

Avoid Using `while !(not)`

def play
    while !exceeded_max_guesses?
    	....
    end
end

Instead of a while not, we can simply use until:

直到exceeded_max_guesses?
    ....
end

或者用肯定的情况更好:

虽然has_remaining_guesses?
    ....
end

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

练习并加入Ruby社区.

人们期望道达尔工程师不断提高他们的技能. 让你的Ruby技能保持敏锐的可能方法有:

  • Read books. 我最喜欢的书之一是 Outliers by Malcolm Gladwell. 在书中作者谈到 10,000 hours rule.
  • 继续写代码和练习. 您可以查看您喜欢的库的源代码,并尝试与尽可能多的优秀开发人员配对.
  • 加入一个当地的Ruby小组. Ruby社区对新手非常有帮助和包容.
  • 不要羞于使用Ruby的IRC频道# Ruby -lang.
  • 最后,但并非最不重要的,试着享受你的工作.

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

如何在非布尔值上使用布尔运算符?

你可能知道,使用 ||= 如果变量未定义,将用右边的值返回表达式更新变量吗. 我们大多数人都知道这一点,但你可能不知道的是 &&=.

为了解释它是如何工作的,让我们看一下下面的简单代码片段:

str &&= str + "Talent" #=> nil
str = "Top"
str &&= str + "Talent" #=> "TopTalent"

正如你从上面的例子中看到的, str &&= str + "Talent" is the equivalent of (str = str + "Talent".

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

Use the `!!'(双bang)布尔值运算符

# BAD
def revealed?
    revealed
end

在大多数编程语言中,包括Ruby, ! 会返回与操作数的布尔值相反的值吗. 因此,当您将两个感叹号连接在一起时,它将值转换为布尔值.

# GOOD
def revealed?
    !!revealed
end

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

Avoid Using the `Array.new带有自定义默认值的构造函数

# BAD
@masked_word = Array.new(word.size, '_').join
# GOOD
@masked_word =“_”* word.size

Using the Array.new 带有自定义默认值的构造函数是有风险的, 因为数组被相同的实例填充. 这里有一个简单的例子来说明这种风险:

arr = Array.new(3, "foo")
#=> ["foo", "foo", "foo"]
arr[0].replace("bar")
#=> "bar"
arr
#=> ["bar", "bar", "bar"]

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

使用' loop do '代替' while(true) '

# BAD
def play
    get_guess
    while true
        ...
        ...
    end
end
# GOOD
def play
    get_guess
    loop do
        ...
        ...
    end
end

Why? The loop do Construct在使用外部迭代器时提供了更清晰的语法.g:

# No loop do
my_iterator = (1..9).each
begin
    while(true)
    	puts my_iterator.next
    end
rescue StopIteration => e
    puts e
end

And now with loop do this would become:

my_iterator = (1..9).each
loop do
    puts my_iterator.next
end

异常会为你处理. Not convinced yet? Another reason to use loop do 它是否还允许您同时循环两个集合. 一旦其中一个耗尽了元素,循环就会优雅地退出:

iterator = (1..9).each
iterator_two = (1..5).each

loop do
    puts iterator.next
    puts iterator_two.next
end

#=> 1,1,2,2,3,3,4,4,5,5,6.

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

使用格式插值技术来格式化小数和修改字符串很容易

为了简化格式化字符串数据的创建,Ruby使用字符串格式语法,即 % operator. 该操作符使我们能够在运行时将字符串的某些部分替换为实际值. After the % 操作符,我们指定参数. % 接受单个元素或元素数组作为其唯一参数.

这里有几个例子来说明 % operator in action:

>> gpa = 3.8
=> 3.8
>> "%.2f" % gpa
=> "3.80"
>> '%d - %d' % [50, 50]
=> '50 - 50'
>> "%.5f" % gpa
=> "3.80000"
>> "**%s**" % "Toptal"
=> "**Toptal**"

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

推荐Ruby ide和编辑器

一些开发人员喜欢使用ide来自动生成代码, autocomplete, navigating, integrated debugging, and more. Ruby没有官方的IDE,但是 RubyMine 可能是最接近的,因为它得到了广泛的支持和使用. Nevertheless, 大多数Ruby开发人员都在使用编辑器, 因为它们提供的简单和速度.

下面是可以与Ruby一起使用的编辑器的快速回顾:

  • RubyMine如前所述,这是一个IDE而不是编辑器. 尽管Ruby不像Java或c++那样需要IDE来构建应用程序. Why? 首先,Ruby是一种解释型语言,它的代码不需要编译. Second, 因为Ruby的本质和Ruby on Rails的扩展, 一般来说,它试图写得非常简单和自然. 例如,Ruby on Rails中的配置文件就是Ruby文件. 不需要学习新的语法, 您可以使用该语言中几乎任何可用的结构,而无需浪费太多时间学习IDE.
  • Sublime Text这是我最喜欢的编辑. 它有一个流畅的UI和一个庞大的社区,并且比大多数其他编辑器有更好的性能. 只是不要忘记安装和使用其相应的 Ruby package.
  • Textmate非常受Mac用户欢迎. DHH, the creator of Rails framework, and Ryan Bates, the producer of RailsCasts 其中许多人更喜欢这个编辑器.
  • Vim这是一个必须知道的编辑, 或者,如果您需要远程编辑文件,至少需要了解基本知识. 在您的Ruby开发生涯中,很可能有一段时间您需要SSH到您的服务器,并且需要编辑一些文件. 如果你愿意花一些时间学习捷径,它可以非常快速和高效. 只是不要忘记使用正确的插件集来提高效率. There is the popular Janus: Vim Distribution and Srushti’s Vim setup.
  • Emacs一种流行的Vim替代品. 您希望自定义它并使其对Rails友好? Don’t forget to check Emacs Wiki. 需要另一个使用它的理由? Matz is using it.

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

如何跟踪运行过程?

假设您想通过使用using来跟踪正在运行的进程 ps command. 如果您可以命名您的过程,以便您可以轻松地跟踪它,那不是很好吗? 好消息是你可以. 诀窍是将字符串赋值给全局变量 $PROGRAM_NAME:

echo '$PROGRAM_NAME = "Toptal"; sleep 5' >> my_processs.rb
ruby my_processs.rb
ps -A | grep Toptal

如果您希望共享进程的状态而不是记录信息,这个技巧也会很有帮助.

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

如何转换任何基数在Ruby?

需要将数字从十进制转换为十六进制或二进制? Good news. 在Ruby中,只需一行代码就可以转换为2到36之间的任意基数.

Using the Fixnum#to_s 方法,您可以快速将任何Fixnum对象转换为另一个基的文本格式:

5.to_s(2) #=> "101"
5.to_s(3) #=> "12"
5.to_s(8) #=> "5"

# To convert back

"12".to_i(3) #=> 5

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

Avoid Using Evil 'rescue Exception => e'

假设你想捕获异常细节,就像下面的例子:

def do_something!
  # ... do something ...
  success
rescue Exception => e
  failed e
end

This is a terrible idea. Why? Exception 是在Ruby异常类层次结构的根. 的子类,从信号处理到内存错误 Exception. 你可以检查ruby-core中的异常列表,我们将在抢救Exception时抢救这些异常.

SystemStackError
NoMemoryError
SecurityError
ScriptError
  NotImplementedError
  LoadError
    Gem::LoadError
  SyntaxError
SignalException
  Interrupt
SystemExit
  Gem::SystemExitException

Do you want to rescue Exception in general like NoMemoryError? 假设这是一个mailer脚本,我们是否需要在作业失败时向用户发送电子邮件?

What to do instead? Start using rescue => e as it’s the same for rescue StandardError => e 几乎可以肯定,它是我们想要拯救的最广泛的例外类型.

def do_something!
  # ... do something ...
  success
rescue => e
  failed e
end

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

在数组以外的对象上使用Splat展开器.

Splat operator, *,在Ruby中用于简化代码. For example, 以简单的方式将值强制转换为数组并将其赋值给变量, 我们可以在值前面加上星号(splat操作符), 如下面的代码片段所示:

t,o,p,t,a,l = *(1..6) #=> [1, 2, 3, 4, 5, 6]
puts p #=> 3

这里的技巧是,我们也可以对数组以外的对象使用splat展开器:

Toptaller = Struct.new(:name, :tech)
toptaller = Toptaller.new("Eqbal", "Ruby")
name, tech = *toptaller
puts tech #=> Ruby

Contributors

Eqbal Quran

自由Ruby开发人员

Jordan

Eqbal是一名高级全栈开发人员,拥有超过十年的web和移动开发经验. 他是解决问题的高手,并拥有广泛的成品专业产品组合.

Show More

如何快速彩色终端打印输出?

Ruby有一些很棒的宝石可以将输出打印着色到终端, 但有时您只需要打印几次,而不想为此添加另一个宝石.

例如,代替:

puts "\e[31mThis is red!\e[0m"
这是绿色的!\e[0m"

您可以使用。创建分隔变量的格式 %s placeholder (printf format):

red = "\e[31m%s\e[0m"
green = "\e[32m%s\e[0m"

Then use the % 可读格式操作符:

puts red % 'Red Again!'
绿色再次变绿!'
puts 'Mixed %s with %s!' %[红色% '红色',绿色% '绿色']

让我们来看另一个例子:

a = 2
b = 3
sum = a + b
format = '%s + %s = %s'
放置格式%[红色% a,红色% b,绿色% sum]

这个例子比下面的代码更具可读性:

把“\ e[31米# {}\ e [0 m + \ e[31米# {b} \ e [0 m = \ e [32 m #{和}\ e [0 m”

这可以以一种简单而不引人注目的方式使用,并且可以在一个地方使用,例如log方法:

class MyClass
  def log(message, level)
    red = "\e[31m%s\e[0m"
    green = "\e[32m%s\e[0m"

    显示“%s: %s”%[红色%级别,绿色%消息]
  end
end

如果你想全局使用这个方法,你可以monkey patch String类:

class String
  def red
    "\e[31m#{self}\e[0m"
  end

  def green
    "\e[32m#{self}\e[0m"
  end
end

然后在代码的任何地方使用它们:

puts "Red again!".red
puts "Green again!".green
puts "Mixed %s with %s!" % ["red".red, "green".green]

让我们重新使用之前使用的相同示例,但现在使用新的语法:

a = 2
b = 3
format = "%s + %s = %s"
puts format % [a.to_s.red, b.to_s.red, (a + b).to_s.green]

一个更礼貌的猴子补丁变体是使用一个模块:

module ConsoleColors
  def red
    "\e[31m#{self}\e[0m"
  end

  def green
    "\e[32m#{self}\e[0m"
  end
end

String.include ConsoleColors

如果你仍然想全局使用它,但不想monkey patch String, 您可以使用以下代码变体:

class Color
  # constants
  RED = "\e[31m%s\e[0m"
  GREEN = "\e[32m%s\e[0m"

  # or methods
  def self.red(s)
    "\e[31m#{s}\e[0m"
  end

  def self.green(s)
    "\e[32m#{s}\e[0m"
  end
end

put Color::RED % 'reddish'
put Color::GREEN % 'greenish'

puts Color.red 'reddish method'
puts Color.green 'greenish method'

最后,您可以使用Ruby 2.0改进以限制更改的范围;

模块ConsoleColorsStringRefinement
  refine String do
    def red
      "\e[31m#{self}\e[0m"
    end

    def green
      "\e[32m#{self}\e[0m"
    end
  end
end

class MyLogClass
  使用ConsoleColorsStringRefinement

  def log(message, level)
    puts "%s: %s" % [level.to_s.red, message.to_s.green]
  end
end

MyLogClass.new.log('My Message', 'DEBUG') # DEBUG: My Message

Contributors

Boško Ivanišević

自由Ruby开发人员

Serbia

Boško是一位经验丰富的架构师/开发人员,他热衷于编写可维护和可读的代码. 他在许多领域都有丰富的经验,包括桌面和web应用程序. Boško是一个伟大的人与工作,将是一个资产的任何项目.

Show More

Marcos Neves

全栈web开发人员(自由职业者)

1999年开始开发全栈web, 2011年开始开发移动应用. 现在全职使用Rails和AngularJS.

Submit a tip

提交的问题和答案将被审查和编辑, 并可能会或可能不会选择张贴, 由Toptal全权决定, LLC.

*所有字段均为必填项

Toptal Connects the Top 3% 世界各地的自由职业人才.

加入Toptal社区.