1. Preparation
1.1. Create the basic app
In this tutorial we will create a basic rails application with 1 resource: bird. Start out by building the basic rails app:
rails plugin_demo cd plugin_demo script/generate scaffold bird name:string rake db:migrate script/server
Then navigate to http://localhost:3000/birds. Make sure you have a functioning rails app before continuing.
|
|
The aforementioned instructions will work for sqlite3. For more detailed instructions on how to create a rails app for other databases see the API docs. |
1.2. Create the plugin
The built-in Rails plugin generator stubs out a new plugin. Pass the plugin name, either CamelCased or under_scored, as an argument. Pass --with-generator to add an example generator also.
This creates a plugin in vendor/plugins including an init.rb and README as well as standard lib, task, and test directories.
Examples:
./script/generate plugin BrowserFilters ./script/generate plugin BrowserFilters --with-generator
Later in the plugin we will create a generator, so go ahead and add the --with-generator option now:
script/generate plugin yaffle --with-generator
You should see the following output:
create vendor/plugins/yaffle/lib create vendor/plugins/yaffle/tasks create vendor/plugins/yaffle/test create vendor/plugins/yaffle/README create vendor/plugins/yaffle/MIT-LICENSE create vendor/plugins/yaffle/Rakefile create vendor/plugins/yaffle/init.rb create vendor/plugins/yaffle/install.rb create vendor/plugins/yaffle/uninstall.rb create vendor/plugins/yaffle/lib/yaffle.rb create vendor/plugins/yaffle/tasks/yaffle_tasks.rake create vendor/plugins/yaffle/test/core_ext_test.rb create vendor/plugins/yaffle/generators create vendor/plugins/yaffle/generators/yaffle create vendor/plugins/yaffle/generators/yaffle/templates create vendor/plugins/yaffle/generators/yaffle/yaffle_generator.rb create vendor/plugins/yaffle/generators/yaffle/USAGE
For this plugin you won't need the file vendor/plugins/yaffle/lib/yaffle.rb so you can delete that.
rm vendor/plugins/yaffle/lib/yaffle.rb
|
|
Editor's note: Many plugin authors prefer to keep this file, and add all of the require statements in it. That way, they only line in init.rb would be require "yaffle". If you are developing a plugin that has a lot of files in the lib directory, you may want to create a subdirectory like lib/yaffle and store your files in there. That way your init.rb file stays clean |
1.3. Setup the plugin for testing
Testing plugins that use the entire Rails stack can be complex, and the generator doesn't offer any help. In this tutorial you will learn how to test your plugin against multiple different adapters using ActiveRecord. This tutorial will not cover how to use fixtures in plugin tests.
To setup your plugin to allow for easy testing you'll need to add 3 files:
-
A database.yml file with all of your connection strings.
-
A schema.rb file with your table definitions.
-
A test helper that sets up the database before your tests.
For this plugin you'll need 2 tables/models, Hickwalls and Wickwalls, so add the following files:
vendor/plugins/yaffle/test/database.yml:
sqlite: :adapter: sqlite :dbfile: yaffle_plugin.sqlite.db sqlite3: :adapter: sqlite3 :dbfile: yaffle_plugin.sqlite3.db postgresql: :adapter: postgresql :username: postgres :password: postgres :database: yaffle_plugin_test :min_messages: ERROR mysql: :adapter: mysql :host: localhost :username: rails :password: :database: yaffle_plugin_test
vendor/plugins/yaffle/test/test_helper.rb:
ActiveRecord::Schema.define(:version => 0) do create_table :hickwalls, :force => true do |t| t.string :name t.string :last_squawk t.datetime :last_squawked_at end create_table :wickwalls, :force => true do |t| t.string :name t.string :last_tweet t.datetime :last_tweeted_at end end # File: vendor/plugins/yaffle/test/test_helper.rb ENV['RAILS_ENV'] = 'test' ENV['RAILS_ROOT'] ||= File.dirname(__FILE__) + '/../../../..' require 'test/unit' require File.expand_path(File.join(ENV['RAILS_ROOT'], 'config/environment.rb')) config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml')) ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log") db_adapter = ENV['DB'] # no db passed, try one of these fine config-free DBs before bombing. db_adapter ||= begin require 'rubygems' require 'sqlite' 'sqlite' rescue MissingSourceFile begin require 'sqlite3' 'sqlite3' rescue MissingSourceFile end end if db_adapter.nil? raise "No DB Adapter selected. Pass the DB= option to pick one, or install Sqlite or Sqlite3." end ActiveRecord::Base.establish_connection(config[db_adapter]) load(File.dirname(__FILE__) + "/schema.rb") require File.dirname(__FILE__) + '/../init.rb' class Hickwall < ActiveRecord::Base acts_as_yaffle end class Wickwall < ActiveRecord::Base acts_as_yaffle :yaffle_text_field => :last_tweet, :yaffle_date_field => :last_tweeted_at end
