Ruby on Rails:
      Plug-in Development 101
      ...and some...




http://jimeh.me/           by Jim Myhrberg
The Basics
Helpers
Controller Methods
Controllers, Helpers & Views
The Basics
to get you started
Generate a Plug-in
      $ script/generate plugin hello_world
install.rb is executed once during installation.

init.rb is the only file included by Rails.

The lib folder is your sanctuary.

Aside from hello_world.rb, place all Ruby source files in
lib/hello_world/ to avoid naming collisions.
Example: Collecta_ruby
Single-file Plug-in

 install.rb copies collecta.yml
 to Rails’ config folder during
 installation.

 init.rb requires lib/collecta.rb,
 loads settings from installed
 collecta.yml and applies them
 to the Collecta class.

 lib/collecta.rb is the ‘heart’ of
 the plug-in.
install.rb

     require "rubygems"
     require "fileutils"

     dir = File.dirname(__FILE__)
     templates = File.join(dir, "templates")
     files = [
       File.join("config", "collecta.yml")
     ]

     files.each do |file|
       if !File.exist?(File.join(RAILS_ROOT, file))
         FileUtils.cp File.join(templates, file), File.join(RAILS_ROOT, file)
       end
     end
init.rb


    if defined? Rails
      require "collecta"
      config_file = File.join(RAILS_ROOT, "config", "collecta.yml")
      if File.exist?(config_file)
        config = YAML.load_file(config_file)
        if !config[RAILS_ENV.to_s].nil? && !config[RAILS_ENV.to_s]["api_key"].nil?
          Collecta.api_key = config[RAILS_ENV.to_s]["api_key"]
        end
      end
    end
collecta.rb

        require   "rubygems"
        require   "net/http"
        require   "uri"
        require   "cgi"
        require   "json"
        require   "xml"

        class Collecta

          @@api_key = nil
          @@api_url = "http://api.collecta.com/search"

          # rest of the class...
        end
Example: Facebooker Plus
Multi-file Plug-in

 init.rb requires all needed files
 from lib folder, and calls an init
 method too boot the plugin.

 Notice how all files are located
 under lib/facebooker_plus/.
 This avoids any naming
 collisions from other plug-ins,
 gems, or system.
init.rb
 if defined? Rails
   if defined? Facebooker
     require 'facebooker_plus/facebooker_plus'
     require 'facebooker_plus/rails/fb_sig_add'
     require 'facebooker_plus/rails/controller'
     require 'facebooker_plus/rails/helper'
     require 'facebooker_plus/extensions/action_controller'
     require 'facebooker_plus/extensions/action_view'
     require 'facebooker_plus/extensions/session'

     FacebookerPlus::Base.init(defined?(config) ? config : nil)

   else
     STDERR.puts "** [FacebookerPlus] ERROR: Please load Facebooker before Facebooker Plus.n"
   end
 end
Helpers
create or overload helpers
One of the simplest things to implement in a Plug-in.
action_view.rb
action_view.rb



     ActionView::Base.send(:include, FacebookerPlus::Rails::Helper)
helper.rb
helper.rb

  module FacebookerPlus
    module Rails
      module Helper

        def url_for(options = {})
          options.is_a?(Hash) ? super(options) : fb_sig_add(super(options))
        end

        def form_for(record_or_name_or_array, *args, &proc)
          args[0][:url] = fb_sig_add(args[0][:url]) if !args[0][:url].nil?
          super(record_or_name_or_array, *args, &proc)
        end

      end
    end
  end
Controller Methods
access custom methods in all controllers
Makes it easy to control different aspects of your plug-
in from within controllers.

Easily create global before/after filters which run from
your plug-in.

Create class methods to enable/disable your plugin on
a per-controller basis.
action_controller.rb
action_controller.rb

     module ::ActionController
       class Base
         def self.inherited_with_facebooker_plus(subclass)
           inherited_without_facebooker_plus(subclass)
           if subclass.to_s == "ApplicationController"
             subclass.send(:include, FacebookerPlus::Rails::Controller)
           end
         end
         class << self
           alias_method_chain :inherited, :facebooker_plus
         end
       end
     end
controller.rb
controller.rb
module FacebookerPlus
  module Rails
    module Controller
      def self.included(controller)
        controller.extend ClassMethods
      end
      def send_p3p_headers
        if !params[:fb_sig_in_iframe].blank?
          headers['P3P'] = 'CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"'
        end
      end
      def url_for(options = {})
        fb_sig_add(super(options)) rescue super(options)
      end
      module ClassMethods
        def init_facebooker_plus(options = {})
          before_filter :send_p3p_headers
        end
      end
    end
  end
end
Fancy initialization
application_controller.rb



        class ApplicationController < ActionController::Base

          init_facebooker_plus(:app_class => "App")

        end
application_controller.rb



        class ApplicationController < ActionController::Base

          init_facebooker_plus(:app_class => "App")

        end
controller.rb
 module FacebookerPlus
   module Rails
     module Controller
       def self.included(controller)
         controller.extend ClassMethods
       end
       def set_facebooker_plus_options(options = {})
         @facebooker_plus_options = options
       end
       def apply_facebooker_options(options = {})
         if @facebooker_plus_options.has_key?(:app_class) then end
       end
       def create_session_cookie_if_needed # magic happens here
       end
       module ClassMethods
         def init_facebooker_plus(options = {})
           before_filter { |controller| controller.set_facebooker_plus_options(options) }
           before_filter :create_session_cookie_if_needed
           before_filter :apply_facebooker_options
         end
       end
     end
   end
 end
controller.rb
 module FacebookerPlus
   module Rails
     module Controller
       def self.included(controller)
         controller.extend ClassMethods
       end
       def set_facebooker_plus_options(options = {})
         @facebooker_plus_options = options
       end
       def apply_facebooker_options(options = {})
         if @facebooker_plus_options.has_key?(:app_class) then end
       end
       def create_session_cookie_if_needed # magic happens here
       end
       module ClassMethods
         def init_facebooker_plus(options = {})
           before_filter { |controller| controller.set_facebooker_plus_options(options) }
           before_filter :create_session_cookie_if_needed
           before_filter :apply_facebooker_options
         end
       end
     end
   end
 end
controller.rb
 module FacebookerPlus
   module Rails
     module Controller
       def self.included(controller)
         controller.extend ClassMethods
       end
       def set_facebooker_plus_options(options = {})
         @facebooker_plus_options = options
       end
       def apply_facebooker_options(options = {})
         if @facebooker_plus_options.has_key?(:app_class) then end
       end
       def create_session_cookie_if_needed # magic happens here
       end
       module ClassMethods
         def init_facebooker_plus(options = {})
           before_filter { |controller| controller.set_facebooker_plus_options(options) }
           before_filter :create_session_cookie_if_needed
           before_filter :apply_facebooker_options
         end
       end
     end
   end
 end
controller.rb
 module FacebookerPlus
   module Rails
     module Controller
       def self.included(controller)
         controller.extend ClassMethods
       end
       def set_facebooker_plus_options(options = {})
         @facebooker_plus_options = options
       end
       def apply_facebooker_options(options = {})
         if @facebooker_plus_options.has_key?(:app_class) then end
       end
       def create_session_cookie_if_needed # magic happens here
       end
       module ClassMethods
         def init_facebooker_plus(options = {})
           before_filter { |controller| controller.set_facebooker_plus_options(options) }
           before_filter :create_session_cookie_if_needed
           before_filter :apply_facebooker_options
         end
       end
     end
   end
 end
controller.rb
 module FacebookerPlus
   module Rails
     module Controller
       def self.included(controller)
         controller.extend ClassMethods
       end
       def set_facebooker_plus_options(options = {})
         @facebooker_plus_options = options
       end
       def apply_facebooker_options(options = {})
         if @facebooker_plus_options.has_key?(:app_class) then end
       end
       def create_session_cookie_if_needed # magic happens here
       end
       module ClassMethods
         def init_facebooker_plus(options = {})
           before_filter { |controller| controller.set_facebooker_plus_options(options) }
           before_filter :create_session_cookie_if_needed
           before_filter :apply_facebooker_options
         end
       end
     end
   end
 end
Controllers, Helpers & Views
full controllers, helpers and views in your plug-in
Very useful in some scenarios when complex
functionality is needed.

New Relic’s RPM plug-in uses it to display application
performance under http://localhost:3000/newrelic.

Decently complex to setup.
init.rb

 if defined? Rails
   if defined? Facebooker
     require 'facebooker_plus/facebooker_plus'
     require 'facebooker_plus/rails/fb_sig_add'
     require 'facebooker_plus/rails/controller'
     require 'facebooker_plus/rails/helper'
     require 'facebooker_plus/extensions/action_controller'
     require 'facebooker_plus/extensions/action_view'
     require 'facebooker_plus/extensions/session'

     FacebookerPlus::Base.init(defined?(config) ? config : nil)

   else
     STDERR.puts "** [FacebookerPlus] ERROR: Please load Facebooker before Facebooker Plus.n"
   end
 end
init.rb

 if defined? Rails
   if defined? Facebooker
     require 'facebooker_plus/facebooker_plus'
     require 'facebooker_plus/rails/fb_sig_add'
     require 'facebooker_plus/rails/controller'
     require 'facebooker_plus/rails/helper'
     require 'facebooker_plus/extensions/action_controller'
     require 'facebooker_plus/extensions/action_view'
     require 'facebooker_plus/extensions/session'

     FacebookerPlus::Base.init(defined?(config) ? config : nil)

   else
     STDERR.puts "** [FacebookerPlus] ERROR: Please load Facebooker before Facebooker Plus.n"
   end
 end
facebooker_plus.rb
facebooker_plus.rb
   module FacebookerPlus
     class Base
       def self.init(rails_config)

         controller_path = File.join(facebooker_plus_root, 'lib', 'facebooker_plus', 'rails', 'app', 'controllers')
         helper_path = File.join(facebooker_plus_root, 'lib', 'facebooker_plus', 'rails', 'app', 'helpers')
         $LOAD_PATH << controller_path
         $LOAD_PATH << helper_path

         if defined? ActiveSupport::Dependencies
           ActiveSupport::Dependencies.load_paths << controller_path
           ActiveSupport::Dependencies.load_paths << helper_path
         elsif defined? Dependencies.load_paths
           Dependencies.load_paths << controller_path
           Dependencies.load_paths << helper_path
         else
           to_stderr "ERROR: Rails version #{(RAILS_GEM_VERSION) ? RAILS_GEM_VERSION : ''} too old."
           return
         end

         if rails_config
           rails_config.controller_paths << controller_path
         else
           current_paths = ActionController::Routing.controller_paths
           if current_paths.nil? || current_paths.empty?
              to_stderr "WARNING: Unable to modify the routes in this version of Rails.   Developer mode not available."
           end
           current_paths << controller_path
         end

       end
       # more code here
     end
   end
facebooker_plus.rb



controller_path = File.join(facebooker_plus_root, 'lib', 'facebooker_plus', 'rails', 'app', 'controllers')
helper_path = File.join(facebooker_plus_root, 'lib', 'facebooker_plus', 'rails', 'app', 'helpers')
$LOAD_PATH << controller_path
$LOAD_PATH << helper_path
facebooker_plus.rb


 if defined? ActiveSupport::Dependencies
   ActiveSupport::Dependencies.load_paths << controller_path
   ActiveSupport::Dependencies.load_paths << helper_path
 elsif defined? Dependencies.load_paths
   Dependencies.load_paths << controller_path
   Dependencies.load_paths << helper_path
 else
   to_stderr "ERROR: Rails version #{(RAILS_GEM_VERSION) ? RAILS_GEM_VERSION : ''} too old."
   return
 end
facebooker_plus.rb


 if rails_config
   rails_config.controller_paths << controller_path
 else
   current_paths = ActionController::Routing.controller_paths
   if current_paths.nil? || current_paths.empty?
      to_stderr "WARNING: Unable to modify the routes in this version of Rails.   " +
        "Developer mode not available."
   end
   current_paths << controller_path
 end
controller.rb

 module FacebookerPlus
   module Rails
     module Controller
       def self.included(controller)
         controller.extend ClassMethods
         view_path = File.join(File.dirname(__FILE__), "app", "views")
         if controller.public_methods.include?("append_view_path") # rails 2.1+
           controller.append_view_path(view_path)
         elsif controller.public_methods.include?("view_paths")    # rails 2.0+
           controller.view_paths << view_path
         else                                                      # rails <2.0
           controller.template_root = view_path
         end
       end
     end
   end
 end
controller.rb

 module FacebookerPlus
   module Rails
     module Controller
       def self.included(controller)
         controller.extend ClassMethods
         view_path = File.join(File.dirname(__FILE__), "app", "views")
         if controller.public_methods.include?("append_view_path") # rails 2.1+
           controller.append_view_path(view_path)
         elsif controller.public_methods.include?("view_paths")    # rails 2.0+
           controller.view_paths << view_path
         else                                                      # rails <2.0
           controller.template_root = view_path
         end
       end
     end
   end
 end
The Plug-in “app” folder
Collecta_ruby source:
          http://github.com/jimeh/collecta_ruby

          Facebooker Plus source:
          http://github.com/jimeh/facebooker_plus

          Railscasts: Making a Plug-in:
          http://railscasts.com/episodes/33-making-a-plugin




email: contact@jimeh.me — twitter: @jimeh     slideshare: http://www.slideshare.net/jimeh

Rails Plugin Development 101 (...and some...)

  • 1.
    Ruby on Rails: Plug-in Development 101 ...and some... http://jimeh.me/ by Jim Myhrberg
  • 2.
  • 3.
    The Basics to getyou started
  • 4.
    Generate a Plug-in $ script/generate plugin hello_world
  • 5.
    install.rb is executedonce during installation. init.rb is the only file included by Rails. The lib folder is your sanctuary. Aside from hello_world.rb, place all Ruby source files in lib/hello_world/ to avoid naming collisions.
  • 6.
  • 7.
    Single-file Plug-in install.rbcopies collecta.yml to Rails’ config folder during installation. init.rb requires lib/collecta.rb, loads settings from installed collecta.yml and applies them to the Collecta class. lib/collecta.rb is the ‘heart’ of the plug-in.
  • 8.
    install.rb require "rubygems" require "fileutils" dir = File.dirname(__FILE__) templates = File.join(dir, "templates") files = [ File.join("config", "collecta.yml") ] files.each do |file| if !File.exist?(File.join(RAILS_ROOT, file)) FileUtils.cp File.join(templates, file), File.join(RAILS_ROOT, file) end end
  • 9.
    init.rb if defined? Rails require "collecta" config_file = File.join(RAILS_ROOT, "config", "collecta.yml") if File.exist?(config_file) config = YAML.load_file(config_file) if !config[RAILS_ENV.to_s].nil? && !config[RAILS_ENV.to_s]["api_key"].nil? Collecta.api_key = config[RAILS_ENV.to_s]["api_key"] end end end
  • 10.
    collecta.rb require "rubygems" require "net/http" require "uri" require "cgi" require "json" require "xml" class Collecta @@api_key = nil @@api_url = "http://api.collecta.com/search" # rest of the class... end
  • 11.
  • 12.
    Multi-file Plug-in init.rbrequires all needed files from lib folder, and calls an init method too boot the plugin. Notice how all files are located under lib/facebooker_plus/. This avoids any naming collisions from other plug-ins, gems, or system.
  • 13.
    init.rb if defined?Rails if defined? Facebooker require 'facebooker_plus/facebooker_plus' require 'facebooker_plus/rails/fb_sig_add' require 'facebooker_plus/rails/controller' require 'facebooker_plus/rails/helper' require 'facebooker_plus/extensions/action_controller' require 'facebooker_plus/extensions/action_view' require 'facebooker_plus/extensions/session' FacebookerPlus::Base.init(defined?(config) ? config : nil) else STDERR.puts "** [FacebookerPlus] ERROR: Please load Facebooker before Facebooker Plus.n" end end
  • 14.
  • 15.
    One of thesimplest things to implement in a Plug-in.
  • 16.
  • 17.
    action_view.rb ActionView::Base.send(:include, FacebookerPlus::Rails::Helper)
  • 18.
  • 19.
    helper.rb moduleFacebookerPlus module Rails module Helper def url_for(options = {}) options.is_a?(Hash) ? super(options) : fb_sig_add(super(options)) end def form_for(record_or_name_or_array, *args, &proc) args[0][:url] = fb_sig_add(args[0][:url]) if !args[0][:url].nil? super(record_or_name_or_array, *args, &proc) end end end end
  • 20.
    Controller Methods access custommethods in all controllers
  • 21.
    Makes it easyto control different aspects of your plug- in from within controllers. Easily create global before/after filters which run from your plug-in. Create class methods to enable/disable your plugin on a per-controller basis.
  • 22.
  • 23.
    action_controller.rb module ::ActionController class Base def self.inherited_with_facebooker_plus(subclass) inherited_without_facebooker_plus(subclass) if subclass.to_s == "ApplicationController" subclass.send(:include, FacebookerPlus::Rails::Controller) end end class << self alias_method_chain :inherited, :facebooker_plus end end end
  • 24.
  • 25.
    controller.rb module FacebookerPlus module Rails module Controller def self.included(controller) controller.extend ClassMethods end def send_p3p_headers if !params[:fb_sig_in_iframe].blank? headers['P3P'] = 'CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT"' end end def url_for(options = {}) fb_sig_add(super(options)) rescue super(options) end module ClassMethods def init_facebooker_plus(options = {}) before_filter :send_p3p_headers end end end end end
  • 26.
  • 27.
    application_controller.rb class ApplicationController < ActionController::Base init_facebooker_plus(:app_class => "App") end
  • 28.
    application_controller.rb class ApplicationController < ActionController::Base init_facebooker_plus(:app_class => "App") end
  • 29.
    controller.rb module FacebookerPlus module Rails module Controller def self.included(controller) controller.extend ClassMethods end def set_facebooker_plus_options(options = {}) @facebooker_plus_options = options end def apply_facebooker_options(options = {}) if @facebooker_plus_options.has_key?(:app_class) then end end def create_session_cookie_if_needed # magic happens here end module ClassMethods def init_facebooker_plus(options = {}) before_filter { |controller| controller.set_facebooker_plus_options(options) } before_filter :create_session_cookie_if_needed before_filter :apply_facebooker_options end end end end end
  • 30.
    controller.rb module FacebookerPlus module Rails module Controller def self.included(controller) controller.extend ClassMethods end def set_facebooker_plus_options(options = {}) @facebooker_plus_options = options end def apply_facebooker_options(options = {}) if @facebooker_plus_options.has_key?(:app_class) then end end def create_session_cookie_if_needed # magic happens here end module ClassMethods def init_facebooker_plus(options = {}) before_filter { |controller| controller.set_facebooker_plus_options(options) } before_filter :create_session_cookie_if_needed before_filter :apply_facebooker_options end end end end end
  • 31.
    controller.rb module FacebookerPlus module Rails module Controller def self.included(controller) controller.extend ClassMethods end def set_facebooker_plus_options(options = {}) @facebooker_plus_options = options end def apply_facebooker_options(options = {}) if @facebooker_plus_options.has_key?(:app_class) then end end def create_session_cookie_if_needed # magic happens here end module ClassMethods def init_facebooker_plus(options = {}) before_filter { |controller| controller.set_facebooker_plus_options(options) } before_filter :create_session_cookie_if_needed before_filter :apply_facebooker_options end end end end end
  • 32.
    controller.rb module FacebookerPlus module Rails module Controller def self.included(controller) controller.extend ClassMethods end def set_facebooker_plus_options(options = {}) @facebooker_plus_options = options end def apply_facebooker_options(options = {}) if @facebooker_plus_options.has_key?(:app_class) then end end def create_session_cookie_if_needed # magic happens here end module ClassMethods def init_facebooker_plus(options = {}) before_filter { |controller| controller.set_facebooker_plus_options(options) } before_filter :create_session_cookie_if_needed before_filter :apply_facebooker_options end end end end end
  • 33.
    controller.rb module FacebookerPlus module Rails module Controller def self.included(controller) controller.extend ClassMethods end def set_facebooker_plus_options(options = {}) @facebooker_plus_options = options end def apply_facebooker_options(options = {}) if @facebooker_plus_options.has_key?(:app_class) then end end def create_session_cookie_if_needed # magic happens here end module ClassMethods def init_facebooker_plus(options = {}) before_filter { |controller| controller.set_facebooker_plus_options(options) } before_filter :create_session_cookie_if_needed before_filter :apply_facebooker_options end end end end end
  • 34.
    Controllers, Helpers &Views full controllers, helpers and views in your plug-in
  • 35.
    Very useful insome scenarios when complex functionality is needed. New Relic’s RPM plug-in uses it to display application performance under http://localhost:3000/newrelic. Decently complex to setup.
  • 36.
    init.rb if defined?Rails if defined? Facebooker require 'facebooker_plus/facebooker_plus' require 'facebooker_plus/rails/fb_sig_add' require 'facebooker_plus/rails/controller' require 'facebooker_plus/rails/helper' require 'facebooker_plus/extensions/action_controller' require 'facebooker_plus/extensions/action_view' require 'facebooker_plus/extensions/session' FacebookerPlus::Base.init(defined?(config) ? config : nil) else STDERR.puts "** [FacebookerPlus] ERROR: Please load Facebooker before Facebooker Plus.n" end end
  • 37.
    init.rb if defined?Rails if defined? Facebooker require 'facebooker_plus/facebooker_plus' require 'facebooker_plus/rails/fb_sig_add' require 'facebooker_plus/rails/controller' require 'facebooker_plus/rails/helper' require 'facebooker_plus/extensions/action_controller' require 'facebooker_plus/extensions/action_view' require 'facebooker_plus/extensions/session' FacebookerPlus::Base.init(defined?(config) ? config : nil) else STDERR.puts "** [FacebookerPlus] ERROR: Please load Facebooker before Facebooker Plus.n" end end
  • 38.
  • 39.
    facebooker_plus.rb module FacebookerPlus class Base def self.init(rails_config) controller_path = File.join(facebooker_plus_root, 'lib', 'facebooker_plus', 'rails', 'app', 'controllers') helper_path = File.join(facebooker_plus_root, 'lib', 'facebooker_plus', 'rails', 'app', 'helpers') $LOAD_PATH << controller_path $LOAD_PATH << helper_path if defined? ActiveSupport::Dependencies ActiveSupport::Dependencies.load_paths << controller_path ActiveSupport::Dependencies.load_paths << helper_path elsif defined? Dependencies.load_paths Dependencies.load_paths << controller_path Dependencies.load_paths << helper_path else to_stderr "ERROR: Rails version #{(RAILS_GEM_VERSION) ? RAILS_GEM_VERSION : ''} too old." return end if rails_config rails_config.controller_paths << controller_path else current_paths = ActionController::Routing.controller_paths if current_paths.nil? || current_paths.empty? to_stderr "WARNING: Unable to modify the routes in this version of Rails. Developer mode not available." end current_paths << controller_path end end # more code here end end
  • 40.
    facebooker_plus.rb controller_path = File.join(facebooker_plus_root,'lib', 'facebooker_plus', 'rails', 'app', 'controllers') helper_path = File.join(facebooker_plus_root, 'lib', 'facebooker_plus', 'rails', 'app', 'helpers') $LOAD_PATH << controller_path $LOAD_PATH << helper_path
  • 41.
    facebooker_plus.rb if defined?ActiveSupport::Dependencies ActiveSupport::Dependencies.load_paths << controller_path ActiveSupport::Dependencies.load_paths << helper_path elsif defined? Dependencies.load_paths Dependencies.load_paths << controller_path Dependencies.load_paths << helper_path else to_stderr "ERROR: Rails version #{(RAILS_GEM_VERSION) ? RAILS_GEM_VERSION : ''} too old." return end
  • 42.
    facebooker_plus.rb if rails_config rails_config.controller_paths << controller_path else current_paths = ActionController::Routing.controller_paths if current_paths.nil? || current_paths.empty? to_stderr "WARNING: Unable to modify the routes in this version of Rails. " + "Developer mode not available." end current_paths << controller_path end
  • 43.
    controller.rb module FacebookerPlus module Rails module Controller def self.included(controller) controller.extend ClassMethods view_path = File.join(File.dirname(__FILE__), "app", "views") if controller.public_methods.include?("append_view_path") # rails 2.1+ controller.append_view_path(view_path) elsif controller.public_methods.include?("view_paths") # rails 2.0+ controller.view_paths << view_path else # rails <2.0 controller.template_root = view_path end end end end end
  • 44.
    controller.rb module FacebookerPlus module Rails module Controller def self.included(controller) controller.extend ClassMethods view_path = File.join(File.dirname(__FILE__), "app", "views") if controller.public_methods.include?("append_view_path") # rails 2.1+ controller.append_view_path(view_path) elsif controller.public_methods.include?("view_paths") # rails 2.0+ controller.view_paths << view_path else # rails <2.0 controller.template_root = view_path end end end end end
  • 45.
  • 46.
    Collecta_ruby source: http://github.com/jimeh/collecta_ruby Facebooker Plus source: http://github.com/jimeh/facebooker_plus Railscasts: Making a Plug-in: http://railscasts.com/episodes/33-making-a-plugin email: contact@jimeh.me — twitter: @jimeh slideshare: http://www.slideshare.net/jimeh