1 設定
目前,Rails 外掛程式是建構為寶石,寶石化的外掛程式。如果需要,它們可以使用 RubyGems 和 Bundler 在不同的 Rails 應用程式中分享。
1.1 產生一個寶石化的外掛程式
Rails 內建一個 rails plugin new
指令,它會建立一個架構,用於開發任何類型的 Rails 擴充功能,並具備使用虛擬 Rails 應用程式執行整合測試的能力。使用指令建立你的外掛程式
$ rails plugin new yaffle
透過尋求協助,查看用法和選項
$ rails plugin new --help
2 測試你新產生的外掛程式
導覽到包含外掛程式的目錄,並編輯 yaffle.gemspec
,以取代任何具有 TODO
值的行
spec.homepage = "http://example.com"
spec.summary = "Summary of Yaffle."
spec.description = "Description of Yaffle."
...
spec.metadata["source_code_uri"] = "http://example.com"
spec.metadata["changelog_uri"] = "http://example.com"
然後執行 bundle install
指令。
現在你可以使用 bin/test
指令執行測試,你應該會看到
$ bin/test
...
1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
這會告訴你所有內容都已正確產生,你已準備好開始新增功能。
3 擴充核心類別
本節將說明如何新增一個方法到 String,該方法將可在你的 Rails 應用程式中的任何地方使用。
在此範例中,你將新增一個名為 to_squawk
的方法到 String。首先,建立一個新的測試檔案,並包含一些斷言
# yaffle/test/core_ext_test.rb
require "test_helper"
class CoreExtTest < ActiveSupport::TestCase
def test_to_squawk_prepends_the_word_squawk
assert_equal "squawk! Hello World", "Hello World".to_squawk
end
end
執行 bin/test
以執行測試。此測試應該會失敗,因為我們尚未實作 to_squawk
方法
$ bin/test
E
Error:
CoreExtTest#test_to_squawk_prepends_the_word_squawk:
NoMethodError: undefined method `to_squawk' for "Hello World":String
bin/test /path/to/yaffle/test/core_ext_test.rb:4
.
Finished in 0.003358s, 595.6483 runs/s, 297.8242 assertions/s.
2 runs, 1 assertions, 0 failures, 1 errors, 0 skips
太棒了 - 現在你已準備好開始開發。
在 lib/yaffle.rb
中,新增 require "yaffle/core_ext"
# yaffle/lib/yaffle.rb
require "yaffle/version"
require "yaffle/railtie"
require "yaffle/core_ext"
module Yaffle
# Your code goes here...
end
最後,建立 core_ext.rb
檔案,並新增 to_squawk
方法
# yaffle/lib/yaffle/core_ext.rb
class String
def to_squawk
"squawk! #{self}".strip
end
end
若要測試方法是否如預期運作,請從外掛目錄執行 bin/test
來執行單元測試。
$ bin/test
...
2 runs, 2 assertions, 0 failures, 0 errors, 0 skips
若要實際測試,請切換到 test/dummy
目錄,啟動 bin/rails console
,並開始發出叫聲
irb> "Hello World".to_squawk
=> "squawk! Hello World"
4 新增「acts_as」方法至 Active Record
外掛中常見的模式是將名為 acts_as_something
的方法新增至模型。在本例中,您要撰寫一個名為 acts_as_yaffle
的方法,將 squawk
方法新增至 Active Record 模型。
首先,設定檔案,以便您擁有
# yaffle/test/acts_as_yaffle_test.rb
require "test_helper"
class ActsAsYaffleTest < ActiveSupport::TestCase
end
# yaffle/lib/yaffle.rb
require "yaffle/version"
require "yaffle/railtie"
require "yaffle/core_ext"
require "yaffle/acts_as_yaffle"
module Yaffle
# Your code goes here...
end
# yaffle/lib/yaffle/acts_as_yaffle.rb
module Yaffle
module ActsAsYaffle
end
end
4.1 新增類別方法
此外掛會預期您已將名為 last_squawk
的方法新增至模型。然而,外掛使用者可能已在模型中定義名為 last_squawk
的方法,用於其他用途。此外掛允許透過新增名為 yaffle_text_field
的類別方法來變更名稱。
首先,撰寫一個失敗測試,顯示您想要的行為
# yaffle/test/acts_as_yaffle_test.rb
require "test_helper"
class ActsAsYaffleTest < ActiveSupport::TestCase
def test_a_hickwalls_yaffle_text_field_should_be_last_squawk
assert_equal "last_squawk", Hickwall.yaffle_text_field
end
def test_a_wickwalls_yaffle_text_field_should_be_last_tweet
assert_equal "last_tweet", Wickwall.yaffle_text_field
end
end
執行 bin/test
時,您應該會看到以下訊息
$ bin/test
# Running:
..E
Error:
ActsAsYaffleTest#test_a_wickwalls_yaffle_text_field_should_be_last_tweet:
NameError: uninitialized constant ActsAsYaffleTest::Wickwall
bin/test /path/to/yaffle/test/acts_as_yaffle_test.rb:8
E
Error:
ActsAsYaffleTest#test_a_hickwalls_yaffle_text_field_should_be_last_squawk:
NameError: uninitialized constant ActsAsYaffleTest::Hickwall
bin/test /path/to/yaffle/test/acts_as_yaffle_test.rb:4
Finished in 0.004812s, 831.2949 runs/s, 415.6475 assertions/s.
4 runs, 2 assertions, 0 failures, 2 errors, 0 skips
這表示我們沒有要測試的必要模型 (Hickwall 和 Wickwall)。我們可以從 test/dummy
目錄執行下列指令,在「dummy」Rails 應用程式中輕鬆產生這些模型
$ cd test/dummy
$ bin/rails generate model Hickwall last_squawk:string
$ bin/rails generate model Wickwall last_squawk:string last_tweet:string
現在,您可以透過前往 dummy 應用程式並遷移資料庫,在測試資料庫中建立必要的資料庫表格。首先,執行
$ cd test/dummy
$ bin/rails db:migrate
在此同時,變更 Hickwall 和 Wickwall 模型,讓它們知道它們應該像 yaffle 一樣運作。
# test/dummy/app/models/hickwall.rb
class Hickwall < ApplicationRecord
acts_as_yaffle
end
# test/dummy/app/models/wickwall.rb
class Wickwall < ApplicationRecord
acts_as_yaffle yaffle_text_field: :last_tweet
end
我們也會新增程式碼來定義 acts_as_yaffle
方法。
# yaffle/lib/yaffle/acts_as_yaffle.rb
module Yaffle
module ActsAsYaffle
extend ActiveSupport::Concern
class_methods do
def acts_as_yaffle(options = {})
end
end
end
end
# test/dummy/app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
include Yaffle::ActsAsYaffle
self.abstract_class = true
end
然後你可以回到你的外掛程式根目錄 (cd ../..
) 並使用 bin/test
重新執行測試。
$ bin/test
# Running:
.E
Error:
ActsAsYaffleTest#test_a_hickwalls_yaffle_text_field_should_be_last_squawk:
NoMethodError: undefined method `yaffle_text_field' for #<Class:0x0055974ebbe9d8>
bin/test /path/to/yaffle/test/acts_as_yaffle_test.rb:4
E
Error:
ActsAsYaffleTest#test_a_wickwalls_yaffle_text_field_should_be_last_tweet:
NoMethodError: undefined method `yaffle_text_field' for #<Class:0x0055974eb8cfc8>
bin/test /path/to/yaffle/test/acts_as_yaffle_test.rb:8
.
Finished in 0.008263s, 484.0999 runs/s, 242.0500 assertions/s.
4 runs, 2 assertions, 0 failures, 2 errors, 0 skips
越來越接近了... 現在我們將實作 acts_as_yaffle
方法的程式碼,讓測試通過。
# yaffle/lib/yaffle/acts_as_yaffle.rb
module Yaffle
module ActsAsYaffle
extend ActiveSupport::Concern
class_methods do
def acts_as_yaffle(options = {})
cattr_accessor :yaffle_text_field, default: (options[:yaffle_text_field] || :last_squawk).to_s
end
end
end
end
# test/dummy/app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
include Yaffle::ActsAsYaffle
self.abstract_class = true
end
執行 bin/test
時,你應該會看到所有測試都通過
$ bin/test
...
4 runs, 4 assertions, 0 failures, 0 errors, 0 skips
4.2 新增一個實例方法
這個外掛程式會新增一個名為 'squawk' 的方法到任何呼叫 acts_as_yaffle
的 Active Record 物件。'squawk' 方法會單純設定資料庫中某個欄位的數值。
首先,撰寫一個失敗測試,顯示您想要的行為
# yaffle/test/acts_as_yaffle_test.rb
require "test_helper"
class ActsAsYaffleTest < ActiveSupport::TestCase
def test_a_hickwalls_yaffle_text_field_should_be_last_squawk
assert_equal "last_squawk", Hickwall.yaffle_text_field
end
def test_a_wickwalls_yaffle_text_field_should_be_last_tweet
assert_equal "last_tweet", Wickwall.yaffle_text_field
end
def test_hickwalls_squawk_should_populate_last_squawk
hickwall = Hickwall.new
hickwall.squawk("Hello World")
assert_equal "squawk! Hello World", hickwall.last_squawk
end
def test_wickwalls_squawk_should_populate_last_tweet
wickwall = Wickwall.new
wickwall.squawk("Hello World")
assert_equal "squawk! Hello World", wickwall.last_tweet
end
end
執行測試,確保最後兩個測試失敗,並出現包含 "NoMethodError: undefined method `squawk'" 的錯誤,然後更新 acts_as_yaffle.rb
,讓它看起來像這樣
# yaffle/lib/yaffle/acts_as_yaffle.rb
module Yaffle
module ActsAsYaffle
extend ActiveSupport::Concern
included do
def squawk(string)
write_attribute(self.class.yaffle_text_field, string.to_squawk)
end
end
class_methods do
def acts_as_yaffle(options = {})
cattr_accessor :yaffle_text_field, default: (options[:yaffle_text_field] || :last_squawk).to_s
end
end
end
end
# test/dummy/app/models/application_record.rb
class ApplicationRecord < ActiveRecord::Base
include Yaffle::ActsAsYaffle
self.abstract_class = true
end
最後執行一次 bin/test
,你應該會看到
$ bin/test
...
6 runs, 6 assertions, 0 failures, 0 errors, 0 skips
使用 write_attribute
來寫入模型中的欄位,只是一個外掛程式如何與模型互動的範例,而且並不總是正確的方法。例如,你也可以使用
send("#{self.class.yaffle_text_field}=", string.to_squawk)
5 產生器
只要在你的外掛程式的 lib/generators
目錄中建立產生器,就可以將產生器包含在你的 gem 中。有關建立產生器的更多資訊,請參閱 產生器指南。
6 發布你的 Gem
目前正在開發中的 Gem 外掛程式可以輕鬆地從任何 Git 儲存庫分享。要與其他人分享 Yaffle gem,只要將程式碼提交到 Git 儲存庫(例如 GitHub),並在有問題的應用程式的 Gemfile
中新增一行
gem "yaffle", git: "https://github.com/rails/yaffle.git"
執行 bundle install
之後,你的 gem 功能就會提供給應用程式使用。
當 gem 準備好要作為正式版本分享時,可以將它發布到 RubyGems。
或者,你可以受益於 Bundler 的 Rake 任務。你可以使用以下指令看到完整的清單
$ bundle exec rake -T
$ bundle exec rake build
# Build yaffle-0.1.0.gem into the pkg directory
$ bundle exec rake install
# Build and install yaffle-0.1.0.gem into system gems
$ bundle exec rake release
# Create tag v0.1.0 and build and push yaffle-0.1.0.gem to Rubygems
有關在 RubyGems 中發佈寶石的更多資訊,請參閱:發佈您的寶石。
7 RDoc 文件
外掛程式穩定後,您準備好部署時,請發揮善心,為它撰寫文件!幸運的是,為外掛程式撰寫文件很簡單。
第一步是更新 README 檔案,其中包含有關如何使用外掛程式的詳細資訊。幾個關鍵事項包括
- 您的姓名
- 如何安裝
- 如何將功能新增到應用程式(幾個常見使用案例範例)
- 警告、陷阱或提示,可能有助於使用者並節省他們的時間
README 檔案完善後,請瀏覽並將 RDoc 註解新增至開發人員將使用的所有方法。慣例上,也會將 # :nodoc:
註解新增至未包含在公開 API 中的程式碼部分。
註解完善後,請導覽至外掛程式目錄並執行
$ bundle exec rake rdoc
7.1 參考
意見回饋
我們鼓勵您協助提升本指南的品質。
如果您發現任何錯字或事實錯誤,請協助我們修正。若要開始,您可以閱讀我們的文件貢獻部分。
您也可能發現不完整或過時的內容。請務必新增任何遺漏的說明文件。請務必先查看Edge Guides,以驗證問題是否已在主分支中修正。查看Ruby on Rails 指南準則,了解風格和慣例。
如果您發現需要修復但無法自行修補的問題,請開啟問題。
最後但同樣重要的是,歡迎在官方 Ruby on Rails 論壇上針對 Ruby on Rails 文件進行任何討論。