]> git.wincent.com - wikitext.git/commitdiff
Auto-initialize under Rails 3
authorWincent Colaiuta <win@wincent.com>
Sat, 12 Jun 2010 18:47:30 +0000 (20:47 +0200)
committerWincent Colaiuta <win@wincent.com>
Sat, 12 Jun 2010 18:55:59 +0000 (20:55 +0200)
Under Rails 2 we get free auto-initialization behavior by including a
"rails/init.rb" file in our gem.

Under Rails 3 things have changed as described here:

  http://railsdispatch.com/posts/how-rails-3-enables-more-choices-part-1

Rails will effectively do a:

  require 'wikitext'

Early on in the application boot process. In our case, that effectively
means that the code in the C extension's Init_wikitext() function will
be evaluated.

So, in this commit, we replicate in C what we would have done in the
following manner if the Wikitext gem were just a pure Ruby project:

  if Object.const_defined? :ActiveSupport
    # we are running under Rails
    require 'wikitext/nil_class'
    require 'wikitext/string'

    if ActiveSupport.respond_to? :on_load
      # running under Rails 3
      ActiveSupport.on_load :action_view do
        require 'wikitext/rails_template_handler'
      end
    else
      # running under Rails 2
      require 'wikitext/rails_template_handler'
    end

Note that because one of the code paths involves passing in a block, we
have to define a couple of ancilliary helper functions and use
rb_iterate() to achieve the same effect in C.

Signed-off-by: Wincent Colaiuta <win@wincent.com>
README.rdoc
doc/RELEASE-NOTES
ext/wikitext.c

index dd5f9b50eb7a507d459d8ddb0a099a93ded6bbee..5c08a13330d8855c6d0a3bb8980c76bbaf6c814c 100644 (file)
@@ -332,14 +332,6 @@ Add a line like the following to your Gemfile:
 Note that while older versions of Wikitext do work with Rails 3 to some degree,
 for full compatibility Wikitext version 2.0 or higher should be used.
 
-At the time of writing, it appears that Rails 3 and Bundler do not
-automatically call the <tt>rails/init.rb</tt> file any more, so it is necessary
-to explicitly activate the Rails support (the template handler, +to_wikitext+
-and +w+ methods, and +shared_parser+ instance) by adding a line like this
-to a file under <tt>config/initializers</tt>:
-
-  require 'wikitext/rails'
-
 = Links
 
 * RubyForge project page: http://rubyforge.org/projects/wikitext
index 5b2fa981bd01713e3e96087966515d0294542877..e45e1e5253995e72edd8ab5b27dbb2ea31e8454d 100644 (file)
@@ -9,6 +9,7 @@ the source code repository at: http://git.wincent.com.
 = Changes in 2.0
 
 * compatibility with the Rails 3 template handler API
+* use Rails 3 hooks to auto-initialize when listed in Gemfile
 * +code+ tags are now emitted instead of +tt+ tags for compliance
   with the HTML5 specification
 
index 982058fdd6471a8de68a67c84cd98cb18e97970a..251a0540a9a165f9af1ba6b51b2f865a18bfdcc4 100644 (file)
@@ -29,6 +29,36 @@ VALUE cWikitextParser        = 0;   // class Wikitext::Parser
 VALUE eWikitextParserError   = 0;   // class Wikitext::Parser::Error
 VALUE cWikitextParserToken   = 0;   // class Wikitext::Parser::Token
 
+// In order to replicate this Ruby code:
+//
+//   ActiveSupport.on_load(:action_view) do
+//     require 'wikitext/rails_template_handler'
+//   end
+//
+// here in C we have to jump through some hoops using the following two
+// functions.
+//
+// First we have wikitext_on_load_block(), which is a function which defines
+// the "block" of code that we want to have evaluated.
+//
+// To actually pass this block in to the ActiveSupport::on_load method we
+// need the help of an intermediate helper function,
+// wikitext_block_forwarder(), which we invoke with the aid of rb_iterate()
+// later on.
+//
+// This works because the rb_funcall() function in wikitext_block_forwarder()
+// propagates the block through to the called method.
+VALUE wikitext_on_load_block(VALUE yielded, VALUE other)
+{
+    return rb_require("wikitext/rails_template_handler");
+}
+
+VALUE wikitext_block_forwarder(VALUE receiver)
+{
+    return rb_funcall(receiver, rb_intern("on_load"), 1,
+        ID2SYM(rb_intern("action_view")));
+}
+
 void Init_wikitext()
 {
     // Wikitext
@@ -69,4 +99,24 @@ void Init_wikitext()
     rb_define_attr(cWikitextParserToken, "code_point", Qtrue, Qfalse);
     rb_define_attr(cWikitextParserToken, "token_type", Qtrue, Qfalse);
     rb_define_attr(cWikitextParserToken, "string_value", Qtrue, Qfalse);
+
+    // check to see if ::ActiveSupport is defined
+    if (rb_funcall(rb_cObject, rb_intern("const_defined?"), 1,
+        ID2SYM(rb_intern("ActiveSupport"))) == Qtrue)
+    {
+        // we are running under Rails
+        rb_require("wikitext/nil_class");
+        rb_require("wikitext/string");
+
+        // now check for Rails version
+        VALUE active_support = rb_const_get(rb_cObject,
+            rb_intern("ActiveSupport"));
+        if (rb_respond_to(active_support, rb_intern("on_load")))
+            // running under Rails 3
+            rb_iterate(wikitext_block_forwarder, active_support,
+                wikitext_on_load_block, Qnil);
+        else
+            // running under Rails 2
+            rb_require("wikitext/rails_template_handler");
+    }
 }