diff options
author | Jeff Dean <jeff@zilkey.com> | 2008-11-13 00:51:54 -0500 |
---|---|---|
committer | Jeff Dean <jeff@zilkey.com> | 2008-11-13 00:51:54 -0500 |
commit | bc75de8e4f60a774423290872aeb25d09561531b (patch) | |
tree | f72f1fcfa8d01d9eca88e247c5546d3b074e0424 /railties/doc/guides/source | |
parent | c78c247c7293781438ba524b15d1ca6c5989ed0e (diff) | |
download | rails-bc75de8e4f60a774423290872aeb25d09561531b.tar.gz rails-bc75de8e4f60a774423290872aeb25d09561531b.tar.bz2 rails-bc75de8e4f60a774423290872aeb25d09561531b.zip |
Plugin Guide: updated core_extensions section
Diffstat (limited to 'railties/doc/guides/source')
-rw-r--r-- | railties/doc/guides/source/creating_plugins/core_ext.txt | 126 | ||||
-rw-r--r-- | railties/doc/guides/source/creating_plugins/index.txt | 4 | ||||
-rw-r--r-- | railties/doc/guides/source/creating_plugins/odds_and_ends.txt | 34 | ||||
-rw-r--r-- | railties/doc/guides/source/creating_plugins/string_to_squawk.txt | 102 | ||||
-rw-r--r-- | railties/doc/guides/source/creating_plugins/test_setup.txt (renamed from railties/doc/guides/source/creating_plugins/preparation.txt) | 0 |
5 files changed, 128 insertions, 138 deletions
diff --git a/railties/doc/guides/source/creating_plugins/core_ext.txt b/railties/doc/guides/source/creating_plugins/core_ext.txt new file mode 100644 index 0000000000..33d3dc8ce7 --- /dev/null +++ b/railties/doc/guides/source/creating_plugins/core_ext.txt @@ -0,0 +1,126 @@ +== Extending core classes == + +This section will explain how to add a method to String that will be available anywhere in your rails app by: + + * Writing tests for the desired behavior + * Creating and requiring the correct files + + +=== Working with init.rb === + +When rails loads plugins it looks for the file named init.rb. However, the plugin initializer script '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' itself, 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`. + +If you must reopen a class in `init.rb` you can use `module_eval` or `class_eval`: + +*vendor/plugins/yaffle/init.rb* + +[source, ruby] +--------------------------------------------------- +Hash.class_eval do + def is_a_special_hash? + true + end +end +--------------------------------------------------- + +Another way is to explicitly define the top-level module space for all modules and classes, like `::Hash`: + +*vendor/plugins/yaffle/init.rb* + +[source, ruby] +--------------------------------------------------- +class ::Hash + def is_a_special_hash? + true + end +end +--------------------------------------------------- + +=== Creating the test === + +In this example you will add a method to String named `to_squawk`. To begin, create a new test file with a few assertions: + +*vendor/plugins/yaffle/test/core_ext_test.rb* + +[source, ruby] +-------------------------------------------------------- +require File.dirname(__FILE__) + '/test_helper.rb' + +class CoreExtTest < Test::Unit::TestCase + def test_to_squawk_prepends_the_word_squawk + assert_equal "squawk! Hello World", "Hello World".to_squawk + end +end +-------------------------------------------------------- + +Navigate to your plugin directory and run `rake test`: + +-------------------------------------------------------- +cd vendor/plugins/yaffle +rake test +-------------------------------------------------------- + +The test above should fail with the message: + +-------------------------------------------------------- + 1) Error: +test_to_squawk_prepends_the_word_squawk(CoreExtTest): +NoMethodError: undefined method `to_squawk' for "Hello World":String + ./test/core_ext_test.rb:5:in `test_to_squawk_prepends_the_word_squawk' +-------------------------------------------------------- + +Great - now you are ready to start development. + +=== Organize your files === + +A common pattern in rails plugins is to set up the file structure something like this: + +-------------------------------------------------------- +|-- init.rb +|-- lib +| |-- yaffle +| | `-- core_ext.rb +| `-- yaffle.rb +-------------------------------------------------------- + +The first thing we need to to is to require our 'lib/yaffle.rb' file from 'init.rb': + +*vendor/plugins/yaffle/init.rb* + +[source, ruby] +-------------------------------------------------------- +require 'yaffle' +-------------------------------------------------------- + +Then in 'lib/yaffle.rb' require 'lib/core_ext.rb': + +*vendor/plugins/yaffle/lib/yaffle.rb* + +[source, ruby] +-------------------------------------------------------- +require "yaffle/core_ext" +-------------------------------------------------------- + +Finally, create the 'core_ext.rb' file and add the 'to_squawk' method: + +*vendor/plugins/yaffle/lib/yaffle/core_ext.rb* + +[source, ruby] +-------------------------------------------------------- +String.class_eval do + def to_squawk + "squawk! #{self}".strip + end +end +-------------------------------------------------------- + +To test that your method does what it says it does, run the unit tests with `rake` from your plugin directory. To see this in action, fire up a console and start squawking: + +-------------------------------------------------------- +$ ./script/console +>> "Hello World".to_squawk +=> "squawk! Hello World" +-------------------------------------------------------- + diff --git a/railties/doc/guides/source/creating_plugins/index.txt b/railties/doc/guides/source/creating_plugins/index.txt index d3042f8d56..91d7027323 100644 --- a/railties/doc/guides/source/creating_plugins/index.txt +++ b/railties/doc/guides/source/creating_plugins/index.txt @@ -29,9 +29,9 @@ This guide describes how to build a test-driven plugin that will: For the purpose of this guide pretend for a moment that you are an avid bird watcher. Your favorite bird is the Yaffle, and you want to create a plugin that allows other developers to share in the Yaffle goodness. First, you need to get setup for development. -include::preparation.txt[] +include::test_setup.txt[] -include::string_to_squawk.txt[] +include::core_ext.txt[] include::acts_as_yaffle.txt[] diff --git a/railties/doc/guides/source/creating_plugins/odds_and_ends.txt b/railties/doc/guides/source/creating_plugins/odds_and_ends.txt index 88cd4fe9ed..a52e1c8fdb 100644 --- a/railties/doc/guides/source/creating_plugins/odds_and_ends.txt +++ b/railties/doc/guides/source/creating_plugins/odds_and_ends.txt @@ -1,39 +1,5 @@ == Odds and ends == -=== Work with init.rb === - -The plugin initializer script 'init.rb' is invoked via `eval` (not `require`) so it has slightly different behavior. - -If you reopen any classes in init.rb itself your changes will potentially be made to the wrong module. As a rule, it's better not to open any classes in `init.rb`, and it makes the plugin more difficult to turn into a gem. - -A better alternative is to reopen the class in a different file, and require that file from `init.rb`. - -If you must reopen a class in `init.rb`, there are various techniques. One way is to use `module_eval` or `class_eval`: - -*vendor/plugins/yaffle/init.rb* - -[source, ruby] ---------------------------------------------------- -Hash.class_eval do - def is_a_special_hash? - true - end -end ---------------------------------------------------- - -Another way is to explicitly define the top-level module space for all modules and classes, like `::Hash`: - -*vendor/plugins/yaffle/init.rb* - -[source, ruby] ---------------------------------------------------- -class ::Hash - def is_a_special_hash? - true - end -end ---------------------------------------------------- - === Generate RDoc Documentation === Once your plugin is stable, the tests pass on all database and you are ready to deploy do everyone else a favor and document it! Luckily, writing documentation for your plugin is easy. diff --git a/railties/doc/guides/source/creating_plugins/string_to_squawk.txt b/railties/doc/guides/source/creating_plugins/string_to_squawk.txt deleted file mode 100644 index 63f1131442..0000000000 --- a/railties/doc/guides/source/creating_plugins/string_to_squawk.txt +++ /dev/null @@ -1,102 +0,0 @@ -== Add a `to_squawk` method to String == - -To update a core class you will have to: - - * Write tests for the desired functionality. - * Create a file for the code you wish to use. - * 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* - -[source, ruby] --------------------------------------------------------- -require 'test/unit' - -class CoreExtTest < Test::Unit::TestCase - # Replace this with your real tests. - def test_this_plugin - flunk - end -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* - -[source, ruby] --------------------------------------------------------- -require File.dirname(__FILE__) + '/test_helper.rb' - -class CoreExtTest < Test::Unit::TestCase -end --------------------------------------------------------- - -Navigate to your plugin directory and run `rake test`: - --------------------------------------------------------- -cd vendor/plugins/yaffle -rake test --------------------------------------------------------- - -Your test should fail with `no such file to load -- ./test/../lib/core_ext.rb (LoadError)` because we haven't created any file yet. Create the file 'lib/core_ext.rb' and re-run the tests. You should see a different error message: - --------------------------------------------------------- -1.) Failure ... -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* - -[source, ruby] --------------------------------------------------------- -class CoreExtTest < Test::Unit::TestCase - def test_string_should_respond_to_squawk - assert_equal true, "".respond_to?(:to_squawk) - end - - def test_string_prepend_empty_strings_with_the_word_squawk - assert_equal "squawk!", "".to_squawk - end - - def test_string_prepend_non_empty_strings_with_the_word_squawk - assert_equal "squawk! Hello World", "Hello World".to_squawk - end -end --------------------------------------------------------- - -*vendor/plugins/yaffle/init.rb* - -[source, ruby] --------------------------------------------------------- -require "core_ext" --------------------------------------------------------- - -*vendor/plugins/yaffle/lib/core_ext.rb* - -[source, ruby] --------------------------------------------------------- -String.class_eval do - def to_squawk - "squawk! #{self}".strip - end -end --------------------------------------------------------- - -When monkey-patching existing classes it's often better to use `class_eval` instead of opening the class directly. - -To test that your method does what it says it does, run the unit tests. To test this manually, fire up a console and start squawking: - --------------------------------------------------------- -$ ./script/console ->> "Hello World".to_squawk -=> "squawk! Hello World" --------------------------------------------------------- - -If that worked, congratulations! You just created your first test-driven plugin that extends a core ruby class. diff --git a/railties/doc/guides/source/creating_plugins/preparation.txt b/railties/doc/guides/source/creating_plugins/test_setup.txt index dc9ef6bc29..dc9ef6bc29 100644 --- a/railties/doc/guides/source/creating_plugins/preparation.txt +++ b/railties/doc/guides/source/creating_plugins/test_setup.txt |