rails_test 4.2.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +83 -0
  3. data/guides/CHANGELOG.md +27 -0
  4. data/guides/Rakefile +77 -0
  5. data/guides/assets/images/akshaysurve.jpg +0 -0
  6. data/guides/assets/images/belongs_to.png +0 -0
  7. data/guides/assets/images/book_icon.gif +0 -0
  8. data/guides/assets/images/bullet.gif +0 -0
  9. data/guides/assets/images/chapters_icon.gif +0 -0
  10. data/guides/assets/images/check_bullet.gif +0 -0
  11. data/guides/assets/images/credits_pic_blank.gif +0 -0
  12. data/guides/assets/images/csrf.png +0 -0
  13. data/guides/assets/images/edge_badge.png +0 -0
  14. data/guides/assets/images/favicon.ico +0 -0
  15. data/guides/assets/images/feature_tile.gif +0 -0
  16. data/guides/assets/images/footer_tile.gif +0 -0
  17. data/guides/assets/images/fxn.png +0 -0
  18. data/guides/assets/images/getting_started/article_with_comments.png +0 -0
  19. data/guides/assets/images/getting_started/challenge.png +0 -0
  20. data/guides/assets/images/getting_started/confirm_dialog.png +0 -0
  21. data/guides/assets/images/getting_started/forbidden_attributes_for_new_article.png +0 -0
  22. data/guides/assets/images/getting_started/form_with_errors.png +0 -0
  23. data/guides/assets/images/getting_started/index_action_with_edit_link.png +0 -0
  24. data/guides/assets/images/getting_started/new_article.png +0 -0
  25. data/guides/assets/images/getting_started/rails_welcome.png +0 -0
  26. data/guides/assets/images/getting_started/routing_error_no_controller.png +0 -0
  27. data/guides/assets/images/getting_started/routing_error_no_route_matches.png +0 -0
  28. data/guides/assets/images/getting_started/show_action_for_articles.png +0 -0
  29. data/guides/assets/images/getting_started/template_is_missing_articles_new.png +0 -0
  30. data/guides/assets/images/getting_started/unknown_action_create_for_articles.png +0 -0
  31. data/guides/assets/images/getting_started/unknown_action_new_for_articles.png +0 -0
  32. data/guides/assets/images/grey_bullet.gif +0 -0
  33. data/guides/assets/images/habtm.png +0 -0
  34. data/guides/assets/images/has_many.png +0 -0
  35. data/guides/assets/images/has_many_through.png +0 -0
  36. data/guides/assets/images/has_one.png +0 -0
  37. data/guides/assets/images/has_one_through.png +0 -0
  38. data/guides/assets/images/header_backdrop.png +0 -0
  39. data/guides/assets/images/header_tile.gif +0 -0
  40. data/guides/assets/images/i18n/demo_html_safe.png +0 -0
  41. data/guides/assets/images/i18n/demo_localized_pirate.png +0 -0
  42. data/guides/assets/images/i18n/demo_translated_en.png +0 -0
  43. data/guides/assets/images/i18n/demo_translated_pirate.png +0 -0
  44. data/guides/assets/images/i18n/demo_translation_missing.png +0 -0
  45. data/guides/assets/images/i18n/demo_untranslated.png +0 -0
  46. data/guides/assets/images/icons/README +5 -0
  47. data/guides/assets/images/icons/callouts/1.png +0 -0
  48. data/guides/assets/images/icons/callouts/10.png +0 -0
  49. data/guides/assets/images/icons/callouts/11.png +0 -0
  50. data/guides/assets/images/icons/callouts/12.png +0 -0
  51. data/guides/assets/images/icons/callouts/13.png +0 -0
  52. data/guides/assets/images/icons/callouts/14.png +0 -0
  53. data/guides/assets/images/icons/callouts/15.png +0 -0
  54. data/guides/assets/images/icons/callouts/2.png +0 -0
  55. data/guides/assets/images/icons/callouts/3.png +0 -0
  56. data/guides/assets/images/icons/callouts/4.png +0 -0
  57. data/guides/assets/images/icons/callouts/5.png +0 -0
  58. data/guides/assets/images/icons/callouts/6.png +0 -0
  59. data/guides/assets/images/icons/callouts/7.png +0 -0
  60. data/guides/assets/images/icons/callouts/8.png +0 -0
  61. data/guides/assets/images/icons/callouts/9.png +0 -0
  62. data/guides/assets/images/icons/caution.png +0 -0
  63. data/guides/assets/images/icons/example.png +0 -0
  64. data/guides/assets/images/icons/home.png +0 -0
  65. data/guides/assets/images/icons/important.png +0 -0
  66. data/guides/assets/images/icons/next.png +0 -0
  67. data/guides/assets/images/icons/note.png +0 -0
  68. data/guides/assets/images/icons/prev.png +0 -0
  69. data/guides/assets/images/icons/tip.png +0 -0
  70. data/guides/assets/images/icons/up.png +0 -0
  71. data/guides/assets/images/icons/warning.png +0 -0
  72. data/guides/assets/images/nav_arrow.gif +0 -0
  73. data/guides/assets/images/oscardelben.jpg +0 -0
  74. data/guides/assets/images/polymorphic.png +0 -0
  75. data/guides/assets/images/radar.png +0 -0
  76. data/guides/assets/images/rails4_features.png +0 -0
  77. data/guides/assets/images/rails_guides_kindle_cover.jpg +0 -0
  78. data/guides/assets/images/rails_guides_logo.gif +0 -0
  79. data/guides/assets/images/rails_logo_remix.gif +0 -0
  80. data/guides/assets/images/session_fixation.png +0 -0
  81. data/guides/assets/images/tab_grey.gif +0 -0
  82. data/guides/assets/images/tab_info.gif +0 -0
  83. data/guides/assets/images/tab_note.gif +0 -0
  84. data/guides/assets/images/tab_red.gif +0 -0
  85. data/guides/assets/images/tab_yellow.gif +0 -0
  86. data/guides/assets/images/tab_yellow.png +0 -0
  87. data/guides/assets/images/vijaydev.jpg +0 -0
  88. data/guides/assets/javascripts/guides.js +59 -0
  89. data/guides/assets/javascripts/jquery.min.js +4 -0
  90. data/guides/assets/javascripts/responsive-tables.js +43 -0
  91. data/guides/assets/javascripts/syntaxhighlighter/shBrushAS3.js +59 -0
  92. data/guides/assets/javascripts/syntaxhighlighter/shBrushAppleScript.js +75 -0
  93. data/guides/assets/javascripts/syntaxhighlighter/shBrushBash.js +59 -0
  94. data/guides/assets/javascripts/syntaxhighlighter/shBrushCSharp.js +65 -0
  95. data/guides/assets/javascripts/syntaxhighlighter/shBrushColdFusion.js +100 -0
  96. data/guides/assets/javascripts/syntaxhighlighter/shBrushCpp.js +97 -0
  97. data/guides/assets/javascripts/syntaxhighlighter/shBrushCss.js +91 -0
  98. data/guides/assets/javascripts/syntaxhighlighter/shBrushDelphi.js +55 -0
  99. data/guides/assets/javascripts/syntaxhighlighter/shBrushDiff.js +41 -0
  100. data/guides/assets/javascripts/syntaxhighlighter/shBrushErlang.js +52 -0
  101. data/guides/assets/javascripts/syntaxhighlighter/shBrushGroovy.js +67 -0
  102. data/guides/assets/javascripts/syntaxhighlighter/shBrushJScript.js +52 -0
  103. data/guides/assets/javascripts/syntaxhighlighter/shBrushJava.js +57 -0
  104. data/guides/assets/javascripts/syntaxhighlighter/shBrushJavaFX.js +58 -0
  105. data/guides/assets/javascripts/syntaxhighlighter/shBrushPerl.js +72 -0
  106. data/guides/assets/javascripts/syntaxhighlighter/shBrushPhp.js +88 -0
  107. data/guides/assets/javascripts/syntaxhighlighter/shBrushPlain.js +33 -0
  108. data/guides/assets/javascripts/syntaxhighlighter/shBrushPowerShell.js +74 -0
  109. data/guides/assets/javascripts/syntaxhighlighter/shBrushPython.js +64 -0
  110. data/guides/assets/javascripts/syntaxhighlighter/shBrushRuby.js +55 -0
  111. data/guides/assets/javascripts/syntaxhighlighter/shBrushSass.js +94 -0
  112. data/guides/assets/javascripts/syntaxhighlighter/shBrushScala.js +51 -0
  113. data/guides/assets/javascripts/syntaxhighlighter/shBrushSql.js +66 -0
  114. data/guides/assets/javascripts/syntaxhighlighter/shBrushVb.js +56 -0
  115. data/guides/assets/javascripts/syntaxhighlighter/shBrushXml.js +69 -0
  116. data/guides/assets/javascripts/syntaxhighlighter/shCore.js +17 -0
  117. data/guides/assets/stylesheets/fixes.css +16 -0
  118. data/guides/assets/stylesheets/kindle.css +11 -0
  119. data/guides/assets/stylesheets/main.css +713 -0
  120. data/guides/assets/stylesheets/print.css +52 -0
  121. data/guides/assets/stylesheets/reset.css +43 -0
  122. data/guides/assets/stylesheets/responsive-tables.css +50 -0
  123. data/guides/assets/stylesheets/style.css +13 -0
  124. data/guides/assets/stylesheets/syntaxhighlighter/shCore.css +226 -0
  125. data/guides/assets/stylesheets/syntaxhighlighter/shCoreDefault.css +328 -0
  126. data/guides/assets/stylesheets/syntaxhighlighter/shCoreDjango.css +331 -0
  127. data/guides/assets/stylesheets/syntaxhighlighter/shCoreEclipse.css +339 -0
  128. data/guides/assets/stylesheets/syntaxhighlighter/shCoreEmacs.css +324 -0
  129. data/guides/assets/stylesheets/syntaxhighlighter/shCoreFadeToGrey.css +328 -0
  130. data/guides/assets/stylesheets/syntaxhighlighter/shCoreMDUltra.css +324 -0
  131. data/guides/assets/stylesheets/syntaxhighlighter/shCoreMidnight.css +324 -0
  132. data/guides/assets/stylesheets/syntaxhighlighter/shCoreRDark.css +324 -0
  133. data/guides/assets/stylesheets/syntaxhighlighter/shThemeDefault.css +117 -0
  134. data/guides/assets/stylesheets/syntaxhighlighter/shThemeDjango.css +120 -0
  135. data/guides/assets/stylesheets/syntaxhighlighter/shThemeEclipse.css +128 -0
  136. data/guides/assets/stylesheets/syntaxhighlighter/shThemeEmacs.css +113 -0
  137. data/guides/assets/stylesheets/syntaxhighlighter/shThemeFadeToGrey.css +117 -0
  138. data/guides/assets/stylesheets/syntaxhighlighter/shThemeMDUltra.css +113 -0
  139. data/guides/assets/stylesheets/syntaxhighlighter/shThemeMidnight.css +113 -0
  140. data/guides/assets/stylesheets/syntaxhighlighter/shThemeRDark.css +113 -0
  141. data/guides/assets/stylesheets/syntaxhighlighter/shThemeRailsGuides.css +116 -0
  142. data/guides/bug_report_templates/action_controller_gem.rb +47 -0
  143. data/guides/bug_report_templates/action_controller_master.rb +56 -0
  144. data/guides/bug_report_templates/active_record_gem.rb +40 -0
  145. data/guides/bug_report_templates/active_record_master.rb +51 -0
  146. data/guides/rails_guides.rb +63 -0
  147. data/guides/rails_guides/generator.rb +248 -0
  148. data/guides/rails_guides/helpers.rb +53 -0
  149. data/guides/rails_guides/indexer.rb +68 -0
  150. data/guides/rails_guides/kindle.rb +119 -0
  151. data/guides/rails_guides/levenshtein.rb +39 -0
  152. data/guides/rails_guides/markdown.rb +167 -0
  153. data/guides/rails_guides/markdown/renderer.rb +82 -0
  154. data/guides/source/2_2_release_notes.md +435 -0
  155. data/guides/source/2_3_release_notes.md +621 -0
  156. data/guides/source/3_0_release_notes.md +611 -0
  157. data/guides/source/3_1_release_notes.md +559 -0
  158. data/guides/source/3_2_release_notes.md +568 -0
  159. data/guides/source/4_0_release_notes.md +279 -0
  160. data/guides/source/4_1_release_notes.md +730 -0
  161. data/guides/source/4_2_release_notes.md +736 -0
  162. data/guides/source/_license.html.erb +2 -0
  163. data/guides/source/_welcome.html.erb +19 -0
  164. data/guides/source/action_controller_overview.md +1247 -0
  165. data/guides/source/action_mailer_basics.md +738 -0
  166. data/guides/source/action_view_overview.md +1621 -0
  167. data/guides/source/active_job_basics.md +285 -0
  168. data/guides/source/active_model_basics.md +223 -0
  169. data/guides/source/active_record_basics.md +374 -0
  170. data/guides/source/active_record_callbacks.md +413 -0
  171. data/guides/source/active_record_migrations.md +1016 -0
  172. data/guides/source/active_record_postgresql.md +438 -0
  173. data/guides/source/active_record_querying.md +1785 -0
  174. data/guides/source/active_record_validations.md +1169 -0
  175. data/guides/source/active_support_core_extensions.md +3924 -0
  176. data/guides/source/active_support_instrumentation.md +497 -0
  177. data/guides/source/api_documentation_guidelines.md +361 -0
  178. data/guides/source/asset_pipeline.md +1361 -0
  179. data/guides/source/association_basics.md +2238 -0
  180. data/guides/source/caching_with_rails.md +379 -0
  181. data/guides/source/command_line.md +634 -0
  182. data/guides/source/configuring.md +1019 -0
  183. data/guides/source/contributing_to_ruby_on_rails.md +607 -0
  184. data/guides/source/credits.html.erb +80 -0
  185. data/guides/source/debugging_rails_applications.md +861 -0
  186. data/guides/source/development_dependencies_install.md +289 -0
  187. data/guides/source/documents.yaml +197 -0
  188. data/guides/source/engines.md +1401 -0
  189. data/guides/source/form_helpers.md +1010 -0
  190. data/guides/source/generators.md +676 -0
  191. data/guides/source/getting_started.md +2085 -0
  192. data/guides/source/i18n.md +1073 -0
  193. data/guides/source/index.html.erb +28 -0
  194. data/guides/source/initialization.md +704 -0
  195. data/guides/source/kindle/copyright.html.erb +1 -0
  196. data/guides/source/kindle/layout.html.erb +27 -0
  197. data/guides/source/kindle/rails_guides.opf.erb +52 -0
  198. data/guides/source/kindle/toc.html.erb +24 -0
  199. data/guides/source/kindle/toc.ncx.erb +64 -0
  200. data/guides/source/kindle/welcome.html.erb +5 -0
  201. data/guides/source/layout.html.erb +143 -0
  202. data/guides/source/layouts_and_rendering.md +1227 -0
  203. data/guides/source/maintenance_policy.md +75 -0
  204. data/guides/source/nested_model_forms.md +228 -0
  205. data/guides/source/plugins.md +444 -0
  206. data/guides/source/rails_application_templates.md +266 -0
  207. data/guides/source/rails_on_rack.md +332 -0
  208. data/guides/source/routing.md +1141 -0
  209. data/guides/source/ruby_on_rails_guides_guidelines.md +126 -0
  210. data/guides/source/security.md +1024 -0
  211. data/guides/source/testing.md +1055 -0
  212. data/guides/source/upgrading_ruby_on_rails.md +1046 -0
  213. data/guides/source/working_with_javascript_in_rails.md +407 -0
  214. data/guides/w3c_validator.rb +97 -0
  215. metadata +404 -0
@@ -0,0 +1,40 @@
1
+ # Activate the gem you are reporting the issue against.
2
+ gem 'activerecord', '4.0.0'
3
+ require 'active_record'
4
+ require 'minitest/autorun'
5
+ require 'logger'
6
+
7
+ # Ensure backward compatibility with Minitest 4
8
+ Minitest::Test = MiniTest::Unit::TestCase unless defined?(Minitest::Test)
9
+
10
+ # This connection will do for database-independent bug reports.
11
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
12
+ ActiveRecord::Base.logger = Logger.new(STDOUT)
13
+
14
+ ActiveRecord::Schema.define do
15
+ create_table :posts do |t|
16
+ end
17
+
18
+ create_table :comments do |t|
19
+ t.integer :post_id
20
+ end
21
+ end
22
+
23
+ class Post < ActiveRecord::Base
24
+ has_many :comments
25
+ end
26
+
27
+ class Comment < ActiveRecord::Base
28
+ belongs_to :post
29
+ end
30
+
31
+ class BugTest < Minitest::Test
32
+ def test_association_stuff
33
+ post = Post.create!
34
+ post.comments << Comment.create!
35
+
36
+ assert_equal 1, post.comments.count
37
+ assert_equal 1, Comment.count
38
+ assert_equal post.id, Comment.first.post.id
39
+ end
40
+ end
@@ -0,0 +1,51 @@
1
+ unless File.exist?('Gemfile')
2
+ File.write('Gemfile', <<-GEMFILE)
3
+ source 'https://rubygems.org'
4
+ gem 'rails', github: 'rails/rails'
5
+ gem 'arel', github: 'rails/arel'
6
+ gem 'rack', github: 'rack/rack'
7
+ gem 'i18n', github: 'svenfuchs/i18n'
8
+ gem 'sqlite3'
9
+ GEMFILE
10
+
11
+ system 'bundle'
12
+ end
13
+
14
+ require 'bundler'
15
+ Bundler.setup(:default)
16
+
17
+ require 'active_record'
18
+ require 'minitest/autorun'
19
+ require 'logger'
20
+
21
+ # This connection will do for database-independent bug reports.
22
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
23
+ ActiveRecord::Base.logger = Logger.new(STDOUT)
24
+
25
+ ActiveRecord::Schema.define do
26
+ create_table :posts do |t|
27
+ end
28
+
29
+ create_table :comments do |t|
30
+ t.integer :post_id
31
+ end
32
+ end
33
+
34
+ class Post < ActiveRecord::Base
35
+ has_many :comments
36
+ end
37
+
38
+ class Comment < ActiveRecord::Base
39
+ belongs_to :post
40
+ end
41
+
42
+ class BugTest < Minitest::Test
43
+ def test_association_stuff
44
+ post = Post.create!
45
+ post.comments << Comment.create!
46
+
47
+ assert_equal 1, post.comments.count
48
+ assert_equal 1, Comment.count
49
+ assert_equal post.id, Comment.first.post.id
50
+ end
51
+ end
@@ -0,0 +1,63 @@
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.exist?('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 LoadError
26
+ # This can happen if doc:guides is executed in an application.
27
+ $stderr.puts('Generating guides requires Redcarpet 3.1.2+.')
28
+ $stderr.puts(<<ERROR) if bundler?
29
+ Please add
30
+
31
+ gem 'redcarpet', '~> 3.1.2'
32
+
33
+ to the Gemfile, run
34
+
35
+ bundle install
36
+
37
+ and try again.
38
+ ERROR
39
+ exit 1
40
+ end
41
+
42
+ begin
43
+ require 'nokogiri'
44
+ rescue LoadError
45
+ # This can happen if doc:guides is executed in an application.
46
+ $stderr.puts('Generating guides requires Nokogiri.')
47
+ $stderr.puts(<<ERROR) if bundler?
48
+ Please add
49
+
50
+ gem 'nokogiri'
51
+
52
+ to the Gemfile, run
53
+
54
+ bundle install
55
+
56
+ and try again.
57
+ ERROR
58
+ exit 1
59
+ end
60
+
61
+ require 'rails_guides/markdown'
62
+ require "rails_guides/generator"
63
+ 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.exist?(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,53 @@
1
+ require 'yaml'
2
+
3
+ module RailsGuides
4
+ module Helpers
5
+ def guide(name, url, options = {}, &block)
6
+ link = content_tag(:a, :href => url) { name }
7
+ result = content_tag(:dt, link)
8
+
9
+ if options[:work_in_progress]
10
+ result << content_tag(:dd, 'Work in progress', :class => 'work-in-progress')
11
+ end
12
+
13
+ result << content_tag(:dd, capture(&block))
14
+ result
15
+ end
16
+
17
+ def documents_by_section
18
+ @documents_by_section ||= YAML.load_file(File.expand_path('../../source/documents.yaml', __FILE__))
19
+ end
20
+
21
+ def documents_flat
22
+ documents_by_section.flat_map {|section| section['documents']}
23
+ end
24
+
25
+ def finished_documents(documents)
26
+ documents.reject { |document| document['work_in_progress'] }
27
+ end
28
+
29
+ def docs_for_menu(position=nil)
30
+ if position.nil?
31
+ documents_by_section
32
+ elsif position == 'L'
33
+ documents_by_section.to(3)
34
+ else
35
+ documents_by_section.from(4)
36
+ end
37
+ end
38
+
39
+ def author(name, nick, image = 'credits_pic_blank.gif', &block)
40
+ image = "images/#{image}"
41
+
42
+ result = tag(:img, :src => image, :class => 'left pic', :alt => name, :width => 91, :height => 91)
43
+ result << content_tag(:h3, name)
44
+ result << content_tag(:p, capture(&block))
45
+ content_tag(:div, result, :class => 'clearfix', :id => nick)
46
+ end
47
+
48
+ def code(&block)
49
+ c = capture(&block)
50
+ content_tag(:code, c)
51
+ end
52
+ end
53
+ end