rails 3.2.22.2 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (216) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +85 -0
  3. data/guides/CHANGELOG.md +31 -0
  4. data/guides/Rakefile +79 -0
  5. data/guides/assets/images/akshaysurve.jpg +0 -0
  6. data/guides/assets/images/belongs_to.png +0 -0
  7. data/guides/assets/images/book_icon.gif +0 -0
  8. data/guides/assets/images/bullet.gif +0 -0
  9. data/guides/assets/images/chapters_icon.gif +0 -0
  10. data/guides/assets/images/check_bullet.gif +0 -0
  11. data/guides/assets/images/credits_pic_blank.gif +0 -0
  12. data/guides/assets/images/csrf.png +0 -0
  13. data/guides/assets/images/edge_badge.png +0 -0
  14. data/guides/assets/images/favicon.ico +0 -0
  15. data/guides/assets/images/feature_tile.gif +0 -0
  16. data/guides/assets/images/footer_tile.gif +0 -0
  17. data/guides/assets/images/fxn.png +0 -0
  18. data/guides/assets/images/getting_started/article_with_comments.png +0 -0
  19. data/guides/assets/images/getting_started/challenge.png +0 -0
  20. data/guides/assets/images/getting_started/confirm_dialog.png +0 -0
  21. data/guides/assets/images/getting_started/forbidden_attributes_for_new_article.png +0 -0
  22. data/guides/assets/images/getting_started/form_with_errors.png +0 -0
  23. data/guides/assets/images/getting_started/index_action_with_edit_link.png +0 -0
  24. data/guides/assets/images/getting_started/new_article.png +0 -0
  25. data/guides/assets/images/getting_started/rails_welcome.png +0 -0
  26. data/guides/assets/images/getting_started/routing_error_no_controller.png +0 -0
  27. data/guides/assets/images/getting_started/routing_error_no_route_matches.png +0 -0
  28. data/guides/assets/images/getting_started/show_action_for_articles.png +0 -0
  29. data/guides/assets/images/getting_started/template_is_missing_articles_new.png +0 -0
  30. data/guides/assets/images/getting_started/unknown_action_create_for_articles.png +0 -0
  31. data/guides/assets/images/getting_started/unknown_action_new_for_articles.png +0 -0
  32. data/guides/assets/images/grey_bullet.gif +0 -0
  33. data/guides/assets/images/habtm.png +0 -0
  34. data/guides/assets/images/has_many.png +0 -0
  35. data/guides/assets/images/has_many_through.png +0 -0
  36. data/guides/assets/images/has_one.png +0 -0
  37. data/guides/assets/images/has_one_through.png +0 -0
  38. data/guides/assets/images/header_backdrop.png +0 -0
  39. data/guides/assets/images/header_tile.gif +0 -0
  40. data/guides/assets/images/i18n/demo_html_safe.png +0 -0
  41. data/guides/assets/images/i18n/demo_localized_pirate.png +0 -0
  42. data/guides/assets/images/i18n/demo_translated_en.png +0 -0
  43. data/guides/assets/images/i18n/demo_translated_pirate.png +0 -0
  44. data/guides/assets/images/i18n/demo_translation_missing.png +0 -0
  45. data/guides/assets/images/i18n/demo_untranslated.png +0 -0
  46. data/guides/assets/images/icons/README +5 -0
  47. data/guides/assets/images/icons/callouts/1.png +0 -0
  48. data/guides/assets/images/icons/callouts/10.png +0 -0
  49. data/guides/assets/images/icons/callouts/11.png +0 -0
  50. data/guides/assets/images/icons/callouts/12.png +0 -0
  51. data/guides/assets/images/icons/callouts/13.png +0 -0
  52. data/guides/assets/images/icons/callouts/14.png +0 -0
  53. data/guides/assets/images/icons/callouts/15.png +0 -0
  54. data/guides/assets/images/icons/callouts/2.png +0 -0
  55. data/guides/assets/images/icons/callouts/3.png +0 -0
  56. data/guides/assets/images/icons/callouts/4.png +0 -0
  57. data/guides/assets/images/icons/callouts/5.png +0 -0
  58. data/guides/assets/images/icons/callouts/6.png +0 -0
  59. data/guides/assets/images/icons/callouts/7.png +0 -0
  60. data/guides/assets/images/icons/callouts/8.png +0 -0
  61. data/guides/assets/images/icons/callouts/9.png +0 -0
  62. data/guides/assets/images/icons/caution.png +0 -0
  63. data/guides/assets/images/icons/example.png +0 -0
  64. data/guides/assets/images/icons/home.png +0 -0
  65. data/guides/assets/images/icons/important.png +0 -0
  66. data/guides/assets/images/icons/next.png +0 -0
  67. data/guides/assets/images/icons/note.png +0 -0
  68. data/guides/assets/images/icons/prev.png +0 -0
  69. data/guides/assets/images/icons/tip.png +0 -0
  70. data/guides/assets/images/icons/up.png +0 -0
  71. data/guides/assets/images/icons/warning.png +0 -0
  72. data/guides/assets/images/nav_arrow.gif +0 -0
  73. data/guides/assets/images/oscardelben.jpg +0 -0
  74. data/guides/assets/images/polymorphic.png +0 -0
  75. data/guides/assets/images/radar.png +0 -0
  76. data/guides/assets/images/rails4_features.png +0 -0
  77. data/guides/assets/images/rails_guides_kindle_cover.jpg +0 -0
  78. data/guides/assets/images/rails_guides_logo.gif +0 -0
  79. data/guides/assets/images/rails_logo_remix.gif +0 -0
  80. data/guides/assets/images/session_fixation.png +0 -0
  81. data/guides/assets/images/tab_grey.gif +0 -0
  82. data/guides/assets/images/tab_info.gif +0 -0
  83. data/guides/assets/images/tab_note.gif +0 -0
  84. data/guides/assets/images/tab_red.gif +0 -0
  85. data/guides/assets/images/tab_yellow.gif +0 -0
  86. data/guides/assets/images/tab_yellow.png +0 -0
  87. data/guides/assets/images/vijaydev.jpg +0 -0
  88. data/guides/assets/javascripts/guides.js +59 -0
  89. data/guides/assets/javascripts/jquery.min.js +4 -0
  90. data/guides/assets/javascripts/responsive-tables.js +43 -0
  91. data/guides/assets/javascripts/syntaxhighlighter/shBrushAS3.js +59 -0
  92. data/guides/assets/javascripts/syntaxhighlighter/shBrushAppleScript.js +75 -0
  93. data/guides/assets/javascripts/syntaxhighlighter/shBrushBash.js +59 -0
  94. data/guides/assets/javascripts/syntaxhighlighter/shBrushCSharp.js +65 -0
  95. data/guides/assets/javascripts/syntaxhighlighter/shBrushColdFusion.js +100 -0
  96. data/guides/assets/javascripts/syntaxhighlighter/shBrushCpp.js +97 -0
  97. data/guides/assets/javascripts/syntaxhighlighter/shBrushCss.js +91 -0
  98. data/guides/assets/javascripts/syntaxhighlighter/shBrushDelphi.js +55 -0
  99. data/guides/assets/javascripts/syntaxhighlighter/shBrushDiff.js +41 -0
  100. data/guides/assets/javascripts/syntaxhighlighter/shBrushErlang.js +52 -0
  101. data/guides/assets/javascripts/syntaxhighlighter/shBrushGroovy.js +67 -0
  102. data/guides/assets/javascripts/syntaxhighlighter/shBrushJScript.js +52 -0
  103. data/guides/assets/javascripts/syntaxhighlighter/shBrushJava.js +57 -0
  104. data/guides/assets/javascripts/syntaxhighlighter/shBrushJavaFX.js +58 -0
  105. data/guides/assets/javascripts/syntaxhighlighter/shBrushPerl.js +72 -0
  106. data/guides/assets/javascripts/syntaxhighlighter/shBrushPhp.js +88 -0
  107. data/guides/assets/javascripts/syntaxhighlighter/shBrushPlain.js +33 -0
  108. data/guides/assets/javascripts/syntaxhighlighter/shBrushPowerShell.js +74 -0
  109. data/guides/assets/javascripts/syntaxhighlighter/shBrushPython.js +64 -0
  110. data/guides/assets/javascripts/syntaxhighlighter/shBrushRuby.js +55 -0
  111. data/guides/assets/javascripts/syntaxhighlighter/shBrushSass.js +94 -0
  112. data/guides/assets/javascripts/syntaxhighlighter/shBrushScala.js +51 -0
  113. data/guides/assets/javascripts/syntaxhighlighter/shBrushSql.js +66 -0
  114. data/guides/assets/javascripts/syntaxhighlighter/shBrushVb.js +56 -0
  115. data/guides/assets/javascripts/syntaxhighlighter/shBrushXml.js +69 -0
  116. data/guides/assets/javascripts/syntaxhighlighter/shCore.js +17 -0
  117. data/guides/assets/stylesheets/fixes.css +16 -0
  118. data/guides/assets/stylesheets/kindle.css +11 -0
  119. data/guides/assets/stylesheets/main.css +713 -0
  120. data/guides/assets/stylesheets/print.css +52 -0
  121. data/guides/assets/stylesheets/reset.css +43 -0
  122. data/guides/assets/stylesheets/responsive-tables.css +50 -0
  123. data/guides/assets/stylesheets/style.css +13 -0
  124. data/guides/assets/stylesheets/syntaxhighlighter/shCore.css +226 -0
  125. data/guides/assets/stylesheets/syntaxhighlighter/shCoreDefault.css +328 -0
  126. data/guides/assets/stylesheets/syntaxhighlighter/shCoreDjango.css +331 -0
  127. data/guides/assets/stylesheets/syntaxhighlighter/shCoreEclipse.css +339 -0
  128. data/guides/assets/stylesheets/syntaxhighlighter/shCoreEmacs.css +324 -0
  129. data/guides/assets/stylesheets/syntaxhighlighter/shCoreFadeToGrey.css +328 -0
  130. data/guides/assets/stylesheets/syntaxhighlighter/shCoreMDUltra.css +324 -0
  131. data/guides/assets/stylesheets/syntaxhighlighter/shCoreMidnight.css +324 -0
  132. data/guides/assets/stylesheets/syntaxhighlighter/shCoreRDark.css +324 -0
  133. data/guides/assets/stylesheets/syntaxhighlighter/shThemeDefault.css +117 -0
  134. data/guides/assets/stylesheets/syntaxhighlighter/shThemeDjango.css +120 -0
  135. data/guides/assets/stylesheets/syntaxhighlighter/shThemeEclipse.css +128 -0
  136. data/guides/assets/stylesheets/syntaxhighlighter/shThemeEmacs.css +113 -0
  137. data/guides/assets/stylesheets/syntaxhighlighter/shThemeFadeToGrey.css +117 -0
  138. data/guides/assets/stylesheets/syntaxhighlighter/shThemeMDUltra.css +113 -0
  139. data/guides/assets/stylesheets/syntaxhighlighter/shThemeMidnight.css +113 -0
  140. data/guides/assets/stylesheets/syntaxhighlighter/shThemeRDark.css +113 -0
  141. data/guides/assets/stylesheets/syntaxhighlighter/shThemeRailsGuides.css +116 -0
  142. data/guides/bug_report_templates/action_controller_gem.rb +47 -0
  143. data/guides/bug_report_templates/action_controller_master.rb +54 -0
  144. data/guides/bug_report_templates/active_record_gem.rb +40 -0
  145. data/guides/bug_report_templates/active_record_master.rb +49 -0
  146. data/guides/rails_guides/generator.rb +248 -0
  147. data/guides/rails_guides/helpers.rb +53 -0
  148. data/guides/rails_guides/indexer.rb +68 -0
  149. data/guides/rails_guides/kindle.rb +119 -0
  150. data/guides/rails_guides/levenshtein.rb +39 -0
  151. data/guides/rails_guides/markdown/renderer.rb +82 -0
  152. data/guides/rails_guides/markdown.rb +167 -0
  153. data/guides/rails_guides.rb +63 -0
  154. data/guides/source/2_2_release_notes.md +435 -0
  155. data/guides/source/2_3_release_notes.md +621 -0
  156. data/guides/source/3_0_release_notes.md +611 -0
  157. data/guides/source/3_1_release_notes.md +559 -0
  158. data/guides/source/3_2_release_notes.md +568 -0
  159. data/guides/source/4_0_release_notes.md +279 -0
  160. data/guides/source/4_1_release_notes.md +730 -0
  161. data/guides/source/4_2_release_notes.md +850 -0
  162. data/guides/source/_license.html.erb +2 -0
  163. data/guides/source/_welcome.html.erb +19 -0
  164. data/guides/source/action_controller_overview.md +1249 -0
  165. data/guides/source/action_mailer_basics.md +752 -0
  166. data/guides/source/action_view_overview.md +1620 -0
  167. data/guides/source/active_job_basics.md +318 -0
  168. data/guides/source/active_model_basics.md +554 -0
  169. data/guides/source/active_record_basics.md +374 -0
  170. data/guides/source/active_record_callbacks.md +413 -0
  171. data/guides/source/active_record_migrations.md +1018 -0
  172. data/guides/source/active_record_postgresql.md +433 -0
  173. data/guides/source/active_record_querying.md +1783 -0
  174. data/guides/source/active_record_validations.md +1178 -0
  175. data/guides/source/active_support_core_extensions.md +3904 -0
  176. data/guides/source/active_support_instrumentation.md +499 -0
  177. data/guides/source/api_documentation_guidelines.md +361 -0
  178. data/guides/source/asset_pipeline.md +1360 -0
  179. data/guides/source/association_basics.md +2236 -0
  180. data/guides/source/caching_with_rails.md +379 -0
  181. data/guides/source/command_line.md +625 -0
  182. data/guides/source/configuring.md +1045 -0
  183. data/guides/source/constant_autoloading_and_reloading.md +1297 -0
  184. data/guides/source/contributing_to_ruby_on_rails.md +624 -0
  185. data/guides/source/credits.html.erb +80 -0
  186. data/guides/source/debugging_rails_applications.md +861 -0
  187. data/guides/source/development_dependencies_install.md +289 -0
  188. data/guides/source/documents.yaml +205 -0
  189. data/guides/source/engines.md +1412 -0
  190. data/guides/source/form_helpers.md +1024 -0
  191. data/guides/source/generators.md +676 -0
  192. data/guides/source/getting_started.md +2085 -0
  193. data/guides/source/i18n.md +1086 -0
  194. data/guides/source/index.html.erb +28 -0
  195. data/guides/source/initialization.md +704 -0
  196. data/guides/source/kindle/copyright.html.erb +1 -0
  197. data/guides/source/kindle/layout.html.erb +27 -0
  198. data/guides/source/kindle/rails_guides.opf.erb +52 -0
  199. data/guides/source/kindle/toc.html.erb +24 -0
  200. data/guides/source/kindle/toc.ncx.erb +64 -0
  201. data/guides/source/kindle/welcome.html.erb +5 -0
  202. data/guides/source/layout.html.erb +143 -0
  203. data/guides/source/layouts_and_rendering.md +1227 -0
  204. data/guides/source/maintenance_policy.md +78 -0
  205. data/guides/source/nested_model_forms.md +228 -0
  206. data/guides/source/plugins.md +444 -0
  207. data/guides/source/rails_application_templates.md +266 -0
  208. data/guides/source/rails_on_rack.md +336 -0
  209. data/guides/source/routing.md +1141 -0
  210. data/guides/source/ruby_on_rails_guides_guidelines.md +127 -0
  211. data/guides/source/security.md +1024 -0
  212. data/guides/source/testing.md +1123 -0
  213. data/guides/source/upgrading_ruby_on_rails.md +1154 -0
  214. data/guides/source/working_with_javascript_in_rails.md +407 -0
  215. data/guides/w3c_validator.rb +97 -0
  216. metadata +290 -44
@@ -0,0 +1,1412 @@
1
+ Getting Started with Engines
2
+ ============================
3
+
4
+ In this guide you will learn about engines and how they can be used to provide
5
+ additional functionality to their host applications through a clean and very
6
+ easy-to-use interface.
7
+
8
+ After reading this guide, you will know:
9
+
10
+ * What makes an engine.
11
+ * How to generate an engine.
12
+ * Building features for the engine.
13
+ * Hooking the engine into an application.
14
+ * Overriding engine functionality in the application.
15
+
16
+ --------------------------------------------------------------------------------
17
+
18
+ What are engines?
19
+ -----------------
20
+
21
+ Engines can be considered miniature applications that provide functionality to
22
+ their host applications. A Rails application is actually just a "supercharged"
23
+ engine, with the `Rails::Application` class inheriting a lot of its behavior
24
+ from `Rails::Engine`.
25
+
26
+ Therefore, engines and applications can be thought of almost the same thing,
27
+ just with subtle differences, as you'll see throughout this guide. Engines and
28
+ applications also share a common structure.
29
+
30
+ Engines are also closely related to plugins. The two share a common `lib`
31
+ directory structure, and are both generated using the `rails plugin new`
32
+ generator. The difference is that an engine is considered a "full plugin" by
33
+ Rails (as indicated by the `--full` option that's passed to the generator
34
+ command). We'll actually be using the `--mountable` option here, which includes
35
+ all the features of `--full`, and then some. This guide will refer to these
36
+ "full plugins" simply as "engines" throughout. An engine **can** be a plugin,
37
+ and a plugin **can** be an engine.
38
+
39
+ The engine that will be created in this guide will be called "blorgh". This
40
+ engine will provide blogging functionality to its host applications, allowing
41
+ for new articles and comments to be created. At the beginning of this guide, you
42
+ will be working solely within the engine itself, but in later sections you'll
43
+ see how to hook it into an application.
44
+
45
+ Engines can also be isolated from their host applications. This means that an
46
+ application is able to have a path provided by a routing helper such as
47
+ `articles_path` and use an engine also that provides a path also called
48
+ `articles_path`, and the two would not clash. Along with this, controllers, models
49
+ and table names are also namespaced. You'll see how to do this later in this
50
+ guide.
51
+
52
+ It's important to keep in mind at all times that the application should
53
+ **always** take precedence over its engines. An application is the object that
54
+ has final say in what goes on in its environment. The engine should
55
+ only be enhancing it, rather than changing it drastically.
56
+
57
+ To see demonstrations of other engines, check out
58
+ [Devise](https://github.com/plataformatec/devise), an engine that provides
59
+ authentication for its parent applications, or
60
+ [Forem](https://github.com/radar/forem), an engine that provides forum
61
+ functionality. There's also [Spree](https://github.com/spree/spree) which
62
+ provides an e-commerce platform, and
63
+ [RefineryCMS](https://github.com/refinery/refinerycms), a CMS engine.
64
+
65
+ Finally, engines would not have been possible without the work of James Adam,
66
+ Piotr Sarnacki, the Rails Core Team, and a number of other people. If you ever
67
+ meet them, don't forget to say thanks!
68
+
69
+ Generating an engine
70
+ --------------------
71
+
72
+ To generate an engine, you will need to run the plugin generator and pass it
73
+ options as appropriate to the need. For the "blorgh" example, you will need to
74
+ create a "mountable" engine, running this command in a terminal:
75
+
76
+ ```bash
77
+ $ rails plugin new blorgh --mountable
78
+ ```
79
+
80
+ The full list of options for the plugin generator may be seen by typing:
81
+
82
+ ```bash
83
+ $ rails plugin --help
84
+ ```
85
+
86
+ The `--mountable` option tells the generator that you want to create a
87
+ "mountable" and namespace-isolated engine. This generator will provide the same
88
+ skeleton structure as would the `--full` option. The `--full` option tells the
89
+ generator that you want to create an engine, including a skeleton structure
90
+ that provides the following:
91
+
92
+ * An `app` directory tree
93
+ * A `config/routes.rb` file:
94
+
95
+ ```ruby
96
+ Rails.application.routes.draw do
97
+ end
98
+ ```
99
+
100
+ * A file at `lib/blorgh/engine.rb`, which is identical in function to a
101
+ standard Rails application's `config/application.rb` file:
102
+
103
+ ```ruby
104
+ module Blorgh
105
+ class Engine < ::Rails::Engine
106
+ end
107
+ end
108
+ ```
109
+
110
+ The `--mountable` option will add to the `--full` option:
111
+
112
+ * Asset manifest files (`application.js` and `application.css`)
113
+ * A namespaced `ApplicationController` stub
114
+ * A namespaced `ApplicationHelper` stub
115
+ * A layout view template for the engine
116
+ * Namespace isolation to `config/routes.rb`:
117
+
118
+ ```ruby
119
+ Blorgh::Engine.routes.draw do
120
+ end
121
+ ```
122
+
123
+ * Namespace isolation to `lib/blorgh/engine.rb`:
124
+
125
+ ```ruby
126
+ module Blorgh
127
+ class Engine < ::Rails::Engine
128
+ isolate_namespace Blorgh
129
+ end
130
+ end
131
+ ```
132
+
133
+ Additionally, the `--mountable` option tells the generator to mount the engine
134
+ inside the dummy testing application located at `test/dummy` by adding the
135
+ following to the dummy application's routes file at
136
+ `test/dummy/config/routes.rb`:
137
+
138
+ ```ruby
139
+ mount Blorgh::Engine => "/blorgh"
140
+ ```
141
+
142
+ ### Inside an Engine
143
+
144
+ #### Critical Files
145
+
146
+ At the root of this brand new engine's directory lives a `blorgh.gemspec` file.
147
+ When you include the engine into an application later on, you will do so with
148
+ this line in the Rails application's `Gemfile`:
149
+
150
+ ```ruby
151
+ gem 'blorgh', path: "vendor/engines/blorgh"
152
+ ```
153
+
154
+ Don't forget to run `bundle install` as usual. By specifying it as a gem within
155
+ the `Gemfile`, Bundler will load it as such, parsing this `blorgh.gemspec` file
156
+ and requiring a file within the `lib` directory called `lib/blorgh.rb`. This
157
+ file requires the `blorgh/engine.rb` file (located at `lib/blorgh/engine.rb`)
158
+ and defines a base module called `Blorgh`.
159
+
160
+ ```ruby
161
+ require "blorgh/engine"
162
+
163
+ module Blorgh
164
+ end
165
+ ```
166
+
167
+ TIP: Some engines choose to use this file to put global configuration options
168
+ for their engine. It's a relatively good idea, so if you want to offer
169
+ configuration options, the file where your engine's `module` is defined is
170
+ perfect for that. Place the methods inside the module and you'll be good to go.
171
+
172
+ Within `lib/blorgh/engine.rb` is the base class for the engine:
173
+
174
+ ```ruby
175
+ module Blorgh
176
+ class Engine < ::Rails::Engine
177
+ isolate_namespace Blorgh
178
+ end
179
+ end
180
+ ```
181
+
182
+ By inheriting from the `Rails::Engine` class, this gem notifies Rails that
183
+ there's an engine at the specified path, and will correctly mount the engine
184
+ inside the application, performing tasks such as adding the `app` directory of
185
+ the engine to the load path for models, mailers, controllers and views.
186
+
187
+ The `isolate_namespace` method here deserves special notice. This call is
188
+ responsible for isolating the controllers, models, routes and other things into
189
+ their own namespace, away from similar components inside the application.
190
+ Without this, there is a possibility that the engine's components could "leak"
191
+ into the application, causing unwanted disruption, or that important engine
192
+ components could be overridden by similarly named things within the application.
193
+ One of the examples of such conflicts is helpers. Without calling
194
+ `isolate_namespace`, the engine's helpers would be included in an application's
195
+ controllers.
196
+
197
+ NOTE: It is **highly** recommended that the `isolate_namespace` line be left
198
+ within the `Engine` class definition. Without it, classes generated in an engine
199
+ **may** conflict with an application.
200
+
201
+ What this isolation of the namespace means is that a model generated by a call
202
+ to `bin/rails g model`, such as `bin/rails g model article`, won't be called `Article`, but
203
+ instead be namespaced and called `Blorgh::Article`. In addition, the table for the
204
+ model is namespaced, becoming `blorgh_articles`, rather than simply `articles`.
205
+ Similar to the model namespacing, a controller called `ArticlesController` becomes
206
+ `Blorgh::ArticlesController` and the views for that controller will not be at
207
+ `app/views/articles`, but `app/views/blorgh/articles` instead. Mailers are namespaced
208
+ as well.
209
+
210
+ Finally, routes will also be isolated within the engine. This is one of the most
211
+ important parts about namespacing, and is discussed later in the
212
+ [Routes](#routes) section of this guide.
213
+
214
+ #### `app` Directory
215
+
216
+ Inside the `app` directory are the standard `assets`, `controllers`, `helpers`,
217
+ `mailers`, `models` and `views` directories that you should be familiar with
218
+ from an application. The `helpers`, `mailers` and `models` directories are
219
+ empty, so they aren't described in this section. We'll look more into models in
220
+ a future section, when we're writing the engine.
221
+
222
+ Within the `app/assets` directory, there are the `images`, `javascripts` and
223
+ `stylesheets` directories which, again, you should be familiar with due to their
224
+ similarity to an application. One difference here, however, is that each
225
+ directory contains a sub-directory with the engine name. Because this engine is
226
+ going to be namespaced, its assets should be too.
227
+
228
+ Within the `app/controllers` directory there is a `blorgh` directory that
229
+ contains a file called `application_controller.rb`. This file will provide any
230
+ common functionality for the controllers of the engine. The `blorgh` directory
231
+ is where the other controllers for the engine will go. By placing them within
232
+ this namespaced directory, you prevent them from possibly clashing with
233
+ identically-named controllers within other engines or even within the
234
+ application.
235
+
236
+ NOTE: The `ApplicationController` class inside an engine is named just like a
237
+ Rails application in order to make it easier for you to convert your
238
+ applications into engines.
239
+
240
+ Lastly, the `app/views` directory contains a `layouts` folder, which contains a
241
+ file at `blorgh/application.html.erb`. This file allows you to specify a layout
242
+ for the engine. If this engine is to be used as a stand-alone engine, then you
243
+ would add any customization to its layout in this file, rather than the
244
+ application's `app/views/layouts/application.html.erb` file.
245
+
246
+ If you don't want to force a layout on to users of the engine, then you can
247
+ delete this file and reference a different layout in the controllers of your
248
+ engine.
249
+
250
+ #### `bin` Directory
251
+
252
+ This directory contains one file, `bin/rails`, which enables you to use the
253
+ `rails` sub-commands and generators just like you would within an application.
254
+ This means that you will be able to generate new controllers and models for this
255
+ engine very easily by running commands like this:
256
+
257
+ ```bash
258
+ $ bin/rails g model
259
+ ```
260
+
261
+ Keep in mind, of course, that anything generated with these commands inside of
262
+ an engine that has `isolate_namespace` in the `Engine` class will be namespaced.
263
+
264
+ #### `test` Directory
265
+
266
+ The `test` directory is where tests for the engine will go. To test the engine,
267
+ there is a cut-down version of a Rails application embedded within it at
268
+ `test/dummy`. This application will mount the engine in the
269
+ `test/dummy/config/routes.rb` file:
270
+
271
+ ```ruby
272
+ Rails.application.routes.draw do
273
+ mount Blorgh::Engine => "/blorgh"
274
+ end
275
+ ```
276
+
277
+ This line mounts the engine at the path `/blorgh`, which will make it accessible
278
+ through the application only at that path.
279
+
280
+ Inside the test directory there is the `test/integration` directory, where
281
+ integration tests for the engine should be placed. Other directories can be
282
+ created in the `test` directory as well. For example, you may wish to create a
283
+ `test/models` directory for your model tests.
284
+
285
+ Providing engine functionality
286
+ ------------------------------
287
+
288
+ The engine that this guide covers provides submitting articles and commenting
289
+ functionality and follows a similar thread to the [Getting Started
290
+ Guide](getting_started.html), with some new twists.
291
+
292
+ ### Generating an Article Resource
293
+
294
+ The first thing to generate for a blog engine is the `Article` model and related
295
+ controller. To quickly generate this, you can use the Rails scaffold generator.
296
+
297
+ ```bash
298
+ $ bin/rails generate scaffold article title:string text:text
299
+ ```
300
+
301
+ This command will output this information:
302
+
303
+ ```
304
+ invoke active_record
305
+ create db/migrate/[timestamp]_create_blorgh_articles.rb
306
+ create app/models/blorgh/article.rb
307
+ invoke test_unit
308
+ create test/models/blorgh/article_test.rb
309
+ create test/fixtures/blorgh/articles.yml
310
+ invoke resource_route
311
+ route resources :articles
312
+ invoke scaffold_controller
313
+ create app/controllers/blorgh/articles_controller.rb
314
+ invoke erb
315
+ create app/views/blorgh/articles
316
+ create app/views/blorgh/articles/index.html.erb
317
+ create app/views/blorgh/articles/edit.html.erb
318
+ create app/views/blorgh/articles/show.html.erb
319
+ create app/views/blorgh/articles/new.html.erb
320
+ create app/views/blorgh/articles/_form.html.erb
321
+ invoke test_unit
322
+ create test/controllers/blorgh/articles_controller_test.rb
323
+ invoke helper
324
+ create app/helpers/blorgh/articles_helper.rb
325
+ invoke assets
326
+ invoke js
327
+ create app/assets/javascripts/blorgh/articles.js
328
+ invoke css
329
+ create app/assets/stylesheets/blorgh/articles.css
330
+ invoke css
331
+ create app/assets/stylesheets/scaffold.css
332
+ ```
333
+
334
+ The first thing that the scaffold generator does is invoke the `active_record`
335
+ generator, which generates a migration and a model for the resource. Note here,
336
+ however, that the migration is called `create_blorgh_articles` rather than the
337
+ usual `create_articles`. This is due to the `isolate_namespace` method called in
338
+ the `Blorgh::Engine` class's definition. The model here is also namespaced,
339
+ being placed at `app/models/blorgh/article.rb` rather than `app/models/article.rb` due
340
+ to the `isolate_namespace` call within the `Engine` class.
341
+
342
+ Next, the `test_unit` generator is invoked for this model, generating a model
343
+ test at `test/models/blorgh/article_test.rb` (rather than
344
+ `test/models/article_test.rb`) and a fixture at `test/fixtures/blorgh/articles.yml`
345
+ (rather than `test/fixtures/articles.yml`).
346
+
347
+ After that, a line for the resource is inserted into the `config/routes.rb` file
348
+ for the engine. This line is simply `resources :articles`, turning the
349
+ `config/routes.rb` file for the engine into this:
350
+
351
+ ```ruby
352
+ Blorgh::Engine.routes.draw do
353
+ resources :articles
354
+ end
355
+ ```
356
+
357
+ Note here that the routes are drawn upon the `Blorgh::Engine` object rather than
358
+ the `YourApp::Application` class. This is so that the engine routes are confined
359
+ to the engine itself and can be mounted at a specific point as shown in the
360
+ [test directory](#test-directory) section. It also causes the engine's routes to
361
+ be isolated from those routes that are within the application. The
362
+ [Routes](#routes) section of this guide describes it in detail.
363
+
364
+ Next, the `scaffold_controller` generator is invoked, generating a controller
365
+ called `Blorgh::ArticlesController` (at
366
+ `app/controllers/blorgh/articles_controller.rb`) and its related views at
367
+ `app/views/blorgh/articles`. This generator also generates a test for the
368
+ controller (`test/controllers/blorgh/articles_controller_test.rb`) and a helper
369
+ (`app/helpers/blorgh/articles_controller.rb`).
370
+
371
+ Everything this generator has created is neatly namespaced. The controller's
372
+ class is defined within the `Blorgh` module:
373
+
374
+ ```ruby
375
+ module Blorgh
376
+ class ArticlesController < ApplicationController
377
+ ...
378
+ end
379
+ end
380
+ ```
381
+
382
+ NOTE: The `ApplicationController` class being inherited from here is the
383
+ `Blorgh::ApplicationController`, not an application's `ApplicationController`.
384
+
385
+ The helper inside `app/helpers/blorgh/articles_helper.rb` is also namespaced:
386
+
387
+ ```ruby
388
+ module Blorgh
389
+ module ArticlesHelper
390
+ ...
391
+ end
392
+ end
393
+ ```
394
+
395
+ This helps prevent conflicts with any other engine or application that may have
396
+ an article resource as well.
397
+
398
+ Finally, the assets for this resource are generated in two files:
399
+ `app/assets/javascripts/blorgh/articles.js` and
400
+ `app/assets/stylesheets/blorgh/articles.css`. You'll see how to use these a little
401
+ later.
402
+
403
+ By default, the scaffold styling is not applied to the engine because the
404
+ engine's layout file, `app/views/layouts/blorgh/application.html.erb`, doesn't
405
+ load it. To make the scaffold styling apply, insert this line into the `<head>`
406
+ tag of this layout:
407
+
408
+ ```erb
409
+ <%= stylesheet_link_tag "scaffold" %>
410
+ ```
411
+
412
+ You can see what the engine has so far by running `rake db:migrate` at the root
413
+ of our engine to run the migration generated by the scaffold generator, and then
414
+ running `rails server` in `test/dummy`. When you open
415
+ `http://localhost:3000/blorgh/articles` you will see the default scaffold that has
416
+ been generated. Click around! You've just generated your first engine's first
417
+ functions.
418
+
419
+ If you'd rather play around in the console, `rails console` will also work just
420
+ like a Rails application. Remember: the `Article` model is namespaced, so to
421
+ reference it you must call it as `Blorgh::Article`.
422
+
423
+ ```ruby
424
+ >> Blorgh::Article.find(1)
425
+ => #<Blorgh::Article id: 1 ...>
426
+ ```
427
+
428
+ One final thing is that the `articles` resource for this engine should be the root
429
+ of the engine. Whenever someone goes to the root path where the engine is
430
+ mounted, they should be shown a list of articles. This can be made to happen if
431
+ this line is inserted into the `config/routes.rb` file inside the engine:
432
+
433
+ ```ruby
434
+ root to: "articles#index"
435
+ ```
436
+
437
+ Now people will only need to go to the root of the engine to see all the articles,
438
+ rather than visiting `/articles`. This means that instead of
439
+ `http://localhost:3000/blorgh/articles`, you only need to go to
440
+ `http://localhost:3000/blorgh` now.
441
+
442
+ ### Generating a Comments Resource
443
+
444
+ Now that the engine can create new articles, it only makes sense to add
445
+ commenting functionality as well. To do this, you'll need to generate a comment
446
+ model, a comment controller and then modify the articles scaffold to display
447
+ comments and allow people to create new ones.
448
+
449
+ From the application root, run the model generator. Tell it to generate a
450
+ `Comment` model, with the related table having two columns: a `article_id` integer
451
+ and `text` text column.
452
+
453
+ ```bash
454
+ $ bin/rails generate model Comment article_id:integer text:text
455
+ ```
456
+
457
+ This will output the following:
458
+
459
+ ```
460
+ invoke active_record
461
+ create db/migrate/[timestamp]_create_blorgh_comments.rb
462
+ create app/models/blorgh/comment.rb
463
+ invoke test_unit
464
+ create test/models/blorgh/comment_test.rb
465
+ create test/fixtures/blorgh/comments.yml
466
+ ```
467
+
468
+ This generator call will generate just the necessary model files it needs,
469
+ namespacing the files under a `blorgh` directory and creating a model class
470
+ called `Blorgh::Comment`. Now run the migration to create our blorgh_comments
471
+ table:
472
+
473
+ ```bash
474
+ $ rake db:migrate
475
+ ```
476
+
477
+ To show the comments on an article, edit `app/views/blorgh/articles/show.html.erb` and
478
+ add this line before the "Edit" link:
479
+
480
+ ```html+erb
481
+ <h3>Comments</h3>
482
+ <%= render @article.comments %>
483
+ ```
484
+
485
+ This line will require there to be a `has_many` association for comments defined
486
+ on the `Blorgh::Article` model, which there isn't right now. To define one, open
487
+ `app/models/blorgh/article.rb` and add this line into the model:
488
+
489
+ ```ruby
490
+ has_many :comments
491
+ ```
492
+
493
+ Turning the model into this:
494
+
495
+ ```ruby
496
+ module Blorgh
497
+ class Article < ActiveRecord::Base
498
+ has_many :comments
499
+ end
500
+ end
501
+ ```
502
+
503
+ NOTE: Because the `has_many` is defined inside a class that is inside the
504
+ `Blorgh` module, Rails will know that you want to use the `Blorgh::Comment`
505
+ model for these objects, so there's no need to specify that using the
506
+ `:class_name` option here.
507
+
508
+ Next, there needs to be a form so that comments can be created on an article. To
509
+ add this, put this line underneath the call to `render @article.comments` in
510
+ `app/views/blorgh/articles/show.html.erb`:
511
+
512
+ ```erb
513
+ <%= render "blorgh/comments/form" %>
514
+ ```
515
+
516
+ Next, the partial that this line will render needs to exist. Create a new
517
+ directory at `app/views/blorgh/comments` and in it a new file called
518
+ `_form.html.erb` which has this content to create the required partial:
519
+
520
+ ```html+erb
521
+ <h3>New comment</h3>
522
+ <%= form_for [@article, @article.comments.build] do |f| %>
523
+ <p>
524
+ <%= f.label :text %><br>
525
+ <%= f.text_area :text %>
526
+ </p>
527
+ <%= f.submit %>
528
+ <% end %>
529
+ ```
530
+
531
+ When this form is submitted, it is going to attempt to perform a `POST` request
532
+ to a route of `/articles/:article_id/comments` within the engine. This route doesn't
533
+ exist at the moment, but can be created by changing the `resources :articles` line
534
+ inside `config/routes.rb` into these lines:
535
+
536
+ ```ruby
537
+ resources :articles do
538
+ resources :comments
539
+ end
540
+ ```
541
+
542
+ This creates a nested route for the comments, which is what the form requires.
543
+
544
+ The route now exists, but the controller that this route goes to does not. To
545
+ create it, run this command from the application root:
546
+
547
+ ```bash
548
+ $ bin/rails g controller comments
549
+ ```
550
+
551
+ This will generate the following things:
552
+
553
+ ```
554
+ create app/controllers/blorgh/comments_controller.rb
555
+ invoke erb
556
+ exist app/views/blorgh/comments
557
+ invoke test_unit
558
+ create test/controllers/blorgh/comments_controller_test.rb
559
+ invoke helper
560
+ create app/helpers/blorgh/comments_helper.rb
561
+ invoke assets
562
+ invoke js
563
+ create app/assets/javascripts/blorgh/comments.js
564
+ invoke css
565
+ create app/assets/stylesheets/blorgh/comments.css
566
+ ```
567
+
568
+ The form will be making a `POST` request to `/articles/:article_id/comments`, which
569
+ will correspond with the `create` action in `Blorgh::CommentsController`. This
570
+ action needs to be created, which can be done by putting the following lines
571
+ inside the class definition in `app/controllers/blorgh/comments_controller.rb`:
572
+
573
+ ```ruby
574
+ def create
575
+ @article = Article.find(params[:article_id])
576
+ @comment = @article.comments.create(comment_params)
577
+ flash[:notice] = "Comment has been created!"
578
+ redirect_to articles_path
579
+ end
580
+
581
+ private
582
+ def comment_params
583
+ params.require(:comment).permit(:text)
584
+ end
585
+ ```
586
+
587
+ This is the final step required to get the new comment form working. Displaying
588
+ the comments, however, is not quite right yet. If you were to create a comment
589
+ right now, you would see this error:
590
+
591
+ ```
592
+ Missing partial blorgh/comments/comment with {:handlers=>[:erb, :builder],
593
+ :formats=>[:html], :locale=>[:en, :en]}. Searched in: *
594
+ "/Users/ryan/Sites/side_projects/blorgh/test/dummy/app/views" *
595
+ "/Users/ryan/Sites/side_projects/blorgh/app/views"
596
+ ```
597
+
598
+ The engine is unable to find the partial required for rendering the comments.
599
+ Rails looks first in the application's (`test/dummy`) `app/views` directory and
600
+ then in the engine's `app/views` directory. When it can't find it, it will throw
601
+ this error. The engine knows to look for `blorgh/comments/comment` because the
602
+ model object it is receiving is from the `Blorgh::Comment` class.
603
+
604
+ This partial will be responsible for rendering just the comment text, for now.
605
+ Create a new file at `app/views/blorgh/comments/_comment.html.erb` and put this
606
+ line inside it:
607
+
608
+ ```erb
609
+ <%= comment_counter + 1 %>. <%= comment.text %>
610
+ ```
611
+
612
+ The `comment_counter` local variable is given to us by the `<%= render
613
+ @article.comments %>` call, which will define it automatically and increment the
614
+ counter as it iterates through each comment. It's used in this example to
615
+ display a small number next to each comment when it's created.
616
+
617
+ That completes the comment function of the blogging engine. Now it's time to use
618
+ it within an application.
619
+
620
+ Hooking Into an Application
621
+ ---------------------------
622
+
623
+ Using an engine within an application is very easy. This section covers how to
624
+ mount the engine into an application and the initial setup required, as well as
625
+ linking the engine to a `User` class provided by the application to provide
626
+ ownership for articles and comments within the engine.
627
+
628
+ ### Mounting the Engine
629
+
630
+ First, the engine needs to be specified inside the application's `Gemfile`. If
631
+ there isn't an application handy to test this out in, generate one using the
632
+ `rails new` command outside of the engine directory like this:
633
+
634
+ ```bash
635
+ $ rails new unicorn
636
+ ```
637
+
638
+ Usually, specifying the engine inside the Gemfile would be done by specifying it
639
+ as a normal, everyday gem.
640
+
641
+ ```ruby
642
+ gem 'devise'
643
+ ```
644
+
645
+ However, because you are developing the `blorgh` engine on your local machine,
646
+ you will need to specify the `:path` option in your `Gemfile`:
647
+
648
+ ```ruby
649
+ gem 'blorgh', path: "/path/to/blorgh"
650
+ ```
651
+
652
+ Then run `bundle` to install the gem.
653
+
654
+ As described earlier, by placing the gem in the `Gemfile` it will be loaded when
655
+ Rails is loaded. It will first require `lib/blorgh.rb` from the engine, then
656
+ `lib/blorgh/engine.rb`, which is the file that defines the major pieces of
657
+ functionality for the engine.
658
+
659
+ To make the engine's functionality accessible from within an application, it
660
+ needs to be mounted in that application's `config/routes.rb` file:
661
+
662
+ ```ruby
663
+ mount Blorgh::Engine, at: "/blog"
664
+ ```
665
+
666
+ This line will mount the engine at `/blog` in the application. Making it
667
+ accessible at `http://localhost:3000/blog` when the application runs with `rails
668
+ server`.
669
+
670
+ NOTE: Other engines, such as Devise, handle this a little differently by making
671
+ you specify custom helpers (such as `devise_for`) in the routes. These helpers
672
+ do exactly the same thing, mounting pieces of the engines's functionality at a
673
+ pre-defined path which may be customizable.
674
+
675
+ ### Engine setup
676
+
677
+ The engine contains migrations for the `blorgh_articles` and `blorgh_comments`
678
+ table which need to be created in the application's database so that the
679
+ engine's models can query them correctly. To copy these migrations into the
680
+ application use this command:
681
+
682
+ ```bash
683
+ $ rake blorgh:install:migrations
684
+ ```
685
+
686
+ If you have multiple engines that need migrations copied over, use
687
+ `railties:install:migrations` instead:
688
+
689
+ ```bash
690
+ $ rake railties:install:migrations
691
+ ```
692
+
693
+ This command, when run for the first time, will copy over all the migrations
694
+ from the engine. When run the next time, it will only copy over migrations that
695
+ haven't been copied over already. The first run for this command will output
696
+ something such as this:
697
+
698
+ ```bash
699
+ Copied migration [timestamp_1]_create_blorgh_articles.rb from blorgh
700
+ Copied migration [timestamp_2]_create_blorgh_comments.rb from blorgh
701
+ ```
702
+
703
+ The first timestamp (`[timestamp_1]`) will be the current time, and the second
704
+ timestamp (`[timestamp_2]`) will be the current time plus a second. The reason
705
+ for this is so that the migrations for the engine are run after any existing
706
+ migrations in the application.
707
+
708
+ To run these migrations within the context of the application, simply run `rake
709
+ db:migrate`. When accessing the engine through `http://localhost:3000/blog`, the
710
+ articles will be empty. This is because the table created inside the application is
711
+ different from the one created within the engine. Go ahead, play around with the
712
+ newly mounted engine. You'll find that it's the same as when it was only an
713
+ engine.
714
+
715
+ If you would like to run migrations only from one engine, you can do it by
716
+ specifying `SCOPE`:
717
+
718
+ ```bash
719
+ rake db:migrate SCOPE=blorgh
720
+ ```
721
+
722
+ This may be useful if you want to revert engine's migrations before removing it.
723
+ To revert all migrations from blorgh engine you can run code such as:
724
+
725
+ ```bash
726
+ rake db:migrate SCOPE=blorgh VERSION=0
727
+ ```
728
+
729
+ ### Using a Class Provided by the Application
730
+
731
+ #### Using a Model Provided by the Application
732
+
733
+ When an engine is created, it may want to use specific classes from an
734
+ application to provide links between the pieces of the engine and the pieces of
735
+ the application. In the case of the `blorgh` engine, making articles and comments
736
+ have authors would make a lot of sense.
737
+
738
+ A typical application might have a `User` class that would be used to represent
739
+ authors for an article or a comment. But there could be a case where the
740
+ application calls this class something different, such as `Person`. For this
741
+ reason, the engine should not hardcode associations specifically for a `User`
742
+ class.
743
+
744
+ To keep it simple in this case, the application will have a class called `User`
745
+ that represents the users of the application (we'll get into making this
746
+ configurable further on). It can be generated using this command inside the
747
+ application:
748
+
749
+ ```bash
750
+ rails g model user name:string
751
+ ```
752
+
753
+ The `rake db:migrate` command needs to be run here to ensure that our
754
+ application has the `users` table for future use.
755
+
756
+ Also, to keep it simple, the articles form will have a new text field called
757
+ `author_name`, where users can elect to put their name. The engine will then
758
+ take this name and either create a new `User` object from it, or find one that
759
+ already has that name. The engine will then associate the article with the found or
760
+ created `User` object.
761
+
762
+ First, the `author_name` text field needs to be added to the
763
+ `app/views/blorgh/articles/_form.html.erb` partial inside the engine. This can be
764
+ added above the `title` field with this code:
765
+
766
+ ```html+erb
767
+ <div class="field">
768
+ <%= f.label :author_name %><br>
769
+ <%= f.text_field :author_name %>
770
+ </div>
771
+ ```
772
+
773
+ Next, we need to update our `Blorgh::ArticleController#article_params` method to
774
+ permit the new form parameter:
775
+
776
+ ```ruby
777
+ def article_params
778
+ params.require(:article).permit(:title, :text, :author_name)
779
+ end
780
+ ```
781
+
782
+ The `Blorgh::Article` model should then have some code to convert the `author_name`
783
+ field into an actual `User` object and associate it as that article's `author`
784
+ before the article is saved. It will also need to have an `attr_accessor` set up
785
+ for this field, so that the setter and getter methods are defined for it.
786
+
787
+ To do all this, you'll need to add the `attr_accessor` for `author_name`, the
788
+ association for the author and the `before_save` call into
789
+ `app/models/blorgh/article.rb`. The `author` association will be hard-coded to the
790
+ `User` class for the time being.
791
+
792
+ ```ruby
793
+ attr_accessor :author_name
794
+ belongs_to :author, class_name: "User"
795
+
796
+ before_save :set_author
797
+
798
+ private
799
+ def set_author
800
+ self.author = User.find_or_create_by(name: author_name)
801
+ end
802
+ ```
803
+
804
+ By representing the `author` association's object with the `User` class, a link
805
+ is established between the engine and the application. There needs to be a way
806
+ of associating the records in the `blorgh_articles` table with the records in the
807
+ `users` table. Because the association is called `author`, there should be an
808
+ `author_id` column added to the `blorgh_articles` table.
809
+
810
+ To generate this new column, run this command within the engine:
811
+
812
+ ```bash
813
+ $ bin/rails g migration add_author_id_to_blorgh_articles author_id:integer
814
+ ```
815
+
816
+ NOTE: Due to the migration's name and the column specification after it, Rails
817
+ will automatically know that you want to add a column to a specific table and
818
+ write that into the migration for you. You don't need to tell it any more than
819
+ this.
820
+
821
+ This migration will need to be run on the application. To do that, it must first
822
+ be copied using this command:
823
+
824
+ ```bash
825
+ $ rake blorgh:install:migrations
826
+ ```
827
+
828
+ Notice that only _one_ migration was copied over here. This is because the first
829
+ two migrations were copied over the first time this command was run.
830
+
831
+ ```
832
+ NOTE Migration [timestamp]_create_blorgh_articles.rb from blorgh has been
833
+ skipped. Migration with the same name already exists. NOTE Migration
834
+ [timestamp]_create_blorgh_comments.rb from blorgh has been skipped. Migration
835
+ with the same name already exists. Copied migration
836
+ [timestamp]_add_author_id_to_blorgh_articles.rb from blorgh
837
+ ```
838
+
839
+ Run the migration using:
840
+
841
+ ```bash
842
+ $ rake db:migrate
843
+ ```
844
+
845
+ Now with all the pieces in place, an action will take place that will associate
846
+ an author - represented by a record in the `users` table - with an article,
847
+ represented by the `blorgh_articles` table from the engine.
848
+
849
+ Finally, the author's name should be displayed on the article's page. Add this code
850
+ above the "Title" output inside `app/views/blorgh/articles/show.html.erb`:
851
+
852
+ ```html+erb
853
+ <p>
854
+ <b>Author:</b>
855
+ <%= @article.author %>
856
+ </p>
857
+ ```
858
+
859
+ By outputting `@article.author` using the `<%=` tag, the `to_s` method will be
860
+ called on the object. By default, this will look quite ugly:
861
+
862
+ ```
863
+ #<User:0x00000100ccb3b0>
864
+ ```
865
+
866
+ This is undesirable. It would be much better to have the user's name there. To
867
+ do this, add a `to_s` method to the `User` class within the application:
868
+
869
+ ```ruby
870
+ def to_s
871
+ name
872
+ end
873
+ ```
874
+
875
+ Now instead of the ugly Ruby object output, the author's name will be displayed.
876
+
877
+ #### Using a Controller Provided by the Application
878
+
879
+ Because Rails controllers generally share code for things like authentication
880
+ and accessing session variables, they inherit from `ApplicationController` by
881
+ default. Rails engines, however are scoped to run independently from the main
882
+ application, so each engine gets a scoped `ApplicationController`. This
883
+ namespace prevents code collisions, but often engine controllers need to access
884
+ methods in the main application's `ApplicationController`. An easy way to
885
+ provide this access is to change the engine's scoped `ApplicationController` to
886
+ inherit from the main application's `ApplicationController`. For our Blorgh
887
+ engine this would be done by changing
888
+ `app/controllers/blorgh/application_controller.rb` to look like:
889
+
890
+ ```ruby
891
+ class Blorgh::ApplicationController < ApplicationController
892
+ end
893
+ ```
894
+
895
+ By default, the engine's controllers inherit from
896
+ `Blorgh::ApplicationController`. So, after making this change they will have
897
+ access to the main application's `ApplicationController`, as though they were
898
+ part of the main application.
899
+
900
+ This change does require that the engine is run from a Rails application that
901
+ has an `ApplicationController`.
902
+
903
+ ### Configuring an Engine
904
+
905
+ This section covers how to make the `User` class configurable, followed by
906
+ general configuration tips for the engine.
907
+
908
+ #### Setting Configuration Settings in the Application
909
+
910
+ The next step is to make the class that represents a `User` in the application
911
+ customizable for the engine. This is because that class may not always be
912
+ `User`, as previously explained. To make this setting customizable, the engine
913
+ will have a configuration setting called `author_class` that will be used to
914
+ specify which class represents users inside the application.
915
+
916
+ To define this configuration setting, you should use a `mattr_accessor` inside
917
+ the `Blorgh` module for the engine. Add this line to `lib/blorgh.rb` inside the
918
+ engine:
919
+
920
+ ```ruby
921
+ mattr_accessor :author_class
922
+ ```
923
+
924
+ This method works like its brothers, `attr_accessor` and `cattr_accessor`, but
925
+ provides a setter and getter method on the module with the specified name. To
926
+ use it, it must be referenced using `Blorgh.author_class`.
927
+
928
+ The next step is to switch the `Blorgh::Article` model over to this new setting.
929
+ Change the `belongs_to` association inside this model
930
+ (`app/models/blorgh/article.rb`) to this:
931
+
932
+ ```ruby
933
+ belongs_to :author, class_name: Blorgh.author_class
934
+ ```
935
+
936
+ The `set_author` method in the `Blorgh::Article` model should also use this class:
937
+
938
+ ```ruby
939
+ self.author = Blorgh.author_class.constantize.find_or_create_by(name: author_name)
940
+ ```
941
+
942
+ To save having to call `constantize` on the `author_class` result all the time,
943
+ you could instead just override the `author_class` getter method inside the
944
+ `Blorgh` module in the `lib/blorgh.rb` file to always call `constantize` on the
945
+ saved value before returning the result:
946
+
947
+ ```ruby
948
+ def self.author_class
949
+ @@author_class.constantize
950
+ end
951
+ ```
952
+
953
+ This would then turn the above code for `set_author` into this:
954
+
955
+ ```ruby
956
+ self.author = Blorgh.author_class.find_or_create_by(name: author_name)
957
+ ```
958
+
959
+ Resulting in something a little shorter, and more implicit in its behavior. The
960
+ `author_class` method should always return a `Class` object.
961
+
962
+ Since we changed the `author_class` method to return a `Class` instead of a
963
+ `String`, we must also modify our `belongs_to` definition in the `Blorgh::Article`
964
+ model:
965
+
966
+ ```ruby
967
+ belongs_to :author, class_name: Blorgh.author_class.to_s
968
+ ```
969
+
970
+ To set this configuration setting within the application, an initializer should
971
+ be used. By using an initializer, the configuration will be set up before the
972
+ application starts and calls the engine's models, which may depend on this
973
+ configuration setting existing.
974
+
975
+ Create a new initializer at `config/initializers/blorgh.rb` inside the
976
+ application where the `blorgh` engine is installed and put this content in it:
977
+
978
+ ```ruby
979
+ Blorgh.author_class = "User"
980
+ ```
981
+
982
+ WARNING: It's very important here to use the `String` version of the class,
983
+ rather than the class itself. If you were to use the class, Rails would attempt
984
+ to load that class and then reference the related table. This could lead to
985
+ problems if the table wasn't already existing. Therefore, a `String` should be
986
+ used and then converted to a class using `constantize` in the engine later on.
987
+
988
+ Go ahead and try to create a new article. You will see that it works exactly in the
989
+ same way as before, except this time the engine is using the configuration
990
+ setting in `config/initializers/blorgh.rb` to learn what the class is.
991
+
992
+ There are now no strict dependencies on what the class is, only what the API for
993
+ the class must be. The engine simply requires this class to define a
994
+ `find_or_create_by` method which returns an object of that class, to be
995
+ associated with an article when it's created. This object, of course, should have
996
+ some sort of identifier by which it can be referenced.
997
+
998
+ #### General Engine Configuration
999
+
1000
+ Within an engine, there may come a time where you wish to use things such as
1001
+ initializers, internationalization or other configuration options. The great
1002
+ news is that these things are entirely possible, because a Rails engine shares
1003
+ much the same functionality as a Rails application. In fact, a Rails
1004
+ application's functionality is actually a superset of what is provided by
1005
+ engines!
1006
+
1007
+ If you wish to use an initializer - code that should run before the engine is
1008
+ loaded - the place for it is the `config/initializers` folder. This directory's
1009
+ functionality is explained in the [Initializers
1010
+ section](configuring.html#initializers) of the Configuring guide, and works
1011
+ precisely the same way as the `config/initializers` directory inside an
1012
+ application. The same thing goes if you want to use a standard initializer.
1013
+
1014
+ For locales, simply place the locale files in the `config/locales` directory,
1015
+ just like you would in an application.
1016
+
1017
+ Testing an engine
1018
+ -----------------
1019
+
1020
+ When an engine is generated, there is a smaller dummy application created inside
1021
+ it at `test/dummy`. This application is used as a mounting point for the engine,
1022
+ to make testing the engine extremely simple. You may extend this application by
1023
+ generating controllers, models or views from within the directory, and then use
1024
+ those to test your engine.
1025
+
1026
+ The `test` directory should be treated like a typical Rails testing environment,
1027
+ allowing for unit, functional and integration tests.
1028
+
1029
+ ### Functional Tests
1030
+
1031
+ A matter worth taking into consideration when writing functional tests is that
1032
+ the tests are going to be running on an application - the `test/dummy`
1033
+ application - rather than your engine. This is due to the setup of the testing
1034
+ environment; an engine needs an application as a host for testing its main
1035
+ functionality, especially controllers. This means that if you were to make a
1036
+ typical `GET` to a controller in a controller's functional test like this:
1037
+
1038
+ ```ruby
1039
+ module Blorgh
1040
+ class FooControllerTest < ActionController::TestCase
1041
+ def test_index
1042
+ get :index
1043
+ ...
1044
+ end
1045
+ end
1046
+ end
1047
+ ```
1048
+
1049
+ It may not function correctly. This is because the application doesn't know how
1050
+ to route these requests to the engine unless you explicitly tell it **how**. To
1051
+ do this, you must set the `@routes` instance variable to the engine's route set
1052
+ in your setup code:
1053
+
1054
+ ```ruby
1055
+ module Blorgh
1056
+ class FooControllerTest < ActionController::TestCase
1057
+ setup do
1058
+ @routes = Engine.routes
1059
+ end
1060
+
1061
+ def test_index
1062
+ get :index
1063
+ ...
1064
+ end
1065
+ end
1066
+ end
1067
+ ```
1068
+
1069
+ This tells the application that you still want to perform a `GET` request to the
1070
+ `index` action of this controller, but you want to use the engine's route to get
1071
+ there, rather than the application's one.
1072
+
1073
+ This also ensures that the engine's URL helpers will work as expected in your
1074
+ tests.
1075
+
1076
+ Improving engine functionality
1077
+ ------------------------------
1078
+
1079
+ This section explains how to add and/or override engine MVC functionality in the
1080
+ main Rails application.
1081
+
1082
+ ### Overriding Models and Controllers
1083
+
1084
+ Engine model and controller classes can be extended by open classing them in the
1085
+ main Rails application (since model and controller classes are just Ruby classes
1086
+ that inherit Rails specific functionality). Open classing an Engine class
1087
+ redefines it for use in the main application. This is usually implemented by
1088
+ using the decorator pattern.
1089
+
1090
+ For simple class modifications, use `Class#class_eval`. For complex class
1091
+ modifications, consider using `ActiveSupport::Concern`.
1092
+
1093
+ #### A note on Decorators and Loading Code
1094
+
1095
+ Because these decorators are not referenced by your Rails application itself,
1096
+ Rails' autoloading system will not kick in and load your decorators. This means
1097
+ that you need to require them yourself.
1098
+
1099
+ Here is some sample code to do this:
1100
+
1101
+ ```ruby
1102
+ # lib/blorgh/engine.rb
1103
+ module Blorgh
1104
+ class Engine < ::Rails::Engine
1105
+ isolate_namespace Blorgh
1106
+
1107
+ config.to_prepare do
1108
+ Dir.glob(Rails.root + "app/decorators/**/*_decorator*.rb").each do |c|
1109
+ require_dependency(c)
1110
+ end
1111
+ end
1112
+ end
1113
+ end
1114
+ ```
1115
+
1116
+ This doesn't apply to just Decorators, but anything that you add in an engine
1117
+ that isn't referenced by your main application.
1118
+
1119
+ #### Implementing Decorator Pattern Using Class#class_eval
1120
+
1121
+ **Adding** `Article#time_since_created`:
1122
+
1123
+ ```ruby
1124
+ # MyApp/app/decorators/models/blorgh/article_decorator.rb
1125
+
1126
+ Blorgh::Article.class_eval do
1127
+ def time_since_created
1128
+ Time.current - created_at
1129
+ end
1130
+ end
1131
+ ```
1132
+
1133
+ ```ruby
1134
+ # Blorgh/app/models/article.rb
1135
+
1136
+ class Article < ActiveRecord::Base
1137
+ has_many :comments
1138
+ end
1139
+ ```
1140
+
1141
+
1142
+ **Overriding** `Article#summary`:
1143
+
1144
+ ```ruby
1145
+ # MyApp/app/decorators/models/blorgh/article_decorator.rb
1146
+
1147
+ Blorgh::Article.class_eval do
1148
+ def summary
1149
+ "#{title} - #{truncate(text)}"
1150
+ end
1151
+ end
1152
+ ```
1153
+
1154
+ ```ruby
1155
+ # Blorgh/app/models/article.rb
1156
+
1157
+ class Article < ActiveRecord::Base
1158
+ has_many :comments
1159
+ def summary
1160
+ "#{title}"
1161
+ end
1162
+ end
1163
+ ```
1164
+
1165
+ #### Implementing Decorator Pattern Using ActiveSupport::Concern
1166
+
1167
+ Using `Class#class_eval` is great for simple adjustments, but for more complex
1168
+ class modifications, you might want to consider using [`ActiveSupport::Concern`]
1169
+ (http://api.rubyonrails.org/classes/ActiveSupport/Concern.html).
1170
+ ActiveSupport::Concern manages load order of interlinked dependent modules and
1171
+ classes at run time allowing you to significantly modularize your code.
1172
+
1173
+ **Adding** `Article#time_since_created` and **Overriding** `Article#summary`:
1174
+
1175
+ ```ruby
1176
+ # MyApp/app/models/blorgh/article.rb
1177
+
1178
+ class Blorgh::Article < ActiveRecord::Base
1179
+ include Blorgh::Concerns::Models::Article
1180
+
1181
+ def time_since_created
1182
+ Time.current - created_at
1183
+ end
1184
+
1185
+ def summary
1186
+ "#{title} - #{truncate(text)}"
1187
+ end
1188
+ end
1189
+ ```
1190
+
1191
+ ```ruby
1192
+ # Blorgh/app/models/article.rb
1193
+
1194
+ class Article < ActiveRecord::Base
1195
+ include Blorgh::Concerns::Models::Article
1196
+ end
1197
+ ```
1198
+
1199
+ ```ruby
1200
+ # Blorgh/lib/concerns/models/article
1201
+
1202
+ module Blorgh::Concerns::Models::Article
1203
+ extend ActiveSupport::Concern
1204
+
1205
+ # 'included do' causes the included code to be evaluated in the
1206
+ # context where it is included (article.rb), rather than being
1207
+ # executed in the module's context (blorgh/concerns/models/article).
1208
+ included do
1209
+ attr_accessor :author_name
1210
+ belongs_to :author, class_name: "User"
1211
+
1212
+ before_save :set_author
1213
+
1214
+ private
1215
+ def set_author
1216
+ self.author = User.find_or_create_by(name: author_name)
1217
+ end
1218
+ end
1219
+
1220
+ def summary
1221
+ "#{title}"
1222
+ end
1223
+
1224
+ module ClassMethods
1225
+ def some_class_method
1226
+ 'some class method string'
1227
+ end
1228
+ end
1229
+ end
1230
+ ```
1231
+
1232
+ ### Overriding Views
1233
+
1234
+ When Rails looks for a view to render, it will first look in the `app/views`
1235
+ directory of the application. If it cannot find the view there, it will check in
1236
+ the `app/views` directories of all engines that have this directory.
1237
+
1238
+ When the application is asked to render the view for `Blorgh::ArticlesController`'s
1239
+ index action, it will first look for the path
1240
+ `app/views/blorgh/articles/index.html.erb` within the application. If it cannot
1241
+ find it, it will look inside the engine.
1242
+
1243
+ You can override this view in the application by simply creating a new file at
1244
+ `app/views/blorgh/articles/index.html.erb`. Then you can completely change what
1245
+ this view would normally output.
1246
+
1247
+ Try this now by creating a new file at `app/views/blorgh/articles/index.html.erb`
1248
+ and put this content in it:
1249
+
1250
+ ```html+erb
1251
+ <h1>Articles</h1>
1252
+ <%= link_to "New Article", new_article_path %>
1253
+ <% @articles.each do |article| %>
1254
+ <h2><%= article.title %></h2>
1255
+ <small>By <%= article.author %></small>
1256
+ <%= simple_format(article.text) %>
1257
+ <hr>
1258
+ <% end %>
1259
+ ```
1260
+
1261
+ ### Routes
1262
+
1263
+ Routes inside an engine are isolated from the application by default. This is
1264
+ done by the `isolate_namespace` call inside the `Engine` class. This essentially
1265
+ means that the application and its engines can have identically named routes and
1266
+ they will not clash.
1267
+
1268
+ Routes inside an engine are drawn on the `Engine` class within
1269
+ `config/routes.rb`, like this:
1270
+
1271
+ ```ruby
1272
+ Blorgh::Engine.routes.draw do
1273
+ resources :articles
1274
+ end
1275
+ ```
1276
+
1277
+ By having isolated routes such as this, if you wish to link to an area of an
1278
+ engine from within an application, you will need to use the engine's routing
1279
+ proxy method. Calls to normal routing methods such as `articles_path` may end up
1280
+ going to undesired locations if both the application and the engine have such a
1281
+ helper defined.
1282
+
1283
+ For instance, the following example would go to the application's `articles_path`
1284
+ if that template was rendered from the application, or the engine's `articles_path`
1285
+ if it was rendered from the engine:
1286
+
1287
+ ```erb
1288
+ <%= link_to "Blog articles", articles_path %>
1289
+ ```
1290
+
1291
+ To make this route always use the engine's `articles_path` routing helper method,
1292
+ we must call the method on the routing proxy method that shares the same name as
1293
+ the engine.
1294
+
1295
+ ```erb
1296
+ <%= link_to "Blog articles", blorgh.articles_path %>
1297
+ ```
1298
+
1299
+ If you wish to reference the application inside the engine in a similar way, use
1300
+ the `main_app` helper:
1301
+
1302
+ ```erb
1303
+ <%= link_to "Home", main_app.root_path %>
1304
+ ```
1305
+
1306
+ If you were to use this inside an engine, it would **always** go to the
1307
+ application's root. If you were to leave off the `main_app` "routing proxy"
1308
+ method call, it could potentially go to the engine's or application's root,
1309
+ depending on where it was called from.
1310
+
1311
+ If a template rendered from within an engine attempts to use one of the
1312
+ application's routing helper methods, it may result in an undefined method call.
1313
+ If you encounter such an issue, ensure that you're not attempting to call the
1314
+ application's routing methods without the `main_app` prefix from within the
1315
+ engine.
1316
+
1317
+ ### Assets
1318
+
1319
+ Assets within an engine work in an identical way to a full application. Because
1320
+ the engine class inherits from `Rails::Engine`, the application will know to
1321
+ look up assets in the engine's 'app/assets' and 'lib/assets' directories.
1322
+
1323
+ Like all of the other components of an engine, the assets should be namespaced.
1324
+ This means that if you have an asset called `style.css`, it should be placed at
1325
+ `app/assets/stylesheets/[engine name]/style.css`, rather than
1326
+ `app/assets/stylesheets/style.css`. If this asset isn't namespaced, there is a
1327
+ possibility that the host application could have an asset named identically, in
1328
+ which case the application's asset would take precedence and the engine's one
1329
+ would be ignored.
1330
+
1331
+ Imagine that you did have an asset located at
1332
+ `app/assets/stylesheets/blorgh/style.css` To include this asset inside an
1333
+ application, just use `stylesheet_link_tag` and reference the asset as if it
1334
+ were inside the engine:
1335
+
1336
+ ```erb
1337
+ <%= stylesheet_link_tag "blorgh/style.css" %>
1338
+ ```
1339
+
1340
+ You can also specify these assets as dependencies of other assets using Asset
1341
+ Pipeline require statements in processed files:
1342
+
1343
+ ```
1344
+ /*
1345
+ *= require blorgh/style
1346
+ */
1347
+ ```
1348
+
1349
+ INFO. Remember that in order to use languages like Sass or CoffeeScript, you
1350
+ should add the relevant library to your engine's `.gemspec`.
1351
+
1352
+ ### Separate Assets & Precompiling
1353
+
1354
+ There are some situations where your engine's assets are not required by the
1355
+ host application. For example, say that you've created an admin functionality
1356
+ that only exists for your engine. In this case, the host application doesn't
1357
+ need to require `admin.css` or `admin.js`. Only the gem's admin layout needs
1358
+ these assets. It doesn't make sense for the host app to include
1359
+ `"blorgh/admin.css"` in its stylesheets. In this situation, you should
1360
+ explicitly define these assets for precompilation. This tells sprockets to add
1361
+ your engine assets when `rake assets:precompile` is triggered.
1362
+
1363
+ You can define assets for precompilation in `engine.rb`:
1364
+
1365
+ ```ruby
1366
+ initializer "blorgh.assets.precompile" do |app|
1367
+ app.config.assets.precompile += %w(admin.css admin.js)
1368
+ end
1369
+ ```
1370
+
1371
+ For more information, read the [Asset Pipeline guide](asset_pipeline.html).
1372
+
1373
+ ### Other Gem Dependencies
1374
+
1375
+ Gem dependencies inside an engine should be specified inside the `.gemspec` file
1376
+ at the root of the engine. The reason is that the engine may be installed as a
1377
+ gem. If dependencies were to be specified inside the `Gemfile`, these would not
1378
+ be recognized by a traditional gem install and so they would not be installed,
1379
+ causing the engine to malfunction.
1380
+
1381
+ To specify a dependency that should be installed with the engine during a
1382
+ traditional `gem install`, specify it inside the `Gem::Specification` block
1383
+ inside the `.gemspec` file in the engine:
1384
+
1385
+ ```ruby
1386
+ s.add_dependency "moo"
1387
+ ```
1388
+
1389
+ To specify a dependency that should only be installed as a development
1390
+ dependency of the application, specify it like this:
1391
+
1392
+ ```ruby
1393
+ s.add_development_dependency "moo"
1394
+ ```
1395
+
1396
+ Both kinds of dependencies will be installed when `bundle install` is run inside
1397
+ of the application. The development dependencies for the gem will only be used
1398
+ when the tests for the engine are running.
1399
+
1400
+ Note that if you want to immediately require dependencies when the engine is
1401
+ required, you should require them before the engine's initialization. For
1402
+ example:
1403
+
1404
+ ```ruby
1405
+ require 'other_engine/engine'
1406
+ require 'yet_another_engine/engine'
1407
+
1408
+ module MyEngine
1409
+ class Engine < ::Rails::Engine
1410
+ end
1411
+ end
1412
+ ```