aboutsummaryrefslogtreecommitdiffstats
path: root/guides/source/engines.md
diff options
context:
space:
mode:
authorPrem Sichanugrist <s@sikachu.com>2012-09-01 17:25:58 -0400
committerPrem Sichanugrist <s@sikac.hu>2012-09-17 15:54:22 -0400
commit872b7af337196febc516cb6218ae3d07f01a11a8 (patch)
treebc31fdc0803fff3aed26b6599cf2df7789055a41 /guides/source/engines.md
parent7bc1ca351523949f6b4ce96018e95e61cbc7719e (diff)
downloadrails-872b7af337196febc516cb6218ae3d07f01a11a8.tar.gz
rails-872b7af337196febc516cb6218ae3d07f01a11a8.tar.bz2
rails-872b7af337196febc516cb6218ae3d07f01a11a8.zip
Convert heading tags and heading section
Diffstat (limited to 'guides/source/engines.md')
-rw-r--r--guides/source/engines.md71
1 files changed, 39 insertions, 32 deletions
diff --git a/guides/source/engines.md b/guides/source/engines.md
index b13f7df350..4ceefdec1c 100644
--- a/guides/source/engines.md
+++ b/guides/source/engines.md
@@ -1,4 +1,5 @@
-h2. Getting Started with Engines
+Getting Started with Engines
+============================
In this guide you will learn about engines and how they can be used to provide additional functionality to their host applications through a clean and very easy-to-use interface. You will learn the following things in this guide:
@@ -8,9 +9,10 @@ In this guide you will learn about engines and how they can be used to provide a
* Hooking the engine into an application
* Overriding engine functionality in the application
-endprologue.
+--------------------------------------------------------------------------------
-h3. What are engines?
+What are engines?
+-----------------
Engines can be considered miniature applications that provide functionality to their host applications. A Rails application is actually just a "supercharged" engine, with the +Rails::Application+ class inheriting a lot of its behaviour from +Rails::Engine+.
@@ -28,7 +30,8 @@ To see demonstrations of other engines, check out "Devise":https://github.com/pl
Finally, engines would not have been possible without the work of James Adam, Piotr Sarnacki, the Rails Core Team, and a number of other people. If you ever meet them, don't forget to say thanks!
-h3. Generating an engine
+Generating an engine
+--------------------
To generate an engine with Rails 3.1, you will need to run the plugin generator and pass it the +--full+ and +--mountable+ options. To generate the beginnings of the "blorgh" engine you will need to run this command in a terminal:
@@ -50,9 +53,9 @@ The +--mountable+ option tells the generator to mount the engine inside the dumm
mount Blorgh::Engine, :at => "blorgh"
```
-h4. Inside an engine
+### Inside an engine
-h5. Critical files
+#### Critical files
At the root of this brand new engine's directory lives a +blorgh.gemspec+ file. When you include the engine into an application later on, you will do so with this line in the Rails application's +Gemfile+:
@@ -91,7 +94,7 @@ What this isolation of the namespace means is that a model generated by a call t
Finally, routes will also be isolated within the engine. This is one of the most important parts about namespacing, and is discussed later in the "Routes":#routes section of this guide.
-h5. +app+ directory
+#### +app+ directory
Inside the +app+ directory are the standard +assets+, +controllers+, +helpers+, +mailers+, +models+ and +views+ directories that you should be familiar with from an application. The +helpers+, +mailers+ and +models+ directories are empty and so aren't described in this section. We'll look more into models in a future section, when we're writing the engine.
@@ -105,7 +108,7 @@ Lastly, the +app/views+ directory contains a +layouts+ folder which contains a f
If you don't want to force a layout on to users of the engine, then you can delete this file and reference a different layout in the controllers of your engine.
-h5. +script+ directory
+#### +script+ directory
This directory contains one file, +script/rails+, which enables you to use the +rails+ sub-commands and generators just like you would within an application. This means that you will very easily be able to generate new controllers and models for this engine by running commands like this:
@@ -115,7 +118,7 @@ rails g model
Keeping in mind, of course, that anything generated with these commands inside an engine that has +isolate_namespace+ inside the +Engine+ class will be namespaced.
-h5. +test+ directory
+#### +test+ directory
The +test+ directory is where tests for the engine will go. To test the engine, there is a cut-down version of a Rails application embedded within it at +test/dummy+. This application will mount the engine in the +test/dummy/config/routes.rb+ file:
@@ -129,11 +132,12 @@ This line mounts the engine at the path +/blorgh+, which will make it accessible
Also in the test directory is the +test/integration+ directory, where integration tests for the engine should be placed. Other directories can be created in the +test+ directory also. For example, you may wish to create a +test/unit+ directory for your unit tests.
-h3. Providing engine functionality
+Providing engine functionality
+------------------------------
The engine that this guide covers provides posting and commenting functionality and follows a similar thread to the "Getting Started Guide":getting_started.html, with some new twists.
-h4. Generating a post resource
+### Generating a post resource
The first thing to generate for a blog engine is the +Post+ model and related controller. To quickly generate this, you can use the Rails scaffold generator.
@@ -240,7 +244,7 @@ root :to => "posts#index"
Now people will only need to go to the root of the engine to see all the posts, rather than visiting +/posts+. This means that instead of +http://localhost:3000/blorgh/posts+, you only need to go to +http://localhost:3000/blorgh+ now.
-h4. Generating a comments resource
+### Generating a comments resource
Now that the engine has the ability to create new blog posts, it only makes sense to add commenting functionality as well. To do get this, you'll need to generate a comment model, a comment controller and then modify the posts scaffold to display comments and allow people to create new ones.
@@ -373,11 +377,12 @@ The +comment_counter+ local variable is given to us by the +&lt;%= render @post.
That completes the comment function of the blogging engine. Now it's time to use it within an application.
-h3. Hooking into an application
+Hooking into an application
+---------------------------
Using an engine within an application is very easy. This section covers how to mount the engine into an application and the initial setup required, as well as linking the engine to a +User+ class provided by the application to provide ownership for posts and comments within the engine.
-h4. Mounting the engine
+### Mounting the engine
First, the engine needs to be specified inside the application's +Gemfile+. If there isn't an application handy to test this out in, generate one using the +rails new+ command outside of the engine directory like this:
@@ -409,7 +414,7 @@ This line will mount the engine at +/blog+ in the application. Making it accessi
NOTE: Other engines, such as Devise, handle this a little differently by making you specify custom helpers such as +devise_for+ in the routes. These helpers do exactly the same thing, mounting pieces of the engines's functionality at a pre-defined path which may be customizable.
-h4. Engine setup
+### Engine setup
The engine contains migrations for the +blorgh_posts+ and +blorgh_comments+ table which need to be created in the application's database so that the engine's models can query them correctly. To copy these migrations into the application use this command:
@@ -446,9 +451,9 @@ This may be useful if you want to revert engine's migrations before removing it.
rake db:migrate SCOPE=blorgh VERSION=0
```
-h4. Using a class provided by the application
+### Using a class provided by the application
-h5. Using a model provided by the application
+#### Using a model provided by the application
When an engine is created, it may want to use specific classes from an application to provide links between the pieces of the engine and the pieces of the application. In the case of the +blorgh+ engine, making posts and comments have authors would make a lot of sense.
@@ -546,7 +551,7 @@ end
Now instead of the ugly Ruby object output the author's name will be displayed.
-h5. Using a controller provided by the application
+#### Using a controller provided by the application
Because Rails controllers generally share code for things like authentication and accessing session variables, by default they inherit from <tt>ApplicationController</tt>. Rails engines, however are scoped to run independently from the main application, so each engine gets a scoped +ApplicationController+. This namespace prevents code collisions, but often engine controllers should access methods in the main application's +ApplicationController+. An easy way to provide this access is to change the engine's scoped +ApplicationController+ to inherit from the main application's +ApplicationController+. For our Blorgh engine this would be done by changing +app/controllers/blorgh/application_controller.rb+ to look like:
@@ -559,11 +564,11 @@ By default, the engine's controllers inherit from <tt>Blorgh::ApplicationControl
This change does require that the engine is run from a Rails application that has an +ApplicationController+.
-h4. Configuring an engine
+### Configuring an engine
This section covers how to make the +User+ class configurable, followed by general configuration tips for the engine.
-h5. Setting configuration settings in the application
+#### Setting configuration settings in the application
The next step is to make the class that represents a +User+ in the application customizable for the engine. This is because, as explained before, that class may not always be +User+. To make this customizable, the engine will have a configuration setting called +user_class+ that will be used to specify what the class representing users is inside the application.
@@ -617,7 +622,7 @@ Go ahead and try to create a new post. You will see that it works exactly in the
There are now no strict dependencies on what the class is, only what the API for the class must be. The engine simply requires this class to define a +find_or_create_by_name+ method which returns an object of that class to be associated with a post when it's created. This object, of course, should have some sort of identifier by which it can be referenced.
-h5. General engine configuration
+#### General engine configuration
Within an engine, there may come a time where you wish to use things such as initializers, internationalization or other configuration options. The great news is that these things are entirely possible because a Rails engine shares much the same functionality as a Rails application. In fact, a Rails application's functionality is actually a superset of what is provided by engines!
@@ -625,13 +630,14 @@ If you wish to use an initializer -- code that should run before the engine is l
For locales, simply place the locale files in the +config/locales+ directory, just like you would in an application.
-h3. Testing an engine
+Testing an engine
+-----------------
When an engine is generated there is a smaller dummy application created inside it at +test/dummy+. This application is used as a mounting point for the engine to make testing the engine extremely simple. You may extend this application by generating controllers, models or views from within the directory, and then use those to test your engine.
The +test+ directory should be treated like a typical Rails testing environment, allowing for unit, functional and integration tests.
-h4. Functional tests
+### Functional tests
A matter worth taking into consideration when writing functional tests is that the tests are going to be running on an application -- the +test/dummy+ application -- rather than your engine. This is due to the setup of the testing environment; an engine needs an application as a host for testing its main functionality, especially controllers. This means that if you were to make a typical +GET+ to a controller in a controller's functional test like this:
@@ -647,17 +653,18 @@ get :index, :use_route => :blorgh
This tells the application that you still want to perform a +GET+ request to the +index+ action of this controller, just that you want to use the engine's route to get there, rather than the application.
-h3. Improving engine functionality
+Improving engine functionality
+------------------------------
This section explains how to add and/or override engine MVC functionality in the main Rails application.
-h4. Overriding Models and Controllers
+### Overriding Models and Controllers
Engine model and controller classes can be extended by open classing them in the main Rails application (since model and controller classes are just Ruby classes that inherit Rails specific functionality). Open classing an Engine class redefines it for use in the main applicaiton. This is usually implemented by using the decorator pattern.
For simple class modifications use +Class#class_eval+, and for complex class modifications, consider using +ActiveSupport::Concern+.
-h5. Implementing Decorator Pattern Using Class#class_eval
+#### Implementing Decorator Pattern Using Class#class_eval
**Adding** +Post#time_since_created+,
@@ -704,7 +711,7 @@ end
```
-h5. Implementing Decorator Pattern Using ActiveSupport::Concern
+#### Implementing Decorator Pattern Using ActiveSupport::Concern
Using +Class#class_eval+ is great for simple adjustments, but for more complex class modifications, you might want to consider using +ActiveSupport::Concern+. ["**ActiveSupport::Concern**":http://edgeapi.rubyonrails.org/classes/ActiveSupport/Concern.html] helps manage the load order of interlinked dependencies at run time allowing you to significantly modularize your code.
@@ -769,7 +776,7 @@ module Blorgh::Concerns::Models::Post
end
```
-h4. Overriding views
+### Overriding views
When Rails looks for a view to render, it will first look in the +app/views+ directory of the application. If it cannot find the view there, then it will check in the +app/views+ directories of all engines which have this directory.
@@ -790,7 +797,7 @@ Try this now by creating a new file at +app/views/blorgh/posts/index.html.erb+ a
<% end %>
```
-h4. Routes
+### Routes
Routes inside an engine are, by default, isolated from the application. This is done by the +isolate_namespace+ call inside the +Engine+ class. This essentially means that the application and its engines can have identically named routes, and that they will not clash.
@@ -826,7 +833,7 @@ If you were to use this inside an engine, it would *always* go to the applicatio
If a template is rendered from within an engine and it's attempting to use one of the application's routing helper methods, it may result in an undefined method call. If you encounter such an issue, ensure that you're not attempting to call the application's routing methods without the +main_app+ prefix from within the engine.
-h4. Assets
+### Assets
Assets within an engine work in an identical way to a full application. Because the engine class inherits from +Rails::Engine+, the application will know to look up in the engine's +app/assets+ and +lib/assets+ directories for potential assets.
@@ -848,7 +855,7 @@ You can also specify these assets as dependencies of other assets using the Asse
INFO. Remember that in order to use languages like Sass or CoffeeScript, you should add the relevant library to your engine's +.gemspec+.
-h4. Separate Assets & Precompiling
+### Separate Assets & Precompiling
There are some situations where your engine's assets are not required by the host application. For example, say that you've created
an admin functionality that only exists for your engine. In this case, the host application doesn't need to require +admin.css+
@@ -865,7 +872,7 @@ end
For more information, read the "Asset Pipeline guide":http://guides.rubyonrails.org/asset_pipeline.html
-h4. Other gem dependencies
+### Other gem dependencies
Gem dependencies inside an engine should be specified inside the +.gemspec+ file at the root of the engine. The reason for this is because the engine may
be installed as a gem. If dependencies were to be specified inside the +Gemfile+,