2018年2月27日 星期二

rails table_name_prefix



```rb
module Snapshot
  def self.table_name_prefix
    'snapshot_'
  end
end
```


```rb
class Snapshot::Schedule < ActiveRecord::Base
end
```

會使用 snapshot_schesules table

2018年2月26日 星期一

想在 server 上持續性地跑個簡單的 script


screen


進到 screen

```sh
screen
```

Detach (離開 screen, 但是讓 screen 裡面的東西繼續執行)

```
ctrl+a d
```


Re-attach (重回 screen)


```sh
screen -r
```

如果有多個就先 screen -ls 找到 screen id 然後 `screen -r screen_id`, ex:

```sh
pungki@mint ~ $ screen -ls
There are screens on:
7849.pts-0.mint (10/06/2013 01:50:45 PM)        (Detached)
5561.pts-0.mint (10/06/2013 11:12:05 AM)        (Detached)
2 Sockets in /var/run/screen/S-pungki
```

```sh
pungki@mint ~ $ screen -r 7849
```



https://www.tecmint.com/screen-command-examples-to-manage-linux-terminals/
https://stackoverflow.com/questions/4797050/how-to-run-process-as-background-and-never-die

2018年2月24日 星期六

RSpec best practice



https://github.com/thoughtbot/guides/tree/dee16052f49cb4b41fb8d090ffdb75942512ddb1/best-practices#testing


https://robots.thoughtbot.com/lets-not

看到一個不錯的 mock example (RSpec)

之前一篇文章提到 RSpec 盡量不用 let, 那要用啥?可以用 method。

另外看到一個不錯的 mock example, 用 tap 來 return double 但是 yield Authentictor

```rb
def stub_authenticator(auth_hash)
  double('authenticator').tap do |authenticator|
    Authenticator.stub(:new).with(authenticator).and_return(authenticator)
  end
end

def stub_find_user(attributes = {})
  build_stubbed(:user, attributes).tap do |user|
    User.stub(:find).with(user.to_param).and_return(user)
  end
end
```

https://apidock.com/ruby/Object/tap

from https://thoughtbot.com/upcase/videos/rspec-best-practices

find out bin/setup is quite helpful


https://github.com/ajkamel/cover/blob/master/bin/setup


great feature spec example



```rb
feature 'User views all books' do
  scenario 'list all books' do
    create(:book, title: 'Practical Vim')
    create(:book, title: 'The Giver')

    visit books_path

    expect(page).to have_book('Practical Vim')
    expect(page).to have_book('The Giver')
  end

  # ...

  def have_book(title)
    have_selector('.book', text: title)
  end
end

```

Mutation in Ruby, it tells why more and more people like pure functional (immutable function)

Some mind blown examples:


```rb
[1] pry(main)> list = Array.new(5, "foo")
# => ["foo", "foo", "foo", "foo", "foo"]
[2] pry(main)> list[4].clear
# => ""
[3] pry(main)> list
# => ["", "", "", "", ""]
```

因為每個 default foo 都是同一個 object


以及

```rb
[1] pry(main)> master_list = Hash.new([])
# => {}
[2] pry(main)> master_list[:evens] << 2
# => [2]
[3] pry(main)> master_list[:odds] << 3
# => [2, 3]
[4] pry(main)> master_list
# => {}
[5] pry(main)> master_list[:evens] <<= 4
# => [2, 3, 4]
[6] pry(main)> master_list
# => {:evens=>[2, 3, 4]}
[7] pry(main)> master_list[:odds] <<= 5
# => [2, 3, 4, 5]
[8] pry(main)> master_list
# => {:evens=>[2, 3, 4, 5], :odds=>[2, 3, 4, 5]}
```

一樣的原理,每個 default array 都是同一個 object

一個避免這樣的做法是用 proc 確保每個 default 值是不同 object,例如:

```rb
Array.new(5) { "foo" }
Hash.new { [] }
```

ex:

```rb
[1] pry(main)> Array.new(5) { "foo" }
=> ["foo", "foo", "foo", "foo", "foo"]
[2] pry(main)> a = Array.new(5) { "foo" }
=> ["foo", "foo", "foo", "foo", "foo"]
[3] pry(main)> a[2].clear
=> ""
[4] pry(main)> a
=> ["foo", "foo", "", "foo", "foo"]
[5] pry(main)>
```


另外還有更有趣的「以你為 freeze 了是吧?Boom~!」

```rb
[1] pry(main)> CONSTANT = ["foo"]
# => ["foo"]
[2] pry(main)> CONSTANT << "bar"
# => ["foo", "bar"]
[3] pry(main)> CONSTANT.freeze
# => ["foo", "bar"]
[4] pry(main)> CONSTANT << "baz"
# RuntimeError: can't modify frozen Array
# from (pry):4:in `__pry__'
[5] pry(main)> CONSTANT[1] << "baz"
# => "barbaz"
[6] pry(main)> CONSTANT
# => ["foo", "barbaz"]
```

這是因為 freeze 是 freeze CONSTANT 這個 Array 的 object,沒有 freeze 裡面的 string,所以 string 還是 mutable

(Ice Nine gem for deep freezing)

為了拯救 developers 於水深火熱的加班 debug 地獄中,不需要 mutate 的時候就不要 mutate,寫每個 function 都想一下「這真的有必要 mutate 嗎?」