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

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

1 comments

Comments 1 - 1 of 1 previous next Post a comment

Post a comment
Embed Video
Edit your comment Cancel

2 Favorites

Rails Plugin Development 101 (...and some...) - Presentation Transcript

  1. Ruby on Rails: Plug-in Development 101 ...and some... http://jimeh.me/ by Jim Myhrberg
  2. The Basics Helpers Controller Methods Controllers, Helpers & Views
  3. The Basics to get you started
  4. Generate a Plug-in $ script/generate plugin hello_world
  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. Example: Collecta_ruby
  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. 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. Example: Facebooker Plus
  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. 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. Helpers create or overload helpers
  15. One of the simplest things to implement in a Plug-in.
  16. action_view.rb
  17. action_view.rb ActionView::Base.send(:include, FacebookerPlus::Rails::Helper)
  18. action_view.rb
  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. Controller Methods access custom methods in all controllers
  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. action_controller.rb
  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. controller.rb
  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. Fancy initialization
  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 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. 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. facebooker_plus.rb
  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. The Plug-in “app” folder
  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

+ Jim MyhrbergJim Myhrberg, 1 month ago

custom

254 views, 2 favs, 0 embeds more stats

A basic introduction of Ruby on Rails plug-in devel more

More info about this document

© All Rights Reserved

Go to text version

  • Total Views 254
    • 254 on SlideShare
    • 0 from embeds
  • Comments 1
  • Favorites 2
  • Downloads 10
Most viewed embeds

more

All embeds

less

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

Cancel
File a copyright complaint
Having problems? Go to our helpdesk?

Categories