diff options
Diffstat (limited to 'railties/guides')
-rw-r--r-- | railties/guides/images/fxn.jpg | bin | 17868 -> 17773 bytes | |||
-rw-r--r-- | railties/guides/rails_guides.rb | 1 | ||||
-rw-r--r-- | railties/guides/rails_guides/generator.rb | 34 | ||||
-rw-r--r-- | railties/guides/rails_guides/levenshtein.rb | 29 | ||||
-rw-r--r-- | railties/guides/source/active_record_querying.textile | 1 | ||||
-rw-r--r-- | railties/guides/source/form_helpers.textile | 2 | ||||
-rw-r--r-- | railties/guides/source/layouts_and_rendering.textile | 2 |
7 files changed, 66 insertions, 3 deletions
diff --git a/railties/guides/images/fxn.jpg b/railties/guides/images/fxn.jpg Binary files differindex b661a0e402..81999341f1 100644 --- a/railties/guides/images/fxn.jpg +++ b/railties/guides/images/fxn.jpg diff --git a/railties/guides/rails_guides.rb b/railties/guides/rails_guides.rb index b73e10e43f..e0532812e4 100644 --- a/railties/guides/rails_guides.rb +++ b/railties/guides/rails_guides.rb @@ -33,6 +33,7 @@ module RailsGuides autoload :Indexer, "rails_guides/indexer" autoload :Helpers, "rails_guides/helpers" autoload :TextileExtensions, "rails_guides/textile_extensions" + autoload :Levenshtein, "rails_guides/levenshtein" end RedCloth.send(:include, RailsGuides::TextileExtensions) diff --git a/railties/guides/rails_guides/generator.rb b/railties/guides/rails_guides/generator.rb index 6c0d9f3c3b..f93282db2e 100644 --- a/railties/guides/rails_guides/generator.rb +++ b/railties/guides/rails_guides/generator.rb @@ -57,6 +57,7 @@ module RailsGuides result = view.render(:layout => 'layout', :text => textile(body)) f.write result + warn_about_broken_links(result) if ENV.key?("WARN_BROKEN_LINKS") end end end @@ -134,5 +135,38 @@ module RailsGuides code_blocks[$1.to_i] end end + + def warn_about_broken_links(html) + anchors = extract_anchors(html) + check_fragment_identifiers(html, anchors) + end + + def extract_anchors(html) + # Textile generates headers with IDs computed from titles. + anchors = Set.new + html.scan(/<h\d\s+id="([^"]+)/).flatten.each do |anchor| + if anchors.member?(anchor) + puts "*** DUPLICATE HEADER ID: #{anchor}, please consider rewording" if ENV.key?("WARN_DUPLICATE_HEADERS") + else + anchors << anchor + end + end + + # Also, footnotes are rendered as paragraphs this way. + anchors += Set.new(html.scan(/<p\s+class="footnote"\s+id="([^"]+)/).flatten) + return anchors + end + + def check_fragment_identifiers(html, anchors) + html.scan(/<a\s+href="#([^"]+)/).flatten.each do |fragment_identifier| + next if fragment_identifier == 'mainCol' # in layout, jumps to some DIV + unless anchors.member?(fragment_identifier) + guess = anchors.min { |a, b| + Levenshtein.distance(fragment_identifier, a) <=> Levenshtein.distance(fragment_identifier, b) + } + puts "*** BROKEN LINK: ##{fragment_identifier}, perhaps you meant ##{guess}." + end + end + end end end diff --git a/railties/guides/rails_guides/levenshtein.rb b/railties/guides/rails_guides/levenshtein.rb new file mode 100644 index 0000000000..4010b61e26 --- /dev/null +++ b/railties/guides/rails_guides/levenshtein.rb @@ -0,0 +1,29 @@ +module Levenshtein + # Based on the pseudocode in http://en.wikipedia.org/wiki/Levenshtein_distance. + def self.distance(s1, s2) + s = s1.unpack('U*') + t = s2.unpack('U*') + m = s.length + n = t.length + + # matrix initialization + d = [] + 0.upto(m) { |i| d << [i] } + 0.upto(n) { |j| d[0][j] = j } + + # distance computation + 1.upto(m) do |i| + 1.upto(n) do |j| + cost = s[i] == t[j] ? 0 : 1 + d[i][j] = [ + d[i-1][j] + 1, # deletion + d[i][j-1] + 1, # insertion + d[i-1][j-1] + cost, # substitution + ].min + end + end + + # all done + return d[m][n] + end +end diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile index 442521cbf4..b112c4f5fb 100644 --- a/railties/guides/source/active_record_querying.textile +++ b/railties/guides/source/active_record_querying.textile @@ -111,7 +111,6 @@ h5. +last+ <tt>Model.last(options = nil)</tt> finds the last record matched by the supplied options. If no +options+ are supplied, the last matching record is returned. For example: <ruby> -# Find the client with primary key (id) 10. client = Client.last => #<Client id: 221, name: => "Russel"> </ruby> diff --git a/railties/guides/source/form_helpers.textile b/railties/guides/source/form_helpers.textile index 9ab4deff4e..22d24b0903 100644 --- a/railties/guides/source/form_helpers.textile +++ b/railties/guides/source/form_helpers.textile @@ -683,7 +683,7 @@ This would result in +params[:addresses]+ being an array of hashes with keys +li There's a restriction, however, while hashes can be nested arbitrarily, only one level of "arrayness" is allowed. Arrays can be usually replaced by hashes, for example instead of having an array of model objects one can have a hash of model objects keyed by their id, an array index or some other parameter. -WARNING: Array parameters do not play well with the +check_box+ helper. According to the HTML specification unchecked checkboxes submit no value. However it is often convenient for a checkbox to always submit a value. The +check_box+ helper fakes this by creating a second hidden input with the same name. If the checkbox is unchecked only the hidden input is submitted and if it is checked then both are submitted but the value submitted by the checkbox takes precedence. When working with array parameters this duplicate submission will confuse Rails since duplicate input names are how it decides when to start a new array element. It is preferable to either use +check_box_tag+ or to use hashes instead of arrays. +WARNING: Array parameters do not play well with the +check_box+ helper. According to the HTML specification unchecked checkboxes submit no value. However it is often convenient for a checkbox to always submit a value. The +check_box+ helper fakes this by creating an auxiliary hidden input with the same name. If the checkbox is unchecked only the hidden input is submitted and if it is checked then both are submitted but the value submitted by the checkbox takes precedence. When working with array parameters this duplicate submission will confuse Rails since duplicate input names are how it decides when to start a new array element. It is preferable to either use +check_box_tag+ or to use hashes instead of arrays. h4. Using Form Helpers diff --git a/railties/guides/source/layouts_and_rendering.textile b/railties/guides/source/layouts_and_rendering.textile index 69faa1b449..809d2b2172 100644 --- a/railties/guides/source/layouts_and_rendering.textile +++ b/railties/guides/source/layouts_and_rendering.textile @@ -959,7 +959,7 @@ On pages generated by +NewsController+, you want to hide the top menu and add a <div id="right_menu">Right menu items here</div> <%= yield(:news_content) or yield %> <% end -%> -<% render :file => 'layouts/application' %> +<%= render :file => 'layouts/application' %> </erb> That's it. The News views will use the new layout, hiding the top menu and adding a new right menu inside the "content" div. |