Tongfei's Blog

Ruby on Rails wizard

Read this first

Thoughts about Rails testing and debugging

Good and well-covered unit tests prevents breaking changes and helps refactoring in the future.

In this article, i will write up some tips and thoughts about unit testing in Ruby on Rails development. I hope you find some of them helpful.

 Fail fast

Fail fast is very useful when doing TDD (Test Driven Development), or when there are a bunch of failed tests need to be fixed one by one. Instead of running all your test suites, fail fast will abort once your test runner fails to pass one test suite. It saves time and let you focus on single problem.

Rails 5 has shipped fail fast feature for you, simply use rails test -f or rails test --fail-fast to enable fail fast option.

For older versions, you can try minitest-fail-fast gem. Notice that i did not check if minitest-fail-fast is still working, you can figure it out by yourself.

 m: run single test by line number

If you have used...

Continue reading →


Refactoring Your Rails App: Using Service Object

 What is service object for?

In short, service objects are for slimming down your controllers. You may have heard of the principle of keeping controller skinny. You can achieve it by moving business logic to service objects.

 Example

Consider we have an app and we need to implement a feature to create orders.

Assume our products table looks like this:

t.string :name
t.integer :quantity
t.decimal :price
t.integer :lock_version # use lock_version for optimistic locking
...

and orders table:

t.integer :user_id
t.integer :state
t.integer :product_id
...

Let’s implement it now without using service objects, code would look like this.

# orders_controller.rb
...
def create
  begin
    ActiveRecord::Base.transaction do
      product = Product.find_by(id: params[:product_id])
      order = Order.find_or_initialize_by(user: current_user, product: product)
      return render json: {
...

Continue reading →


Ruby3和类型推导

比起大家津津乐道的Ruby 3的性能和并发模型,关于Ruby 3类型系统的讨论真是少之又少。由于对类型系统稍有兴趣,最近一直在收集关于Ruby3的类型系统的话题。

https://bugs.ruby-lang.org/issues/5583

https://bugs.ruby-lang.org/issues/9999

很久以前有人提案建议Ruby增加type annotation,但是后来都因为语法层面的改动较大被Matz拒绝。

不过Matz 在 https://bugs.ruby-lang.org/issues/9999#note-13 提到Ruby 3会使用type inference(类型推导),这确实是个好消息。

1.png

什么是类型推导?

类型推导是一种根据上下文推断数据类型的技术。Java,C等语言是静态类型语言,这意味着在这几个语言中每个data binding都有对应的类型,他们的类型都在编译时确定。在编译时会运行type checker(类型检查器),它会用于检查程序的类型是否有不一致等问题。而Ruby是动态类型语言,类型绑定和类型检查是在运行时(run-time)进行。

有了类型推导,很多bug就可以在运行前发现。

我们都知道Java和C都需要显性声明数据或函数的类型,所以就会有这样的语法:

int a = 1;
boolean result = true;

但是显式声明类型显然和Ruby八字不合,没有一个Ruby程序员愿意写上面那样的代码。

所以Ruby未来采取的类型方案肯定是基于隐式类型(implicitly typing)。

关于ML的类型推导原理

(注:以下提到的ML都为Standard ML语言)

ML和Java、C一样,是一个静态类型语言,但是它的类型可以通过隐式声明。如果想要了解ML的语法访问 https://learnxinyminutes.com/docs/standard-ml/

总而言之,在ML中,你不必声明变量的类型,你可以这样写程序:

val x = 1
val result = true
...

Continue reading →