2016年2月15日 星期一

張五常:思考的方法



一、誰是誰非不重要

二、問題要達、要淺、要重要、要有不同答案的可能性
          問題要一針見血
          問題要問得淺
          要斷定問題的重要性

三、不要將預感抹殺了
          純以預感而起,加上想像力去多方推敲,有了大概,再反覆以邏輯證實,是最有效的思考方法。只要得到的理論或見解是合乎邏輯及方法論的規格,是怎樣想出來的無關重要

四、轉換角度可事半功倍
          茅塞可以頓開
          角度可以衡量
          角度有遠近之分

五、例子遠勝符號
          例子要簡而貼切
          例子要分真假
          例子要新奇
          要將例子一般化
          要試找反證的例子

六、百思不解就要暫時擱置



2016年2月13日 星期六

ActiveModel: Make Any Ruby Object Feel Like ActiveRecord


  • ActiveModel API

the important thing about the ActiveModel API is that your models can become ActiveModel compliant without using a single line of Rails code
use "include ActiveModel::Lint::Tests” to make sure your model become ActiveModel compliant

  • The Validations System

use "include ActiveModel::Validations” to add validation module to your model

The validations system calls read_attribute_for_validation to get the attribute, but by default, it aliases that method to send, which supports the standard Ruby attribute system of attr accessor

validates_presence_of is using the more primitive validates_with, passing it the validator class, merging in {:attributes => attribute names} into the options passed to the validator

  • Serialization

include ActiveModel::Serialization

ActiveRecord also comes with default serialization for JSON and XML


  • AttributeMethods: Makes it easy to add attributes that are set like table_name :foo
  • Callbacks: ActiveRecord-style lifecycle callbacks.
  • Dirty: Support for dirty tracking
  • Naming: Default implementations of model.model_name, which are used by ActionPack (for instance, when you do render :partial => model
  • Observing: ActiveRecord-style observers
  • StateMachine: A simple state-machine implementation for models
  • Translation: The core translation support

2016年2月8日 星期一

Confident Ruby

chapter 1.
     four parts of a method
  • collecting input
  • performing work
  • delivering output
  • handling failures
chapter 2.
1. We must identify the messages we want to send in order to accomplish the task at hand.
2. We must identify the roles which correspond to those messages.
3. We must ensure the method's logic receives objects which can play those roles
第二張 performing work
在講說
method裡面要做的事情
要定義好說
要傳遞的訊息是什麼(Message) 以及 誰接收這個訊息(Receiver Role)

def import_legacy_purchase_data(data)
          purchase_list = legacy_data_parser.parse_purchase_records(data)
purchase_list.each do |purchase_record|      
customer =    customer_list.get_customer(purchase_record.email_address)      
product  =    product_inventory.get_product(purchase_record.product_id)      
customer.add_purchased_product(product)      
customer.notify_of_files_available(product)      
log_successful_import(purchase_record)
end
end

chapter 3.
3.2 Use built-in conversion protocols
If we want to provide maximum leeway in input, we can use explicit conversion methods like #to_i. If we want to provide a little  exibility while ensuring that client code isn't blatantly mis-using our method, we can use an implicit conversion such as #to_int
3.3 Conditionally call conversion methods
在講說 有時候輸入的參數 要確認型別時 就條件式的轉換
她有這種型別方法的時候 就轉換
可能可以有好幾種型別  都沒有的時候就報錯
3.4 Define your own conversion protocols
建立自己的轉換型別的方法
3.5 Define conversions to user-defined types
定義好轉型的方法

主要方法接收參數時 只接有此轉型方法的參數
其餘的要報錯誤

3.6 Use built-in conversion functions
用最大的力量來轉型

3.7 Use the Array() conversion function to array-ify inputs
當參數需要是array時 用Array(參數) 先來強制轉型 

3.8 Define conversion functions
建立一個idempotent的方法 強制轉換, 中間可能包含多種的轉換 不過結果就是出來一種型態
當我們需要某一個型態的時候 都用這個方法來強制轉換

3.9 Replace "string typing" with classes
當傳入的參數是string 而且方法裡面有很多case when的時候
試著把傳入的參數 變成有意義的物件

3.12 Reject unworkable values with preconditions
在preconditions就把一些需要的檢查做掉 還有需要使用到的變數轉換

3.13 Use #fetch to assert the presence of Hash keys
用fetch來判斷hash有沒有哪些key值

3.14 Use #fetch for defaults
用fetch來判斷default值
用block來當做參數 丟入fetch
If we had used the block form, the expensive computation would only have been triggered when it was actually needed.

3.15 Document assumptions with assertions
接外部可能會變動的api時
要再接的時候 針對每個參數 做處理檢查 一有不同 就要報錯
ex: hash要用 fetch確保參數都有, 型別轉換也要不是這個型別的話 就要報錯  Kernel#Float
amount = transaction.fetch("amount")
amount_cents = (Float(amount) * 100).to_i

3.16 Handle special cases with a Guard Clause
特別case的處理時 可以放在方法的最上方 當發生時 就導去別處
而不用因為用到if else 導致程式的結構不好閱讀
方法裡面主要就放常常發生的case

3.17 Represent special cases as objects
特別的case處理時 如果這個case再很多地方用到
可以用一個特別的class來處理他
例如current_user,  可以有一個特別的class => GuessUser 來代表沒有current_user的情況

3.18 Represent do-nothing cases as null objects
有時候會有一些要判斷是不是nil的情況時
可以用一個null object來處理  就不用寫很多if來判斷是不是nil
但是在null object裡面 log要寫好 不然有一些錯誤永遠不會發現
class NullObject < BasicObject
     def method_missing(*) end
     def respond_to_missing?(name) true end
     def nil? true end
     def ! true end
end

3.19 Substitute a benign value for nil
當nil的情況 是要走另一種情形 不會導致錯誤, 給他一個有意義的值

3.20 Use symbols as placeholder objects
當nil的情況 會導致錯誤時
給他一個有意義的symbol來報錯 會比較好debug

3.21 Bundle arguments into parameter objects
當兩個參數一定是要一起出現時 用一個物件把他包起來
當有if的情況出現時, 看是不是可以在refactor

3.22 Yield a parameter builder object
後面看不太懂

3.23 Receive policies instead of data
可以用block的方式 來做錯誤處理
def delete_files(files, &error_policy)
     error_policy ||= ->(file, error) { raise error }
     files.each do |file|
          begin
                File.delete(file)
           rescue => error
               error_policy.call(file, error)
           end
     end
end

4.1 Write total functions
當回傳的形態是array時
不管任何情形都要回array

4.2 Call back instead of returning
有時候用callback來取代回傳直會更好
用callback有時能更明顯的表達出這個function在做什麼
command-query separation (CQS). CQS is a simplifying principle of OO design which advises us to write methods which either have side effects (commands), or return values (queries), but never both

4.3 Represent failure with a benign value
不要用nil回復失敗的情況
用個有意義一點的值

4.4 Represent failure with a special case object
錯誤case時用特別的物件來回
反正不要nil就是了

4.5 Return a status object
當回傳情況有多種時 可以用一個新的狀態物件來回傳

4.6 Yield a status object
一樣用callback 可以讓function更清楚的表達她是要做什麼
callback是一個狀態物件的各種處理情形
就可以知道回傳的各種情況 是怎麼處理

4.7 Signal early termination with throw
用throw和catch來提早結束某些情況

5.1 Prefer top-level rescue clause
用top-level的rescue

5.2 Use checked methods for risky operations
還是用block的方式 傳入錯誤的時候要怎麼處理

5.3 Use bouncer methods

在用另一個方法 來包裝錯誤處理完後 要回傳的東西 

2014年11月15日 星期六

production環境上 也能直接顯示css js的變動

production環境上 也能直接顯示css js的變動

因為人因需求 需要直接修改production環境的css檔
因此先修改production.rb的設定
rails s -e production
# Code is not reloaded between requests.
# config.cache_classes = true
   config.cache_classes = false

# Disable Rails's static asset server (Apache or nginx will already do this).
  #config.serve_static_assets = false
  config.serve_static_assets = true

# Do not fallback to assets pipeline if a precompiled asset is missed.
  # config.assets.compile = false
  config.assets.compile = true

# Generate digests for assets URLs.
  #config.assets.digest = true
  config.assets.digest = false

2014年10月29日 星期三

GIT 常用指令

http://homeserver.com.tw/2013/09/24/git-%E5%B8%B8%E7%94%A8%E6%8C%87%E4%BB%A4/


注意事項

由 project/.git/config 可知: (若有更多, 亦可由此得知)
  • origin(remote) 是 Repository 的版本
  • master(branch) 是 local 端, 正在修改的版本
平常沒事不要去動到 origin, 如果動到, 可用 git reset –hard 回覆到沒修改的狀態.

Git 新增檔案

  • git add . # 將資料先暫存到 staging area, add 之後再新增的資料, 於此次 commit 不會含在裡面.
  • git add filename
  • git add modify-file # 修改過的檔案, 也要 add. (不然 commit 要加上 -a 的參數)
  • git add -u # 只加修改過的檔案, 新增的檔案不加入.
  • git add -i # 進入互動模式

Git 刪除檔案

  • git rm filename

Git 修改檔名、搬移目錄

  • git mv filename new-filename

Git status 看目前的狀態

  • git status # 看目前檔案的狀態

Git Commit

  • git commit
  • git commit -m ‘commit message’
  • git commit -a -m ‘commit -message’ # 將所有修改過得檔案都 commit, 但是 新增的檔案 還是得要先 add.
  • git commit -a -v # -v 可以看到檔案哪些內容有被更改, -a 把所有修改的檔案都 commit

Git 產生新的 branch

  • git branch # 列出目前有多少 branch
  • git branch new-branch # 產生新的 branch (名稱: new-branch), 若沒有特別指定, 會由目前所在的 branch / master 直接複製一份.
  • git branch new-branch master # 由 master 產生新的 branch(new-branch)
  • git branch new-branch v1 # 由 tag(v1) 產生新的 branch(new-branch)
  • git branch -d new-branch # 刪除 new-branch
  • git branch -D new-branch # 強制刪除 new-branch
  • git checkout -b new-branch test # 產生新的 branch, 並同時切換過去 new-branch
  • # 與 remote repository 有關
  • git branch -r # 列出所有 Repository branch
  • git branch -a # 列出所有 branch

Git checkout 切換 branch

  • git checkout branch-name # 切換到 branch-name
  • git checkout master # 切換到 master
  • git checkout -b new-branch master # 從 master 建立新的 new-branch, 並同時切換過去 new-branch
  • git checkout -b newbranch # 由現在的環境為基礎, 建立新的 branch
  • git checkout -b newbranch origin # 於 origin 的基礎, 建立新的 branch
  • git checkout filename # 還原檔案到 Repository 狀態
  • git checkout HEAD . # 將所有檔案都 checkout 出來(最後一次 commit 的版本), 注意, 若有修改的檔案都會被還原到上一版. (git checkout -f 亦可)
  • git checkout xxxx . # 將所有檔案都 checkout 出來(xxxx commit 的版本, xxxx 是 commit 的編號前四碼), 注意, 若有修改的檔案都會被還原到上一版.
  • git checkout — * # 恢復到上一次 Commit 的狀態(* 改成檔名, 就可以只恢復那個檔案)

Git diff

  • git diff master # 與 Master 有哪些資料不同
  • git diff –cached # 比較 staging area 跟本來的 Repository
  • git diff tag1 tag2 # tag1, 與 tag2 的 diff
  • git diff tag1:file1 tag2:file2 # tag1, 與 tag2 的 file1, file2 的 diff
  • git diff # 比較 目前位置 與 staging area
  • git diff –cached # 比較 staging area 與 Repository 差異
  • git diff HEAD # 比較目前位置 與 Repository 差別
  • git diff new-branch # 比較目前位置 與 branch(new-branch) 的差別
  • git diff –stat

Git Tag

  • git tag v1 ebff # log 是 commit ebff810c461ad1924fc422fd1d01db23d858773b 的內容, 設定簡短好記得 Tag: v1
  • git tag 中文 ebff # tag 也可以下中文, 任何文字都可以
  • git tag -d 中文 # 把 tag=中文 刪掉

Git log

  • git log # 將所有 log 秀出
  • git log –all # 秀出所有的 log (含 branch)
  • git log -p # 將所有 log 和修改過得檔案內容列出
  • git log -p filename # 將此檔案的 commit log 和 修改檔案內容差異部份列出
  • git log –name-only # 列出此次 log 有哪些檔案被修改
  • git log –stat –summary # 查每個版本間的更動檔案和行數
  • git log filename # 這個檔案的所有 log
  • git log directory # 這個目錄的所有 log
  • git log -S’foo()’ # log 裡面有 foo() 這字串的.
  • git log –no-merges # 不要秀出 merge 的 log
  • git log –since="2 weeks ago" # 最後這 2週的 log
  • git log –pretty=oneline # 秀 log 的方式
  • git log –pretty=short # 秀 log 的方式
  • git log –pretty=format:’%h was %an, %ar, message: %s’
  • git log –pretty=format:’%h : %s’ –graph # 會有簡單的文字圖形化, 分支等.
  • git log –pretty=format:’%h : %s’ –topo-order –graph # 依照主分支排序
  • git log –pretty=format:’%h : %s’ –date-order –graph # 依照時間排序

Git show

  • git show ebff # 查 log 是 commit ebff810c461ad1924fc422fd1d01db23d858773b 的內容
  • git show v1 # 查 tag:v1 的修改內容
  • git show v1:test.txt # 查 tag:v1 的 test.txt 檔案修改內容
  • git show HEAD # 此版本修改的資料
  • git show HEAD^ # 前一版修改的資料
  • git show HEAD^^ # 前前一版修改的資料
  • git show HEAD~4 # 前前前前一版修改的資料

Git reset 還原

  • git reset –hard HEAD # 還原到最前面
  • git reset –hard HEAD~3
  • git reset –soft HEAD~3
  • git reset HEAD filename # 從 staging area 狀態回到 unstaging 或 untracked (檔案內容並不會改變)

Git grep

  • git grep “te" v1 # 查 v1 是否有 “te" 的字串
  • git grep “te" # 查現在版本是否有 “te" 的字串

Git stash 暫存

  • git stash # 丟進暫存區
  • git stash list # 列出所有暫存區的資料
  • git stash pop # 取出最新的一筆, 並移除.
  • git stash apply # 取出最新的一筆 stash 暫存資料. 但是 stash 資料不移除
  • git stash clear # 把 stash 都清掉

Git merge 合併

  • Straight merge 預設的合併模式,會有全部的被合併的 branch commits 記錄加上一個 merge-commit,看線圖會有兩條 Parents 線,並保留所有 commit log。
  • Squashed commit 壓縮成只有一個 merge-commit,不會有被合併的 log。SVN 的 merge 即是如此。
  • cherry-pick 只合併指定的 commit
  • rebase 變更 branch 的分支點:找到要合併的兩個 branch 的共同的祖先,然後先只用要被 merge 的 branch 來 commit 一遍,然後再用目前 branch 再 commit 上去。這方式僅適合還沒分享給別人的 local branch,因為等於砍掉重練 commit log。
指令操作
  • git merge <branch_name> # 合併另一個 branch,若沒有 conflict 衝突會直接 commit。若需要解決衝突則會再多一個 commit。
  • git merge –squash <branch_name> # 將另一個 branch 的 commit 合併為一筆,特別適合需要做實驗的 fixes bug 或 new feature,最後只留結果。合併完不會幫你先 commit。
  • git cherry-pick 321d76f # 只合併特定其中一個 commit。如果要合併多個,可以加上 -n 指令就不會先幫你 commit,這樣可以多 pick幾個要合併的 commit,最後再 git commit 即可。

Git blame

  • git blame filename # 關於此檔案的所有 commit 紀錄

Git 還原已被刪除的檔案

  • git ls-files -d # 查看已刪除的檔案
  • git ls-files -d | xargs git checkout — # 將已刪除的檔案還原

Git 維護

  • git gc # 整理前和整理後的差異, 可由: git count-objects 看到.
  • git fsck –full

Git revert 資料還原

  • git revert HEAD # 回到前一次 commit 的狀態
  • git revert HEAD^ # 回到前前一次 commit 的狀態
  • git reset HEAD filename # 從 staging area 狀態回到 unstaging 或 untracked (檔案內容並不會改變)
  • git checkout filename # 從 unstaging 狀態回到最初 Repository 的檔案(檔案內容變回修改前)

Git Rollback 還原到上一版

  • git reset –soft HEAD^
  • 編輯 + git add filename
  • git commit -m ‘rollback’
以下與 遠端 Repository 相關

Git remote 維護遠端檔案

  • git remote
  • git remote add new-branch http://git.example.com.tw/project.git # 增加遠端 Repository 的 branch(origin -> project)
  • git remote show # 秀出現在有多少 Repository
  • git remote rm new-branch # 刪掉
  • git remote update # 更新所有 Repository branch
  • git branch -r # 列出所有 Repository branch

抓取 / 切換 Repository 的 branch

  • git fetch origin
  • git checkout –track -b reps-branch origin/reps-branch # 抓取 reps-branch, 並將此 branch 建立於 local 的 reps-branch

刪除 Repository 的 branch

  • git push origin :heads/reps-branch

2014年10月26日 星期日

Symbol#to_proc

class Symbol
  def to_proc
    Proc.new { |obj, *args| obj.send(self, *args) }
  end
end