Merge branch 'master' of git@github.com:rails/rails
1
.gitignore
vendored
@ -14,6 +14,7 @@ railties/pkg
|
|||||||
railties/test/500.html
|
railties/test/500.html
|
||||||
railties/doc/guides/html/images
|
railties/doc/guides/html/images
|
||||||
railties/doc/guides/html/stylesheets
|
railties/doc/guides/html/stylesheets
|
||||||
|
railties/guides/output
|
||||||
*.rbc
|
*.rbc
|
||||||
*.swp
|
*.swp
|
||||||
*.swo
|
*.swo
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
*Edge*
|
||||||
|
|
||||||
|
* Fixed that ActionMailer should send correctly formatted Return-Path in MAIL FROM for SMTP #1842 [Matt Jones]
|
||||||
|
|
||||||
|
|
||||||
*2.3.0 [RC1] (February 1st, 2009)*
|
*2.3.0 [RC1] (February 1st, 2009)*
|
||||||
|
|
||||||
* Fixed RFC-2045 quoted-printable bug #1421 [squadette]
|
* Fixed RFC-2045 quoted-printable bug #1421 [squadette]
|
||||||
|
@ -672,7 +672,7 @@ def create_mail
|
|||||||
def perform_delivery_smtp(mail)
|
def perform_delivery_smtp(mail)
|
||||||
destinations = mail.destinations
|
destinations = mail.destinations
|
||||||
mail.ready_to_send
|
mail.ready_to_send
|
||||||
sender = mail['return-path'] || mail.from
|
sender = (mail['return-path'] && mail['return-path'].spec) || mail.from
|
||||||
|
|
||||||
smtp = Net::SMTP.new(smtp_settings[:address], smtp_settings[:port])
|
smtp = Net::SMTP.new(smtp_settings[:address], smtp_settings[:port])
|
||||||
smtp.enable_starttls_auto if smtp_settings[:enable_starttls_auto] && smtp.respond_to?(:enable_starttls_auto)
|
smtp.enable_starttls_auto if smtp_settings[:enable_starttls_auto] && smtp.respond_to?(:enable_starttls_auto)
|
||||||
|
@ -938,6 +938,7 @@ def test_return_path_with_deliver
|
|||||||
ActionMailer::Base.delivery_method = :smtp
|
ActionMailer::Base.delivery_method = :smtp
|
||||||
TestMailer.deliver_return_path
|
TestMailer.deliver_return_path
|
||||||
assert_match %r{^Return-Path: <another@somewhere.test>}, MockSMTP.deliveries[0][0]
|
assert_match %r{^Return-Path: <another@somewhere.test>}, MockSMTP.deliveries[0][0]
|
||||||
|
assert_equal "another@somewhere.test", MockSMTP.deliveries[0][1].to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_body_is_stored_as_an_ivar
|
def test_body_is_stored_as_an_ivar
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
*Edge*
|
*Edge*
|
||||||
|
|
||||||
|
* Fix a syntax error in current_page?() that was prevent matches against URL's with multiple query parameters #1385, #1868 [chris finne/Andrew White]
|
||||||
|
|
||||||
* Added localized rescue template when I18n.locale is set (ex: public/404.da.html) #1835 [José Valim]
|
* Added localized rescue template when I18n.locale is set (ex: public/404.da.html) #1835 [José Valim]
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ def define_dispatcher_callbacks(cache_classes)
|
|||||||
unless cache_classes
|
unless cache_classes
|
||||||
# Development mode callbacks
|
# Development mode callbacks
|
||||||
before_dispatch :reload_application
|
before_dispatch :reload_application
|
||||||
after_dispatch :cleanup_application
|
|
||||||
|
|
||||||
ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false
|
ActionView::Helpers::AssetTagHelper.cache_asset_timestamps = false
|
||||||
end
|
end
|
||||||
@ -93,11 +92,9 @@ def reload_application
|
|||||||
run_callbacks :prepare_dispatch
|
run_callbacks :prepare_dispatch
|
||||||
|
|
||||||
Routing::Routes.reload
|
Routing::Routes.reload
|
||||||
end
|
|
||||||
|
|
||||||
# Cleanup the application by clearing out loaded classes so they can
|
# Cleanup the application by clearing out loaded classes so they can
|
||||||
# be reloaded on the next request without restarting the server.
|
# be reloaded on the next request without restarting the server.
|
||||||
def cleanup_application
|
|
||||||
ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord)
|
ActiveRecord::Base.reset_subclasses if defined?(ActiveRecord)
|
||||||
ActiveSupport::Dependencies.clear
|
ActiveSupport::Dependencies.clear
|
||||||
ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord)
|
ActiveRecord::Base.clear_reloadable_connections! if defined?(ActiveRecord)
|
||||||
|
@ -173,7 +173,7 @@ def layout_conditions #:nodoc:
|
|||||||
end
|
end
|
||||||
|
|
||||||
def default_layout(format) #:nodoc:
|
def default_layout(format) #:nodoc:
|
||||||
layout = read_inheritable_attribute(:layout)
|
layout = read_inheritable_attribute(:layout) unless format == :js
|
||||||
return layout unless read_inheritable_attribute(:auto_layout)
|
return layout unless read_inheritable_attribute(:auto_layout)
|
||||||
find_layout(layout, format)
|
find_layout(layout, format)
|
||||||
end
|
end
|
||||||
|
@ -58,9 +58,28 @@ def loaded?
|
|||||||
end
|
end
|
||||||
|
|
||||||
def load!
|
def load!
|
||||||
@id, session = @by.send(:load_session, @env)
|
stale_session_check! do
|
||||||
replace(session)
|
@id, session = @by.send(:load_session, @env)
|
||||||
@loaded = true
|
replace(session)
|
||||||
|
@loaded = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def stale_session_check!
|
||||||
|
yield
|
||||||
|
rescue ArgumentError => argument_error
|
||||||
|
if argument_error.message =~ %r{undefined class/module ([\w:]*\w)}
|
||||||
|
begin
|
||||||
|
# Note that the regexp does not allow $1 to end with a ':'
|
||||||
|
$1.constantize
|
||||||
|
rescue LoadError, NameError => const_error
|
||||||
|
raise ActionController::SessionRestoreError, "Session contains objects whose class definition isn\\'t available.\nRemember to require the classes for all objects kept in the session.\n(Original exception: \#{const_error.message} [\#{const_error.class}])\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
retry
|
||||||
|
else
|
||||||
|
raise
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -516,7 +516,8 @@ def self.cache_asset_timestamps=(value)
|
|||||||
def compute_public_path(source, dir, ext = nil, include_host = true)
|
def compute_public_path(source, dir, ext = nil, include_host = true)
|
||||||
has_request = @controller.respond_to?(:request)
|
has_request = @controller.respond_to?(:request)
|
||||||
|
|
||||||
if ext && (File.extname(source).blank? || File.exist?(File.join(ASSETS_DIR, dir, "#{source}.#{ext}")))
|
source_ext = File.extname(source)[1..-1]
|
||||||
|
if ext && (source_ext.blank? || (ext != source_ext && File.exist?(File.join(ASSETS_DIR, dir, "#{source}.#{ext}"))))
|
||||||
source += ".#{ext}"
|
source += ".#{ext}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ module AtomFeedHelper
|
|||||||
# app/views/posts/index.atom.builder:
|
# app/views/posts/index.atom.builder:
|
||||||
# atom_feed do |feed|
|
# atom_feed do |feed|
|
||||||
# feed.title("My great blog!")
|
# feed.title("My great blog!")
|
||||||
# feed.updated((@posts.first.created_at))
|
# feed.updated(@posts.first.created_at)
|
||||||
#
|
#
|
||||||
# for post in @posts
|
# for post in @posts
|
||||||
# feed.entry(post) do |entry|
|
# feed.entry(post) do |entry|
|
||||||
|
@ -971,7 +971,8 @@ def fields_for_with_nested_attributes(association_name, args, block)
|
|||||||
@template.fields_for(child_name, child, *args, &block)
|
@template.fields_for(child_name, child, *args, &block)
|
||||||
end.join
|
end.join
|
||||||
else
|
else
|
||||||
@template.fields_for(name, association, *args, &block)
|
object = args.first.respond_to?(:new_record?) ? args.first : association
|
||||||
|
@template.fields_for(name, object, *args, &block)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -507,7 +507,30 @@ def mail_to(email_address, name = nil, html_options = {})
|
|||||||
# current_page?(:controller => 'shop', :action => 'checkout')
|
# current_page?(:controller => 'shop', :action => 'checkout')
|
||||||
# # => true
|
# # => true
|
||||||
#
|
#
|
||||||
# current_page?(:controller => 'shop', :action => 'checkout', :order => 'asc)
|
# current_page?(:controller => 'shop', :action => 'checkout', :order => 'asc')
|
||||||
|
# # => false
|
||||||
|
#
|
||||||
|
# current_page?(:action => 'checkout')
|
||||||
|
# # => true
|
||||||
|
#
|
||||||
|
# current_page?(:controller => 'library', :action => 'checkout')
|
||||||
|
# # => false
|
||||||
|
#
|
||||||
|
# Let's say we're in the <tt>/shop/checkout?order=desc&page=1</tt> action.
|
||||||
|
#
|
||||||
|
# current_page?(:action => 'process')
|
||||||
|
# # => false
|
||||||
|
#
|
||||||
|
# current_page?(:controller => 'shop', :action => 'checkout')
|
||||||
|
# # => true
|
||||||
|
#
|
||||||
|
# current_page?(:controller => 'shop', :action => 'checkout', :order => 'desc', :page=>'1')
|
||||||
|
# # => true
|
||||||
|
#
|
||||||
|
# current_page?(:controller => 'shop', :action => 'checkout', :order => 'desc', :page=>'2')
|
||||||
|
# # => false
|
||||||
|
#
|
||||||
|
# current_page?(:controller => 'shop', :action => 'checkout', :order => 'desc')
|
||||||
# # => false
|
# # => false
|
||||||
#
|
#
|
||||||
# current_page?(:action => 'checkout')
|
# current_page?(:action => 'checkout')
|
||||||
@ -516,7 +539,7 @@ def mail_to(email_address, name = nil, html_options = {})
|
|||||||
# current_page?(:controller => 'library', :action => 'checkout')
|
# current_page?(:controller => 'library', :action => 'checkout')
|
||||||
# # => false
|
# # => false
|
||||||
def current_page?(options)
|
def current_page?(options)
|
||||||
url_string = CGI.escapeHTML(url_for(options))
|
url_string = CGI.unescapeHTML(url_for(options))
|
||||||
request = @controller.request
|
request = @controller.request
|
||||||
# We ignore any extra parameters in the request_uri if the
|
# We ignore any extra parameters in the request_uri if the
|
||||||
# submitted url doesn't have any either. This lets the function
|
# submitted url doesn't have any either. This lets the function
|
||||||
|
@ -2,7 +2,11 @@ module ActionView #:nodoc:
|
|||||||
class PathSet < Array #:nodoc:
|
class PathSet < Array #:nodoc:
|
||||||
def self.type_cast(obj)
|
def self.type_cast(obj)
|
||||||
if obj.is_a?(String)
|
if obj.is_a?(String)
|
||||||
Template::EagerPath.new(obj)
|
if !Object.const_defined?(:Rails) || Rails.configuration.cache_classes
|
||||||
|
Template::EagerPath.new(obj)
|
||||||
|
else
|
||||||
|
Template::Path.new(obj)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
obj
|
obj
|
||||||
end
|
end
|
||||||
|
@ -277,6 +277,9 @@ def render_explicit_html_template
|
|||||||
def render_implicit_html_template_from_xhr_request
|
def render_implicit_html_template_from_xhr_request
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def render_implicit_js_template_without_layout
|
||||||
|
end
|
||||||
|
|
||||||
def formatted_html_erb
|
def formatted_html_erb
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -681,7 +684,8 @@ def determine_layout
|
|||||||
"render_with_explicit_string_template",
|
"render_with_explicit_string_template",
|
||||||
"render_js_with_explicit_template",
|
"render_js_with_explicit_template",
|
||||||
"render_js_with_explicit_action_template",
|
"render_js_with_explicit_action_template",
|
||||||
"delete_with_js", "update_page", "update_page_with_instance_variables"
|
"delete_with_js", "update_page", "update_page_with_instance_variables",
|
||||||
|
"render_implicit_js_template_without_layout"
|
||||||
|
|
||||||
"layouts/standard"
|
"layouts/standard"
|
||||||
when "action_talk_to_layout", "layout_overriding_layout"
|
when "action_talk_to_layout", "layout_overriding_layout"
|
||||||
@ -1018,6 +1022,11 @@ def test_should_implicitly_render_html_template_from_xhr_request
|
|||||||
assert_equal "Hello HTML!", @response.body
|
assert_equal "Hello HTML!", @response.body
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_should_implicitly_render_js_template_without_layout
|
||||||
|
get :render_implicit_js_template_without_layout, :format => :js
|
||||||
|
assert_no_match /<html>/, @response.body
|
||||||
|
end
|
||||||
|
|
||||||
def test_should_render_formatted_template
|
def test_should_render_formatted_template
|
||||||
get :formatted_html_erb
|
get :formatted_html_erb
|
||||||
assert_equal 'formatted html erb', @response.body
|
assert_equal 'formatted html erb', @response.body
|
||||||
|
1
actionpack/test/fixtures/test/render_implicit_js_template_without_layout.js.erb
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
alert('hello');
|
@ -586,6 +586,15 @@ def test_nested_fields_for_with_a_new_record_on_a_nested_attributes_one_to_one_a
|
|||||||
assert_dom_equal expected, output_buffer
|
assert_dom_equal expected, output_buffer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_nested_fields_for_with_explicitly_passed_object_on_a_nested_attributes_one_to_one_association
|
||||||
|
form_for(:post, @post) do |f|
|
||||||
|
f.fields_for(:author, Author.new(123)) do |af|
|
||||||
|
assert_not_nil af.object
|
||||||
|
assert_equal 123, af.object.id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_nested_fields_for_with_an_existing_record_on_a_nested_attributes_one_to_one_association
|
def test_nested_fields_for_with_an_existing_record_on_a_nested_attributes_one_to_one_association
|
||||||
@post.author = Author.new(321)
|
@post.author = Author.new(321)
|
||||||
|
|
||||||
|
@ -252,6 +252,27 @@ def test_link_to_if
|
|||||||
assert_equal "Showing", link_to_if(false, "Showing", :action => "show", :controller => "weblog", :id => 1)
|
assert_equal "Showing", link_to_if(false, "Showing", :action => "show", :controller => "weblog", :id => 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_current_page_with_simple_url
|
||||||
|
@controller.request = RequestMock.new("http://www.example.com/weblog/show")
|
||||||
|
@controller.url = "http://www.example.com/weblog/show"
|
||||||
|
assert current_page?({ :action => "show", :controller => "weblog" })
|
||||||
|
assert current_page?("http://www.example.com/weblog/show")
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_current_page_ignoring_params
|
||||||
|
@controller.request = RequestMock.new("http://www.example.com/weblog/show?order=desc&page=1")
|
||||||
|
@controller.url = "http://www.example.com/weblog/show?order=desc&page=1"
|
||||||
|
assert current_page?({ :action => "show", :controller => "weblog" })
|
||||||
|
assert current_page?("http://www.example.com/weblog/show")
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_current_page_with_params_that_match
|
||||||
|
@controller.request = RequestMock.new("http://www.example.com/weblog/show?order=desc&page=1")
|
||||||
|
@controller.url = "http://www.example.com/weblog/show?order=desc&page=1"
|
||||||
|
assert current_page?({ :action => "show", :controller => "weblog", :order => "desc", :page => "1" })
|
||||||
|
assert current_page?("http://www.example.com/weblog/show?order=desc&page=1")
|
||||||
|
end
|
||||||
|
|
||||||
def test_link_unless_current
|
def test_link_unless_current
|
||||||
@controller.request = RequestMock.new("http://www.example.com/weblog/show")
|
@controller.request = RequestMock.new("http://www.example.com/weblog/show")
|
||||||
@controller.url = "http://www.example.com/weblog/show"
|
@controller.url = "http://www.example.com/weblog/show"
|
||||||
@ -263,11 +284,23 @@ def test_link_unless_current
|
|||||||
assert_equal "Showing", link_to_unless_current("Showing", { :action => "show", :controller => "weblog" })
|
assert_equal "Showing", link_to_unless_current("Showing", { :action => "show", :controller => "weblog" })
|
||||||
assert_equal "Showing", link_to_unless_current("Showing", "http://www.example.com/weblog/show")
|
assert_equal "Showing", link_to_unless_current("Showing", "http://www.example.com/weblog/show")
|
||||||
|
|
||||||
|
@controller.request = RequestMock.new("http://www.example.com/weblog/show?order=desc&page=1")
|
||||||
|
@controller.url = "http://www.example.com/weblog/show?order=desc&page=1"
|
||||||
|
assert_equal "Showing", link_to_unless_current("Showing", { :action => "show", :controller => "weblog", :order=>'desc', :page=>'1' })
|
||||||
|
assert_equal "Showing", link_to_unless_current("Showing", "http://www.example.com/weblog/show?order=desc&page=1")
|
||||||
|
assert_equal "Showing", link_to_unless_current("Showing", "http://www.example.com/weblog/show?order=desc&page=1")
|
||||||
|
|
||||||
@controller.request = RequestMock.new("http://www.example.com/weblog/show?order=desc")
|
@controller.request = RequestMock.new("http://www.example.com/weblog/show?order=desc")
|
||||||
@controller.url = "http://www.example.com/weblog/show?order=asc"
|
@controller.url = "http://www.example.com/weblog/show?order=asc"
|
||||||
assert_equal "<a href=\"http://www.example.com/weblog/show?order=asc\">Showing</a>", link_to_unless_current("Showing", { :action => "show", :controller => "weblog" })
|
assert_equal "<a href=\"http://www.example.com/weblog/show?order=asc\">Showing</a>", link_to_unless_current("Showing", { :action => "show", :controller => "weblog" })
|
||||||
assert_equal "<a href=\"http://www.example.com/weblog/show?order=asc\">Showing</a>", link_to_unless_current("Showing", "http://www.example.com/weblog/show?order=asc")
|
assert_equal "<a href=\"http://www.example.com/weblog/show?order=asc\">Showing</a>", link_to_unless_current("Showing", "http://www.example.com/weblog/show?order=asc")
|
||||||
|
|
||||||
|
@controller.request = RequestMock.new("http://www.example.com/weblog/show?order=desc&page=1")
|
||||||
|
@controller.url = "http://www.example.com/weblog/show?order=desc&page=2"
|
||||||
|
assert_equal "<a href=\"http://www.example.com/weblog/show?order=desc&page=2\">Showing</a>", link_to_unless_current("Showing", { :action => "show", :controller => "weblog" })
|
||||||
|
assert_equal "<a href=\"http://www.example.com/weblog/show?order=desc&page=2\">Showing</a>", link_to_unless_current("Showing", "http://www.example.com/weblog/show?order=desc&page=2")
|
||||||
|
|
||||||
|
|
||||||
@controller.request = RequestMock.new("http://www.example.com/weblog/show")
|
@controller.request = RequestMock.new("http://www.example.com/weblog/show")
|
||||||
@controller.url = "http://www.example.com/weblog/list"
|
@controller.url = "http://www.example.com/weblog/list"
|
||||||
assert_equal "<a href=\"http://www.example.com/weblog/list\">Listing</a>",
|
assert_equal "<a href=\"http://www.example.com/weblog/list\">Listing</a>",
|
||||||
@ -319,7 +352,7 @@ def test_mail_to_with_replace_options
|
|||||||
assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", "My email", :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)")
|
assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%4d%79%20%65%6d%61%69%6c%3c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", "My email", :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)")
|
||||||
assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%6d%65%28%61%74%29%64%6f%6d%61%69%6e%28%64%6f%74%29%63%6f%6d%3c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", nil, :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)")
|
assert_dom_equal "<script type=\"text/javascript\">eval(decodeURIComponent('%64%6f%63%75%6d%65%6e%74%2e%77%72%69%74%65%28%27%3c%61%20%68%72%65%66%3d%22%6d%61%69%6c%74%6f%3a%6d%65%40%64%6f%6d%61%69%6e%2e%63%6f%6d%22%3e%6d%65%28%61%74%29%64%6f%6d%61%69%6e%28%64%6f%74%29%63%6f%6d%3c%2f%61%3e%27%29%3b'))</script>", mail_to("me@domain.com", nil, :encode => "javascript", :replace_at => "(at)", :replace_dot => "(dot)")
|
||||||
end
|
end
|
||||||
|
|
||||||
def protect_against_forgery?
|
def protect_against_forgery?
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
*Edge*
|
||||||
|
|
||||||
|
* Added that ActiveRecord::Base.exists? can be called with no arguments #1817 [Scott Taylor]
|
||||||
|
|
||||||
|
|
||||||
*2.3.0 [RC1] (February 1st, 2009)*
|
*2.3.0 [RC1] (February 1st, 2009)*
|
||||||
|
|
||||||
* Add Support for updating deeply nested models from a single form. #1202 [Eloy Duran]
|
* Add Support for updating deeply nested models from a single form. #1202 [Eloy Duran]
|
||||||
|
@ -1090,6 +1090,22 @@ def belongs_to(association_id, options = {})
|
|||||||
# but it in fact generates a join table name of "paper_boxes_papers". Be aware of this caveat, and use the
|
# but it in fact generates a join table name of "paper_boxes_papers". Be aware of this caveat, and use the
|
||||||
# custom <tt>:join_table</tt> option if you need to.
|
# custom <tt>:join_table</tt> option if you need to.
|
||||||
#
|
#
|
||||||
|
# The join table should not have a primary key or a model associated with it. You must manually generate the
|
||||||
|
# join table with a migration such as this:
|
||||||
|
#
|
||||||
|
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration
|
||||||
|
# def self.up
|
||||||
|
# create_table :developers_projects, :id => false do |t|
|
||||||
|
# t.integer :developer_id
|
||||||
|
# t.integer :project_id
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# def self.down
|
||||||
|
# drop_table :developers_projects
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
# Deprecated: Any additional fields added to the join table will be placed as attributes when pulling records out through
|
# Deprecated: Any additional fields added to the join table will be placed as attributes when pulling records out through
|
||||||
# +has_and_belongs_to_many+ associations. Records returned from join tables with additional attributes will be marked as
|
# +has_and_belongs_to_many+ associations. Records returned from join tables with additional attributes will be marked as
|
||||||
# readonly (because we can't save changes to the additional attributes). It's strongly recommended that you upgrade any
|
# readonly (because we can't save changes to the additional attributes). It's strongly recommended that you upgrade any
|
||||||
|
@ -324,6 +324,7 @@ def query_attribute(attr_name)
|
|||||||
if Numeric === value || value !~ /[^0-9]/
|
if Numeric === value || value !~ /[^0-9]/
|
||||||
!value.to_i.zero?
|
!value.to_i.zero?
|
||||||
else
|
else
|
||||||
|
return false if ActiveRecord::ConnectionAdapters::Column::FALSE_VALUES.include?(value)
|
||||||
!value.blank?
|
!value.blank?
|
||||||
end
|
end
|
||||||
elsif column.number?
|
elsif column.number?
|
||||||
|
@ -129,6 +129,7 @@ def self.included(base)
|
|||||||
base.class_eval do
|
base.class_eval do
|
||||||
alias_method_chain :reload, :autosave_associations
|
alias_method_chain :reload, :autosave_associations
|
||||||
alias_method_chain :save, :autosave_associations
|
alias_method_chain :save, :autosave_associations
|
||||||
|
alias_method_chain :save!, :autosave_associations
|
||||||
alias_method_chain :valid?, :autosave_associations
|
alias_method_chain :valid?, :autosave_associations
|
||||||
|
|
||||||
%w{ has_one belongs_to has_many has_and_belongs_to_many }.each do |type|
|
%w{ has_one belongs_to has_many has_and_belongs_to_many }.each do |type|
|
||||||
@ -161,6 +162,17 @@ def save_with_autosave_associations(perform_validation = true)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Attempts to save the record just like save_with_autosave_associations but
|
||||||
|
# will raise a RecordInvalid exception instead of returning false if the
|
||||||
|
# record is not valid.
|
||||||
|
def save_with_autosave_associations!
|
||||||
|
if valid_with_autosave_associations?
|
||||||
|
save_with_autosave_associations(false) || raise(RecordNotSaved)
|
||||||
|
else
|
||||||
|
raise RecordInvalid.new(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Returns whether or not the parent, <tt>self</tt>, and any loaded autosave associations are valid.
|
# Returns whether or not the parent, <tt>self</tt>, and any loaded autosave associations are valid.
|
||||||
def valid_with_autosave_associations?
|
def valid_with_autosave_associations?
|
||||||
if valid_without_autosave_associations?
|
if valid_without_autosave_associations?
|
||||||
|
@ -663,7 +663,7 @@ def find_by_sql(sql)
|
|||||||
|
|
||||||
|
|
||||||
# Returns true if a record exists in the table that matches the +id+ or
|
# Returns true if a record exists in the table that matches the +id+ or
|
||||||
# conditions given, or false otherwise. The argument can take four forms:
|
# conditions given, or false otherwise. The argument can take five forms:
|
||||||
#
|
#
|
||||||
# * Integer - Finds the record with this primary key.
|
# * Integer - Finds the record with this primary key.
|
||||||
# * String - Finds the record with a primary key corresponding to this
|
# * String - Finds the record with a primary key corresponding to this
|
||||||
@ -672,6 +672,7 @@ def find_by_sql(sql)
|
|||||||
# (such as <tt>['color = ?', 'red']</tt>).
|
# (such as <tt>['color = ?', 'red']</tt>).
|
||||||
# * Hash - Finds the record that matches these +find+-style conditions
|
# * Hash - Finds the record that matches these +find+-style conditions
|
||||||
# (such as <tt>{:color => 'red'}</tt>).
|
# (such as <tt>{:color => 'red'}</tt>).
|
||||||
|
# * No args - Returns false if the table is empty, true otherwise.
|
||||||
#
|
#
|
||||||
# For more information about specifying conditions as a Hash or Array,
|
# For more information about specifying conditions as a Hash or Array,
|
||||||
# see the Conditions section in the introduction to ActiveRecord::Base.
|
# see the Conditions section in the introduction to ActiveRecord::Base.
|
||||||
@ -685,7 +686,8 @@ def find_by_sql(sql)
|
|||||||
# Person.exists?('5')
|
# Person.exists?('5')
|
||||||
# Person.exists?(:name => "David")
|
# Person.exists?(:name => "David")
|
||||||
# Person.exists?(['name LIKE ?', "%#{query}%"])
|
# Person.exists?(['name LIKE ?', "%#{query}%"])
|
||||||
def exists?(id_or_conditions)
|
# Person.exists?
|
||||||
|
def exists?(id_or_conditions = {})
|
||||||
connection.select_all(
|
connection.select_all(
|
||||||
construct_finder_sql(
|
construct_finder_sql(
|
||||||
:select => "#{quoted_table_name}.#{primary_key}",
|
:select => "#{quoted_table_name}.#{primary_key}",
|
||||||
@ -1990,12 +1992,16 @@ def all_attributes_exists?(attribute_names)
|
|||||||
attribute_names.all? { |name| column_methods_hash.include?(name.to_sym) }
|
attribute_names.all? { |name| column_methods_hash.include?(name.to_sym) }
|
||||||
end
|
end
|
||||||
|
|
||||||
def attribute_condition(argument)
|
def attribute_condition(quoted_column_name, argument)
|
||||||
case argument
|
case argument
|
||||||
when nil then "IS ?"
|
when nil then "#{quoted_column_name} IS ?"
|
||||||
when Array, ActiveRecord::Associations::AssociationCollection, ActiveRecord::NamedScope::Scope then "IN (?)"
|
when Array, ActiveRecord::Associations::AssociationCollection, ActiveRecord::NamedScope::Scope then "#{quoted_column_name} IN (?)"
|
||||||
when Range then "BETWEEN ? AND ?"
|
when Range then if argument.exclude_end?
|
||||||
else "= ?"
|
"#{quoted_column_name} >= ? AND #{quoted_column_name} < ?"
|
||||||
|
else
|
||||||
|
"#{quoted_column_name} BETWEEN ? AND ?"
|
||||||
|
end
|
||||||
|
else "#{quoted_column_name} = ?"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2305,7 +2311,7 @@ def sanitize_sql_hash_for_conditions(attrs, table_name = quoted_table_name)
|
|||||||
table_name = connection.quote_table_name(table_name)
|
table_name = connection.quote_table_name(table_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
"#{table_name}.#{connection.quote_column_name(attr)} #{attribute_condition(value)}"
|
attribute_condition("#{table_name}.#{connection.quote_column_name(attr)}", value)
|
||||||
else
|
else
|
||||||
sanitize_sql_hash_for_conditions(value, connection.quote_table_name(attr.to_s))
|
sanitize_sql_hash_for_conditions(value, connection.quote_table_name(attr.to_s))
|
||||||
end
|
end
|
||||||
|
@ -8,6 +8,7 @@ module ConnectionAdapters #:nodoc:
|
|||||||
# An abstract definition of a column in a table.
|
# An abstract definition of a column in a table.
|
||||||
class Column
|
class Column
|
||||||
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE'].to_set
|
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE'].to_set
|
||||||
|
FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE'].to_set
|
||||||
|
|
||||||
module Format
|
module Format
|
||||||
ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/
|
ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/
|
||||||
|
@ -86,7 +86,8 @@ def self.included(base)
|
|||||||
# For each key in the hash that starts with the string 'new' a new model
|
# For each key in the hash that starts with the string 'new' a new model
|
||||||
# will be instantiated. When the proc given with the <tt>:reject_if</tt>
|
# will be instantiated. When the proc given with the <tt>:reject_if</tt>
|
||||||
# option evaluates to +false+ for a certain attribute hash no record will
|
# option evaluates to +false+ for a certain attribute hash no record will
|
||||||
# be built for that hash.
|
# be built for that hash. (Rejecting new records can alternatively be done
|
||||||
|
# by utilizing the <tt>'_delete'</tt> key. Scroll down for more info.)
|
||||||
#
|
#
|
||||||
# params = { 'member' => {
|
# params = { 'member' => {
|
||||||
# 'name' => 'joe', 'posts_attributes' => {
|
# 'name' => 'joe', 'posts_attributes' => {
|
||||||
@ -258,11 +259,14 @@ def should_destroy_nested_attributes_record?(allow_destroy, attributes)
|
|||||||
# If a <tt>:reject_if</tt> proc exists for this association, it will be
|
# If a <tt>:reject_if</tt> proc exists for this association, it will be
|
||||||
# called with the attributes as its argument. If the proc returns a truthy
|
# called with the attributes as its argument. If the proc returns a truthy
|
||||||
# value, the record is _not_ build.
|
# value, the record is _not_ build.
|
||||||
|
#
|
||||||
|
# Alternatively, you can specify the <tt>'_delete'</tt> key to _not_ build
|
||||||
|
# a record. See should_destroy_nested_attributes_record? for more info.
|
||||||
def build_new_nested_attributes_record(association_name, attributes)
|
def build_new_nested_attributes_record(association_name, attributes)
|
||||||
if reject_proc = self.class.reject_new_nested_attributes_procs[association_name]
|
if reject_proc = self.class.reject_new_nested_attributes_procs[association_name]
|
||||||
return if reject_proc.call(attributes)
|
return if reject_proc.call(attributes)
|
||||||
end
|
end
|
||||||
send(association_name).build(attributes)
|
send(association_name).build(attributes) unless should_destroy_nested_attributes_record?(true, attributes)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Assigns the attributes to the record specified by +id+. Or marks it for
|
# Assigns the attributes to the record specified by +id+. Or marks it for
|
||||||
|
@ -99,7 +99,7 @@ def self.find_by_session_id(*args)
|
|||||||
define_method(:session_id=) { |session_id| self.sessid = session_id }
|
define_method(:session_id=) { |session_id| self.sessid = session_id }
|
||||||
else
|
else
|
||||||
def self.find_by_session_id(session_id)
|
def self.find_by_session_id(session_id)
|
||||||
find :first, :conditions => ["session_id #{attribute_condition(session_id)}", session_id]
|
find :first, :conditions => {:session_id=>session_id}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -744,7 +744,7 @@ def validates_uniqueness_of(*attr_names)
|
|||||||
if scope = configuration[:scope]
|
if scope = configuration[:scope]
|
||||||
Array(scope).map do |scope_item|
|
Array(scope).map do |scope_item|
|
||||||
scope_value = record.send(scope_item)
|
scope_value = record.send(scope_item)
|
||||||
condition_sql << " AND #{record.class.quoted_table_name}.#{scope_item} #{attribute_condition(scope_value)}"
|
condition_sql << " AND " << attribute_condition("#{record.class.quoted_table_name}.#{scope_item}", scope_value)
|
||||||
condition_params << scope_value
|
condition_params << scope_value
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -56,6 +56,18 @@ def test_should_unserialize_attributes_for_frozen_records
|
|||||||
assert_equal myobj, topic.content
|
assert_equal myobj, topic.content
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_typecast_attribute_from_select_to_false
|
||||||
|
topic = Topic.create(:title => 'Budget')
|
||||||
|
topic = Topic.find(:first, :select => "topics.*, 1=2 as is_test")
|
||||||
|
assert !topic.is_test?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_typecast_attribute_from_select_to_true
|
||||||
|
topic = Topic.create(:title => 'Budget')
|
||||||
|
topic = Topic.find(:first, :select => "topics.*, 2=2 as is_test")
|
||||||
|
assert topic.is_test?
|
||||||
|
end
|
||||||
|
|
||||||
def test_kernel_methods_not_implemented_in_activerecord
|
def test_kernel_methods_not_implemented_in_activerecord
|
||||||
%w(test name display y).each do |method|
|
%w(test name display y).each do |method|
|
||||||
assert !ActiveRecord::Base.instance_method_already_implemented?(method), "##{method} is defined"
|
assert !ActiveRecord::Base.instance_method_already_implemented?(method), "##{method} is defined"
|
||||||
|
@ -169,6 +169,12 @@ def test_should_automatically_save_the_associated_model
|
|||||||
assert_equal 'The Vile Insanity', @pirate.reload.ship.name
|
assert_equal 'The Vile Insanity', @pirate.reload.ship.name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_should_automatically_save_bang_the_associated_model
|
||||||
|
@pirate.ship.name = 'The Vile Insanity'
|
||||||
|
@pirate.save!
|
||||||
|
assert_equal 'The Vile Insanity', @pirate.reload.ship.name
|
||||||
|
end
|
||||||
|
|
||||||
def test_should_automatically_validate_the_associated_model
|
def test_should_automatically_validate_the_associated_model
|
||||||
@pirate.ship.name = ''
|
@pirate.ship.name = ''
|
||||||
assert !@pirate.valid?
|
assert !@pirate.valid?
|
||||||
@ -245,6 +251,12 @@ def test_should_automatically_save_the_associated_model
|
|||||||
assert_equal 'Arr', @ship.reload.pirate.catchphrase
|
assert_equal 'Arr', @ship.reload.pirate.catchphrase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_should_automatically_save_bang_the_associated_model
|
||||||
|
@ship.pirate.catchphrase = 'Arr'
|
||||||
|
@ship.save!
|
||||||
|
assert_equal 'Arr', @ship.reload.pirate.catchphrase
|
||||||
|
end
|
||||||
|
|
||||||
def test_should_automatically_validate_the_associated_model
|
def test_should_automatically_validate_the_associated_model
|
||||||
@ship.pirate.catchphrase = ''
|
@ship.pirate.catchphrase = ''
|
||||||
assert !@ship.valid?
|
assert !@ship.valid?
|
||||||
@ -298,6 +310,14 @@ def test_should_automatically_save_the_associated_models
|
|||||||
assert_equal new_names, @pirate.reload.send(@association_name).map(&:name)
|
assert_equal new_names, @pirate.reload.send(@association_name).map(&:name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_should_automatically_save_bang_the_associated_models
|
||||||
|
new_names = ['Grace OMalley', 'Privateers Greed']
|
||||||
|
@pirate.send(@association_name).each_with_index { |child, i| child.name = new_names[i] }
|
||||||
|
|
||||||
|
@pirate.save!
|
||||||
|
assert_equal new_names, @pirate.reload.send(@association_name).map(&:name)
|
||||||
|
end
|
||||||
|
|
||||||
def test_should_automatically_validate_the_associated_models
|
def test_should_automatically_validate_the_associated_models
|
||||||
@pirate.send(@association_name).each { |child| child.name = '' }
|
@pirate.send(@association_name).each { |child| child.name = '' }
|
||||||
|
|
||||||
@ -347,7 +367,9 @@ def test_should_still_raise_an_ActiveRecordRecord_Invalid_exception_if_we_want_t
|
|||||||
def test_should_not_load_the_associated_models_if_they_were_not_loaded_yet
|
def test_should_not_load_the_associated_models_if_they_were_not_loaded_yet
|
||||||
assert_queries(1) { @pirate.catchphrase = 'Arr'; @pirate.save! }
|
assert_queries(1) { @pirate.catchphrase = 'Arr'; @pirate.save! }
|
||||||
|
|
||||||
assert_queries(2) do
|
@pirate.send(@association_name).class # hack to load the target
|
||||||
|
|
||||||
|
assert_queries(3) do
|
||||||
@pirate.catchphrase = 'Yarr'
|
@pirate.catchphrase = 'Yarr'
|
||||||
new_names = ['Grace OMalley', 'Privateers Greed']
|
new_names = ['Grace OMalley', 'Privateers Greed']
|
||||||
@pirate.send(@association_name).each_with_index { |child, i| child.name = new_names[i] }
|
@pirate.send(@association_name).each_with_index { |child, i| child.name = new_names[i] }
|
||||||
|
@ -26,6 +26,7 @@ class PostgresqlDataTypeTest < ActiveRecord::TestCase
|
|||||||
|
|
||||||
def setup
|
def setup
|
||||||
@connection = ActiveRecord::Base.connection
|
@connection = ActiveRecord::Base.connection
|
||||||
|
@connection.execute("set lc_monetary = 'C'")
|
||||||
|
|
||||||
@connection.execute("INSERT INTO postgresql_arrays (commission_by_quarter, nicknames) VALUES ( '{35000,21000,18000,17000}', '{foo,bar,baz}' )")
|
@connection.execute("INSERT INTO postgresql_arrays (commission_by_quarter, nicknames) VALUES ( '{35000,21000,18000,17000}', '{foo,bar,baz}' )")
|
||||||
@first_array = PostgresqlArray.find(1)
|
@first_array = PostgresqlArray.find(1)
|
||||||
|
@ -94,7 +94,16 @@ def test_exists
|
|||||||
|
|
||||||
assert_raise(NoMethodError) { Topic.exists?([1,2]) }
|
assert_raise(NoMethodError) { Topic.exists?([1,2]) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_exists_returns_true_with_one_record_and_no_args
|
||||||
|
assert Topic.exists?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_does_not_exist_with_empty_table_and_no_args_given
|
||||||
|
Topic.delete_all
|
||||||
|
assert !Topic.exists?
|
||||||
|
end
|
||||||
|
|
||||||
def test_exists_with_aggregate_having_three_mappings
|
def test_exists_with_aggregate_having_three_mappings
|
||||||
existing_address = customers(:david).address
|
existing_address = customers(:david).address
|
||||||
assert Customer.exists?(:address => existing_address)
|
assert Customer.exists?(:address => existing_address)
|
||||||
@ -298,6 +307,12 @@ def test_find_on_hash_conditions_with_range
|
|||||||
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :id => 2..3 }) }
|
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :id => 2..3 }) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_find_on_hash_conditions_with_end_exclusive_range
|
||||||
|
assert_equal [1,2,3], Topic.find(:all, :conditions => { :id => 1..3 }).map(&:id).sort
|
||||||
|
assert_equal [1,2], Topic.find(:all, :conditions => { :id => 1...3 }).map(&:id).sort
|
||||||
|
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(3, :conditions => { :id => 2...3 }) }
|
||||||
|
end
|
||||||
|
|
||||||
def test_find_on_hash_conditions_with_multiple_ranges
|
def test_find_on_hash_conditions_with_multiple_ranges
|
||||||
assert_equal [1,2,3], Comment.find(:all, :conditions => { :id => 1..3, :post_id => 1..2 }).map(&:id).sort
|
assert_equal [1,2,3], Comment.find(:all, :conditions => { :id => 1..3, :post_id => 1..2 }).map(&:id).sort
|
||||||
assert_equal [1], Comment.find(:all, :conditions => { :id => 1..1, :post_id => 1..10 }).map(&:id).sort
|
assert_equal [1], Comment.find(:all, :conditions => { :id => 1..1, :post_id => 1..10 }).map(&:id).sort
|
||||||
|
@ -233,6 +233,20 @@ def test_should_automatically_build_new_associated_models_for_each_entry_in_a_ha
|
|||||||
assert_equal 'Privateers Greed', @pirate.send(@association_name).last.name
|
assert_equal 'Privateers Greed', @pirate.send(@association_name).last.name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_should_remove_delete_key_from_arguments_hash_of_new_records
|
||||||
|
assert_nothing_raised ActiveRecord::UnknownAttributeError do
|
||||||
|
@pirate.send(association_setter, { 'new_1' => { '_delete' => '0' }})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_should_ignore_new_associated_records_with_truthy_delete_attribute
|
||||||
|
@pirate.send(@association_name).destroy_all
|
||||||
|
@pirate.reload.attributes = { association_getter => { 'new_1' => { :name => 'Grace OMalley' }, 'new_2' => { :name => 'Privateers Greed', '_delete' => '1' }}}
|
||||||
|
|
||||||
|
assert_equal 1, @pirate.send(@association_name).length
|
||||||
|
assert_equal 'Grace OMalley', @pirate.send(@association_name).first.name
|
||||||
|
end
|
||||||
|
|
||||||
def test_should_sort_the_hash_by_the_keys_before_building_new_associated_models
|
def test_should_sort_the_hash_by_the_keys_before_building_new_associated_models
|
||||||
attributes = ActiveSupport::OrderedHash.new
|
attributes = ActiveSupport::OrderedHash.new
|
||||||
attributes['new_123726353'] = { :name => 'Grace OMalley' }
|
attributes['new_123726353'] = { :name => 'Grace OMalley' }
|
||||||
|
@ -284,7 +284,7 @@ def transliterate(string)
|
|||||||
|
|
||||||
# The iconv transliteration code doesn't function correctly
|
# The iconv transliteration code doesn't function correctly
|
||||||
# on some platforms, but it's very fast where it does function.
|
# on some platforms, but it's very fast where it does function.
|
||||||
elsif "foo" != Inflector.transliterate("föö")
|
elsif "foo" != (Inflector.transliterate("föö") rescue nil)
|
||||||
undef_method :transliterate
|
undef_method :transliterate
|
||||||
def transliterate(string)
|
def transliterate(string)
|
||||||
string.mb_chars.normalize(:kd). # Decompose accented characters
|
string.mb_chars.normalize(:kd). # Decompose accented characters
|
||||||
|
@ -244,6 +244,11 @@ def copy_with_rewritten_ruby_path(src_file, dest_file)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
desc 'Generate guides (for authors), use ONLY=foo to process just "foo.textile"'
|
||||||
|
task :guides do
|
||||||
|
ruby "guides/rails_guides.rb"
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
# Generate documentation ------------------------------------------------------------------
|
# Generate documentation ------------------------------------------------------------------
|
||||||
|
|
||||||
|
188
railties/guides/files/javascripts/code_highlighter.js
Executable file
@ -0,0 +1,188 @@
|
|||||||
|
/* Unobtrustive Code Highlighter By Dan Webb 11/2005
|
||||||
|
Version: 0.4
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
Add a script tag for this script and any stylesets you need to use
|
||||||
|
to the page in question, add correct class names to CODE elements,
|
||||||
|
define CSS styles for elements. That's it!
|
||||||
|
|
||||||
|
Known to work on:
|
||||||
|
IE 5.5+ PC
|
||||||
|
Firefox/Mozilla PC/Mac
|
||||||
|
Opera 7.23 + PC
|
||||||
|
Safari 2
|
||||||
|
|
||||||
|
Known to degrade gracefully on:
|
||||||
|
IE5.0 PC
|
||||||
|
|
||||||
|
Note: IE5.0 fails due to the use of lookahead in some stylesets. To avoid script errors
|
||||||
|
in older browsers use expressions that use lookahead in string format when defining stylesets.
|
||||||
|
|
||||||
|
This script is inspired by star-light by entirely cunning Dean Edwards
|
||||||
|
http://dean.edwards.name/star-light/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// replace callback support for safari.
|
||||||
|
if ("a".replace(/a/, function() {return "b"}) != "b") (function(){
|
||||||
|
var default_replace = String.prototype.replace;
|
||||||
|
String.prototype.replace = function(search,replace){
|
||||||
|
// replace is not function
|
||||||
|
if(typeof replace != "function"){
|
||||||
|
return default_replace.apply(this,arguments)
|
||||||
|
}
|
||||||
|
var str = "" + this;
|
||||||
|
var callback = replace;
|
||||||
|
// search string is not RegExp
|
||||||
|
if(!(search instanceof RegExp)){
|
||||||
|
var idx = str.indexOf(search);
|
||||||
|
return (
|
||||||
|
idx == -1 ? str :
|
||||||
|
default_replace.apply(str,[search,callback(search, idx, str)])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
var reg = search;
|
||||||
|
var result = [];
|
||||||
|
var lastidx = reg.lastIndex;
|
||||||
|
var re;
|
||||||
|
while((re = reg.exec(str)) != null){
|
||||||
|
var idx = re.index;
|
||||||
|
var args = re.concat(idx, str);
|
||||||
|
result.push(
|
||||||
|
str.slice(lastidx,idx),
|
||||||
|
callback.apply(null,args).toString()
|
||||||
|
);
|
||||||
|
if(!reg.global){
|
||||||
|
lastidx += RegExp.lastMatch.length;
|
||||||
|
break
|
||||||
|
}else{
|
||||||
|
lastidx = reg.lastIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.push(str.slice(lastidx));
|
||||||
|
return result.join("")
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
var CodeHighlighter = { styleSets : new Array };
|
||||||
|
|
||||||
|
CodeHighlighter.addStyle = function(name, rules) {
|
||||||
|
// using push test to disallow older browsers from adding styleSets
|
||||||
|
if ([].push) this.styleSets.push({
|
||||||
|
name : name,
|
||||||
|
rules : rules,
|
||||||
|
ignoreCase : arguments[2] || false
|
||||||
|
})
|
||||||
|
|
||||||
|
function setEvent() {
|
||||||
|
// set highlighter to run on load (use LowPro if present)
|
||||||
|
if (typeof Event != 'undefined' && typeof Event.onReady == 'function')
|
||||||
|
return Event.onReady(CodeHighlighter.init.bind(CodeHighlighter));
|
||||||
|
|
||||||
|
var old = window.onload;
|
||||||
|
|
||||||
|
if (typeof window.onload != 'function') {
|
||||||
|
window.onload = function() { CodeHighlighter.init() };
|
||||||
|
} else {
|
||||||
|
window.onload = function() {
|
||||||
|
old();
|
||||||
|
CodeHighlighter.init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// only set the event when the first style is added
|
||||||
|
if (this.styleSets.length==1) setEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeHighlighter.init = function() {
|
||||||
|
if (!document.getElementsByTagName) return;
|
||||||
|
if ("a".replace(/a/, function() {return "b"}) != "b") return; // throw out Safari versions that don't support replace function
|
||||||
|
// throw out older browsers
|
||||||
|
|
||||||
|
var codeEls = document.getElementsByTagName("CODE");
|
||||||
|
// collect array of all pre elements
|
||||||
|
codeEls.filter = function(f) {
|
||||||
|
var a = new Array;
|
||||||
|
for (var i = 0; i < this.length; i++) if (f(this[i])) a[a.length] = this[i];
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
var rules = new Array;
|
||||||
|
rules.toString = function() {
|
||||||
|
// joins regexes into one big parallel regex
|
||||||
|
var exps = new Array;
|
||||||
|
for (var i = 0; i < this.length; i++) exps.push(this[i].exp);
|
||||||
|
return exps.join("|");
|
||||||
|
}
|
||||||
|
|
||||||
|
function addRule(className, rule) {
|
||||||
|
// add a replace rule
|
||||||
|
var exp = (typeof rule.exp != "string")?String(rule.exp).substr(1, String(rule.exp).length-2):rule.exp;
|
||||||
|
// converts regex rules to strings and chops of the slashes
|
||||||
|
rules.push({
|
||||||
|
className : className,
|
||||||
|
exp : "(" + exp + ")",
|
||||||
|
length : (exp.match(/(^|[^\\])\([^?]/g) || "").length + 1, // number of subexps in rule
|
||||||
|
replacement : rule.replacement || null
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse(text, ignoreCase) {
|
||||||
|
// main text parsing and replacement
|
||||||
|
return text.replace(new RegExp(rules, (ignoreCase)?"gi":"g"), function() {
|
||||||
|
var i = 0, j = 1, rule;
|
||||||
|
while (rule = rules[i++]) {
|
||||||
|
if (arguments[j]) {
|
||||||
|
// if no custom replacement defined do the simple replacement
|
||||||
|
if (!rule.replacement) return "<span class=\"" + rule.className + "\">" + arguments[0] + "</span>";
|
||||||
|
else {
|
||||||
|
// replace $0 with the className then do normal replaces
|
||||||
|
var str = rule.replacement.replace("$0", rule.className);
|
||||||
|
for (var k = 1; k <= rule.length - 1; k++) str = str.replace("$" + k, arguments[j + k]);
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
} else j+= rule.length;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function highlightCode(styleSet) {
|
||||||
|
// clear rules array
|
||||||
|
var parsed, clsRx = new RegExp("(\\s|^)" + styleSet.name + "(\\s|$)");
|
||||||
|
rules.length = 0;
|
||||||
|
|
||||||
|
// get stylable elements by filtering out all code elements without the correct className
|
||||||
|
var stylableEls = codeEls.filter(function(item) { return clsRx.test(item.className) });
|
||||||
|
|
||||||
|
// add style rules to parser
|
||||||
|
for (var className in styleSet.rules) addRule(className, styleSet.rules[className]);
|
||||||
|
|
||||||
|
|
||||||
|
// replace for all elements
|
||||||
|
for (var i = 0; i < stylableEls.length; i++) {
|
||||||
|
// EVIL hack to fix IE whitespace badness if it's inside a <pre>
|
||||||
|
if (/MSIE/.test(navigator.appVersion) && stylableEls[i].parentNode.nodeName == 'PRE') {
|
||||||
|
stylableEls[i] = stylableEls[i].parentNode;
|
||||||
|
|
||||||
|
parsed = stylableEls[i].innerHTML.replace(/(<code[^>]*>)([^<]*)<\/code>/i, function() {
|
||||||
|
return arguments[1] + parse(arguments[2], styleSet.ignoreCase) + "</code>"
|
||||||
|
});
|
||||||
|
parsed = parsed.replace(/\n( *)/g, function() {
|
||||||
|
var spaces = "";
|
||||||
|
for (var i = 0; i < arguments[1].length; i++) spaces+= " ";
|
||||||
|
return "\n" + spaces;
|
||||||
|
});
|
||||||
|
parsed = parsed.replace(/\t/g, " ");
|
||||||
|
parsed = parsed.replace(/\n(<\/\w+>)?/g, "<br />$1").replace(/<br \/>[\n\r\s]*<br \/>/g, "<p><br></p>");
|
||||||
|
|
||||||
|
} else parsed = parse(stylableEls[i].innerHTML, styleSet.ignoreCase);
|
||||||
|
|
||||||
|
stylableEls[i].innerHTML = parsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// run highlighter on all stylesets
|
||||||
|
for (var i=0; i < this.styleSets.length; i++) {
|
||||||
|
highlightCode(this.styleSets[i]);
|
||||||
|
}
|
||||||
|
}
|
8
railties/guides/files/javascripts/guides.js
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
function guideMenu(){
|
||||||
|
|
||||||
|
if (document.getElementById('guides').style.display == "none") {
|
||||||
|
document.getElementById('guides').style.display = "block";
|
||||||
|
} else {
|
||||||
|
document.getElementById('guides').style.display = "none";
|
||||||
|
}
|
||||||
|
}
|
90
railties/guides/files/javascripts/highlighters.js
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
CodeHighlighter.addStyle("css", {
|
||||||
|
comment : {
|
||||||
|
exp : /\/\*[^*]*\*+([^\/][^*]*\*+)*\//
|
||||||
|
},
|
||||||
|
keywords : {
|
||||||
|
exp : /@\w[\w\s]*/
|
||||||
|
},
|
||||||
|
selectors : {
|
||||||
|
exp : "([\\w-:\\[.#][^{};>]*)(?={)"
|
||||||
|
},
|
||||||
|
properties : {
|
||||||
|
exp : "([\\w-]+)(?=\\s*:)"
|
||||||
|
},
|
||||||
|
units : {
|
||||||
|
exp : /([0-9])(em|en|px|%|pt)\b/,
|
||||||
|
replacement : "$1<span class=\"$0\">$2</span>"
|
||||||
|
},
|
||||||
|
urls : {
|
||||||
|
exp : /url\([^\)]*\)/
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
CodeHighlighter.addStyle("ruby",{
|
||||||
|
comment : {
|
||||||
|
exp : /#[^\n]+/
|
||||||
|
},
|
||||||
|
brackets : {
|
||||||
|
exp : /\(|\)/
|
||||||
|
},
|
||||||
|
string : {
|
||||||
|
exp : /'[^']*'|"[^"]*"/
|
||||||
|
},
|
||||||
|
keywords : {
|
||||||
|
exp : /\b(do|end|self|class|def|if|module|yield|then|else|for|until|unless|while|elsif|case|when|break|retry|redo|rescue|require|raise)\b/
|
||||||
|
},
|
||||||
|
/* Added by Shelly Fisher (shelly@agileevolved.com) */
|
||||||
|
symbol : {
|
||||||
|
exp : /([^:])(:[A-Za-z0-9_!?]+)/
|
||||||
|
},
|
||||||
|
ivar : {
|
||||||
|
exp : /\@[A-Za-z0-9_!?]+/
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
CodeHighlighter.addStyle("html", {
|
||||||
|
comment : {
|
||||||
|
exp: /<!\s*(--([^-]|[\r\n]|-[^-])*--\s*)>/
|
||||||
|
},
|
||||||
|
tag : {
|
||||||
|
exp: /(<\/?)([a-zA-Z1-9]+\s?)/,
|
||||||
|
replacement: "$1<span class=\"$0\">$2</span>"
|
||||||
|
},
|
||||||
|
string : {
|
||||||
|
exp : /'[^']*'|"[^"]*"/
|
||||||
|
},
|
||||||
|
attribute : {
|
||||||
|
exp: /\b([a-zA-Z-:]+)(=)/,
|
||||||
|
replacement: "<span class=\"$0\">$1</span>$2"
|
||||||
|
},
|
||||||
|
doctype : {
|
||||||
|
exp: /<!DOCTYPE([^&]|&[^g]|&g[^t])*>/
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
CodeHighlighter.addStyle("javascript",{
|
||||||
|
comment : {
|
||||||
|
exp : /(\/\/[^\n]*(\n|$))|(\/\*[^*]*\*+([^\/][^*]*\*+)*\/)/
|
||||||
|
},
|
||||||
|
brackets : {
|
||||||
|
exp : /\(|\)/
|
||||||
|
},
|
||||||
|
string : {
|
||||||
|
exp : /'[^']*'|"[^"]*"/
|
||||||
|
},
|
||||||
|
keywords : {
|
||||||
|
exp : /\b(arguments|break|case|continue|default|delete|do|else|false|for|function|if|in|instanceof|new|null|return|switch|this|true|typeof|var|void|while|with)\b/
|
||||||
|
},
|
||||||
|
global : {
|
||||||
|
exp : /\b(toString|valueOf|window|element|prototype|constructor|document|escape|unescape|parseInt|parseFloat|setTimeout|clearTimeout|setInterval|clearInterval|NaN|isNaN|Infinity)\b/
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
CodeHighlighter.addStyle("yaml", {
|
||||||
|
keyword : {
|
||||||
|
exp : /\/\*[^*]*\*+([^\/][^*]*\*+)*\//
|
||||||
|
},
|
||||||
|
value : {
|
||||||
|
exp : /@\w[\w\s]*/
|
||||||
|
},
|
||||||
|
});
|
436
railties/guides/files/stylesheets/main.css
Normal file
@ -0,0 +1,436 @@
|
|||||||
|
/* Guides.rubyonrails.org */
|
||||||
|
/* Main.css */
|
||||||
|
/* Created January 30, 2009 */
|
||||||
|
/* Modified January 31, 2009
|
||||||
|
--------------------------------------- */
|
||||||
|
|
||||||
|
/* General
|
||||||
|
--------------------------------------- */
|
||||||
|
|
||||||
|
.left {float: left; margin-right: 1em;}
|
||||||
|
.right {float: right; margin-left: 1em;}
|
||||||
|
.small {font-size: smaller;}
|
||||||
|
.large {font-size: larger;}
|
||||||
|
.hide {display: none;}
|
||||||
|
|
||||||
|
li ul, li ol { margin:0 1.5em; }
|
||||||
|
ul, ol { margin: 0 1.5em 1.5em 1.5em; }
|
||||||
|
|
||||||
|
ul { list-style-type: disc; }
|
||||||
|
ol { list-style-type: decimal; }
|
||||||
|
|
||||||
|
dl { margin: 0 0 1.5em 0; }
|
||||||
|
dl dt { font-weight: bold; }
|
||||||
|
dd { margin-left: 1.5em;}
|
||||||
|
|
||||||
|
pre,code { margin: 1.5em 0; white-space: pre; }
|
||||||
|
pre,code,tt { font: 1em 'andale mono', 'lucida console', monospace; line-height: 1.5; }
|
||||||
|
|
||||||
|
abbr, acronym { border-bottom: 1px dotted #666; }
|
||||||
|
address { margin: 0 0 1.5em; font-style: italic; }
|
||||||
|
del { color:#666; }
|
||||||
|
|
||||||
|
blockquote { margin: 1.5em; color: #666; font-style: italic; }
|
||||||
|
strong { font-weight: bold; }
|
||||||
|
em, dfn { font-style: italic; }
|
||||||
|
dfn { font-weight: bold; }
|
||||||
|
sup, sub { line-height: 0; }
|
||||||
|
p {margin: 0 0 1.5em;}
|
||||||
|
|
||||||
|
label { font-weight: bold; }
|
||||||
|
fieldset { padding:1.4em; margin: 0 0 1.5em 0; border: 1px solid #ccc; }
|
||||||
|
legend { font-weight: bold; font-size:1.2em; }
|
||||||
|
|
||||||
|
input.text, input.title,
|
||||||
|
textarea, select {
|
||||||
|
margin:0.5em 0;
|
||||||
|
border:1px solid #bbb;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
margin: 1em 0;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
background: #f4f4f4;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table th, table td {
|
||||||
|
padding: 0.25em;
|
||||||
|
border-right: 1px dotted #e0e0e0;
|
||||||
|
border-bottom: 1px dotted #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
table th:last-child, table td:last-child {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
table th {
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
background: #f0f0f0;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
table td {
|
||||||
|
}
|
||||||
|
|
||||||
|
table tt {
|
||||||
|
padding: 0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Structure and Layout
|
||||||
|
--------------------------------------- */
|
||||||
|
|
||||||
|
body {
|
||||||
|
text-align: center;
|
||||||
|
font-family: Helvetica, Arial, sans-serif;
|
||||||
|
font-size: 87.5%;
|
||||||
|
line-height: 1.5em;
|
||||||
|
background: #222;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
text-align: left;
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 69em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#topNav {
|
||||||
|
padding: 1em 0;
|
||||||
|
color: #565656;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header {
|
||||||
|
background: #c52f24 url(../../images/header_tile.gif) repeat-x;
|
||||||
|
color: #FFF;
|
||||||
|
padding: 1.5em 0;
|
||||||
|
position: relative;
|
||||||
|
z-index: 99;
|
||||||
|
}
|
||||||
|
|
||||||
|
#feature {
|
||||||
|
background: #d5e9f6 url(../../images/feature_tile.gif) repeat-x;
|
||||||
|
color: #333;
|
||||||
|
padding: 0.5em 0 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container {
|
||||||
|
background: #FFF;
|
||||||
|
color: #333;
|
||||||
|
padding: 0.5em 0 1.5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mainCol {
|
||||||
|
width: 45em;
|
||||||
|
margin-left: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subCol {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 0;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
background: #FFF;
|
||||||
|
padding: 1em 1.5em 1em 1.25em;
|
||||||
|
width: 17em;
|
||||||
|
font-size: 0.9285em;
|
||||||
|
line-height: 1.3846em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#extraCol {display: none;}
|
||||||
|
|
||||||
|
#footer {
|
||||||
|
padding: 2em 0;
|
||||||
|
background: url(../../images/footer_tile.gif) repeat-x;
|
||||||
|
}
|
||||||
|
#footer .wrapper {
|
||||||
|
padding-left: 2em;
|
||||||
|
width: 67em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header .wrapper, #topNav .wrapper, #feature .wrapper {padding-left: 1em; width: 68em;}
|
||||||
|
#feature .wrapper {width: 45em; padding-right: 23em; position: relative; z-index: 0;}
|
||||||
|
|
||||||
|
/* Links
|
||||||
|
--------------------------------------- */
|
||||||
|
|
||||||
|
a, a:link, a:visited {
|
||||||
|
color: #ee3f3f;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mainCol a, #subCol a {color: #980905;}
|
||||||
|
|
||||||
|
|
||||||
|
/* Navigation
|
||||||
|
--------------------------------------- */
|
||||||
|
|
||||||
|
.nav {margin: 0; padding: 0;}
|
||||||
|
.nav li {display: inline; list-style: none;}
|
||||||
|
|
||||||
|
#header .nav {
|
||||||
|
float: right;
|
||||||
|
margin-top: 1.5em;
|
||||||
|
font-size: 1.2857em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header .nav li {margin: 0 0 0 0.5em;}
|
||||||
|
#header .nav a {color: #FFF; text-decoration: none;}
|
||||||
|
#header .nav a:hover {text-decoration: underline;}
|
||||||
|
|
||||||
|
#header .nav .index {
|
||||||
|
padding: 0.5em 1.5em;
|
||||||
|
border-radius: 1em;
|
||||||
|
-webkit-border-radius: 1em;
|
||||||
|
-moz-border-radius: 1em;
|
||||||
|
background: #980905;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header .nav .index a {
|
||||||
|
background: #980905 url(../../images/nav_arrow.gif) no-repeat right top;
|
||||||
|
padding-right: 1em;
|
||||||
|
position: relative;
|
||||||
|
z-index: 15;
|
||||||
|
padding-bottom: 0.125em;
|
||||||
|
}
|
||||||
|
#header .nav .index:hover a, #header .nav .index a:hover {background-position: right -81px;}
|
||||||
|
|
||||||
|
#guides {
|
||||||
|
width: 27em;
|
||||||
|
display: block;
|
||||||
|
background: #980905;
|
||||||
|
border-radius: 1em;
|
||||||
|
-webkit-border-radius: 1em;
|
||||||
|
-moz-border-radius: 1em;
|
||||||
|
-webkit-box-shadow: 0.25em 0.25em 1em rgba(0,0,0,0.25);
|
||||||
|
-moz-box-shadow: rgba(0,0,0,0.25) 0.25em 0.25em 1em;
|
||||||
|
color: #f1938c;
|
||||||
|
padding: 1.5em 2em;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 10;
|
||||||
|
top: -0.25em;
|
||||||
|
right: 0;
|
||||||
|
padding-top: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#guides dt, #guides dd {
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 0.722em;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
#guides dt {padding:0; margin: 0.5em 0 0;}
|
||||||
|
#guides a {color: #FFF; background: none !important;}
|
||||||
|
#guides .L, #guides .R {float: left; width: 50%; margin: 0; padding: 0;}
|
||||||
|
#guides .R {float: right;}
|
||||||
|
#guides hr {
|
||||||
|
display: block;
|
||||||
|
border: none;
|
||||||
|
height: 1px;
|
||||||
|
color: #f1938c;
|
||||||
|
background: #f1938c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Headings
|
||||||
|
--------------------------------------- */
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 2.5em;
|
||||||
|
line-height: 1em;
|
||||||
|
margin: 0.6em 0 .2em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 2.1428em;
|
||||||
|
line-height: 1em;
|
||||||
|
margin: 0.7em 0 .2333em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.7142em;
|
||||||
|
line-height: 1.286em;
|
||||||
|
margin: 0.875em 0 0.2916em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size: 1.2857em;
|
||||||
|
line-height: 1.2em;
|
||||||
|
margin: 1.6667em 0 .3887em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
font-size: 1em;
|
||||||
|
line-height: 1.5em;
|
||||||
|
margin: 1em 0 .5em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h6 {
|
||||||
|
font-size: 1em;
|
||||||
|
line-height: 1.5em;
|
||||||
|
margin: 1em 0 .5em;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Content
|
||||||
|
--------------------------------------- */
|
||||||
|
|
||||||
|
.pic {
|
||||||
|
margin: 0 2em 2em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#topNav strong {color: #999; margin-right: 0.5em;}
|
||||||
|
#topNav strong a {color: #FFF;}
|
||||||
|
|
||||||
|
#header h1 {
|
||||||
|
float: left;
|
||||||
|
background: url(../../images/ruby_guides_logo.gif) no-repeat;
|
||||||
|
width: 492px;
|
||||||
|
text-indent: -9999em;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#header h1 a {
|
||||||
|
text-decoration: none;
|
||||||
|
display: block;
|
||||||
|
height: 77px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#feature p {
|
||||||
|
font-size: 1.2857em;
|
||||||
|
margin-bottom: 0.75em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#feature ul {margin-left: 0;}
|
||||||
|
#feature ul li {
|
||||||
|
list-style: none;
|
||||||
|
background: url(../../images/check_bullet.gif) no-repeat left 0.5em;
|
||||||
|
padding: 0.5em 1.75em 0.5em 1.75em;
|
||||||
|
font-size: 1.1428em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mainCol dd, #subCol dd {
|
||||||
|
padding: 0.25em 0 1em;
|
||||||
|
border-bottom: 1px solid #CCC;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
margin-left: 0;
|
||||||
|
padding-left: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mainCol dt, #subCol dt {
|
||||||
|
font-size: 1.2857em;
|
||||||
|
padding: 0.125em 0 0.25em 28px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
background: url(../../images/book_icon.gif) no-repeat left top;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mainCol dd.ticket, #subCol dd.ticket {
|
||||||
|
background: #fff9d8 url(../../images/tab_yellow.gif) no-repeat left top;
|
||||||
|
border: none;
|
||||||
|
padding: 1.25em 1em 1.25em 48px;
|
||||||
|
margin-left: 0;
|
||||||
|
margin-top: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mainCol dd.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;
|
||||||
|
margin-left: 0;
|
||||||
|
margin-top: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subCol .chapters {color: #980905;}
|
||||||
|
#subCol .chapters a {font-weight: bold;}
|
||||||
|
#subCol .chapters ul a {font-weight: normal;}
|
||||||
|
#subCol .chapters li {margin-bottom: 0.75em;}
|
||||||
|
#subCol h3.chapter {margin-top: 0.25em;}
|
||||||
|
#subCol h3.chapter img {vertical-align: text-bottom;}
|
||||||
|
#subCol .chapters ul {margin-left: 0; margin-top: 0.5em;}
|
||||||
|
#subCol .chapters ul li {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0 0 0 1em;
|
||||||
|
background: url(../../images/bullet.gif) no-repeat left 0.45em;
|
||||||
|
margin-left: 0;
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
tt {
|
||||||
|
background: #EEE;
|
||||||
|
border: 1px solid #CCC;
|
||||||
|
padding: 0.25em 0.5em;
|
||||||
|
font-family: monaco, "Bitstream Vera Sans Mono", "Courier New", courier, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
code, pre {
|
||||||
|
font-family: monaco, "Bitstream Vera Sans Mono", "Courier New", courier, monospace;
|
||||||
|
background: #EEE url(../../images/tab_grey.gif) no-repeat left top;
|
||||||
|
border: none;
|
||||||
|
padding: 0.25em 1em 0.5em 48px;
|
||||||
|
margin-left: 0;
|
||||||
|
margin-top: 0.25em;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note {
|
||||||
|
background: #fff9d8 url(../../images/tab_note.gif) no-repeat left top;
|
||||||
|
border: none;
|
||||||
|
padding: 1em 1em 0.25em 48px;
|
||||||
|
margin-left: 0;
|
||||||
|
margin-top: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
background: #d5e9f6 url(../../images/tab_info.gif) no-repeat left top;
|
||||||
|
border: none;
|
||||||
|
padding: 1em 1em 0.25em 48px;
|
||||||
|
margin-left: 0;
|
||||||
|
margin-top: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning {
|
||||||
|
background: #f9d9d8 url(../../images/tab_red.gif) no-repeat left top;
|
||||||
|
border: none;
|
||||||
|
padding: 1em 1em 0.25em 48px;
|
||||||
|
margin-left: 0;
|
||||||
|
margin-top: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning tt, .note tt, .info tt {border:none; background: none; padding: 0;}
|
||||||
|
|
||||||
|
em.highlight {
|
||||||
|
background: #fffcdb;
|
||||||
|
padding: 0 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#mainCol ul li {
|
||||||
|
list-style:none;
|
||||||
|
background: url(../../images/grey_bullet.gif) no-repeat left 0.5em;
|
||||||
|
padding-left: 1em;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clearing
|
||||||
|
--------------------------------------- */
|
||||||
|
|
||||||
|
.clearfix:after {
|
||||||
|
content: ".";
|
||||||
|
display: block;
|
||||||
|
height: 0;
|
||||||
|
clear: both;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clearfix {display: inline-block;}
|
||||||
|
* html .clearfix {height: 1%;}
|
||||||
|
.clearfix {display: block;}
|
||||||
|
.clear { clear:both; }
|
52
railties/guides/files/stylesheets/print.css
Executable file
@ -0,0 +1,52 @@
|
|||||||
|
/* Guides.rubyonrails.org */
|
||||||
|
/* Print.css */
|
||||||
|
/* Created January 30, 2009 */
|
||||||
|
/* Modified January 31, 2009
|
||||||
|
--------------------------------------- */
|
||||||
|
|
||||||
|
body, .wrapper, .note, .info, code, #topNav, .L, .R, #frame, #container, #header, #navigation, #footer, #feature, #mainCol, #subCol, #extraCol, .content {position: static; text-align: left; text-indent: 0; background: White; color: Black; border-color: Black; width: auto; height: auto; display: block; float: none; min-height: 0; margin: 0; padding: 0;}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: #FFF;
|
||||||
|
font-size: 10pt !important;
|
||||||
|
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: #000;
|
||||||
|
padding: 0 3%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hide, .nav {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:link, a:visited {
|
||||||
|
background: transparent;
|
||||||
|
font-weight: bold;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
background:#ccc;
|
||||||
|
color:#ccc;
|
||||||
|
width:100%;
|
||||||
|
height:2px;
|
||||||
|
margin:2em 0;
|
||||||
|
padding:0;
|
||||||
|
border:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,h2,h3,h4,h5,h6 { font-family: "Helvetica Neue", Arial, "Lucida Grande", sans-serif; }
|
||||||
|
code { font:.9em "Courier New", Monaco, Courier, monospace; }
|
||||||
|
|
||||||
|
img { float:left; margin:1.5em 1.5em 1.5em 0; }
|
||||||
|
a img { border:none; }
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
margin:1.5em;
|
||||||
|
padding:1em;
|
||||||
|
font-style:italic;
|
||||||
|
font-size:.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small { font-size: .9em; }
|
||||||
|
.large { font-size: 1.1em; }
|
43
railties/guides/files/stylesheets/reset.css
Executable file
@ -0,0 +1,43 @@
|
|||||||
|
/* Guides.rubyonrails.org */
|
||||||
|
/* Reset.css */
|
||||||
|
/* Created January 30, 2009
|
||||||
|
--------------------------------------- */
|
||||||
|
|
||||||
|
html, body, div, span, applet, object, iframe,
|
||||||
|
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||||
|
a, abbr, acronym, address, big, cite, code,
|
||||||
|
del, dfn, em, font, img, ins, kbd, q, s, samp,
|
||||||
|
small, strike, strong, sub, sup, tt, var,
|
||||||
|
b, u, i, center,
|
||||||
|
dl, dt, dd, ol, ul, li,
|
||||||
|
fieldset, form, label, legend,
|
||||||
|
table, caption, tbody, tfoot, thead, tr, th, td {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
outline: 0;
|
||||||
|
font-size: 100%;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {line-height: 1; color: black; background: white;}
|
||||||
|
a img {border:none;}
|
||||||
|
ins {text-decoration: none;}
|
||||||
|
del {text-decoration: line-through;}
|
||||||
|
|
||||||
|
:focus {
|
||||||
|
-moz-outline:0;
|
||||||
|
outline:0;
|
||||||
|
outline-offset:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* tables still need 'cellspacing="0"' in the markup */
|
||||||
|
table {border-collapse: collapse; border-spacing: 0;}
|
||||||
|
caption, th, td {text-align: left; font-weight: normal;}
|
||||||
|
|
||||||
|
blockquote, q {quotes: none;}
|
||||||
|
blockquote:before, blockquote:after,
|
||||||
|
q:before, q:after {
|
||||||
|
content: '';
|
||||||
|
content: none;
|
||||||
|
}
|
13
railties/guides/files/stylesheets/style.css
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
/* Guides.rubyonrails.org */
|
||||||
|
/* Style.css */
|
||||||
|
/* Created January 30, 2009
|
||||||
|
--------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
---------------------------------------
|
||||||
|
Import advanced style sheet
|
||||||
|
---------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import url("reset.css");
|
||||||
|
@import url("main.css");
|
31
railties/guides/files/stylesheets/syntax.css
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
.html .tag {
|
||||||
|
color : green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.html .doctype {
|
||||||
|
color: #708090;
|
||||||
|
}
|
||||||
|
|
||||||
|
.erb .tag {
|
||||||
|
color : green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.erb .doctype {
|
||||||
|
color: #708090;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ruby .keywords {
|
||||||
|
color : red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ruby .ivar {
|
||||||
|
color : blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ruby .comment {
|
||||||
|
color: #708090;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ruby .symbol {
|
||||||
|
color: green;
|
||||||
|
}
|
BIN
railties/guides/images/belongs_to.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
railties/guides/images/book_icon.gif
Normal file
After Width: | Height: | Size: 337 B |
BIN
railties/guides/images/bullet.gif
Normal file
After Width: | Height: | Size: 60 B |
BIN
railties/guides/images/chapters_icon.gif
Normal file
After Width: | Height: | Size: 628 B |
BIN
railties/guides/images/check_bullet.gif
Normal file
After Width: | Height: | Size: 384 B |
BIN
railties/guides/images/credits_pic_blank.gif
Normal file
After Width: | Height: | Size: 613 B |
BIN
railties/guides/images/csrf.png
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
railties/guides/images/customized_error_messages.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
BIN
railties/guides/images/error_messages.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
BIN
railties/guides/images/feature_tile.gif
Normal file
After Width: | Height: | Size: 43 B |
BIN
railties/guides/images/footer_tile.gif
Normal file
After Width: | Height: | Size: 44 B |
BIN
railties/guides/images/grey_bullet.gif
Normal file
After Width: | Height: | Size: 45 B |
BIN
railties/guides/images/habtm.png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
railties/guides/images/has_many.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
railties/guides/images/has_many_through.png
Normal file
After Width: | Height: | Size: 98 KiB |
BIN
railties/guides/images/has_one.png
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
railties/guides/images/has_one_through.png
Normal file
After Width: | Height: | Size: 90 KiB |
BIN
railties/guides/images/header_backdrop.png
Normal file
After Width: | Height: | Size: 882 B |
BIN
railties/guides/images/header_tile.gif
Normal file
After Width: | Height: | Size: 44 B |
BIN
railties/guides/images/i18n/demo_localized_pirate.png
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
railties/guides/images/i18n/demo_translated_en.png
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
railties/guides/images/i18n/demo_translated_pirate.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
railties/guides/images/i18n/demo_translation_missing.png
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
railties/guides/images/i18n/demo_untranslated.png
Normal file
After Width: | Height: | Size: 32 KiB |
5
railties/guides/images/icons/README
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
Replaced the plain DocBook XSL admonition icons with Jimmac's DocBook
|
||||||
|
icons (http://jimmac.musichall.cz/ikony.php3). I dropped transparency
|
||||||
|
from the Jimmac icons to get round MS IE and FOP PNG incompatibilies.
|
||||||
|
|
||||||
|
Stuart Rackham
|
BIN
railties/guides/images/icons/callouts/1.png
Normal file
After Width: | Height: | Size: 329 B |
BIN
railties/guides/images/icons/callouts/10.png
Normal file
After Width: | Height: | Size: 361 B |
BIN
railties/guides/images/icons/callouts/11.png
Normal file
After Width: | Height: | Size: 565 B |
BIN
railties/guides/images/icons/callouts/12.png
Normal file
After Width: | Height: | Size: 617 B |
BIN
railties/guides/images/icons/callouts/13.png
Normal file
After Width: | Height: | Size: 623 B |
BIN
railties/guides/images/icons/callouts/14.png
Normal file
After Width: | Height: | Size: 411 B |
BIN
railties/guides/images/icons/callouts/15.png
Normal file
After Width: | Height: | Size: 640 B |
BIN
railties/guides/images/icons/callouts/2.png
Normal file
After Width: | Height: | Size: 353 B |
BIN
railties/guides/images/icons/callouts/3.png
Normal file
After Width: | Height: | Size: 350 B |
BIN
railties/guides/images/icons/callouts/4.png
Normal file
After Width: | Height: | Size: 345 B |
BIN
railties/guides/images/icons/callouts/5.png
Normal file
After Width: | Height: | Size: 348 B |
BIN
railties/guides/images/icons/callouts/6.png
Normal file
After Width: | Height: | Size: 355 B |
BIN
railties/guides/images/icons/callouts/7.png
Normal file
After Width: | Height: | Size: 344 B |
BIN
railties/guides/images/icons/callouts/8.png
Normal file
After Width: | Height: | Size: 357 B |
BIN
railties/guides/images/icons/callouts/9.png
Normal file
After Width: | Height: | Size: 357 B |
BIN
railties/guides/images/icons/caution.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
railties/guides/images/icons/example.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
railties/guides/images/icons/home.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
railties/guides/images/icons/important.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
railties/guides/images/icons/next.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
railties/guides/images/icons/note.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
railties/guides/images/icons/prev.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
railties/guides/images/icons/tip.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
railties/guides/images/icons/up.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
railties/guides/images/icons/warning.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
railties/guides/images/nav_arrow.gif
Normal file
After Width: | Height: | Size: 427 B |
BIN
railties/guides/images/polymorphic.png
Normal file
After Width: | Height: | Size: 83 KiB |
BIN
railties/guides/images/posts_index.png
Normal file
After Width: | Height: | Size: 5.7 KiB |
BIN
railties/guides/images/rails_logo_remix.gif
Normal file
After Width: | Height: | Size: 8.3 KiB |
BIN
railties/guides/images/rails_welcome.png
Normal file
After Width: | Height: | Size: 75 KiB |
BIN
railties/guides/images/ruby_guides_logo.gif
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
railties/guides/images/ruby_on_rails_by_mike_rundle2.gif
Normal file
After Width: | Height: | Size: 6.6 KiB |
BIN
railties/guides/images/session_fixation.png
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
railties/guides/images/tab_grey.gif
Normal file
After Width: | Height: | Size: 2.4 KiB |