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
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>
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>
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
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
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...
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>
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。