From 236142d23eb083d0a755d29d6365925ae5cc9f03 Mon Sep 17 00:00:00 2001 From: Jeff Dean Date: Mon, 17 Nov 2008 00:15:20 -0500 Subject: Rails plugin: misc error fixes. --- railties/doc/guides/html/creating_plugins.html | 141 +++++++++++++++---------- 1 file changed, 85 insertions(+), 56 deletions(-) (limited to 'railties/doc/guides/html') diff --git a/railties/doc/guides/html/creating_plugins.html b/railties/doc/guides/html/creating_plugins.html index 8f32f72458..ba7962d9ca 100644 --- a/railties/doc/guides/html/creating_plugins.html +++ b/railties/doc/guides/html/creating_plugins.html @@ -290,6 +290,8 @@ ul#navMain {
  • References
  • +
  • Contents of lib/yaffle.rb
  • +
  • Final plugin directory structure
  • @@ -708,10 +710,10 @@ http://www.gnu.org/software/src-highlite --> => "squawk! Hello World"

    3.1. Working with init.rb

    -

    When rails loads plugins it looks for the file named init.rb. However, when the plugin is initialized, init.rb is invoked via eval (not require) so it has slightly different behavior.

    +

    When rails loads plugins it looks for the file named init.rb or rails/init.rb. However, when the plugin is initialized, init.rb is invoked via eval (not require) so it has slightly different behavior.

    Under certain circumstances if you reopen classes or modules in init.rb you may inadvertently create a new class, rather than reopening an existing class. A better alternative is to reopen the class in a different file, and require that file from init.rb, as shown above.

    If you must reopen a class in init.rb you can use module_eval or class_eval to avoid any issues:

    -

    vendor/plugins/yaffle/init.rb

    +

    vendor/plugins/yaffle/rails/init.rb

    end

    Another way is to explicitly define the top-level module space for all modules and classes, like ::Hash:

    -

    vendor/plugins/yaffle/init.rb

    +

    vendor/plugins/yaffle/rails/init.rb

    by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    ActiveRecord::Schema.define(:version => 0) do
    -  create_table :woodpeckers, :force => true do |t|
    -    t.string :name
    -  end
    +
    create_table :woodpeckers, :force => true do |t|
    +  t.string :name
     end
     

    Now your test should be passing, and you should be able to use the Woodpecker model from within your rails app, and any changes made to it are reflected immediately when running in development mode.

    @@ -1027,6 +1027,10 @@ http://www.gnu.org/software/src-highlite --> @controller = WoodpeckersController.new @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new + + ActionController::Routing::Routes.draw do |map| + map.resources :woodpeckers + end end def test_index @@ -1097,8 +1101,6 @@ http://www.gnu.org/software/src-highlite --> ActiveSupport::Dependencies.load_paths << path ActiveSupport::Dependencies.load_once_paths.delete(path) end - -ActionView::Base.send :include, WoodpeckersHelper

    vendor/plugins/yaffle/lib/app/helpers/woodpeckers_helper.rb:

    @@ -1141,26 +1143,21 @@ http://www.gnu.org/software/src-highlite --> private - # yes, I know about assert_recognizes, but it has proven problematic to - # use in these tests, since it uses RouteSet#recognize (which actually - # tries to instantiate the controller) and because it uses an awkward - # parameter order. def assert_recognition(method, path, options) result = ActionController::Routing::Routes.recognize_path(path, :method => method) assert_equal options, result end end
    -

    vendor/plugins/yaffle/init.rb

    +

    vendor/plugins/yaffle/lib/yaffle.rb

    -
    require "routing"
    -ActionController::Routing::RouteSet::Mapper.send :include, Yaffle::Routing::MapperExtensions
    +
    require "yaffle/routing"
     
    -

    vendor/plugins/yaffle/lib/routing.rb

    +

    vendor/plugins/yaffle/lib/yaffle/routing.rb

    end end end +ActionController::Routing::RouteSet::Mapper.send :include, Yaffle::Routing::MapperExtensions

    config/routes.rb

    @@ -1183,7 +1181,6 @@ by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite -->
    ActionController::Routing::Routes.draw do |map|
    -  ...
       map.yaffles
     end
     
    @@ -1253,14 +1250,6 @@ http://www.gnu.org/software/src-highlite --> class DefinitionGeneratorTest < Test::Unit::TestCase - def fake_rails_root - File.join(File.dirname(__FILE__), 'rails_root') - end - - def file_list - Dir.glob(File.join(fake_rails_root, "*")) - end - def setup FileUtils.mkdir_p(fake_rails_root) @original_files = file_list @@ -1276,6 +1265,16 @@ http://www.gnu.org/software/src-highlite --> assert_equal "definition.txt", File.basename(new_file) end + private + + def fake_rails_root + File.join(File.dirname(__FILE__), 'rails_root') + end + + def file_list + Dir.glob(File.join(fake_rails_root, "*")) + end + end

    You can run rake from the plugin directory to see this fail. Unless you are doing more advanced generator commands it typically suffices to just test the Generate script, and trust that rails will handle the Destroy and Update commands for you.

    @@ -1334,14 +1333,6 @@ http://www.gnu.org/software/src-highlite --> class RouteGeneratorTest < Test::Unit::TestCase - def fake_rails_root - File.join(File.dirname(__FILE__), "rails_root") - end - - def routes_path - File.join(fake_rails_root, "config", "routes.rb") - end - def setup FileUtils.mkdir_p(File.join(fake_rails_root, "config")) end @@ -1360,13 +1351,13 @@ http://www.gnu.org/software/src-highlite --> File.open(routes_path, 'wb') {|f| f.write(content) } Rails::Generator::Scripts::Generate.new.run(["yaffle_route"], :destination => fake_rails_root) - assert_match /map\.yaffle/, File.read(routes_path) + assert_match /map\.yaffles/, File.read(routes_path) end def test_destroys_route content = <<-END ActionController::Routing::Routes.draw do |map| - map.yaffle + map.yaffles map.connect ':controller/:action/:id' map.connect ':controller/:action/:id.:format' end @@ -1374,8 +1365,19 @@ http://www.gnu.org/software/src-highlite --> File.open(routes_path, 'wb') {|f| f.write(content) } Rails::Generator::Scripts::Destroy.new.run(["yaffle_route"], :destination => fake_rails_root) - assert_no_match /map\.yaffle/, File.read(routes_path) + assert_no_match /map\.yaffles/, File.read(routes_path) end + + private + + def fake_rails_root + File.join(File.dirname(__FILE__), "rails_root") + end + + def routes_path + File.join(fake_rails_root, "config", "routes.rb") + end + end

    Run rake to watch the test fail, then make the test pass add the following:

    @@ -1404,7 +1406,7 @@ http://www.gnu.org/software/src-highlite --> logger.route "map.yaffle" look_for = 'ActionController::Routing::Routes.draw do |map|' unless options[:pretend] - gsub_file('config/routes.rb', /(#{Regexp.escape(look_for)})/mi){|match| "#{match}\n map.yaffle\n"} + gsub_file('config/routes.rb', /(#{Regexp.escape(look_for)})/mi){|match| "#{match}\n map.yaffles\n"} end end end @@ -1412,7 +1414,7 @@ http://www.gnu.org/software/src-highlite --> module Destroy def yaffle_route logger.route "map.yaffle" - gsub_file 'config/routes.rb', /\n.+?map\.yaffle/mi, '' + gsub_file 'config/routes.rb', /\n.+?map\.yaffles/mi, '' end end @@ -1586,29 +1588,21 @@ http://www.gnu.org/software/src-highlite -->
    require File.dirname(__FILE__) + '/test_helper.rb'
     require 'rails_generator'
     require 'rails_generator/scripts/generate'
    -require 'rails_generator/scripts/destroy'
     
     class MigrationGeneratorTest < Test::Unit::TestCase
     
    -  def fake_rails_root
    -    File.join(File.dirname(__FILE__), 'rails_root')
    -  end
    -
    -  def file_list
    -    Dir.glob(File.join(fake_rails_root, "db", "migrate", "*"))
    -  end
    -
       def setup
         FileUtils.mkdir_p(fake_rails_root)
         @original_files = file_list
       end
     
       def teardown
    +    ActiveRecord::Base.pluralize_table_names = true
         FileUtils.rm_r(fake_rails_root)
       end
     
       def test_generates_correct_file_name
    -    Rails::Generator::Scripts::Generate.new.run(["yaffle", "some_name_nobody_is_likely_to_ever_use_in_a_real_migration"], :destination => fake_rails_root)
    +    Rails::Generator::Scripts::Generate.new.run(["yaffle_migration", "some_name_nobody_is_likely_to_ever_use_in_a_real_migration"], :destination => fake_rails_root)
         new_file = (file_list - @original_files).first
         assert_match /add_yaffle_fields_to_some_name_nobody_is_likely_to_ever_use_in_a_real_migrations/, new_file
         assert_match /add_column :some_name_nobody_is_likely_to_ever_use_in_a_real_migrations do |t|/, File.read(new_file)
    @@ -1616,12 +1610,21 @@ http://www.gnu.org/software/src-highlite -->
     
       def test_pluralizes_properly
         ActiveRecord::Base.pluralize_table_names = false
    -    Rails::Generator::Scripts::Generate.new.run(["yaffle", "some_name_nobody_is_likely_to_ever_use_in_a_real_migration"], :destination => fake_rails_root)
    +    Rails::Generator::Scripts::Generate.new.run(["yaffle_migration", "some_name_nobody_is_likely_to_ever_use_in_a_real_migration"], :destination => fake_rails_root)
         new_file = (file_list - @original_files).first
         assert_match /add_yaffle_fields_to_some_name_nobody_is_likely_to_ever_use_in_a_real_migration/, new_file
         assert_match /add_column :some_name_nobody_is_likely_to_ever_use_in_a_real_migration do |t|/, File.read(new_file)
       end
     
    +  private
    +    def fake_rails_root
    +      File.join(File.dirname(__FILE__), 'rails_root')
    +    end
    +
    +    def file_list
    +      Dir.glob(File.join(fake_rails_root, "db", "migrate", "*"))
    +    end
    +
     end
     
    @@ -1640,7 +1643,7 @@ http://www.gnu.org/software/src-highlite --> by Lorenzo Bettini http://www.lorenzobettini.it http://www.gnu.org/software/src-highlite --> -
    class YaffleGenerator < Rails::Generator::NamedBase
    +
    class YaffleMigrationGenerator < Rails::Generator::NamedBase
       def manifest
         record do |m|
           m.migration_template 'migration:migration.rb', "db/migrate", {:assigns => yaffle_local_assigns,
    @@ -1653,6 +1656,7 @@ http://www.gnu.org/software/src-highlite -->
         def custom_file_name
           custom_name = class_name.underscore.downcase
           custom_name = custom_name.pluralize if ActiveRecord::Base.pluralize_table_names
    +      custom_name
         end
     
         def yaffle_local_assigns
    @@ -1710,9 +1714,7 @@ http://www.gnu.org/software/src-highlite -->
     

    When you run rake -T from your plugin you will see:

    -
    ...
    -yaffle:squawk             # Prints out the word 'Yaffle'
    -...
    +
    yaffle:squawk             # Prints out the word 'Yaffle'

    You can add as many files as you want in the tasks directory, and if they end in .rake Rails will pick them up.

    Note that tasks from vendor/plugins/yaffle/Rakefile are not available to the main app.

    @@ -1829,7 +1831,32 @@ Warning, gotchas or tips that might help save users time

    -

    15.2. Final plugin directory structure

    +

    15.2. Contents of lib/yaffle.rb

    +

    vendor/plugins/yaffle/lib/yaffle.rb:

    +
    +
    +
    require "yaffle/core_ext"
    +require "yaffle/acts_as_yaffle"
    +require "yaffle/commands"
    +require "yaffle/routing"
    +
    +%w{ models controllers helpers }.each do |dir|
    +  path = File.join(File.dirname(__FILE__), 'app', dir)
    +  $LOAD_PATH << path
    +  ActiveSupport::Dependencies.load_paths << path
    +  ActiveSupport::Dependencies.load_once_paths.delete(path)
    +end
    +
    +# optionally:
    +# Dir.glob(File.join(File.dirname(__FILE__), "db", "migrate", "*")).each do |file|
    +#   require file
    +# end
    +
    +
    +

    15.3. Final plugin directory structure

    The final plugin should have a directory structure that looks something like this:

    @@ -1865,7 +1892,8 @@ Warning, gotchas or tips that might help save users time | |-- yaffle | | |-- acts_as_yaffle.rb | | |-- commands.rb -| | `-- core_ext.rb +| | |-- core_ext.rb +| | `-- routing.rb | `-- yaffle.rb |-- pkg | `-- yaffle-0.0.1.gem @@ -1881,6 +1909,7 @@ Warning, gotchas or tips that might help save users time | |-- definition_generator_test.rb | |-- migration_generator_test.rb | |-- route_generator_test.rb +| |-- routes_test.rb | |-- schema.rb | |-- test_helper.rb | |-- woodpecker_test.rb -- cgit v1.2.3