Your SlideShare is downloading. ×
0
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 sanct...
Example: Collecta_ruby
Single-file Plug-in

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

 init.rb requires lib/c...
install.rb

     require "rubygems"
     require "fileutils"

     dir = File.dirname(__FILE__)
     templates = File.join...
init.rb


    if defined? Rails
      require "collecta"
      config_file = File.join(RAILS_ROOT, "config", "collecta.yml...
collecta.rb

        require   "rubygems"
        require   "net/http"
        require   "uri"
        require   "cgi"
   ...
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.

 No...
init.rb
 if defined? Rails
   if defined? Facebooker
     require 'facebooker_plus/facebooker_plus'
     require 'facebook...
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)
action_view.rb
helper.rb

  module FacebookerPlus
    module Rails
      module Helper

        def url_for(options = {})
          optio...
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 fil...
action_controller.rb
action_controller.rb

     module ::ActionController
       class Base
         def self.inherited_with_facebooker_plus(su...
controller.rb
controller.rb
module FacebookerPlus
  module Rails
    module Controller
      def self.included(controller)
        contr...
Fancy initialization
application_controller.rb



        class ApplicationController < ActionController::Base

          init_facebooker_plus(...
application_controller.rb



        class ApplicationController < ActionController::Base

          init_facebooker_plus(...
controller.rb
 module FacebookerPlus
   module Rails
     module Controller
       def self.included(controller)
         ...
controller.rb
 module FacebookerPlus
   module Rails
     module Controller
       def self.included(controller)
         ...
controller.rb
 module FacebookerPlus
   module Rails
     module Controller
       def self.included(controller)
         ...
controller.rb
 module FacebookerPlus
   module Rails
     module Controller
       def self.included(controller)
         ...
controller.rb
 module FacebookerPlus
   module Rails
     module Controller
       def self.included(controller)
         ...
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 applicatio...
init.rb

 if defined? Rails
   if defined? Facebooker
     require 'facebooker_plus/facebooker_plus'
     require 'faceboo...
init.rb

 if defined? Rails
   if defined? Facebooker
     require 'facebooker_plus/facebooker_plus'
     require 'faceboo...
facebooker_plus.rb
facebooker_plus.rb
   module FacebookerPlus
     class Base
       def self.init(rails_config)

         controller_path =...
facebooker_plus.rb



controller_path = File.join(facebooker_plus_root, 'lib', 'facebooker_plus', 'rails', 'app', 'control...
facebooker_plus.rb


 if defined? ActiveSupport::Dependencies
   ActiveSupport::Dependencies.load_paths << controller_path...
facebooker_plus.rb


 if rails_config
   rails_config.controller_paths << controller_path
 else
   current_paths = ActionC...
controller.rb

 module FacebookerPlus
   module Rails
     module Controller
       def self.included(controller)
        ...
controller.rb

 module FacebookerPlus
   module Rails
     module Controller
       def self.included(controller)
        ...
The Plug-in “app” folder
Collecta_ruby source:
          http://github.com/jimeh/collecta_ruby

          Facebooker Plus source:
          http://...
Upcoming SlideShare
Loading in...5
×

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

1,447

Published on

A basic introduction of Ruby on Rails plug-in development which goes on to more advanced plug-in development.

Published in: Technology
1 Comment
2 Likes
Statistics
Notes
No Downloads
Views
Total Views
1,447
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
25
Comments
1
Likes
2
Embeds 0
No embeds

No notes for slide

Transcript of "Rails Plugin Development 101 (...and some...)"

  1. 1. Ruby on Rails: Plug-in Development 101 ...and some... http://jimeh.me/ by Jim Myhrberg
  2. 2. The Basics Helpers Controller Methods Controllers, Helpers & Views
  3. 3. The Basics to get you started
  4. 4. Generate a Plug-in $ script/generate plugin hello_world
  5. 5. 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.
  6. 6. Example: Collecta_ruby
  7. 7. 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.
  8. 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. 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. 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. 11. Example: Facebooker Plus
  12. 12. 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.
  13. 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. 14. Helpers create or overload helpers
  15. 15. One of the simplest things to implement in a Plug-in.
  16. 16. action_view.rb
  17. 17. action_view.rb ActionView::Base.send(:include, FacebookerPlus::Rails::Helper)
  18. 18. action_view.rb
  19. 19. 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
  20. 20. Controller Methods access custom methods in all controllers
  21. 21. 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.
  22. 22. action_controller.rb
  23. 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. 24. controller.rb
  25. 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. 26. Fancy initialization
  27. 27. application_controller.rb class ApplicationController < ActionController::Base init_facebooker_plus(:app_class => "App") end
  28. 28. application_controller.rb class ApplicationController < ActionController::Base init_facebooker_plus(:app_class => "App") end
  29. 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. 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. 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. 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. 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. 34. Controllers, Helpers & Views full controllers, helpers and views in your plug-in
  35. 35. 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.
  36. 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. 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. 38. facebooker_plus.rb
  39. 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. 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. 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. 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. 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. 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. 45. The Plug-in “app” folder
  46. 46. Collecta_ruby source: http://github.com/jimeh/collecta_ruby Facebooker Plus source: http://github.com/jimeh/facebooker_plus Railscast: Making a Plug-in: http://railscasts.com/episodes/33-making-a-plugin email: contact@jimeh.me — twitter: @jimeh slideshare: http://www.slideshare.net/jimeh
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×