Project

democi

0.0
No commit activity in last 3 years
No release in over 3 years
just a gem for demo
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Runtime

~> 5.0
 Project Readme

Gem Version Code Climate Test Coverage Build Status

來把 rails app 中常用的 view helper 打包成 gem 吧

目標

  • 把 rails app 的 view helper 打包成 gem
  • gem 本身用 rspec 測試
  • 串接 Code Climate 和 Travis CI
  • 推上 rubygems

由於相關的關鍵字都太 general,組合出來的結果通常不是我在找的東西,踩雷的過程歡樂無比(?),於是決定做個 demo gem 一勞永逸 ✊

打包 gem

這裡有兩種做法,一種是從陽春 gem 開始自幹 railtie,一種是直接做成 mountable rails plugin。以結論來說後者寫起來輕鬆很多,但工程師就是喜歡踩雷自幹,所以還是從這邊開始吧 XD

陽春自幹

起手式 bundle gem democi,生成如下的空包彈:

# projects/democi
.
├── .gitignore
├── .rspec
├── .travis.yml
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── democi.gemspec
├── bin
│   ├── console
│   └── setup
├── lib
│   ├── democi
│   │   └── version.rb
│   └── democi.rb
└── spec
    ├── democi_spec.rb
    └── spec_helper.rb

接著改一下 gemspec

# democi.gemspec
lib = File.expand_path("../lib", __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require "democi/version"

Gem::Specification.new do |spec|
  spec.name = "democi"
  spec.version = Democi::VERSION
  spec.authors = ["Tsehau Chao"]
  spec.email = ["jodeci@5xruby.tw"]

  spec.description = "just a gem for demo"
  spec.summary = "just a gem for demo"
  spec.homepage = "https://github.com/jodeci/democi"
  spec.files = Dir["lib/**/*", "LICENSE.txt", "README.md"]
end

由於最終目標是要丟上 Travis CI,順手把 add_development_dependency 的 gem 通通移到 Gemfile,不然推上去後 Travis CI 會找不到套件:

# Gemfile
source "https://rubygems.org"
gemspec

group :test, :development do
  gem "bundler"
  gem "rake"
  gem "rspec"
end

確認動作是否正常:

$ bundle install
$ gem build democi
$ rake spec

用 railtie 自幹 helper

如果一開始就乖乖用 mountable rails plugin 來做的話,這邊就不需要這麼麻煩 XD

先把要打包的功能寫在 Democi::ViewHelpers

# lib/democi/view_helpers.rb
module Democi
  module ViewHelpers
  	def demo
  	  "hello, world!"
  	end
  end
end

接著透過 railtie 讓 rails app 可以使用Democi::ViewHelpers

# lib/democi/railtie.rb
require "rails/railtie"
require "democi/view_helpers"
module Democi
  class Railtie < ::Rails::Railtie
    initializer "democi.view_helpers" do
      ActiveSupport.on_load(:action_view) { include Democi::ViewHelpers }
    end
  end
end

railtie.rb 需要再載入 gem 的主程式:

# lib/democi.rb
require "democi/version"
require "democi/railtie"
module Democi
end

gemspec 也補一下 dependency:

# democi.gemspec
Gem::Specification.new do |spec|
  # ...
  spec.add_dependency "rails", "~> 5.0"
  spec.add_dependency "activesupport", "~> 5.0"
end

把目前的進度打進 gem 裡,順便確定一下環境沒有被玩壞:

$ bundle install
$ gem build democi
$ rake spec

拿進 rails app 實測

隨便開一個 rails app,把剛剛打包的 gem 裝進來:

# Gemfile
gem "democi", path: "projects/democi" # 先測本機就好

隨便找個 view 戳一下我們剛剛包進去的 demo() 方法:

# view/something.html.erb
<%= demo %>
=> hello, world!

恭喜,可以動了!

那來補測試吧

這裡有兩個選擇,一個是徹底硬幹,模擬最低限度的 rails 環境,一個是老老實實弄成 rails engine,該有什麼功能就有什麼功能。以本文的範例來說雖然的確可以自幹,但實務上很快就會遇到自幹的極限,所以這邊還是乖乖做成 rails engine 吧。

產生 dummy app

找一個不會礙事的地方,產生 plugin 的空包彈:

# temp
$ rails plugin new democi --mountable --dummy-path=spec/dummy --skip-test-unit

空包彈裡有很多檔案,我們只需要 spec/dummy 這個目錄:

$ cp -rf temp/democi/spec/dummy projects/spec/dummy
$ rm -rf temp/democi

加進測試用的 gem:

# Gemfile
group :test, :development do
  # ..
  gem "rspec-rails"
  gem "sqlite3"
end

補強一下 .gitignore(記得先 commit):

# .gitignore
/spec/dummy/db/*.sqlite3
/spec/dummy/log/*.log
/spec/dummy/tmp/*
!/spec/dummy/tmp/.keep

重新 bundle,來開看看 dummy app:

$ bundle install
$ cd spec/dummy
$ rails server

喔喔喔噴錯了!

uninitialized constant Democi::Engine (NameError)

自幹 engine

從錯誤訊息來看就是要再自幹 engine:

# lib/democi/engine.rb
require "rails/engine"
module Democi
  class Engine < ::Rails::Engine
  end
end

一樣也是要把 engine.rb 載入主程式:

# lib/democi.rb
require "democi/engine"

再來啟動一次看看:

$ cd spec/dummy
$ rails s

成功了!這樣就算是初步設定好 dummy app 了。保險起見,確認一下可以正常動作(到底踩了多少雷):

$ rake spec

設定 rspec

先做一支 rails_helper 給測試程式使用:

# spec/rails_helper.rb
require "spec_helper"
require "dummy/config/environment"
require "rspec/rails"

馬上來寫測試:

# spec/helpers/application_helper_spec.rb
require "rails_helper"
describe ApplicationHelper, type: :helper do
  it { expect(helper.demo).to eq "hello, world!" }
end

覺得礙眼的話,就順手把預設的 democi_spec.rb 砍掉吧。寫完之後,依開發環境的狀況,rake spec 可能會狂噴錯 XD 由於通常都是路徑問題,因此補強一下:

# .rspec
--format documentation
--color
--require spec_helper
# spec/spec_helper.rb
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
require "rubygems"
require "bundler/setup"
require "democi"

再來跑一次應該就會過了:

$ rake spec

Code Climate & Travis CI

先到這邊把你的 github repo 設定起來。Open source 專案可以免費使用。直接以自己的 github 帳號登入最單純:

加進 test coverage 的 gem 並 bundle:

# Gemfile
group :test do
  gem "simplecov"
  gem "codeclimate-test-reporter", "~> 1.0.0"
end

加進 test coverage 的設定。這要放在檔案最上面,爬的範圍才會正確:

# spec/spec_helper.rb
require "simplecov"
SimpleCov.start do
  add_filter "spec"
end

$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
require "rubygems"
require "bundler/setup"
require "democi"

從 Code Climate 管理介面取得 repo token,加進 Travis CI 的設定檔:

# .travis.yml
addons:
  code_climate:
     repo_token: {token}
     
after_success:
  - bundle exec codeclimate-test-reporter

改好推上去,就可以在 Code Climate 和 Travis CI 的管理介面看到結果了:

$ git push

沒有另外設定的話,Travis CI 是預設用 rake spec 跑測試的。實務上大家都知道這個常常會杯具,所以通常是會再調教的:

# .travis.yml
script:
  - bundle exec rake -f spec/dummy/Rakefile db:migrate
  - bundle exec rspec spec --format documentation

rubygems

這部分網路上資料很多,就隨便講一下就好(喂)

先到 RubyGems.org 註冊帳號。其實打包 gem 的第一步是要先想一個響亮又沒有人用的名字 XD 確定沒有人用的話,就是把打包完的 gem 推上去:

$ gem build democi
$ gem push democi-0.1.0.gem

推上去之後,其他人就可以用 gem install democi 安裝了!