Howto: Write a plug-in

In my previous post, I listed 6 things that you should try in Rails. I also promised some example code to get you started. Since I have already covered installing and upgrading rails, the next cab off the rank is writing a plug-in.

Plug-ins are fantastic – they allow you to abstract away common code into nice little bundles that you can re-use on other projects. Rails even has a built-in system for downloading other peoples plug-ins straight from their SVN repository. With the change over to Rails 2.0, some used-to-be-core functionality has been moved into plug-ins, to clean up the core tree and to allow other developers to release new versions of the plug-ins outside of the regular Rails release cycles.

In this (very brief) tutorial, we will create a plug-in called acts_as_blabbermouth that will print out random quotes . Obviously this plug-in is of little use in the real world, but it should act as a nice demonstration of how plug-ins work.

It’s really easy to generate the boilerplate code thanks to the generate script. To start your plug-in, run the following command in the root of your Rails app:

  script/generate plugin acts_as_blabbermouth 

You should see an output similar to this:

  create  vendor/plugins/acts_as_blabbermouth/lib create  vendor/plugins/acts_as_blabbermouth/tasks create  vendor/plugins/acts_as_blabbermouth/test create  vendor/plugins/acts_as_blabbermouth/README create  vendor/plugins/acts_as_blabbermouth/MIT-LICENSE create  vendor/plugins/acts_as_blabbermouth/Rakefile create  vendor/plugins/acts_as_blabbermouth/init.rb create  vendor/plugins/acts_as_blabbermouth/install.rb create  vendor/plugins/acts_as_blabbermouth/uninstall.rb create  vendor/plugins/acts_as_blabbermouth/lib/acts_as_blabbermouth.rb create  vendor/plugins/acts_as_blabbermouth/tasks/acts_as_blabbermouth_tasks.rake create  vendor/plugins/acts_as_blabbermouth/test/acts_as_blabbermouth_test.rb  

As you can see, all of the boilerplate code has been created in the vendor/plugins/acts_as_blabbermouth directory.

The README and MIT-LICENSE are just generic text files that you should fill out – generally, the README file is the first place a new user will look for instructions on the plug-in.

The lib directory will hold the guts of your plugiin. The tasks directory is a place where you can store any rake tasks that your plug-in might need. The tests directory is, well, pretty self explanatory – just as you can test your Rails app, you can test your plug-in too. The install.rb and uninstall.rb files are called when installing and uninstalling your plug-in – you can place code here to initialize your environment and to cleanup after yourself. Finally, init.rb is the file that Rails actually calls to load your plug-in.

The main file we have to worry about is /lib/acts_as_blabbermouth.rb – this is where our main code will go.

Firstly, we need to include the acts_as_blabbermouth.rb file into the environment. This is done by adding the following line to the init.rb file:

  require File.dirname(__FILE__) + '/lib/acts_as_blabbermouth' 

Next, we add the following code to lib/acts_as_blabbermouth.rb

  # ActsAsBlabbermouth module ActiveRecord #:nodoc:   module Acts #:nodoc:     module Blabbermouth #:nodoc:       def self.included(base)         base.extend(ClassMethods)       end        module ClassMethods         def acts_as_blabbermouth           include ActiveRecord::Acts::Blabbermouth::InstanceMethods           extend ActiveRecord::Acts::Blabbermouth::SingletonMethods         end       end        module SingletonMethods         def quote_me           quotes = [             "When you come to a fork in the road, take it. -Yogi Berra",             "Every child is an artist. The problem is how to remain an artist once he grows up. -Pablo Picasso",             "What we anticipate seldom occurs; what we least expected generally happens. -Benjamin Disraeli",             "Drive-in banks were established so most of the cars today could see their real owners. -E. Joseph Cossman",             "The greatest pleasure in life is doing what people say you cannot do. -Walter Bagehot"           ]            quotes[rand(quotes.size)]         end       end        module InstanceMethods         def quote_me           self.class.quote_me         end       end     end   end end  ActiveRecord::Base.send(:include, ActiveRecord::Acts::Blabbermouth)  

Now, create a model file called quote.rb by running

  script/generate model quote

and add the following line after the class declaration and before the end declaration

  acts_as_blabbermouth 

Fire up the script/console and type:

 Quote.quote_me

Voila! If all went to plan, you should see one of the random quotes. Congratulations! You just wrote a plug-in!

So how did we do it?

  1. We drilled down in to the ActiveRecord::Acts module and mixed in a module called Blabbermouth. This acts like a namespace in other languages, so we can create our own set of classes and methods without stomping on other peoples plug-ins.
  2. We override the included class method, which gets called when the plug-in gets mixed in to another module. Here, we include the ClassMethods module, which exposes the acts_as_blabbermouth method to the model class
  3. We define the acts_as_blabbermouth method. All this method does is include the InstanceMethods and SingletonMethods modules. The InstanceMethods module contains all of the methods available on an instantiated object and SingletonMethods contains all the methods available to the un-instantiated class.
  4. We create a SingletonMethod called quote_me, which returns the random quote. This can be called by calling Quote.quote_me. We also create a method called quote_me in the InstanceMethods module, which calls the SingletonMethod – this way both the class and the object can call the quote_me method.
  5. Finally, we call ActiveRecord::Base.send(:include, ActiveRecord::Acts::Blabbermouth) which tells the ActiveRecord::Base module to include the code we have written.

For those of you playing at home, I’ve attached the plug-in source in a tarball, so you can get a better idea of how it all fits together. So off you go, go and create a plug-in yourself!

Replay

Category: programming Time: 2008-01-16 Views: 1
Tags:

Related post

  • howto write efficient script to have memory(RAM) peak? 2016-06-16

    I have a network with some PCs. I wanted to have peak of the memory for each system. I wrote a script to check the used memory and writes the peak in a file in /tmp; and I've set the script to run in background when the system boots. But it seems tha

  • SitePoint Podcast #96: The Plug-in Wars 2011-01-22

    Episode 96 of The SitePoint Podcast is now available! This week your hosts are Patrick O'Keefe (@iFroggy), Stephan Segraves (@ssegraves), Brad Williams (@williamsba), and Kevin Yank (@sentience). Listen in Your Browser Play this episode directly in y

  • We're not a software company. Is a complete re-write still a bad idea? 2011-05-31

    This question already has an answer here: When is a BIG Rewrite the answer? 25 answers I understand the reasoning behind Joel Spolsky's article "Things You Should Never Do, Part I", but I always see it referenced in regards in situations where t

  • Redirection inside a plug in Phoenix framework 2016-01-24

    I'm trying to write a Plug which will authenticate users (checking session actually). I have trouble getting redirect route. I think it is because the route generation happens after this plug is activated. Anyway I got an error like this: undefined f

  • How to add a Plug in Elixir / Phoenix before the Router? 2016-02-05

    Is there any way to insert a Plug to run prior to the router selecting the controller/action? I've got an app that will redirect to the root path for specific subdomains, regardless of the current path on those domains. So: sub.myapp.com/foo/bar shou

  • IE and Standards: Chris Wilson Talks 2007-12-10

    At Web Directions South this year, I had a chance to talk with Chris Wilson, who needs no introduction. He's the Platform Architect for Internet Explorer at Microsoft. You can listen to this interview if you prefer. SP: Hi Chris. Chris Wilson: Hi. SP

  • SitePoint Podcast #28: Artisanal Bread 2009-09-19

    Episode 28 of The SitePoint Podcast is now available! This week your hosts are Patrick O'Keefe (@ifroggy), Stephan Segraves (@ssegraves), and Kevin Yank (@sentience). Listen in your Browser Play this episode directly in your browser! Just click the o

  • Suggestions for Dressing up blog for the holidays 2010-12-15

    I was wondering what you guys are doing to dress up your blogs ? any plugins that add some cool effects like snow flakes, maybe greeting popup, footer, music, header rotation, list of new years resolution, wishlist widget display .... I was wondering

  • Your experience with haxe and other languages that compile to PHP? 2011-01-13

    I would like to hear opinions from people who have used a language that compiles to php. One such language I know is Haxe. Other ones I've read about are Kira and Pharen. How well do these languages integrate with PHP? Is it relatively easy to write

  • Is there a way to view KML natively in ArcMap? 2011-04-05

    Answering this question: How do I import/export KML to ArcGIS Desktop? raised another one. There are loads of tools to import/export kml/kmz. Are there tools available for native viewing of KML in ArcMap? I'm curious if anyone has built a custom feat

  • Add map making to java desktop software 2011-09-10

    In my project (a desktop application) I need to create a map with three layers, basic geographic layer at the bottom, a GSM coverage area layer on top of it, and then a location based services layer on top of that. After creation, I have to navigate

  • How can I show posts for a single category? 2011-11-27

    Is it possible to show posts for a single category? I tried browsing to the URL http://mysite.com/category/foo which does show all of the posts with category foo, but the posts lose their formatting in the listing. I'd like a full paginated listing o

  • Inserted double quote when prepending to the_content 2012-03-12

    I am trying to write a plug-in to display the RunKeeper Healthy button on single posts, but my output has an extra space and double-quote when I look at the page source. What I'm trying to do with the button is open a new window via inline JavaScript

  • Problems with sharing between Windows 7 and Windows XP 2012-08-15

    I'm trying to share files between a PC with Windows XP and a laptop with Windows 7. I've been trying to do this for years, which may have resulted in a bit of a mess, but I wouldn't know because I understand very little of what's going on. There are

  • Syntax Highlighting for Mathematica on a Blog 2012-10-27

    Every once in a while I want to paste Mathematica code on my blog. When I do, I would like it to be somewhat readable, and it would be nice to have syntax highlighting. So far all my searches have turned up with nothing. There are plenty of ways to c

  • How to install PyQt4 for Python2.6? 2013-01-08

    I am currently stuck using both Python2.6 and Python2.7 on Lubuntu 12.10. 2.6 is required for a piece of software. In attempting to write a plug-in for this software (Opticks), I need to be able to access PyQt4. Using apt-get install python-qt4 I get

  • Permissions - how to make a folder undeleteable? 2013-02-06

    On FreeNAS (FreeBSD) ... I'm trying to make a folder 'undeleteable'. I logged in as root. I created a folder called test and chmod it to 700 (rwx------). Owner is root, group is wheel. Then I log in as a user called john, which is part of group bbsta

  • Convert .osm to .map for mapsforge 2013-08-08

    I have download latest version of osmosis from http://wiki.openstreetmap.org/wiki/Osmosis#Downloading and mapsforge-map-writer-0.3.0-jar-with-dependencies.jar from https://code.google.com/p/mapsforge/downloads/list. I copied mapsforge-map-writer-0.3.

  • secure offline PC storage accessible through javascript 2014-07-23

    I'm attempting to build a browser-based HTML5 application that has the ability to store data locally on a PC (not mobile device) when offline. This data is sensitive and must be secure. Of course the trick is trying to find a way to be able to access

iOS development

Android development

Python development

JAVA development

Development language

PHP development

Ruby development

search

Front-end development

Database

development tools

Open Platform

Javascript development

.NET development

cloud computing

server

Copyright (C) avrocks.com, All Rights Reserved.

processed in 0.645 (s). 13 q(s)