rails 3.2.22.5 → 4.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rails might be problematic. Click here for more details.

Files changed (281) hide show
  1. checksums.yaml +4 -4
  2. data/README.rdoc +77 -0
  3. data/guides/CHANGELOG.md +9 -0
  4. data/guides/Rakefile +77 -0
  5. data/guides/assets/images/belongs_to.png +0 -0
  6. data/guides/assets/images/book_icon.gif +0 -0
  7. data/guides/assets/images/bullet.gif +0 -0
  8. data/guides/assets/images/challenge.png +0 -0
  9. data/guides/assets/images/chapters_icon.gif +0 -0
  10. data/guides/assets/images/check_bullet.gif +0 -0
  11. data/guides/assets/images/credits_pic_blank.gif +0 -0
  12. data/guides/assets/images/csrf.png +0 -0
  13. data/guides/assets/images/edge_badge.png +0 -0
  14. data/guides/assets/images/favicon.ico +0 -0
  15. data/guides/assets/images/feature_tile.gif +0 -0
  16. data/guides/assets/images/footer_tile.gif +0 -0
  17. data/guides/assets/images/fxn.png +0 -0
  18. data/guides/assets/images/getting_started/confirm_dialog.png +0 -0
  19. data/guides/assets/images/getting_started/forbidden_attributes_for_new_post.png +0 -0
  20. data/guides/assets/images/getting_started/form_with_errors.png +0 -0
  21. data/guides/assets/images/getting_started/index_action_with_edit_link.png +0 -0
  22. data/guides/assets/images/getting_started/new_post.png +0 -0
  23. data/guides/assets/images/getting_started/post_with_comments.png +0 -0
  24. data/guides/assets/images/getting_started/routing_error_no_controller.png +0 -0
  25. data/guides/assets/images/getting_started/routing_error_no_route_matches.png +0 -0
  26. data/guides/assets/images/getting_started/show_action_for_posts.png +0 -0
  27. data/guides/assets/images/getting_started/template_is_missing_posts_new.png +0 -0
  28. data/guides/assets/images/getting_started/undefined_method_post_path.png +0 -0
  29. data/guides/assets/images/getting_started/unknown_action_create_for_posts.png +0 -0
  30. data/guides/assets/images/getting_started/unknown_action_new_for_posts.png +0 -0
  31. data/guides/assets/images/grey_bullet.gif +0 -0
  32. data/guides/assets/images/habtm.png +0 -0
  33. data/guides/assets/images/has_many.png +0 -0
  34. data/guides/assets/images/has_many_through.png +0 -0
  35. data/guides/assets/images/has_one.png +0 -0
  36. data/guides/assets/images/has_one_through.png +0 -0
  37. data/guides/assets/images/header_backdrop.png +0 -0
  38. data/guides/assets/images/header_tile.gif +0 -0
  39. data/guides/assets/images/i18n/demo_html_safe.png +0 -0
  40. data/guides/assets/images/i18n/demo_localized_pirate.png +0 -0
  41. data/guides/assets/images/i18n/demo_translated_en.png +0 -0
  42. data/guides/assets/images/i18n/demo_translated_pirate.png +0 -0
  43. data/guides/assets/images/i18n/demo_translation_missing.png +0 -0
  44. data/guides/assets/images/i18n/demo_untranslated.png +0 -0
  45. data/guides/assets/images/icons/README +5 -0
  46. data/guides/assets/images/icons/callouts/1.png +0 -0
  47. data/guides/assets/images/icons/callouts/10.png +0 -0
  48. data/guides/assets/images/icons/callouts/11.png +0 -0
  49. data/guides/assets/images/icons/callouts/12.png +0 -0
  50. data/guides/assets/images/icons/callouts/13.png +0 -0
  51. data/guides/assets/images/icons/callouts/14.png +0 -0
  52. data/guides/assets/images/icons/callouts/15.png +0 -0
  53. data/guides/assets/images/icons/callouts/2.png +0 -0
  54. data/guides/assets/images/icons/callouts/3.png +0 -0
  55. data/guides/assets/images/icons/callouts/4.png +0 -0
  56. data/guides/assets/images/icons/callouts/5.png +0 -0
  57. data/guides/assets/images/icons/callouts/6.png +0 -0
  58. data/guides/assets/images/icons/callouts/7.png +0 -0
  59. data/guides/assets/images/icons/callouts/8.png +0 -0
  60. data/guides/assets/images/icons/callouts/9.png +0 -0
  61. data/guides/assets/images/icons/caution.png +0 -0
  62. data/guides/assets/images/icons/example.png +0 -0
  63. data/guides/assets/images/icons/home.png +0 -0
  64. data/guides/assets/images/icons/important.png +0 -0
  65. data/guides/assets/images/icons/next.png +0 -0
  66. data/guides/assets/images/icons/note.png +0 -0
  67. data/guides/assets/images/icons/prev.png +0 -0
  68. data/guides/assets/images/icons/tip.png +0 -0
  69. data/guides/assets/images/icons/up.png +0 -0
  70. data/guides/assets/images/icons/warning.png +0 -0
  71. data/guides/assets/images/jaimeiniesta.jpg +0 -0
  72. data/guides/assets/images/nav_arrow.gif +0 -0
  73. data/guides/assets/images/oscardelben.jpg +0 -0
  74. data/guides/assets/images/polymorphic.png +0 -0
  75. data/guides/assets/images/radar.png +0 -0
  76. data/guides/assets/images/rails4_features.png +0 -0
  77. data/guides/assets/images/rails_guides_kindle_cover.jpg +0 -0
  78. data/guides/assets/images/rails_guides_logo.gif +0 -0
  79. data/guides/assets/images/rails_logo_remix.gif +0 -0
  80. data/guides/assets/images/rails_welcome.png +0 -0
  81. data/guides/assets/images/session_fixation.png +0 -0
  82. data/guides/assets/images/tab_grey.gif +0 -0
  83. data/guides/assets/images/tab_info.gif +0 -0
  84. data/guides/assets/images/tab_note.gif +0 -0
  85. data/guides/assets/images/tab_red.gif +0 -0
  86. data/guides/assets/images/tab_yellow.gif +0 -0
  87. data/guides/assets/images/tab_yellow.png +0 -0
  88. data/guides/assets/images/vijaydev.jpg +0 -0
  89. data/guides/assets/javascripts/guides.js +57 -0
  90. data/guides/assets/javascripts/jquery.min.js +4 -0
  91. data/guides/assets/javascripts/responsive-tables.js +43 -0
  92. data/guides/assets/javascripts/syntaxhighlighter/shBrushAS3.js +59 -0
  93. data/guides/assets/javascripts/syntaxhighlighter/shBrushAppleScript.js +75 -0
  94. data/guides/assets/javascripts/syntaxhighlighter/shBrushBash.js +59 -0
  95. data/guides/assets/javascripts/syntaxhighlighter/shBrushCSharp.js +65 -0
  96. data/guides/assets/javascripts/syntaxhighlighter/shBrushColdFusion.js +100 -0
  97. data/guides/assets/javascripts/syntaxhighlighter/shBrushCpp.js +97 -0
  98. data/guides/assets/javascripts/syntaxhighlighter/shBrushCss.js +91 -0
  99. data/guides/assets/javascripts/syntaxhighlighter/shBrushDelphi.js +55 -0
  100. data/guides/assets/javascripts/syntaxhighlighter/shBrushDiff.js +41 -0
  101. data/guides/assets/javascripts/syntaxhighlighter/shBrushErlang.js +52 -0
  102. data/guides/assets/javascripts/syntaxhighlighter/shBrushGroovy.js +67 -0
  103. data/guides/assets/javascripts/syntaxhighlighter/shBrushJScript.js +52 -0
  104. data/guides/assets/javascripts/syntaxhighlighter/shBrushJava.js +57 -0
  105. data/guides/assets/javascripts/syntaxhighlighter/shBrushJavaFX.js +58 -0
  106. data/guides/assets/javascripts/syntaxhighlighter/shBrushPerl.js +72 -0
  107. data/guides/assets/javascripts/syntaxhighlighter/shBrushPhp.js +88 -0
  108. data/guides/assets/javascripts/syntaxhighlighter/shBrushPlain.js +33 -0
  109. data/guides/assets/javascripts/syntaxhighlighter/shBrushPowerShell.js +74 -0
  110. data/guides/assets/javascripts/syntaxhighlighter/shBrushPython.js +64 -0
  111. data/guides/assets/javascripts/syntaxhighlighter/shBrushRuby.js +55 -0
  112. data/guides/assets/javascripts/syntaxhighlighter/shBrushSass.js +94 -0
  113. data/guides/assets/javascripts/syntaxhighlighter/shBrushScala.js +51 -0
  114. data/guides/assets/javascripts/syntaxhighlighter/shBrushSql.js +66 -0
  115. data/guides/assets/javascripts/syntaxhighlighter/shBrushVb.js +56 -0
  116. data/guides/assets/javascripts/syntaxhighlighter/shBrushXml.js +69 -0
  117. data/guides/assets/javascripts/syntaxhighlighter/shCore.js +17 -0
  118. data/guides/assets/stylesheets/fixes.css +16 -0
  119. data/guides/assets/stylesheets/kindle.css +11 -0
  120. data/guides/assets/stylesheets/main.css +709 -0
  121. data/guides/assets/stylesheets/print.css +52 -0
  122. data/guides/assets/stylesheets/reset.css +43 -0
  123. data/guides/assets/stylesheets/responsive-tables.css +50 -0
  124. data/guides/assets/stylesheets/style.css +13 -0
  125. data/guides/assets/stylesheets/syntaxhighlighter/shCore.css +226 -0
  126. data/guides/assets/stylesheets/syntaxhighlighter/shCoreDefault.css +328 -0
  127. data/guides/assets/stylesheets/syntaxhighlighter/shCoreDjango.css +331 -0
  128. data/guides/assets/stylesheets/syntaxhighlighter/shCoreEclipse.css +339 -0
  129. data/guides/assets/stylesheets/syntaxhighlighter/shCoreEmacs.css +324 -0
  130. data/guides/assets/stylesheets/syntaxhighlighter/shCoreFadeToGrey.css +328 -0
  131. data/guides/assets/stylesheets/syntaxhighlighter/shCoreMDUltra.css +324 -0
  132. data/guides/assets/stylesheets/syntaxhighlighter/shCoreMidnight.css +324 -0
  133. data/guides/assets/stylesheets/syntaxhighlighter/shCoreRDark.css +324 -0
  134. data/guides/assets/stylesheets/syntaxhighlighter/shThemeDefault.css +117 -0
  135. data/guides/assets/stylesheets/syntaxhighlighter/shThemeDjango.css +120 -0
  136. data/guides/assets/stylesheets/syntaxhighlighter/shThemeEclipse.css +128 -0
  137. data/guides/assets/stylesheets/syntaxhighlighter/shThemeEmacs.css +113 -0
  138. data/guides/assets/stylesheets/syntaxhighlighter/shThemeFadeToGrey.css +117 -0
  139. data/guides/assets/stylesheets/syntaxhighlighter/shThemeMDUltra.css +113 -0
  140. data/guides/assets/stylesheets/syntaxhighlighter/shThemeMidnight.css +113 -0
  141. data/guides/assets/stylesheets/syntaxhighlighter/shThemeRDark.css +113 -0
  142. data/guides/assets/stylesheets/syntaxhighlighter/shThemeRailsGuides.css +116 -0
  143. data/guides/code/getting_started/Gemfile +38 -0
  144. data/guides/code/getting_started/Gemfile.lock +150 -0
  145. data/guides/code/getting_started/README.rdoc +28 -0
  146. data/guides/code/getting_started/Rakefile +6 -0
  147. data/guides/code/getting_started/app/assets/images/rails.png +0 -0
  148. data/guides/code/getting_started/app/assets/javascripts/application.js +16 -0
  149. data/guides/code/getting_started/app/assets/javascripts/comments.js.coffee +3 -0
  150. data/guides/code/getting_started/app/assets/javascripts/posts.js.coffee +3 -0
  151. data/guides/code/getting_started/app/assets/javascripts/welcome.js.coffee +3 -0
  152. data/guides/code/getting_started/app/assets/stylesheets/application.css +13 -0
  153. data/guides/code/getting_started/app/assets/stylesheets/comments.css.scss +3 -0
  154. data/guides/code/getting_started/app/assets/stylesheets/posts.css.scss +3 -0
  155. data/guides/code/getting_started/app/assets/stylesheets/welcome.css.scss +3 -0
  156. data/guides/code/getting_started/app/controllers/application_controller.rb +5 -0
  157. data/guides/code/getting_started/app/controllers/comments_controller.rb +17 -0
  158. data/guides/code/getting_started/app/controllers/posts_controller.rb +47 -0
  159. data/guides/code/getting_started/app/controllers/welcome_controller.rb +4 -0
  160. data/guides/code/getting_started/app/helpers/application_helper.rb +2 -0
  161. data/guides/code/getting_started/app/helpers/comments_helper.rb +2 -0
  162. data/guides/code/getting_started/app/helpers/posts_helper.rb +2 -0
  163. data/guides/code/getting_started/app/helpers/welcome_helper.rb +2 -0
  164. data/guides/code/getting_started/app/models/comment.rb +3 -0
  165. data/guides/code/getting_started/app/models/post.rb +7 -0
  166. data/guides/code/getting_started/app/views/comments/_comment.html.erb +15 -0
  167. data/guides/code/getting_started/app/views/comments/_form.html.erb +13 -0
  168. data/guides/code/getting_started/app/views/layouts/application.html.erb +14 -0
  169. data/guides/code/getting_started/app/views/posts/_form.html.erb +27 -0
  170. data/guides/code/getting_started/app/views/posts/edit.html.erb +5 -0
  171. data/guides/code/getting_started/app/views/posts/index.html.erb +21 -0
  172. data/guides/code/getting_started/app/views/posts/new.html.erb +5 -0
  173. data/guides/code/getting_started/app/views/posts/show.html.erb +18 -0
  174. data/guides/code/getting_started/app/views/welcome/index.html.erb +3 -0
  175. data/guides/code/getting_started/bin/bundle +4 -0
  176. data/guides/code/getting_started/bin/rails +4 -0
  177. data/guides/code/getting_started/bin/rake +4 -0
  178. data/guides/code/getting_started/config.ru +4 -0
  179. data/guides/code/getting_started/config/application.rb +17 -0
  180. data/guides/code/getting_started/config/boot.rb +4 -0
  181. data/guides/code/getting_started/config/database.yml +25 -0
  182. data/guides/code/getting_started/config/environment.rb +5 -0
  183. data/guides/code/getting_started/config/environments/development.rb +30 -0
  184. data/guides/code/getting_started/config/environments/production.rb +80 -0
  185. data/guides/code/getting_started/config/environments/test.rb +36 -0
  186. data/guides/code/getting_started/config/initializers/backtrace_silencers.rb +7 -0
  187. data/guides/code/getting_started/config/initializers/filter_parameter_logging.rb +4 -0
  188. data/guides/code/getting_started/config/initializers/inflections.rb +16 -0
  189. data/guides/code/getting_started/config/initializers/locale.rb +9 -0
  190. data/guides/code/getting_started/config/initializers/mime_types.rb +5 -0
  191. data/guides/code/getting_started/config/initializers/secret_token.rb +12 -0
  192. data/guides/code/getting_started/config/initializers/session_store.rb +3 -0
  193. data/guides/code/getting_started/config/initializers/wrap_parameters.rb +14 -0
  194. data/guides/code/getting_started/config/locales/en.yml +23 -0
  195. data/guides/code/getting_started/config/routes.rb +7 -0
  196. data/guides/code/getting_started/db/migrate/20130122042648_create_posts.rb +10 -0
  197. data/guides/code/getting_started/db/migrate/20130122045842_create_comments.rb +11 -0
  198. data/guides/code/getting_started/db/schema.rb +33 -0
  199. data/guides/code/getting_started/db/seeds.rb +7 -0
  200. data/guides/code/getting_started/public/404.html +27 -0
  201. data/guides/code/getting_started/public/422.html +26 -0
  202. data/guides/code/getting_started/public/500.html +26 -0
  203. data/guides/code/getting_started/public/favicon.ico +0 -0
  204. data/guides/code/getting_started/public/robots.txt +5 -0
  205. data/guides/code/getting_started/test/controllers/comments_controller_test.rb +7 -0
  206. data/guides/code/getting_started/test/controllers/posts_controller_test.rb +7 -0
  207. data/guides/code/getting_started/test/controllers/welcome_controller_test.rb +9 -0
  208. data/guides/code/getting_started/test/fixtures/comments.yml +11 -0
  209. data/guides/code/getting_started/test/fixtures/posts.yml +9 -0
  210. data/guides/code/getting_started/test/helpers/comments_helper_test.rb +4 -0
  211. data/guides/code/getting_started/test/helpers/posts_helper_test.rb +4 -0
  212. data/guides/code/getting_started/test/helpers/welcome_helper_test.rb +4 -0
  213. data/guides/code/getting_started/test/models/comment_test.rb +7 -0
  214. data/guides/code/getting_started/test/models/post_test.rb +7 -0
  215. data/guides/code/getting_started/test/test_helper.rb +15 -0
  216. data/guides/rails_guides.rb +44 -0
  217. data/guides/rails_guides/generator.rb +248 -0
  218. data/guides/rails_guides/helpers.rb +51 -0
  219. data/guides/rails_guides/indexer.rb +68 -0
  220. data/guides/rails_guides/kindle.rb +119 -0
  221. data/guides/rails_guides/levenshtein.rb +31 -0
  222. data/guides/rails_guides/markdown.rb +163 -0
  223. data/guides/rails_guides/markdown/renderer.rb +82 -0
  224. data/guides/source/2_2_release_notes.md +435 -0
  225. data/guides/source/2_3_release_notes.md +621 -0
  226. data/guides/source/3_0_release_notes.md +614 -0
  227. data/guides/source/3_1_release_notes.md +556 -0
  228. data/guides/source/3_2_release_notes.md +565 -0
  229. data/guides/source/4_0_release_notes.md +228 -0
  230. data/guides/source/_license.html.erb +2 -0
  231. data/guides/source/_welcome.html.erb +19 -0
  232. data/guides/source/action_controller_overview.md +872 -0
  233. data/guides/source/action_mailer_basics.md +599 -0
  234. data/guides/source/action_view_overview.md +1565 -0
  235. data/guides/source/active_model_basics.md +200 -0
  236. data/guides/source/active_record_basics.md +370 -0
  237. data/guides/source/active_record_callbacks.md +358 -0
  238. data/guides/source/active_record_querying.md +1621 -0
  239. data/guides/source/active_record_validations.md +1128 -0
  240. data/guides/source/active_support_core_extensions.md +3791 -0
  241. data/guides/source/active_support_instrumentation.md +487 -0
  242. data/guides/source/api_documentation_guidelines.md +209 -0
  243. data/guides/source/asset_pipeline.md +832 -0
  244. data/guides/source/association_basics.md +2129 -0
  245. data/guides/source/caching_with_rails.md +350 -0
  246. data/guides/source/command_line.md +594 -0
  247. data/guides/source/configuring.md +736 -0
  248. data/guides/source/contributing_to_ruby_on_rails.md +455 -0
  249. data/guides/source/credits.html.erb +76 -0
  250. data/guides/source/debugging_rails_applications.md +675 -0
  251. data/guides/source/development_dependencies_install.md +195 -0
  252. data/guides/source/documents.yaml +179 -0
  253. data/guides/source/engines.md +961 -0
  254. data/guides/source/form_helpers.md +955 -0
  255. data/guides/source/generators.md +644 -0
  256. data/guides/source/getting_started.md +1775 -0
  257. data/guides/source/i18n.md +983 -0
  258. data/guides/source/index.html.erb +27 -0
  259. data/guides/source/initialization.md +562 -0
  260. data/guides/source/kindle/KINDLE.md +26 -0
  261. data/guides/source/kindle/copyright.html.erb +1 -0
  262. data/guides/source/kindle/layout.html.erb +27 -0
  263. data/guides/source/kindle/rails_guides.opf.erb +52 -0
  264. data/guides/source/kindle/toc.html.erb +24 -0
  265. data/guides/source/kindle/toc.ncx.erb +64 -0
  266. data/guides/source/kindle/welcome.html.erb +5 -0
  267. data/guides/source/layout.html.erb +148 -0
  268. data/guides/source/layouts_and_rendering.md +1132 -0
  269. data/guides/source/migrations.md +1059 -0
  270. data/guides/source/nested_model_forms.md +225 -0
  271. data/guides/source/plugins.md +435 -0
  272. data/guides/source/rails_application_templates.md +229 -0
  273. data/guides/source/rails_on_rack.md +342 -0
  274. data/guides/source/routing.md +1088 -0
  275. data/guides/source/ruby_on_rails_guides_guidelines.md +124 -0
  276. data/guides/source/security.md +973 -0
  277. data/guides/source/testing.md +981 -0
  278. data/guides/source/upgrading_ruby_on_rails.md +286 -0
  279. data/guides/source/working_with_javascript_in_rails.md +396 -0
  280. data/guides/w3c_validator.rb +95 -0
  281. metadata +315 -31
@@ -0,0 +1,4 @@
1
+ require 'test_helper'
2
+
3
+ class CommentsHelperTest < ActionView::TestCase
4
+ end
@@ -0,0 +1,4 @@
1
+ require 'test_helper'
2
+
3
+ class PostsHelperTest < ActionView::TestCase
4
+ end
@@ -0,0 +1,4 @@
1
+ require 'test_helper'
2
+
3
+ class WelcomeHelperTest < ActionView::TestCase
4
+ end
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class CommentTest < ActiveSupport::TestCase
4
+ # test "the truth" do
5
+ # assert true
6
+ # end
7
+ end
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class PostTest < ActiveSupport::TestCase
4
+ # test "the truth" do
5
+ # assert true
6
+ # end
7
+ end
@@ -0,0 +1,15 @@
1
+ ENV["RAILS_ENV"] = "test"
2
+ require File.expand_path('../../config/environment', __FILE__)
3
+ require 'rails/test_help'
4
+
5
+ class ActiveSupport::TestCase
6
+ ActiveRecord::Migration.check_pending!
7
+
8
+ # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
9
+ #
10
+ # Note: You'll currently still have to declare fixtures explicitly in integration tests
11
+ # -- they do not yet inherit this setting
12
+ fixtures :all
13
+
14
+ # Add more helper methods to be used by all tests here...
15
+ end
@@ -0,0 +1,44 @@
1
+ pwd = File.dirname(__FILE__)
2
+ $:.unshift pwd
3
+
4
+ # This is a predicate useful for the doc:guides task of applications.
5
+ def bundler?
6
+ # Note that rake sets the cwd to the one that contains the Rakefile
7
+ # being executed.
8
+ File.exists?('Gemfile')
9
+ end
10
+
11
+ begin
12
+ # Guides generation in the Rails repo.
13
+ as_lib = File.join(pwd, "../activesupport/lib")
14
+ ap_lib = File.join(pwd, "../actionpack/lib")
15
+
16
+ $:.unshift as_lib if File.directory?(as_lib)
17
+ $:.unshift ap_lib if File.directory?(ap_lib)
18
+ rescue LoadError
19
+ # Guides generation from gems.
20
+ gem "actionpack", '>= 3.0'
21
+ end
22
+
23
+ begin
24
+ require 'redcarpet'
25
+ rescue Gem::LoadError
26
+ # This can happen if doc:guides is executed in an application.
27
+ $stderr.puts('Generating guides requires Redcarpet 2.1.1+.')
28
+ $stderr.puts(<<ERROR) if bundler?
29
+ Please add
30
+
31
+ gem 'redcarpet', '~> 2.1.1'
32
+
33
+ to the Gemfile, run
34
+
35
+ bundle install
36
+
37
+ and try again.
38
+ ERROR
39
+ exit 1
40
+ end
41
+
42
+ require 'rails_guides/markdown'
43
+ require "rails_guides/generator"
44
+ RailsGuides::Generator.new.generate
@@ -0,0 +1,248 @@
1
+ # ---------------------------------------------------------------------------
2
+ #
3
+ # This script generates the guides. It can be invoked via the
4
+ # guides:generate rake task within the guides directory.
5
+ #
6
+ # Guides are taken from the source directory, and the resulting HTML goes into the
7
+ # output directory. Assets are stored under files, and copied to output/files as
8
+ # part of the generation process.
9
+ #
10
+ # Some arguments may be passed via environment variables:
11
+ #
12
+ # WARNINGS
13
+ # If you are writing a guide, please work always with WARNINGS=1. Users can
14
+ # generate the guides, and thus this flag is off by default.
15
+ #
16
+ # Internal links (anchors) are checked. If a reference is broken levenshtein
17
+ # distance is used to suggest an existing one. This is useful since IDs are
18
+ # generated by Markdown from headers and thus edits alter them.
19
+ #
20
+ # Also detects duplicated IDs. They happen if there are headers with the same
21
+ # text. Please do resolve them, if any, so guides are valid XHTML.
22
+ #
23
+ # ALL
24
+ # Set to "1" to force the generation of all guides.
25
+ #
26
+ # ONLY
27
+ # Use ONLY if you want to generate only one or a set of guides. Prefixes are
28
+ # enough:
29
+ #
30
+ # # generates only association_basics.html
31
+ # ONLY=assoc ruby rails_guides.rb
32
+ #
33
+ # Separate many using commas:
34
+ #
35
+ # # generates only association_basics.html and migrations.html
36
+ # ONLY=assoc,migrations ruby rails_guides.rb
37
+ #
38
+ # Note that if you are working on a guide generation will by default process
39
+ # only that one, so ONLY is rarely used nowadays.
40
+ #
41
+ # GUIDES_LANGUAGE
42
+ # Use GUIDES_LANGUAGE when you want to generate translated guides in
43
+ # <tt>source/<GUIDES_LANGUAGE></tt> folder (such as <tt>source/es</tt>).
44
+ # Ignore it when generating English guides.
45
+ #
46
+ # EDGE
47
+ # Set to "1" to indicate generated guides should be marked as edge. This
48
+ # inserts a badge and changes the preamble of the home page.
49
+ #
50
+ # ---------------------------------------------------------------------------
51
+
52
+ require 'set'
53
+ require 'fileutils'
54
+
55
+ require 'active_support/core_ext/string/output_safety'
56
+ require 'active_support/core_ext/object/blank'
57
+ require 'action_controller'
58
+ require 'action_view'
59
+
60
+ require 'rails_guides/indexer'
61
+ require 'rails_guides/helpers'
62
+ require 'rails_guides/levenshtein'
63
+
64
+ module RailsGuides
65
+ class Generator
66
+ attr_reader :guides_dir, :source_dir, :output_dir, :edge, :warnings, :all
67
+
68
+ GUIDES_RE = /\.(?:erb|md)\z/
69
+
70
+ def initialize(output=nil)
71
+ set_flags_from_environment
72
+
73
+ if kindle?
74
+ check_for_kindlegen
75
+ register_kindle_mime_types
76
+ end
77
+
78
+ initialize_dirs(output)
79
+ create_output_dir_if_needed
80
+ end
81
+
82
+ def set_flags_from_environment
83
+ @edge = ENV['EDGE'] == '1'
84
+ @warnings = ENV['WARNINGS'] == '1'
85
+ @all = ENV['ALL'] == '1'
86
+ @kindle = ENV['KINDLE'] == '1'
87
+ @version = ENV['RAILS_VERSION'] || 'local'
88
+ @lang = ENV['GUIDES_LANGUAGE']
89
+ end
90
+
91
+ def register_kindle_mime_types
92
+ Mime::Type.register_alias("application/xml", :opf, %w(opf))
93
+ Mime::Type.register_alias("application/xml", :ncx, %w(ncx))
94
+ end
95
+
96
+ def generate
97
+ generate_guides
98
+ copy_assets
99
+ generate_mobi if kindle?
100
+ end
101
+
102
+ private
103
+
104
+ def kindle?
105
+ @kindle
106
+ end
107
+
108
+ def check_for_kindlegen
109
+ if `which kindlegen`.blank?
110
+ raise "Can't create a kindle version without `kindlegen`."
111
+ end
112
+ end
113
+
114
+ def generate_mobi
115
+ require 'rails_guides/kindle'
116
+ out = "#{output_dir}/kindlegen.out"
117
+ Kindle.generate(output_dir, mobi, out)
118
+ puts "(kindlegen log at #{out})."
119
+ end
120
+
121
+ def mobi
122
+ "ruby_on_rails_guides_#@version%s.mobi" % (@lang.present? ? ".#@lang" : '')
123
+ end
124
+
125
+ def initialize_dirs(output)
126
+ @guides_dir = File.join(File.dirname(__FILE__), '..')
127
+ @source_dir = "#@guides_dir/source/#@lang"
128
+ @output_dir = if output
129
+ output
130
+ elsif kindle?
131
+ "#@guides_dir/output/kindle/#@lang"
132
+ else
133
+ "#@guides_dir/output/#@lang"
134
+ end.sub(%r</$>, '')
135
+ end
136
+
137
+ def create_output_dir_if_needed
138
+ FileUtils.mkdir_p(output_dir)
139
+ end
140
+
141
+ def generate_guides
142
+ guides_to_generate.each do |guide|
143
+ output_file = output_file_for(guide)
144
+ generate_guide(guide, output_file) if generate?(guide, output_file)
145
+ end
146
+ end
147
+
148
+ def guides_to_generate
149
+ guides = Dir.entries(source_dir).grep(GUIDES_RE)
150
+
151
+ if kindle?
152
+ Dir.entries("#{source_dir}/kindle").grep(GUIDES_RE).map do |entry|
153
+ next if entry == 'KINDLE.md'
154
+ guides << "kindle/#{entry}"
155
+ end
156
+ end
157
+
158
+ ENV.key?('ONLY') ? select_only(guides) : guides
159
+ end
160
+
161
+ def select_only(guides)
162
+ prefixes = ENV['ONLY'].split(",").map(&:strip)
163
+ guides.select do |guide|
164
+ prefixes.any? { |p| guide.start_with?(p) || guide.start_with?("kindle") }
165
+ end
166
+ end
167
+
168
+ def copy_assets
169
+ FileUtils.cp_r(Dir.glob("#{guides_dir}/assets/*"), output_dir)
170
+ end
171
+
172
+ def output_file_for(guide)
173
+ if guide.end_with?('.md')
174
+ guide.sub(/md\z/, 'html')
175
+ else
176
+ guide.sub(/\.erb\z/, '')
177
+ end
178
+ end
179
+
180
+ def output_path_for(output_file)
181
+ File.join(output_dir, File.basename(output_file))
182
+ end
183
+
184
+ def generate?(source_file, output_file)
185
+ fin = File.join(source_dir, source_file)
186
+ fout = output_path_for(output_file)
187
+ all || !File.exists?(fout) || File.mtime(fout) < File.mtime(fin)
188
+ end
189
+
190
+ def generate_guide(guide, output_file)
191
+ output_path = output_path_for(output_file)
192
+ puts "Generating #{guide} as #{output_file}"
193
+ layout = kindle? ? 'kindle/layout' : 'layout'
194
+
195
+ File.open(output_path, 'w') do |f|
196
+ view = ActionView::Base.new(source_dir, :edge => @edge, :version => @version, :mobi => "kindle/#{mobi}")
197
+ view.extend(Helpers)
198
+
199
+ if guide =~ /\.(\w+)\.erb$/
200
+ # Generate the special pages like the home.
201
+ # Passing a template handler in the template name is deprecated. So pass the file name without the extension.
202
+ result = view.render(:layout => layout, :formats => [$1], :file => $`)
203
+ else
204
+ body = File.read(File.join(source_dir, guide))
205
+ result = RailsGuides::Markdown.new(view, layout).render(body)
206
+
207
+ warn_about_broken_links(result) if @warnings
208
+ end
209
+
210
+ f.write(result)
211
+ end
212
+ end
213
+
214
+ def warn_about_broken_links(html)
215
+ anchors = extract_anchors(html)
216
+ check_fragment_identifiers(html, anchors)
217
+ end
218
+
219
+ def extract_anchors(html)
220
+ # Markdown generates headers with IDs computed from titles.
221
+ anchors = Set.new
222
+ html.scan(/<h\d\s+id="([^"]+)/).flatten.each do |anchor|
223
+ if anchors.member?(anchor)
224
+ puts "*** DUPLICATE ID: #{anchor}, please make sure that there're no headings with the same name at the same level."
225
+ else
226
+ anchors << anchor
227
+ end
228
+ end
229
+
230
+ # Footnotes.
231
+ anchors += Set.new(html.scan(/<p\s+class="footnote"\s+id="([^"]+)/).flatten)
232
+ anchors += Set.new(html.scan(/<sup\s+class="footnote"\s+id="([^"]+)/).flatten)
233
+ return anchors
234
+ end
235
+
236
+ def check_fragment_identifiers(html, anchors)
237
+ html.scan(/<a\s+href="#([^"]+)/).flatten.each do |fragment_identifier|
238
+ next if fragment_identifier == 'mainCol' # in layout, jumps to some DIV
239
+ unless anchors.member?(fragment_identifier)
240
+ guess = anchors.min { |a, b|
241
+ Levenshtein.distance(fragment_identifier, a) <=> Levenshtein.distance(fragment_identifier, b)
242
+ }
243
+ puts "*** BROKEN LINK: ##{fragment_identifier}, perhaps you meant ##{guess}."
244
+ end
245
+ end
246
+ end
247
+ end
248
+ end
@@ -0,0 +1,51 @@
1
+ module RailsGuides
2
+ module Helpers
3
+ def guide(name, url, options = {}, &block)
4
+ link = content_tag(:a, :href => url) { name }
5
+ result = content_tag(:dt, link)
6
+
7
+ if options[:work_in_progress]
8
+ result << content_tag(:dd, 'Work in progress', :class => 'work-in-progress')
9
+ end
10
+
11
+ result << content_tag(:dd, capture(&block))
12
+ result
13
+ end
14
+
15
+ def documents_by_section
16
+ @documents_by_section ||= YAML.load_file(File.expand_path('../../source/documents.yaml', __FILE__))
17
+ end
18
+
19
+ def documents_flat
20
+ documents_by_section.map {|section| section['documents']}.flatten
21
+ end
22
+
23
+ def finished_documents(documents)
24
+ documents.reject { |document| document['work_in_progress'] }
25
+ end
26
+
27
+ def docs_for_menu(position=nil)
28
+ if position.nil?
29
+ documents_by_section
30
+ elsif position == 'L'
31
+ documents_by_section.to(3)
32
+ else
33
+ documents_by_section.from(4)
34
+ end
35
+ end
36
+
37
+ def author(name, nick, image = 'credits_pic_blank.gif', &block)
38
+ image = "images/#{image}"
39
+
40
+ result = content_tag(:img, nil, :src => image, :class => 'left pic', :alt => name, :width => 91, :height => 91)
41
+ result << content_tag(:h3, name)
42
+ result << content_tag(:p, capture(&block))
43
+ content_tag(:div, result, :class => 'clearfix', :id => nick)
44
+ end
45
+
46
+ def code(&block)
47
+ c = capture(&block)
48
+ content_tag(:code, c)
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,68 @@
1
+ require 'active_support/core_ext/object/blank'
2
+ require 'active_support/core_ext/string/inflections'
3
+
4
+ module RailsGuides
5
+ class Indexer
6
+ attr_reader :body, :result, :warnings, :level_hash
7
+
8
+ def initialize(body, warnings)
9
+ @body = body
10
+ @result = @body.dup
11
+ @warnings = warnings
12
+ end
13
+
14
+ def index
15
+ @level_hash = process(body)
16
+ end
17
+
18
+ private
19
+
20
+ def process(string, current_level=3, counters=[1])
21
+ s = StringScanner.new(string)
22
+
23
+ level_hash = {}
24
+
25
+ while !s.eos?
26
+ re = %r{^h(\d)(?:\((#.*?)\))?\s*\.\s*(.*)$}
27
+ s.match?(re)
28
+ if matched = s.matched
29
+ matched =~ re
30
+ level, idx, title = $1.to_i, $2, $3.strip
31
+
32
+ if level < current_level
33
+ # This is needed. Go figure.
34
+ return level_hash
35
+ elsif level == current_level
36
+ index = counters.join(".")
37
+ idx ||= '#' + title_to_idx(title)
38
+
39
+ raise "Parsing Fail" unless @result.sub!(matched, "h#{level}(#{idx}). #{index} #{title}")
40
+
41
+ key = {
42
+ :title => title,
43
+ :id => idx
44
+ }
45
+ # Recurse
46
+ counters << 1
47
+ level_hash[key] = process(s.post_match, current_level + 1, counters)
48
+ counters.pop
49
+
50
+ # Increment the current level
51
+ last = counters.pop
52
+ counters << last + 1
53
+ end
54
+ end
55
+ s.getch
56
+ end
57
+ level_hash
58
+ end
59
+
60
+ def title_to_idx(title)
61
+ idx = title.strip.parameterize.sub(/^\d+/, '')
62
+ if warnings && idx.blank?
63
+ puts "BLANK ID: please put an explicit ID for section #{title}, as in h5(#my-id)"
64
+ end
65
+ idx
66
+ end
67
+ end
68
+ end