Skip to content

Commit

Permalink
Merge docrails
Browse files Browse the repository at this point in the history
  • Loading branch information
lifo committed Mar 16, 2009
1 parent 4185a4a commit 18eb80c
Show file tree
Hide file tree
Showing 48 changed files with 1,915 additions and 876 deletions.
2 changes: 1 addition & 1 deletion actionpack/lib/action_controller/integration.rb
Expand Up @@ -5,7 +5,7 @@
module ActionController
module Integration #:nodoc:
# An integration Session instance represents a set of requests and responses
# performed sequentially by some virtual user. Becase you can instantiate
# performed sequentially by some virtual user. Because you can instantiate
# multiple sessions and run them side-by-side, you can also mimic (to some
# limited extent) multiple simultaneous users interacting with your system.
#
Expand Down
4 changes: 2 additions & 2 deletions actionpack/lib/action_view/helpers/date_helper.rb
Expand Up @@ -876,8 +876,8 @@ def input_id_from_type(type)
input_name_from_type(type).gsub(/([\[\(])|(\]\[)/, '_').gsub(/[\]\)]/, '')
end

# Given an ordering of datetime components, create the selection html
# and join them with their appropriate seperators
# Given an ordering of datetime components, create the selection HTML
# and join them with their appropriate separators.
def build_selects_from_types(order)
select = ''
order.reverse.each do |type|
Expand Down
2 changes: 1 addition & 1 deletion actionpack/lib/action_view/helpers/number_helper.rb
Expand Up @@ -140,7 +140,7 @@ def number_to_percentage(number, options = {})
# number_with_delimiter(12345678) # => 12,345,678
# number_with_delimiter(12345678.05) # => 12,345,678.05
# number_with_delimiter(12345678, :delimiter => ".") # => 12.345.678
# number_with_delimiter(12345678, :seperator => ",") # => 12,345,678
# number_with_delimiter(12345678, :separator => ",") # => 12,345,678
# number_with_delimiter(98765432.98, :delimiter => " ", :separator => ",")
# # => 98 765 432,98
#
Expand Down
2 changes: 1 addition & 1 deletion activemodel/lib/active_model/validations/inclusion.rb
Expand Up @@ -4,7 +4,7 @@ module ClassMethods
# Validates whether the value of the specified attribute is available in a particular enumerable object.
#
# class Person < ActiveRecord::Base
# validates_inclusion_of :gender, :in => %w( m f ), :message => "woah! what are you then!??!!"
# validates_inclusion_of :gender, :in => %w( m f )
# validates_inclusion_of :age, :in => 0..99
# validates_inclusion_of :format, :in => %w( jpg gif png ), :message => "extension %s is not included in the list"
# end
Expand Down
Expand Up @@ -143,6 +143,8 @@ def transaction(*args)
end

# Remove all records from this association
#
# See delete for more info.
def delete_all
load_target
delete(@target)
Expand Down Expand Up @@ -200,11 +202,11 @@ def delete(*records)
end
end

# Destroy +records+ and remove from this association calling +before_remove+
# and +after_remove+ callbacks.
# Destroy +records+ and remove them from this association calling
# +before_remove+ and +after_remove+ callbacks.
#
# Note this method will always remove records from database ignoring the
# +:dependent+ option.
# Note that this method will _always_ remove records from the database
# ignoring the +:dependent+ option.
def destroy(*records)
remove_records(records) do |records, old_records|
old_records.each { |record| record.destroy }
Expand All @@ -226,7 +228,9 @@ def clear
self
end

# Destory all the records from this association
# Destory all the records from this association.
#
# See destroy for more info.
def destroy_all
load_target
destroy(@target)
Expand Down
4 changes: 2 additions & 2 deletions activerecord/lib/active_record/base.rb
Expand Up @@ -736,12 +736,12 @@ def create(attributes = nil, &block)
# ==== Parameters
#
# * +id+ - This should be the id or an array of ids to be updated.
# * +attributes+ - This should be a Hash of attributes to be set on the object, or an array of Hashes.
# * +attributes+ - This should be a hash of attributes to be set on the object, or an array of hashes.
#
# ==== Examples
#
# # Updating one record:
# Person.update(15, { :user_name => 'Samuel', :group => 'expert' })
# Person.update(15, :user_name => 'Samuel', :group => 'expert')
#
# # Updating multiple records:
# people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
Expand Down
38 changes: 23 additions & 15 deletions activerecord/lib/active_record/batches.rb
Expand Up @@ -4,20 +4,23 @@ def self.included(base)
base.extend(ClassMethods)
end

# When processing large numbers of records, it's often a good idea to do so in batches to prevent memory ballooning.
# When processing large numbers of records, it's often a good idea to do
# so in batches to prevent memory ballooning.
module ClassMethods
# Yields each record that was found by the find +options+. The find is performed by find_in_batches
# with a batch size of 1000 (or as specified by the +batch_size+ option).
# Yields each record that was found by the find +options+. The find is
# performed by find_in_batches with a batch size of 1000 (or as
# specified by the <tt>:batch_size</tt> option).
#
# Example:
#
# Person.find_each(:conditions => "age > 21") do |person|
# person.party_all_night!
# end
#
# Note: This method is only intended to use for batch processing of large amounts of records that wouldn't fit in
# memory all at once. If you just need to loop over less than 1000 records, it's probably better just to use the
# regular find methods.
# Note: This method is only intended to use for batch processing of
# large amounts of records that wouldn't fit in memory all at once. If
# you just need to loop over less than 1000 records, it's probably
# better just to use the regular find methods.
def find_each(options = {})
find_in_batches(options) do |records|
records.each { |record| yield record }
Expand All @@ -26,17 +29,22 @@ def find_each(options = {})
self
end

# Yields each batch of records that was found by the find +options+ as an array. The size of each batch is
# set by the +batch_size+ option; the default is 1000.
# Yields each batch of records that was found by the find +options+ as
# an array. The size of each batch is set by the <tt>:batch_size</tt>
# option; the default is 1000.
#
# You can control the starting point for the batch processing by supplying the +start+ option. This is especially
# useful if you want multiple workers dealing with the same processing queue. You can make worker 1 handle all the
# records between id 0 and 10,000 and worker 2 handle from 10,000 and beyond (by setting the +start+ option on that
# worker).
# You can control the starting point for the batch processing by
# supplying the <tt>:start</tt> option. This is especially useful if you
# want multiple workers dealing with the same processing queue. You can
# make worker 1 handle all the records between id 0 and 10,000 and
# worker 2 handle from 10,000 and beyond (by setting the <tt>:start</tt>
# option on that worker).
#
# It's not possible to set the order. That is automatically set to ascending on the primary key ("id ASC")
# to make the batch ordering work. This also mean that this method only works with integer-based primary keys.
# You can't set the limit either, that's used to control the the batch sizes.
# It's not possible to set the order. That is automatically set to
# ascending on the primary key ("id ASC") to make the batch ordering
# work. This also mean that this method only works with integer-based
# primary keys. You can't set the limit either, that's used to control
# the the batch sizes.
#
# Example:
#
Expand Down
2 changes: 1 addition & 1 deletion activerecord/lib/active_record/validations.rb
Expand Up @@ -802,7 +802,7 @@ def validates_format_of(*attr_names)
# Validates whether the value of the specified attribute is available in a particular enumerable object.
#
# class Person < ActiveRecord::Base
# validates_inclusion_of :gender, :in => %w( m f ), :message => "woah! what are you then!??!!"
# validates_inclusion_of :gender, :in => %w( m f )
# validates_inclusion_of :age, :in => 0..99
# validates_inclusion_of :format, :in => %w( jpg gif png ), :message => "extension {{value}} is not included in the list"
# end
Expand Down
@@ -1,7 +1,7 @@
module ActiveSupport #:nodoc:
module CoreExtensions #:nodoc:
module Date #:nodoc:
# Enables the use of time calculations within Time itself
# Enables the use of time calculations within Date itself
module Calculations
def self.included(base) #:nodoc:
base.extend ClassMethods
Expand Down
16 changes: 14 additions & 2 deletions railties/guides/files/stylesheets/main.css
Expand Up @@ -337,7 +337,7 @@ h6 {
margin-top: 0.25em;
}

#mainCol dd.warning, #subCol dd.warning {
#mainCol div.warning, #subCol dd.warning {
background: #f9d9d8 url(../../images/tab_red.gif) no-repeat left top;
border: none;
padding: 1.25em 1.25em 1.25em 48px;
Expand Down Expand Up @@ -426,4 +426,16 @@ code {
.clearfix {display: inline-block;}
* html .clearfix {height: 1%;}
.clearfix {display: block;}
.clear { clear:both; }
.clear { clear:both; }

/* Same bottom margin for special boxes than for regular paragraphs, this way
intermediate whitespace looks uniform. */
div.code_container, div.important, div.caution, div.warning, div.note, div.info {
margin-bottom: 1.5em;
}

/* Remove bottom margin of paragraphs in special boxes, otherwise they get a
spurious blank area below with the box background. */
div.important p, div.caution p, div.warning p, div.note p, div.info p {
margin-bottom: 0px;
}
Binary file modified railties/guides/images/error_messages.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added railties/guides/images/fxn.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified railties/guides/images/i18n/demo_localized_pirate.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified railties/guides/images/i18n/demo_translated_en.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified railties/guides/images/i18n/demo_translated_pirate.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified railties/guides/images/i18n/demo_translation_missing.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified railties/guides/images/i18n/demo_untranslated.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions railties/guides/rails_guides.rb
Expand Up @@ -22,6 +22,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)
Expand Down
36 changes: 27 additions & 9 deletions railties/guides/rails_guides/generator.rb
Expand Up @@ -109,8 +109,8 @@ def set_index(body, view)
end

def textile(body)
# If the issue with nontextile is fixed just remove the wrapper.
with_workaround_for_nontextile(body) do |body|
# If the issue with notextile is fixed just remove the wrapper.
with_workaround_for_notextile(body) do |body|
t = RedCloth.new(body)
t.hard_breaks = false
t.to_html(:notestuff, :plusplus, :code, :tip)
Expand All @@ -120,33 +120,51 @@ def textile(body)
# For some reason the notextile tag does not always turn off textile. See
# LH ticket of the security guide (#7). As a temporary workaround we deal
# with code blocks by hand.
def with_workaround_for_nontextile(body)
def with_workaround_for_notextile(body)
code_blocks = []
body.gsub!(%r{<(yaml|shell|ruby|erb|html|sql|plain)>(.*?)</\1>}m) do |m|
es = ERB::Util.h($2)
css_class = ['erb', 'shell'].include?($1) ? 'html' : $1
code_blocks << %{<div class="code_container"><code class="#{css_class}">#{es}</code></div>}
"dirty_workaround_for_nontextile_#{code_blocks.size - 1}"
"\ndirty_workaround_for_notextile_#{code_blocks.size - 1}\n"
end

body = yield body

body.gsub(%r{<p>dirty_workaround_for_nontextile_(\d+)</p>}) do |_|
body.gsub(%r{<p>dirty_workaround_for_notextile_(\d+)</p>}) do |_|
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)
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"
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)

# Check fragment identifiers.
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)
puts "BROKEN LINK: ##{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
Expand Down
2 changes: 1 addition & 1 deletion railties/guides/rails_guides/indexer.rb
Expand Up @@ -29,7 +29,7 @@ def process(string, current_level= 3, counters = [1])
return level_hash
elsif level == current_level
index = counters.join(".")
bookmark = '#' + title.gsub(/[^a-z0-9\-_]+/i, '').underscore.dasherize
bookmark = '#' + title.strip.downcase.gsub(/\s+|_/, '-').delete('^a-z0-9-')

raise "Parsing Fail" unless @result.sub!(matched, "h#{level}(#{bookmark}). #{index}#{title}")

Expand Down
112 changes: 112 additions & 0 deletions railties/guides/rails_guides/levenshtein.rb
@@ -0,0 +1,112 @@
#
# Levenshtein distance algorithm implementation for Ruby, with UTF-8 support
#
# Author:: Paul BATTLEY (pbattley @ gmail.com)
# Version:: 1.3
# Date:: 2005-04-19
#
# == About
#
# The Levenshtein distance is a measure of how similar two strings s and t are,
# calculated as the number of deletions/insertions/substitutions needed to
# transform s into t. The greater the distance, the more the strings differ.
#
# The Levenshtein distance is also sometimes referred to as the
# easier-to-pronounce-and-spell 'edit distance'.
#
# == Revision history
#
# * 2005-05-19 1.3 Repairing an oversight, distance can now be called via
# Levenshtein.distance(s, t)
# * 2005-05-04 1.2 Now uses just one 1-dimensional array. I think this is as
# far as optimisation can go.
# * 2005-05-04 1.1 Now storing only the current and previous rows of the matrix
# instead of the whole lot.
#
# == Licence
#
# Copyright (c) 2005 Paul Battley
#
# Usage of the works is permitted provided that this instrument is retained
# with the works, so that any entity that uses the works is notified of this
# instrument.
#
# DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.
#

module Levenshtein

#
# Calculate the Levenshtein distance between two strings +str1+ and +str2+.
# +str1+ and +str2+ should be ASCII or UTF-8.
#
def distance(str1, str2)
s = str1.unpack('U*')
t = str2.unpack('U*')
n = s.length
m = t.length
return m if (0 == n)
return n if (0 == m)

d = (0..m).to_a
x = nil

(0...n).each do |i|
e = i+1
(0...m).each do |j|
cost = (s[i] == t[j]) ? 0 : 1
x = [
d[j+1] + 1, # insertion
e + 1, # deletion
d[j] + cost # substitution
].min
d[j] = e
e = x
end
d[m] = x
end

return x
end

extend self
end

if (__FILE__ == $0)
require 'test/unit'

class LevenshteinTest < Test::Unit::TestCase
include Levenshtein

EXPECTED = [
# Easy ones
['test', 'test', 0],
['test', 'tent', 1],
['gumbo', 'gambol', 2],
['kitten', 'sitting', 3],
# Empty strings
['foo', '', 3],
['', '', 0],
['a', '', 1],
# UTF-8
["f\303\266o", 'foo', 1],
["fran\303\247ais", 'francais', 1],
["fran\303\247ais", "fran\303\246ais", 1],
["\347\247\201\343\201\256\345\220\215\345\211\215\343\201\257"<<
"\343\203\235\343\203\274\343\203\253\343\201\247\343\201\231",
"\343\201\274\343\201\217\343\201\256\345\220\215\345\211\215\343\201"<<
"\257\343\203\235\343\203\274\343\203\253\343\201\247\343\201\231",
2], # Japanese
# Edge cases
['a', 'a', 0],
['0123456789', 'abcdefghijklmnopqrstuvwxyz', 26]
]

def test_known_distances
EXPECTED.each do |a,b,x|
assert_equal(x, distance(a, b))
assert_equal(x, distance(b, a))
end
end
end
end

0 comments on commit 18eb80c

Please sign in to comment.