BigBing 技术博客

推荐学习git的基本原理的两个视频

最近通过两个非常好的视频学习了一些git的基本原理,其中包括了git的对象模型,对象的组织方式等。 在理解了这些基本的原理后,再使用git的命令,就会比较清楚什么是merge,什么是rebase等,以及在不同的场合下合理得使用git命令。

第一个视频是《Metaprogramming Ruby》的作者Paolo Perrotta讲的Wrapping Your Head Around Git,我发现他总是非常擅长讲述一些原理性的知识,让你通过了解底层的原理,来更加扎实得掌握一门技术。

第二个视频是Introduction to Git with Scott Chacon of GitHub, Scott Chacon在github工作, 是git方面的大牛。虽然这个视频是2011年的,但是里面讲的原理和基本概念还是非常有用,绝对没有过时的。

在Ruby的Case表达式中使用Lambda/Proc

大部分的Ruby开发者都知道在case表达式中的when后面可以使用直接量,类,范围(Range)和正则表达式:

case something
when Array then ...
when 1..100 then ...
when /some_regexp/ then ...
end

你可能也知道在case中实际是使用===方法来进行比较。Ruby会将上面的代码象下面一样执行:

case something
when Array === something then ...
when 1..100 === something then ...
when /some_regexp/ === something then...
end

当然你可能不知道Proc类中也定义了===方法,用于执行proc或者lambda。相当于把===右边的参数作为参数传递给Proc#call方法,例如:

is_even = ->(n) { n.even? }

is_even === 5 # => false

#same as
is_even.call(5)

这样我们就可以在when的后面使用proclambda,下面是一个非常简单的例子:

def even?
  ->(n) { n.even? }
end

def odd?
  ->(n) { n.odd? }
end

case x
when even? then puts 'even'
when odd? then puts 'odd'
else puts 'Impossible!'
end

也可以直接在when的后面定义lambda,例如:

case x
when ->(n) { n.even? } then puts 'even'
when ->(n) { n.odd? } then puts 'odd'
else puts 'Impossible!'
end

因为proclambda的闭包特性,所以可以给lambda的定义方法传递参数,进行更强大的比较功能:

def response_code?(code)
  ->(response) { response.code == code }
end

case response
when response_code?(200) then 'OK'
when response_code?(404) then 'Not found'
else 'Unknown code'
end

下面是一个在具体项目中使用的用于对Array进行模式匹配的方法:

def matches(expected)
  ->(actual) {
    expected.zip(actual).all? do |(exp, act)|
      exp === act
    end
  }
end

def __
  ->(x) { true }
end

使用时就可以像下面这样对Array进行匹配:

case [a, b]
when matches([true])
 "matches when a is `true`"
when matches([true, true])
 "matches when a and b are `true`"
when matches([__, true])
 "matches when b is `true`"
when matches([false, (4..10)])
 "matches when a is `false` and b is number in range 4-10"
when matches([Array, Hash])
 "matches when a is an `Array` and b is a `Hash`"

本文参考: Lambdas/Procs in Case Expressions

我的家庭工作站

最近由于很多时间是在家里工作的,所以就需要把家里的工作环境和设施弄得舒服,实用一些。

今天终于把看了很久的Dell U2913WM 29寸的显示器买了回来,这个显示器的比例很特别是21:9的,所以看上去很宽。分辨率是2560*1080,并不是最牛的4k显示器。这是由于我的需求决定,我想用一个显示器来显示两屏的代码,而且4k的显示器,有时候应用菜单或者标题很小,经常需要调整字体大小。当然价钱也是一个考虑因素,这款显示器非常实惠,网上买的价格:580澳币。

小插曲:显示器自带了一根DisplayPort-Mini DisplayPort的线,我的Macbook Pro是可以用,但是一开始显示效果不好,代码看上去模糊,我尝试了各种办法进行调校都没有搞定,准备换一根Mini DisplayPort-Mini DisplayPort的线再试试。后来,我随手升级了一些MacOS的补丁,重启后发现就正常了。

今天还买了宜家的电脑椅,我这屁股对椅子比较挑剔,有一次在一个朋友家坐了几次宜家的电脑椅,发现很舒服。所以就果断买了,型号是:MALKOLM Swivel chair,买之前我专门买了一杯咖啡,然后到宜家的showroom,坐着这把椅子把咖啡喝完。

接下来其实我还想买的就是能够自由升降,可以站立或者坐着办公的桌子,我喜欢站着工作,同时对身体也好。宜家美国的网站已经有有一款这样的新产品BEKANT Desk sit/stand,澳洲这里还没有,再等等吧。不过我在澳洲发现了款不错的替代产品VARIDESK,可以直接放到已有的桌子上进行升降,不需要买一个新的桌子。

看,这就是我现在工作桌面的样子。 My work station

其他的宝贝还有:

  • Bose QuietComfort 25 强力消音耳机(很给力,娃再哭再闹都听不见!)
  • Macbook Pro
  • NSO Power Ball (神奇健身球)
  • 微软的无线键盘鼠标
  • 黑色的Mug (简直太配了!)

常用Ruby Gems列表(持续更新)

性能优化

bullet - 帮忙优化Rails的N+1 queries

日志相关

lograge - 精简rails log的gem activerecord-colored_log_subscriber - 让Rails中不同的sql语句显示不同颜色(Rails5之前)

代码检查

brakeman - 检查应用安全漏洞的gem rubocop - 检查code style

rails_best_practices dawn

开发调试

awesome_print - 漂亮得打印出ruby的对象 rack-dev-mark - 给页面加个彩带,用于区分开发或者测试环境 quiet_assets - 干掉烦人的静态文件的请求日志 activerecord-colored_log_subscriber - 用不同的颜色显示不同的SQL语句 peek - 方便查看应用各个基础服务的信息和性能

环境配置

dotenv-rails - 方便配置和使用

注释相关

annotate - 给ActiveRecord等model加注释

国际化

money - 处理钱或货币的gem money-rails - Ruby Money与Rails的整合

学习使用cucumber和相关技巧

参考资料

这次系统得学习一下cucumber,首先还是通过几个railscasts上的视频进行学习,虽然里面使用的是rails2,我还是用rails3及相关的gem重新实现了一遍。 实现代码:Learn cucumber

Railscasts上相关视频教程:

进一步深入学习的话还有两个资源可以参考:

技巧及经验总结

命令行参数

cucumber features

  • -r :用于指定在那个或者那些目录下面寻找匹配的step definition
  • -t :用于指定scenario的标签。例如: -t @focus, 或者排除指定标签: -t ~@focus

工具

Sublime可以安装Sublime Gherkin Formatter这个插件,可以用于格式化表格数据,快捷键是:<Cmd> + <Shift> + |

DRY

  • 可以使用background定义一系列的scenario需要用到步骤
  • 可以使用scenario outline定义类似的一组测试

使用launchy gem调试

  1. 可以使用step: Then show me the page
  2. 可以在step的定义里面调用: save_and_open_page
  3. 可以用下面的方法当测试失败时,自动打开页面调试:

新建/features/support/debugging.rb, 添加代码:

After do |scenario|
  save_and_open_page if scenario.failed? and (ENV["debug"] == "open")
end

然后运行测试时加上debug环境变量

cucumber features debug=open

使用World扩展cucumber

  • 使用Class进行扩展 例如,需要反复用到用户登录的功能,可以重构一个helper方法:
# features/support/login_helpers.rb
class LoginHelpers

  def login_user(username)
    visit("/login")
    fill_in( "user name", :with => username )
    fill_in( "password", :with => "tester" )
    click_button( "login" )
    page.should have_content("welcome")
  end

  def another_logging_method . . .
end

World do
  LoginHelpers.new
end

# features/step_definitions/user/login.rb
When /^"(.?)" logs in do |username|
  login_user(username)
end
  • 使用Module扩展
# features/support/paths.rb
module NavigationHelpers
  def path_to(page_name)
    case page_name

    when /the homepage/
      root_path
    when /the list of (.+)/
      send "#{$1}_path"
    when /the show page for (.+)/
      polymorphic_path(model($1))
    else
      raise "Can't find mapping from \"#{page_name}\" to a path."
    end
  end
end