aboutsummaryrefslogtreecommitdiffstats
path: root/guides/source/plugins.md
diff options
context:
space:
mode:
Diffstat (limited to 'guides/source/plugins.md')
-rw-r--r--guides/source/plugins.md123
1 files changed, 66 insertions, 57 deletions
diff --git a/guides/source/plugins.md b/guides/source/plugins.md
index f8f04c3c67..7b7eb80081 100644
--- a/guides/source/plugins.md
+++ b/guides/source/plugins.md
@@ -3,9 +3,9 @@ The Basics of Creating Rails Plugins
A Rails plugin is either an extension or a modification of the core framework. Plugins provide:
-* a way for developers to share bleeding-edge ideas without hurting the stable code base
-* a segmented architecture so that units of code can be fixed or updated on their own release schedule
-* an outlet for the core developers so that they don’t have to include every cool new feature under the sun
+* A way for developers to share bleeding-edge ideas without hurting the stable code base.
+* A segmented architecture so that units of code can be fixed or updated on their own release schedule.
+* An outlet for the core developers so that they don't have to include every cool new feature under the sun.
After reading this guide, you will know:
@@ -15,7 +15,7 @@ After reading this guide, you will know:
This guide describes how to build a test-driven plugin that will:
* Extend core Ruby classes like Hash and String.
-* Add methods to ActiveRecord::Base in the tradition of the 'acts_as' plugins.
+* Add methods to `ActiveRecord::Base` in the tradition of the `acts_as` plugins.
* Give you information about where to put generators in your plugin.
For the purpose of this guide pretend for a moment that you are an avid bird watcher.
@@ -34,15 +34,21 @@ different rails applications using RubyGems and Bundler if desired.
Rails ships with a `rails plugin new` command which creates a
- skeleton for developing any kind of Rails extension with the ability
- to run integration tests using a dummy Rails application. See usage
- and options by asking for help:
+skeleton for developing any kind of Rails extension with the ability
+to run integration tests using a dummy Rails application. Create your
+plugin with the command:
```bash
-$ rails plugin --help
+$ rails plugin new yaffle
```
-Testing your newly generated plugin
+See usage and options by asking for help:
+
+```bash
+$ rails plugin new --help
+```
+
+Testing Your Newly Generated Plugin
-----------------------------------
You can navigate to the directory that contains the plugin, run the `bundle install` command
@@ -51,7 +57,7 @@ You can navigate to the directory that contains the plugin, run the `bundle inst
You should see:
```bash
- 2 tests, 2 assertions, 0 failures, 0 errors, 0 skips
+ 1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
```
This will tell you that everything got generated properly and you are ready to start adding functionality.
@@ -68,7 +74,7 @@ In this example you will add a method to String named `to_squawk`. To begin, cre
require 'test_helper'
-class CoreExtTest < Test::Unit::TestCase
+class CoreExtTest < ActiveSupport::TestCase
def test_to_squawk_prepends_the_word_squawk
assert_equal "squawk! Hello World", "Hello World".to_squawk
end
@@ -79,19 +85,19 @@ Run `rake` to run the test. This test should fail because we haven't implemented
```bash
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'
+ CoreExtTest#test_to_squawk_prepends_the_word_squawk:
+ NoMethodError: undefined method `to_squawk' for "Hello World":String
+ /path/to/yaffle/test/core_ext_test.rb:5:in `test_to_squawk_prepends_the_word_squawk'
```
Great - now you are ready to start development.
-Then in `lib/yaffle.rb` require `lib/core_ext`:
+In `lib/yaffle.rb`, add `require 'yaffle/core_ext'`:
```ruby
# yaffle/lib/yaffle.rb
-require "yaffle/core_ext"
+require 'yaffle/core_ext'
module Yaffle
end
@@ -112,13 +118,13 @@ end
To test that your method does what it says it does, run the unit tests with `rake` from your plugin directory.
```bash
- 3 tests, 3 assertions, 0 failures, 0 errors, 0 skips
+ 2 runs, 2 assertions, 0 failures, 0 errors, 0 skips
```
To see this in action, change to the test/dummy directory, fire up a console and start squawking:
```bash
-$ rails console
+$ bin/rails console
>> "Hello World".to_squawk
=> "squawk! Hello World"
```
@@ -126,8 +132,8 @@ $ rails console
Add an "acts_as" Method to Active Record
----------------------------------------
-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 Active Record models.
+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 Active Record models.
To begin, set up your files so that you have:
@@ -136,14 +142,14 @@ To begin, set up your files so that you have:
require 'test_helper'
-class ActsAsYaffleTest < Test::Unit::TestCase
+class ActsAsYaffleTest < ActiveSupport::TestCase
end
```
```ruby
# yaffle/lib/yaffle.rb
-require "yaffle/core_ext"
+require 'yaffle/core_ext'
require 'yaffle/acts_as_yaffle'
module Yaffle
@@ -162,9 +168,9 @@ end
### Add a Class Method
-This plugin will expect that you've added a method to your model named 'last_squawk'. However, the
-plugin users might have already defined a method on their model named 'last_squawk' that they use
-for something else. This plugin will allow the name to be changed by adding a class method called 'yaffle_text_field'.
+This plugin will expect that you've added a method to your model named `last_squawk`. However, the
+plugin users might have already defined a method on their model named `last_squawk` that they use
+for something else. This plugin will allow the name to be changed by adding a class method called `yaffle_text_field`.
To start out, write a failing test that shows the behavior you'd like:
@@ -173,7 +179,7 @@ To start out, write a failing test that shows the behavior you'd like:
require 'test_helper'
-class ActsAsYaffleTest < Test::Unit::TestCase
+class ActsAsYaffleTest < ActiveSupport::TestCase
def test_a_hickwalls_yaffle_text_field_should_be_last_squawk
assert_equal "last_squawk", Hickwall.yaffle_text_field
@@ -190,16 +196,16 @@ When you run `rake`, you should see the following:
```
1) Error:
- test_a_hickwalls_yaffle_text_field_should_be_last_squawk(ActsAsYaffleTest):
+ ActsAsYaffleTest#test_a_hickwalls_yaffle_text_field_should_be_last_squawk:
NameError: uninitialized constant ActsAsYaffleTest::Hickwall
- test/acts_as_yaffle_test.rb:6:in `test_a_hickwalls_yaffle_text_field_should_be_last_squawk'
+ /path/to/yaffle/test/acts_as_yaffle_test.rb:6:in `test_a_hickwalls_yaffle_text_field_should_be_last_squawk'
2) Error:
- test_a_wickwalls_yaffle_text_field_should_be_last_tweet(ActsAsYaffleTest):
+ ActsAsYaffleTest#test_a_wickwalls_yaffle_text_field_should_be_last_tweet:
NameError: uninitialized constant ActsAsYaffleTest::Wickwall
- test/acts_as_yaffle_test.rb:10:in `test_a_wickwalls_yaffle_text_field_should_be_last_tweet'
+ /path/to/yaffle/test/acts_as_yaffle_test.rb:10:in `test_a_wickwalls_yaffle_text_field_should_be_last_tweet'
- 5 tests, 3 assertions, 0 failures, 2 errors, 0 skips
+ 4 runs, 2 assertions, 0 failures, 2 errors, 0 skips
```
This tells us that we don't have the necessary models (Hickwall and Wickwall) that we are trying to test.
@@ -208,17 +214,16 @@ test/dummy directory:
```bash
$ cd test/dummy
-$ rails generate model Hickwall last_squawk:string
-$ rails generate model Wickwall last_squawk:string last_tweet:string
+$ bin/rails generate model Hickwall last_squawk:string
+$ bin/rails generate model Wickwall last_squawk:string last_tweet:string
```
Now you can create the necessary database tables in your testing database by navigating to your dummy app
-and migrating the database. First
+and migrating the database. First, run:
```bash
$ cd test/dummy
-$ rake db:migrate
-$ rake db:test:prepare
+$ bin/rake db:migrate
```
While you are here, change the Hickwall and Wickwall models so that they know that they are supposed to act
@@ -239,7 +244,7 @@ end
```
-We will also add code to define the acts_as_yaffle method.
+We will also add code to define the `acts_as_yaffle` method.
```ruby
# yaffle/lib/yaffle/acts_as_yaffle.rb
@@ -265,22 +270,22 @@ You can then return to the root directory (`cd ../..`) of your plugin and rerun
```
1) Error:
- test_a_hickwalls_yaffle_text_field_should_be_last_squawk(ActsAsYaffleTest):
- NoMethodError: undefined method `yaffle_text_field' for #<Class:0x000001016661b8>
- /Users/xxx/.rvm/gems/ruby-1.9.2-p136@xxx/gems/activerecord-3.0.3/lib/active_record/base.rb:1008:in `method_missing'
- test/acts_as_yaffle_test.rb:5:in `test_a_hickwalls_yaffle_text_field_should_be_last_squawk'
+ ActsAsYaffleTest#test_a_hickwalls_yaffle_text_field_should_be_last_squawk:
+ NoMethodError: undefined method `yaffle_text_field' for #<Class:0x007fd105e3b218>
+ activerecord (4.1.5) lib/active_record/dynamic_matchers.rb:26:in `method_missing'
+ /path/to/yaffle/test/acts_as_yaffle_test.rb:6:in `test_a_hickwalls_yaffle_text_field_should_be_last_squawk'
2) Error:
- test_a_wickwalls_yaffle_text_field_should_be_last_tweet(ActsAsYaffleTest):
- NoMethodError: undefined method `yaffle_text_field' for #<Class:0x00000101653748>
- Users/xxx/.rvm/gems/ruby-1.9.2-p136@xxx/gems/activerecord-3.0.3/lib/active_record/base.rb:1008:in `method_missing'
- test/acts_as_yaffle_test.rb:9:in `test_a_wickwalls_yaffle_text_field_should_be_last_tweet'
+ ActsAsYaffleTest#test_a_wickwalls_yaffle_text_field_should_be_last_tweet:
+ NoMethodError: undefined method `yaffle_text_field' for #<Class:0x007fd105e409c0>
+ activerecord (4.1.5) lib/active_record/dynamic_matchers.rb:26:in `method_missing'
+ /path/to/yaffle/test/acts_as_yaffle_test.rb:10:in `test_a_wickwalls_yaffle_text_field_should_be_last_tweet'
- 5 tests, 3 assertions, 0 failures, 2 errors, 0 skips
+ 4 runs, 2 assertions, 0 failures, 2 errors, 0 skips
```
-Getting closer... Now we will implement the code of the acts_as_yaffle method to make the tests pass.
+Getting closer... Now we will implement the code of the `acts_as_yaffle` method to make the tests pass.
```ruby
# yaffle/lib/yaffle/acts_as_yaffle.rb
@@ -304,10 +309,10 @@ end
ActiveRecord::Base.send :include, Yaffle::ActsAsYaffle
```
-When you run `rake` you should see the tests all pass:
+When you run `rake`, you should see the tests all pass:
```bash
- 5 tests, 5 assertions, 0 failures, 0 errors, 0 skips
+ 4 runs, 4 assertions, 0 failures, 0 errors, 0 skips
```
### Add an Instance Method
@@ -321,7 +326,7 @@ To start out, write a failing test that shows the behavior you'd like:
# yaffle/test/acts_as_yaffle_test.rb
require 'test_helper'
-class ActsAsYaffleTest < Test::Unit::TestCase
+class ActsAsYaffleTest < ActiveSupport::TestCase
def test_a_hickwalls_yaffle_text_field_should_be_last_squawk
assert_equal "last_squawk", Hickwall.yaffle_text_field
@@ -381,10 +386,14 @@ ActiveRecord::Base.send :include, Yaffle::ActsAsYaffle
Run `rake` one final time and you should see:
```
- 7 tests, 7 assertions, 0 failures, 0 errors, 0 skips
+ 6 runs, 6 assertions, 0 failures, 0 errors, 0 skips
```
-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)`.
+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:
+
+```ruby
+send("#{self.class.yaffle_text_field}=", string.to_squawk)
+```
Generators
----------
@@ -392,7 +401,7 @@ Generators
Generators can be included in your gem simply by creating them in a lib/generators directory of your plugin. More information about
the creation of generators can be found in the [Generators Guide](generators.html)
-Publishing your Gem
+Publishing Your Gem
-------------------
Gem plugins currently in development can easily be shared from any Git repository. To share the Yaffle gem with others, simply
@@ -405,12 +414,12 @@ gem 'yaffle', git: 'git://github.com/yaffle_watcher/yaffle.git'
After running `bundle install`, your gem functionality will be available to the application.
When the gem is ready to be shared as a formal release, it can be published to [RubyGems](http://www.rubygems.org).
-For more information about publishing gems to RubyGems, see: [Creating and Publishing Your First Ruby Gem](http://blog.thepete.net/2010/11/creating-and-publishing-your-first-ruby.html)
+For more information about publishing gems to RubyGems, see: [Creating and Publishing Your First Ruby Gem](http://blog.thepete.net/2010/11/creating-and-publishing-your-first-ruby.html).
RDoc Documentation
------------------
-Once your plugin is stable and you are ready to deploy do everyone else a favor and document it! Luckily, writing documentation for your plugin is easy.
+Once your plugin is stable and you are ready to deploy, do everyone else a favor and document it! Luckily, writing documentation for your plugin is easy.
The first step is to update the README file with detailed information about how to use your plugin. A few key things to include are:
@@ -424,12 +433,12 @@ Once your README is solid, go through and add rdoc comments to all of the method
Once your comments are good to go, navigate to your plugin directory and run:
```bash
-$ rake rdoc
+$ bin/rake rdoc
```
### References
* [Developing a RubyGem using Bundler](https://github.com/radar/guides/blob/master/gem-development.md)
* [Using .gemspecs as Intended](http://yehudakatz.com/2010/04/02/using-gemspecs-as-intended/)
-* [Gemspec Reference](http://docs.rubygems.org/read/chapter/20)
+* [Gemspec Reference](http://guides.rubygems.org/specification-reference/)
* [GemPlugins: A Brief Introduction to the Future of Rails Plugins](http://www.intridea.com/blog/2008/6/11/gemplugins-a-brief-introduction-to-the-future-of-rails-plugins)