如何寫一個有View功能的Rails Gem

因為遇到一個需求需要將Rails的View部分抽離到Gem裡面

也就是要實作一個具有Rails View功能的Gem

在此說明一下如何做到這件事情

1. 首先產生一個Gem

bundle gem product_quote

如此就會產生一個product_quote的 gem 所需要的基本文檔

接著要在.product_quote.gemspec裡面打上這個Gem的相關資料

#.product_quote.gemspec

# coding: utf-8

lib = File.expand_path('../lib', **FILE**) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 

require 'product_quote/version

Gem::Specification.new do |spec| 
  spec.name = "product_quote" 
  spec.version = ProductQuote::VERSION 
  spec.authors = ["Honor Lin"] 
  spec.email = ["[email protected]"] 
  spec.summary = "product_quote" 
  spec.description = "product_quote" 
  spec.homepage = "" 
  spec.license = "MIT"

  spec.files = `git ls-files -z`.split("\x0") 
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 
  spec.require_paths = ["lib"]

  spec.add_development_dependency "bundler", "~> 1.7" 
  spec.add_development_dependency "rake", "~> 10.0" 
end 

接著執行

bundle

確認這個gem正確可以執行

如此初步的gem大致上完成

只是為了我們到時方便在主要的Rails Project引入這個Gem, 所以我們必須先記錄一個Gem在本機的路徑

假設為 ~/app/gems/product_quote

2. 建立Rails架構到Gem裡面

假設這個view在原先的Rails的架構會使用到的檔案目錄如下:

app/assets/javascripts/product_quote.js
app/assets/stylesheets/product_quote.scss
app/views/product_quote/.*
app/views/layout

將這幾個目錄和檔案,移到剛剛建立的Gem的根目錄

3. 讓Rails可以認得此Gem裡面的app目錄下的所有結構

要做到這件事情,就必須使用Rails的Engine

在此說明一下Engine的有幾個重點:

  1. 可以說是一個微型的Rails應用程式,完整的Rails應用程式是由Engine擴充來的
  2. Engine和Rails的應用程式分享共同的程式架構,也就是app/controller, app/model, app/views 等的是共通的
  3. Engine和Plugin可以說是密切相關,他們分享相同的/lib目錄,他們都是透過相同的命令方式產生,Engines可以說是全功能的Plugin,也就是說Engine可以是Plugin,Plugin也可以成為Engine
  4. Engine和Rails的應用程式的雖然共用空間結構,但是彼此是隔離的,都可以使用helper,例如articles_path去做對應相關的controller等的,沒有衝突,但是model,controller都可以透過namespaced去做區隔

要在Gem裡面實現Engine的功能只要實做一個繼承Rails::Engine 的class, 然後再Gem載入時的進入檔案,require這個class進來就可以

新增一個 engine.rb 到Gem的lib裡面

#ruby engine.rb

module ProductQuote
  class Engine < ::Rails::Engine
  end
end

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax