如何寫rails插件

如何實現一個簡單的插件?下面實現一個在model中能輸出hello world的插件。

注:()中的斜體是本人的心得體會,可忽略。

 

第一步,在工程目錄下新建一個插件,運行

rails generate plugin HelloWorld


這個命令會生成以下目錄文件:

      create  vendor/plugins/hello_world
      create  vendor/plugins/hello_world/MIT-LICENSE
      create  vendor/plugins/hello_world/README
      create  vendor/plugins/hello_world/Rakefile
      create  vendor/plugins/hello_world/init.rb
      create  vendor/plugins/hello_world/install.rb
      create  vendor/plugins/hello_world/uninstall.rb
      create  vendor/plugins/hello_world/lib
      create  vendor/plugins/hello_world/lib/hello_world.rb
      invoke  test_unit
      inside    vendor/plugins/hello_world
      create      test
      create      test/hello_world_test.rb
      create      test/test_helper.rb

這裏面比較重要的文件就是init.rb和lib/hello_world.rb,在插件被加載時,init.rb會先被加載,完成初始化,lib下放實現代碼庫。

 

第二步,編輯lib下的hello_world.rb文件,定義一個實現輸出Hello World的方法say

hello_world.rb:

module HelloWorld
   def say
     p 'Hello World!'
   end
end

 

第三步,插件完成了,下面在model中使用這個插件。在init.rb文件里加入

init.rb:

ActiveRecord::Base.send(:include, HelloWorld)

這樣就爲所有的model都混入了HelloWorld,say方法也就成了model裏的實例方法了。


這樣就在ActiveRcord:Base裏混入了HelloWorld模塊,而model又是繼承於ActiveRecord::Base,所以model就能直接調用HelloWorld中的靜態方法了。
send所發送的消息,在程序運行時是可變的,而且,send還能打開module或類中的private方法,使用上更加靈活。


在model中使用,post.rb:

class Post < ActiveRecord::Base
end
 

在控制檯中看一下結果: 

1.8.7 :001 >  Post.new.say
"Hello World!"
 => nil 

沒有問題!一個簡單的插件就完成了,但這樣HelloWorld裏的方法對所有的model都是打開的,如果不想這樣,可以這樣這樣寫

hello_world.rb:

module HelloWorld
   def self.included(base)
     base.extend(ClassMethods)
   end
   
   module ClassMethods    
      def hellolize 
        include HelloWorld::InstanceMethods
      end                  
   end
 
   module InstanceMethods
     def say
       p 'Hello World!'
     end
   end
end

 

當HelloWorld模塊被include時,方法included將被調用,混含的類的名字被傳入,再調用了extend方法,ClassMethods模塊中的方法就成了混入類中的類方法了,就可以直接調用了。當hellolize方法被調用時,InstanceMethods就被混入類中了,成了混入類中的實例方法了。這樣做的好處是,我想在哪個model裏便用say方法,就在哪個model裏調用hellolize方法,這樣做保證了方法的安全性


init.rb:

ActiveRecord::Base.send(:include, HelloWorld)


在model中使用,post.rb:

class Post < ActiveRecord::Base
  hellolize
end

 

在控制檯中看一下結果: 

1.8.7 :001 > Post.new.say
"Hello World!"
 => nil 

 

以上只是一個實現過程,可以根據實際情況把重複功能代碼寫成插件使用。

當然,一個完整的插件有完整的驗證和測試,此例子純粹供練手,僅供參考。

 

這裏有個比較好的例子:http://railscasts.com/episodes/33-making-a-plugin?view=asciicast

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章