rails 4.2.0.beta4 → 4.2.0.rc1

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