over 2 years ago

中國區

金數據

投遞管道:China Ruby conf
09/24 - 於會場投遞履歷
09/25 - 早上九點半面試
09/26 - 信件獲得感謝函
面試等待結果共計1天(自最後一次面試起計算)。
結果:感謝函

英語流利說

投遞管道:China Ruby conf
09/24 - 拉勾網投遞履歷
09/24 - 會場當下HR邀約面談
09/27 - 信件收到實作一個mini project
09/29 - 完成並回傳source code and production demo
10/11 - 線上面試
結果:無聲卡

台灣區

snapask

投遞管道:linkedin
09/15 - linkedin收到邀請信
09/26 - 以Email回覆並投遞履歷
09/28 - 第一階段線上面試
10/04 - 第二階段公司面試
10/05 - 收到感謝函
面試等待結果共計1天(自最後一次面試起計算)。
結果:感謝函

貝殼放大Backer-Founder (值得反推薦的公司)

投遞管道:貝殼放大工程部門徵人網站

10/7 - 主動發送履歷至貝殼放大信箱
10/12 - 早上十一點第一次面試
貝殼放大的環境氛圍,令我覺得好奇,在初步面談(第一次面試)時感到非常符合自我期待以及嚮往的地方,面試我的技術長也在對話說不斷表示我的人格特質等一些特點符合他所期待,同時也指點我個人作品的部分程式碼,認為可以有更佳的寫法,並且主動告知我面試題目的一些答案以及著手學習的方向,後面提到技術層面雖有待加強,也認為人格特質比技術層面的人才更難尋,不過提到技術部分認為我可以在短時間內上手,應該不是太大問題,整個過程是輕鬆愉快的。

10/19 - 下午三點第二次面試
第二次面試時由技術長與營運長一同面試,過程中大概就雙方互問問題,公司挖我人格特質以及解決問題的能力,而我反問公司的營運方向以及進到公司首先要碰到哪些問題,可以事先準備,這邊提到的伏筆就是由我主動詢問假設性問題「如果我有幸進到貴公司時,前三個月大概會碰到哪些事情或技術上的問題?」,回答我的除了一些比較針對公司細節的部分這邊不多贅述,有一點比較重要的是提到應該會叫我去做Rebuilding Rails這本電子書,來加強我Ruby的概念以及較底層的觀念與用法,同時我也很認同他們所提到的會寫Rails不一定懂Ruby的想法,也提到對Ruby掌握度較高時,可以在Rails上面開發更有彈性。

10/27 - 我方主動詢問是否有結果(無回音)
然後就沒下文了,在這期間卻可以不斷更新inside職缺以及貝殼放大自家徵人網站上的內容。

11/4 - 我方透過臉書訊息主動詢問營運長面試結果,得到回覆是有收到信,不過剛好在放假所以比較慢回,並且還在評估中,還需約一週時間。

11/11 - 對方寄信反問我面試這一個月下來有何自主進步與收穫

11/12 - 回信告知這一個月的自我學習成長以及部落格技術文的新增

11/14 - 對方寄送感謝函表示不適合

總結
該公司在徵才的過程相當謹慎嚴謹,同時因為非常尊重彼此的交流與契合度,所以電子郵件會以放假及忙碌等理由於兩個禮拜後回信是相當正常的事情,過程中兩次面試給你高度肯定並且表明這職位適合你的時候,完全不代表你有任何機會錄取,這應是所有求職者應當知道的道理,最後,如沒有長期抗戰的心理準備以及夠閒的長時間較不建議投遞該公司職缺。

面試等待結果共計25天(自最後一次面試起計算)。

結果:感謝函

果子云數位科技有限公司

投遞管道:104
11/2 - 下午三點半面試
11/7 - 獲得錄取通知信
面試等待結果共計5天(自最後一次面試起計算)。
結果:offer get

T客邦

投遞管道:104
11/10 - 早上十點面試
11/27 - 收到感謝函
面試等待結果共計17天(自最後一次面試起計算)。
結果:感謝函

睿傑國際商業服務有限公司

投遞管道:104
11/16 - 下午三點第一次面試
11/17 - 下午三點第二次線上面試
11/17 - 晚間六點電話通知錄取結果
面試等待結果共計0.125天(自最後一次面試起計算)。
結果:offer get

幫你優BoniO

投遞管道:104 + 1111
11/14 16:40 - 收到信件做題目,並在一天內作答後回傳
11/14 17:40 - 作答完畢並回傳
11/14 18:25 - 收到面試邀請
11/17 - 早上十點面試
11/23 - 電話通知錄取結果並詢問我考慮時間
面試等待結果共計6天(自最後一次面試起計算)。
結果:offer get

 
over 2 years ago

zsh是一種Shell,與bash, tesh等等shell很像,不過他多了一些很方便的人性化功能,例如在tab的時候會幫你找出相似的路徑或檔案,可以直接選取來幫你補上命令列,如果遇到指令的錯誤還會嘗試幫你糾正。

不過他最厲害的是有oh-my-zsh的plugin可以使用,可以替代很多原本會寫的設定,以外掛的方式掛進去,而且還有很多theme可以選,以及客製化。

這篇文章就以Mac OSX 來作安裝說明,畢竟Debian/Ubuntu Linux不太一樣,需要自行安裝zsh。

使用iTerm2替換掉Mac原生terminal

一般來說用Mac進行程式開發的設計師很少使用原生的Terminal進行開發,多半都是使用iTerm2,並自行設定配色與字體,安裝方式很簡單,到 http://www.iterm2.com/下載後拖拉到應用程式,並打開就可以使用,接下來我們在搭配zsh來使用,就可以做出更強大又美觀的Terminal來開發囉。

1.Install zsh

chsh -s /bin/zsh

2.Install oh-my-zsh

curl -L http://install.ohmyz.sh | sh

3.修改theme
#ZSH_THEME="robbyrussell" <-- 將這行註解掉
ZSH_THEME="agnoster"
4.安裝 agnoster 所需字型

由於 agnoster 需要特殊字型。
所以必須安裝 patched 過的三個字體:https://gist.github.com/1595572。(下載後雙擊安裝這三個字體。)

5. 安裝 SOLARIZED 布景

SOLARIZED 布景是特殊調製的一個背景。按此 下載 最新版本。

解壓縮後裡面有很多布景。

6.替換掉 iTerm 布景
  • Preference -> Profiles -> Colors -> Load Presets -> Import,載入 iterm2-colors-solarized 目錄下的兩個 itermcolors
  • Preference -> Profiles -> Colors -> Load Presets,載入 Solarized Dark
7.替換掉 iTerm 字型
  • Preference -> Profiles -> Text 換成 Menlo 14 字體
8.替換掉 agnoster 的 theme source code

修改 ~/.oh-my-zsh/themes/agnoster.zsh-theme 換成以下內容

https://gist.github.com/agnoster/3712874/raw/c3107c06c04fb42b0ca27b0a81b15854819969c6/agnoster.zsh-theme

9.客製化裝置名稱

打開檔案,編輯他

vim ~/.oh-my-zsh/themes/agnoster.zsh-theme

找到以下內容

# Context: user@hostname (who am I and where am I)

prompt_context() {
  if [[ "$USER" != "$DEFAULT_USER" || -n "$SSH_CLIENT" ]]; then
    prompt_segment black default "%(!.%{%F{yellow}%}.)$USER@%m"
  fi
}

修改為

# Context: user@hostname (who am I and where am I)

prompt_context() {
  if [ $DEFAULT_USER ]; then
    prompt_segment blue 7 "%(!.%{%F{yellow}%}.)$DEFAULT_USER"
  elif [[ "$USER" != "$DEFAULT_USER" || -n "$SSH_CLIENT" ]]; then
    prompt_segment blue 7 "%(!.%{%F{yellow}%}.)$USER@%m"
  fi
}

11.簡化路徑

找到以下

# Dir: current working directory

prompt_dir() {
  prompt_segment blue black '%~'
}

替換成

# Dir: current working directory

prompt_dir() {
  prompt_segment 7 black '%c'
}
12. 加入Ruby version判斷

vim ~/.oh-my-zsh/themes/agnoster.zsh-theme

檔案內任意新增以下程式碼

# Ruby version

prompt_ruby() {
  grep 'rails' 'Gemfile' >/dev/null 2>&1
  if [ $? -eq 0 ]; then
    local ruby_version=''
    if which rvm-prompt &> /dev/null; then
      ruby_version="$(rvm-prompt i v g)"
    else
      if which rbenv &> /dev/null; then
        ruby_version="$(rbenv version | sed -e "s/ (set.*$//")"
      fi
    fi
    prompt_segment red default "$ruby_version"
  fi
}

已經寫好RVM的ruby version block就將其內容載入

找到以下並加入prompt_ruby

Main prompt

build_prompt() {
  RETVAL=$?
  prompt_status
  prompt_context
  prompt_dir
  prompt_ruby
  prompt_git
  prompt_end
}
13.載入美化設定

一樣去編輯剛剛的檔案

vim ~/.oh-my-zsh/themes/agnoster.zsh-theme

在第一行加入以下內容

DEFAULT_USER="Nic"

之後再重新 source ~/.zshrc,就可以完成介面美化囉。

 
over 2 years ago

Dynamic Method

最近因為在應用上覺得了解Ruby的底層可以在程式撰寫的時候有佳的可讀及維護性,一方面也是在網路上看到的資源做個筆記,之前累積太多的技術債該是找時間來還了,這篇就來講講如何讓Ruby做到程式碼自己生產程式碼的一些小tips。

仰賴Ruby的特性,我們可以讓他動態產生method,動態產生是只程式在runtime情況下生成,並不是事先寫好的,而這種應用的情況常常發生於如下的範例情況:

先設定一個SourceData的class,可以從這裡拿到get_name之類的實例方法(instance method)取得實例變數(instance variables)的值。

class SourceData

  def initialize(user)
    @user = user
  end

  def get_name
    puts "#{@user}_name"
  end

  def get_address
    puts "#{@user}_address"
  end

  def get_phone
    puts "#{@user}_phone"
  end

end

我們從另一個叫做User的class,透過SourceData來獲取他的實例變數

class User
  def initialize(source_data)
    @source_data = source_data
  end
  
  def name
    @source_data.get_name
  end
  
  def address
     @source_data.get_address
  end
  
  def phone
     @source_data.get_phone
  end
  
 end

這裡會產生一個問題,如果我們在SourceData的class新增一個get_email的method,勢必得回去User的class裡面多寫一次email的method,這違反了Open/closed principle,在軟體設計原則有個最常聽到的DRY(Don’t Repeat Yourself),簡單來說不需要一直重複寫相同或是類似的程式碼,除了可以讓code看起來更DRY一些,也在日後維護的時候有更高的可讀性與彈性。

舉例來說如上例的程式碼,實作的內容都相近差不多的,其實我們可以用動態定義的方式來整理這些像是重複的程式碼,Ruby定義動態方法使用define_method

define_mehtod用法

define_method :hello do |param|
    puts "Hello, #{param}"
end

這樣一來就可以用define_method來整理剛剛那段看起來有點重複的程式碼

class User

  def initialize(source_data)
    @source_data = source_data
    @source_data.methods.grep(/^get_(.*)$/) {
      User.define_infos($1)
    }
  end

  def self.define_infos(name)
    define_method(name) {
      @source_data.send("get_#{name}")
    }
  end
end

這樣寫的好處是當程式需要延展跟擴充的時候能夠有足夠的彈性,我們不容易牽一髮動全身,可以專注在焦點本身,以上述例子來說,不論SourceData如何新增get_*的實例方法時,都能更優雅以動態方式在User class產生method。

Dynamic Dispatch

如果this_object.call_method,那麼this_object就稱為接收者,Dynamic Dispatch 是指依照接收者的物件類型,來決定呼叫的方法,這個技巧會非常需要用到 send。\

send用法

send.其實一樣,不同的地方是他可以把方法當成參數,傳送給接收者去call_mehtod。

class A
    def call_method
    puts "This is a method in class A"
    end
  end
end

我們可以透過send以及.來呼叫實例方法A

a = A.new
a.call_method                         # => "This is a method in class A"

a.send(:call_method)            # => "This is a method in class A"

這裡把 call_method 當成 send 的參數(可以是 hash,也可以是 string),然後丟給接收者;既然方法可以被當成物件來丟,意思也就是可以把一些方法存起來成一個 array,然後依照不同需求的時候丟給接收者使用。

這樣一來我們學會使用send就跟上面所提到的Dynamic Method有異曲同工之妙

因為send可以當作動態定義來呼叫,所以可以試著這樣寫

a = A.new
str = "call_method"
h = :call_method
a.send(str)          # => "This is a method in class A"

a.send(h)            # => "This is a method in class A"

以上就是動態定義method跟動態call_method的一些小方法。

ref
-Ruby 的 Dynamic Dispatch 技巧
-Ruby 也可這樣寫
-http://blog.chh.tw/posts/dynamic-method/

 
over 2 years ago

這陣子在玩Rebuilding Rails,在教學裡面需要自己做一隻Gem也就是library,雖然對現在來講是兩年前的教學,但電子書寫的非常清楚也很好懂,不過在build gem的時候發生了一些錯誤,就把他筆記下來囉。

當我們下指令 gem build rulers.gemspec

編譯成功的結果應該是

  Successfully built RubyGem
  Name: rulers
  Version: 0.0.1
  File: rulers-0.0.1.gem

但當我們第二次進行編譯時,我拿到一個警告並且無法編譯成功

WARNING:  See http://guides.rubygems.org/specification-reference/ for help
ERROR:  While executing gem ... (Gem::InvalidSpecificationException)
    rulers-0.0.1 contains itself (rulers-0.0.1.gem), check your files list

因為要做套件更新,所以必須重新編譯,但發生了這個錯誤我們嘗試把這隻已編譯的檔案刪除

rm rulers-0.0.1.gem

這時候請在編譯前先做git add .,不然會得到["rulers-0.0.1.gem"] are not files的一個訊息,這是因為編譯時仰賴的rulers.gemspec會去call git並且尋找有什麼檔案是包含在這隻gem裡面,我們可以在這隻檔案的設定裡面看到的定義如下

...
spec.files  = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
...

git ls-files會顯示出每一個git所追蹤的檔案,如果你建立或重新編輯新檔案時,務必在rebuild之前進行git add .

否則就會出現這樣的一個錯誤導致gem無法build。

參考資源:

 
over 2 years ago

include v.s extend

在Ruby裡,Class只能單一繼承,而為了保有DRY(Do not repeat yourself)的風格與彈性,ruby提供了module的概念。

module是一些method的集合,允許class以混入(mixin)的方式去取得這些method來避免重複的程式碼,在這個過程中可以使用include以及extend來辦到,但畢竟兩種寫法一定會有其差異存在,就讓我們用程式碼的方式來了解。

include

module Log 
  def class_type
    "This class is of type: #{self.class}"
  end
end

class TestClass 
  include Log 
end

tc = TestClass.new.class_type
puts tc #This class is of type: TestClass

從上述例子我們可以看到 include是讓class所產生的instance直接繼承module裡的method,有點相似JavaScript裡的function.prototype。

extend

module Log
  def class_type
    "This class is of type: #{self.class}"
  end
end

class TestClass
  extend Log
  # ...

end

tc = TestClass.class_type
puts tc  # This class is of type: TestClass

當用extend來替換掉include時,extend則是讓class具有module裡的method但不會繼承給instance。

如果你直接實例化 TestClass的話會得到一個NoMethodError。

Require

Require方法允許你載入外部的Library,聰明的是他會防止你重複加載一樣的外部函式庫,範例如下:

test_library.rb
  puts "load this library."
test_requiry.rb
puts(require './test_library')
puts(require './test_library')

#結果將為

# load this library.

# true

# false

當你重複載入一個library的時候,將會返回false值。

參考資源:

 
over 2 years ago

Rails裡面我們常調用到來自ActiveRecord::FinderMethods的find_by這個方法,但神奇的是如果我們在後面多加變成find_by_id or find_by_name之類的方式竟然都不會出錯,這個神奇方法的底層就來自於Ruby的method missing,只要在適當的時機覆寫他就可以達到以程式撰寫程式碼的效果也就是所謂Meta-programming。

假設我們不使用method missing,而使用define method,就要定義一些有可能根本用不到的方法,例如:

Read on →
 
over 2 years ago

假設OrderItem.all會把整個訂單的明細都吐出來,但我們只想找這筆訂單裡面food_name這個欄位的最多出現次數。

想法是可以先將這個欄位的東西,都倒進Array裡面,變成陣列之後相對好處理。

實際方法在Rails 3.2之後,有了更好的method,只需對OrderItem下

array = OrderItem.pluck(:food_name)

其結果就會只將所有food_name都倒進去Array

再來要抓出在陣列裡出現最多次數的Item,就可以用max_by

array.max_by { |i| o.count(i)}

來取得結果。

參考:

 
over 2 years ago

Heroku上的時區設定就如同一般Server設定一樣採用UTC(世界標準時間)。

最近在上面架設了Redmine,開出來的票時間跟本地不同,所以必須將UTC+8,不過Heroku上面的設定非常簡單。

你只要輸入

heroku config:add TZ="Asia/Taipei"

就可以將機器時間調整為台北時間了。

至於TZ裡面要改成不一樣國家的時區,可以參照List_of_TZ_Database_Time

 
over 2 years ago

部屬前碎念

我有一個專案是抓subdomin在判斷群組,就像Logdown一樣依照次級網域來引導到不同使用者的部落格一樣,礙於某些因素將其專案從機器上搬出來,原本打算搬到Heroku,但發現naked domain實在是很難搞定,最後決定是搬到Amazon Ec2上面,因為過程其實做過很多次,常常健忘就把這些記錄下來。

網域申請我本身是使用Godaddy,他裡面的CNAME指向不能在heroku上面玩次級網址,因為heroku沒有Public IP給你使用,所以用EC2的彈性會好很多,畢竟服務不一樣。

Heroku是屬於PaaS 類型(Platform as a Service),支援特定語言或框架,幫你把很多細節處理好,一鍵部屬也不必多作設定。

Read on →
 
over 2 years ago

近期看了些文章有感而發,稍微整理成自己腦袋的東西,也順便挑戰這個主題。

前言

社會不斷在變遷,就算待在台灣,你也要知道世界不是繞著台灣轉,而是同步進行激烈的競爭,只是這個被媒體新聞蓋台的世界,讓台灣的井越來越深,以管窺天已經不是一種可笑的形容,而是真真切切變成每一個人的習慣,然後你不得指正別人,因為探出頭看別人的都會被像地鼠一樣打下去,已經形成一種「我不厲害,但你也別想比我厲害」的可怕情況。

這些情況其實都在你我身邊不斷發生,只是我們好像有了默契一樣無力去矯正這些事情,那其實最根本的源頭在於「教育」,不管是學校、補習班、甚至是父母、親人,好像都不斷灌輸一樣的觀念,你只要「念好書」就會理所當然有「好工作」。

Read on →