簡介 plugins


Rails的plugins並非定義用來為Rails作功能修正或擴充,Rails的plugins可以在應用程式載入時啟用,無需開發人員明確地引用,Rails的plugin為應用程式本身作功能裝飾或擴充(像是對Ruby核心程式庫作擴充),但加入後不影響應用程式原有的程式碼,Rails的plugins是可以獨立於應用程式之外發展的元件,擁有自己的開發週期。

例如Ruby核心程式庫中,Array並沒有map_with_index方法,假設你在Rails中,想對Ruby核心程式庫進行擴充,方便程式進行撰寫,則可以如下:

~gossip\$ rails generate plugin core_ext
      create  vendor/plugins/core_ext
      create  vendor/plugins/core_ext/MIT-LICENSE
      create  vendor/plugins/core_ext/README
      create  vendor/plugins/core_ext/Rakefile
      create  vendor/plugins/core_ext/init.rb
      create  vendor/plugins/core_ext/install.rb
      create  vendor/plugins/core_ext/uninstall.rb
      create  vendor/plugins/core_ext/lib
      create  vendor/plugins/core_ext/lib/core_ext.rb
      invoke  test_unit
      inside    vendor/plugins/core_ext
      create      test
      create      test/core_ext_test.rb
      create      test/test_helper.rb


接著開啟vendor/plugins/lib/core_ext.rb進行編輯:
  • core_ext.rb
# CoreExt
class Array def map_with_index mapping = [] each_with_index do |e,i| mapping << yield(e,i) end mapping end end

如此只要require 'core_ext',就可以使用這邊定義的功能,以rails c來驗證一下:

~gossip\$ rails c
irb(main):001:0> require 'core_ext'
=> true
irb(main):002:0> [1, 2, 3].map_with_index do |e, i|
irb(main):003:1*     e + i
irb(main):004:1> end
=> [1, 3, 5]
irb(main):005:0>

為了在Rails啟動應用程式之後,可以這邊執行定義的程式,要編輯vendor/plugins/core_ext/init.rb:
  • init.rb
# Include hook code here
require 'core_ext'

如此啟動Rails之後,Array就會有map_with_index,可以啟動rails c來看一下:

~gossip\$ rails c
Loading development environment (Rails 3.1.3)
irb(main):001:0> [1, 2, 3].map_with_index do |e, i|
irb(main):002:1*     e + i
irb(main):003:1> end
=> [1, 3, 5]
irb(main):004:0>

在vendor/plugins中的plugins,通常是與應用程式相關性高的plugins,稱之為vendored plugin,如果你要開發的plugins具有通用性,則可以建立為Gem,稱之為gemified plugins,Rails 3之後,可以使用rails plugins new建立開發plugins的專案。例如:

~\$ rails plugin new string_ext
      create 
      create  README.rdoc
      create  Rakefile
      create  string_ext.gemspec
      create  MIT-LICENSE
      create  .gitignore
      create  Gemfile
      create  lib/string_ext.rb
      create  lib/tasks/string_ext_tasks.rake
      create  lib/string_ext/version.rb
      create  test/test_helper.rb
      create  test/string_ext_test.rb
      append  Rakefile
  vendor_app  test/dummy
         run  bundle install


接下來編輯lib/string_ext.rb:
  • string_ext.rb
module StringExta
end
class String
    def brace(s, e)
        s + self + e
    end

    def brace!(s, e)
        self[0, 0] = s
        self << e
    end
end

修改一下string_ext_gemspec中的資訊:
  • string_ext_gemspec
...
# Describe your gem and declare its dependencies: Gem::Specification.new do |s| s.name = "string_ext" s.version = StringExt::VERSION s.authors = ["caterpillar"] s.email = ["caterpillar@openhome.cc"] s.homepage = "https://openhome.cc" s.summary = "Summary of StringExt." s.description = "Description of StringExt." s.files = ["lib/string_ext.rb"] end

接著就可以建立Gem了:

~string_ext\$ gem build string_ext.gemspec
WARNING:  no rubyforge_project specified
  Successfully built RubyGem
  Name: string_ext
  Version: 0.0.1
  File: string_ext-0.0.1.gem


如果要安裝這個Gem,可以如下:

~string_ext\$ sudo gem install string_ext-0.0.1.gem
Successfully installed string_ext-0.0.1
1 gem installed
Installing ri documentation for string_ext-0.0.1...
Installing RDoc documentation for string_ext-0.0.1...


使用irb測試一下:

~\$ irb
irb(main):001:0> require 'string_ext'
=> true
irb(main):002:0> name = "Justin"
=> "Justin"
irb(main):003:0> name.brace '[', ']'
=> "[Justin]"
irb(main):004:0> name
=> "Justin"
irb(main):005:0> name.brace! '[', ']'
=> "[Justin]"
irb(main):006:0> name
=> "[Justin]"
irb(main):007:0>

更多Rails plugins的定義與說明,可以參考 The Basics of Creating Rails Plugins,有關 RubyGem 的定義與說明可以參考 RubyGems Guides