From 40bc386ed8cc403050292ab19428f1e467fa1737 Mon Sep 17 00:00:00 2001 From: Jeff Dean Date: Wed, 12 Nov 2008 02:05:19 -0500 Subject: Plugin Guide: cleaned up file paths, made formatting more consistent --- railties/doc/guides/html/creating_plugins.html | 142 +++++++++++-------------- 1 file changed, 63 insertions(+), 79 deletions(-) (limited to 'railties/doc/guides/html/creating_plugins.html') diff --git a/railties/doc/guides/html/creating_plugins.html b/railties/doc/guides/html/creating_plugins.html index 32bcab1359..97e14965a5 100644 --- a/railties/doc/guides/html/creating_plugins.html +++ b/railties/doc/guides/html/creating_plugins.html @@ -605,14 +605,13 @@ Require that file from your init.rb.

Most plugins store their code classes in the plugin's lib directory. When you add a file to the lib directory, you must also require that file from init.rb. The file you are going to add for this tutorial is lib/core_ext.rb.

First, you need to write the tests. Testing plugins is very similar to testing rails apps. The generated test file should look something like this:

+

vendor/plugins/yaffle/test/core_ext_test.rb

-
# File: vendor/plugins/yaffle/test/core_ext_test.rb
-
-require 'test/unit'
+
require 'test/unit'
 
 class CoreExtTest < Test::Unit::TestCase
   # Replace this with your real tests.
@@ -622,15 +621,13 @@ http://www.gnu.org/software/src-highlite -->
 end
 

Start off by removing the default test, and adding a require statement for your test helper.

+

vendor/plugins/yaffle/test/core_ext_test.rb

-
# File: vendor/plugins/yaffle/test/core_ext_test.rb
-
-require 'test/unit'
-require File.dirname(__FILE__) + '/test_helper.rb'
+
require File.dirname(__FILE__) + '/test_helper.rb'
 
 class CoreExtTest < Test::Unit::TestCase
 end
@@ -648,14 +645,13 @@ rake test
No tests were specified

Great - now you are ready to start development. The first thing we'll do is to add a method to String called to_squawk which will prefix the string with the word “squawk!”. The test will look something like this:

+

vendor/plugins/yaffle/init.rb

-
# File: vendor/plugins/yaffle/init.rb
-
-class CoreExtTest < Test::Unit::TestCase
+
class CoreExtTest < Test::Unit::TestCase
   def test_string_should_respond_to_squawk
     assert_equal true, "".respond_to?(:to_squawk)
   end
@@ -669,23 +665,21 @@ http://www.gnu.org/software/src-highlite -->
   end
 end
 
+

vendor/plugins/yaffle/init.rb

-
# File: vendor/plugins/yaffle/init.rb
-
-require "core_ext"
+
require "core_ext"
 
+

vendor/plugins/yaffle/lib/core_ext.rb

-
# File: vendor/plugins/yaffle/lib/core_ext.rb
-
-String.class_eval do
+
String.class_eval do
   def to_squawk
     "squawk! #{self}".strip
   end
@@ -705,14 +699,13 @@ String.class_eval 
 

A common pattern in plugins is to add a method called acts_as_something to models. In this case, you want to write a method called acts_as_yaffle that adds a squawk method to your models.

To keep things clean, create a new test file called acts_as_yaffle_test.rb in your plugin's test directory and require your test helper.

+

vendor/plugins/yaffle/test/acts_as_yaffle_test.rb

-
# File: vendor/plugins/yaffle/test/acts_as_yaffle_test.rb
-
-require File.dirname(__FILE__) + '/test_helper.rb'
+
require File.dirname(__FILE__) + '/test_helper.rb'
 
 class Hickwall < ActiveRecord::Base
   acts_as_yaffle
@@ -721,17 +714,17 @@ http://www.gnu.org/software/src-highlite -->
 class ActsAsYaffleTest < Test::Unit::TestCase
 end
 
+

vendor/plugins/lib/acts_as_yaffle.rb

-
# File: vendor/plugins/lib/acts_as_yaffle.rb
-
-module Yaffle
+
module Yaffle
 end
 

One of the most common plugin patterns for acts_as_yaffle plugins is to structure your file like so:

+

vendor/plugins/lib/acts_as_yaffle.rb

end

Now that test should pass. Since your plugin is going to work with field names, you need to allow people to define the field names, in case there is a naming conflict. You can write a few simple tests for this:

+

vendor/plugins/yaffle/test/acts_as_yaffle_test.rb

-
# File: vendor/plugins/yaffle/test/acts_as_yaffle_test.rb
-
-require File.dirname(__FILE__) + '/test_helper.rb'
+
require File.dirname(__FILE__) + '/test_helper.rb'
 
 class ActsAsYaffleTest < Test::Unit::TestCase
   def test_a_hickwalls_yaffle_text_field_should_be_last_squawk
@@ -797,14 +789,13 @@ http://www.gnu.org/software/src-highlite -->
 end
 

To make these tests pass, you could modify your acts_as_yaffle file like so:

+

vendor/plugins/yaffle/lib/acts_as_yaffle.rb

-
# File: vendor/plugins/yaffle/lib/acts_as_yaffle.rb
-
-module Yaffle
+
module Yaffle
   def self.included(base)
     base.send :extend, ClassMethods
   end
@@ -823,14 +814,13 @@ http://www.gnu.org/software/src-highlite -->
 end
 

Now you can add tests for the instance methods, and the instance method itself:

+

vendor/plugins/yaffle/test/acts_as_yaffle_test.rb

-
# File: vendor/plugins/yaffle/test/acts_as_yaffle_test.rb
-
-require File.dirname(__FILE__) + '/test_helper.rb'
+
require File.dirname(__FILE__) + '/test_helper.rb'
 
 class ActsAsYaffleTest < Test::Unit::TestCase
 
@@ -871,14 +861,13 @@ http://www.gnu.org/software/src-highlite -->
   end
 end
 
+

vendor/plugins/yaffle/lib/acts_as_yaffle.rb

-
# File: vendor/plugins/yaffle/lib/acts_as_yaffle.rb
-
-module Yaffle
+
module Yaffle
   def self.included(base)
     base.send :extend, ClassMethods
   end
@@ -900,7 +889,15 @@ http://www.gnu.org/software/src-highlite -->
   end
 end
 
-

Note the use of write_attribute to write to the field in model.

+
+ + + +
+Note + +
Editor's note:
The use of write_attribute to write to the field in model is just one example of how a plugin can interact with the model, and will not always be the right method to use. For example, you could also use send("#{self.class.yaffle_text_field}=", string.to_squawk).
+

4. Create a squawk_info_for view helper

@@ -923,14 +920,13 @@ Write the tests.

First, create the test to define the functionality you want:

+

vendor/plugins/yaffle/test/view_helpers_test.rb

-
# File: vendor/plugins/yaffle/test/view_helpers_test.rb
-
-require File.dirname(__FILE__) + '/test_helper.rb'
+
require File.dirname(__FILE__) + '/test_helper.rb'
 include YaffleViewHelper
 
 class ViewHelpersTest < Test::Unit::TestCase
@@ -944,25 +940,23 @@ http://www.gnu.org/software/src-highlite -->
 end
 

Then add the following statements to init.rb:

+

vendor/plugins/yaffle/init.rb

-
# File: vendor/plugins/yaffle/init.rb
-
-require "view_helpers"
+
require "view_helpers"
 ActionView::Base.send :include, YaffleViewHelper
 

Then add the view helpers file and

+

vendor/plugins/yaffle/lib/view_helpers.rb

-
# File: vendor/plugins/yaffle/lib/view_helpers.rb
-
-module YaffleViewHelper
+
module YaffleViewHelper
   def squawk_info_for(yaffle)
     returning "" do |result|
       result << yaffle.read_attribute(yaffle.class.yaffle_text_field)
@@ -984,12 +978,12 @@ http://www.gnu.org/software/src-highlite -->
 

When you created the plugin above, you specified the —with-generator option, so you already have the generator stubs in your plugin.

We'll be relying on the built-in rails generate template for this tutorial. Going into the details of generators is beyond the scope of this tutorial.

Type:

-
+
script/generate

You should see the line:

-
+
Plugins (vendor/plugins): yaffle
@@ -1006,14 +1000,13 @@ Example: db/migrate/TIMESTAMP_add_yaffle_fields_to_hickwall

Now you can add code to your generator:

+

vendor/plugins/yaffle/generators/yaffle/yaffle_generator.rb

-
# File: vendor/plugins/yaffle/generators/yaffle/yaffle_generator.rb
-
-class YaffleGenerator < Rails::Generator::NamedBase
+
class YaffleGenerator < Rails::Generator::NamedBase
   def manifest
     record do |m|
       m.migration_template 'migration:migration.rb', "db/migrate", {:assigns => yaffle_local_assigns,
@@ -1054,19 +1047,18 @@ Reuses the built-in rails migration template.
 
 

When you run the generator like

-
+
script/generate yaffle bird

You will see a new file:

+

db/migrate/20080529225649_add_yaffle_fields_to_birds.rb

-
# File: db/migrate/20080529225649_add_yaffle_fields_to_birds.rb
-
-class AddYaffleFieldsToBirds < ActiveRecord::Migration
+
class AddYaffleFieldsToBirds < ActiveRecord::Migration
   def self.up
     add_column :birds, :last_squawk, :string
     add_column :birds, :last_squawked_at, :datetime
@@ -1100,25 +1092,24 @@ Add the method to your generator.
 
 

Working with the internals of generators is beyond the scope of this tutorial, but here is a basic example:

+

vendor/plugins/yaffle/init.rb

-
# File: vendor/plugins/yaffle/init.rb
-require "commands"
+
require "commands"
 Rails::Generator::Commands::Create.send   :include,  Yaffle::Generator::Commands::Create
 Rails::Generator::Commands::Destroy.send  :include,  Yaffle::Generator::Commands::Destroy
 Rails::Generator::Commands::List.send     :include,  Yaffle::Generator::Commands::List
 
+

vendor/plugins/yaffle/lib/commands.rb

-
# File: vendor/plugins/yaffle/lib/commands.rb
-
-require 'rails_generator'
+
require 'rails_generator'
 require 'rails_generator/commands'
 
 module Yaffle #:nodoc:
@@ -1145,20 +1136,18 @@ http://www.gnu.org/software/src-highlite -->
   end
 end
 
+

vendor/plugins/yaffle/generators/yaffle/templates/definition.txt

-
# File: vendor/plugins/yaffle/generators/yaffle/templates/definition.txt
-
-Yaffle is a bird
+
Yaffle is a bird
+

vendor/plugins/yaffle/generators/yaffle/yaffle_generator.rb

-
# File: vendor/plugins/yaffle/generators/yaffle/yaffle_generator.rb
-
-class YaffleGenerator < Rails::Generator::NamedBase
+
class YaffleGenerator < Rails::Generator::NamedBase
   def manifest
     m.yaffle_definition
   end
@@ -1169,14 +1158,13 @@ http://www.gnu.org/software/src-highlite -->
 

7. Add a Custom Route

Testing routes in plugins can be complex, especially if the controllers are also in the plugin itself. Jamis Buck showed a great example of this in http://weblog.jamisbuck.org/2006/10/26/monkey-patching-rails-extending-routes-2.

+

vendor/plugins/yaffle/test/routing_test.rb

-
# File: vendor/plugins/yaffle/test/routing_test.rb
-
-require "#{File.dirname(__FILE__)}/test_helper"
+
require "#{File.dirname(__FILE__)}/test_helper"
 
 class RoutingTest < Test::Unit::TestCase
 
@@ -1202,24 +1190,22 @@ http://www.gnu.org/software/src-highlite -->
     end
 end
 
+

vendor/plugins/yaffle/init.rb

-
# File: vendor/plugins/yaffle/init.rb
-
-require "routing"
+
require "routing"
 ActionController::Routing::RouteSet::Mapper.send :include, Yaffle::Routing::MapperExtensions
 
+

vendor/plugins/yaffle/lib/routing.rb

-
# File: vendor/plugins/yaffle/lib/routing.rb
-
-module Yaffle #:nodoc:
+
module Yaffle #:nodoc:
   module Routing #:nodoc:
     module MapperExtensions
       def yaffles
@@ -1229,14 +1215,13 @@ http://www.gnu.org/software/src-highlite -->
   end
 end
 
+

config/routes.rb

-
# File: config/routes.rb
-
-ActionController::Routing::Routes.draw do |map|
+
ActionController::Routing::Routes.draw do |map|
   ...
   map.yaffles
 end
@@ -1328,14 +1313,13 @@ http://www.gnu.org/software/src-highlite -->
 

8.4. Write custom Rake tasks in your plugin

When you created the plugin with the built-in rails generator, it generated a rake file for you in vendor/plugins/yaffle/tasks/yaffle.rake. Any rake task you add here will be available to the app.

Many plugin authors put all of their rake tasks into a common namespace that is the same as the plugin, like so:

+

vendor/plugins/yaffle/tasks/yaffle.rake

-
# File: vendor/plugins/yaffle/tasks/yaffle.rake
-
-namespace :yaffle do
+
namespace :yaffle do
   desc "Prints out the word 'Yaffle'"
   task :squawk => :environment do
     puts "squawk!"
-- 
cgit v1.2.3