aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew White <andyw@pixeltrix.co.uk>2010-04-04 17:34:23 +0100
committerAndrew White <andyw@pixeltrix.co.uk>2010-04-04 17:34:23 +0100
commit00884a59013a658082dab41da5ff41add31b8c43 (patch)
tree666b862b08b04c7a3727ee22b2cd1a2561af4e52
parent48b2451142355b22de5f8130b3debdd4e53e2ba2 (diff)
parent7d7e0627a0490b6b4ddb0ee5429264ccd46f1245 (diff)
downloadrails-00884a59013a658082dab41da5ff41add31b8c43.tar.gz
rails-00884a59013a658082dab41da5ff41add31b8c43.tar.bz2
rails-00884a59013a658082dab41da5ff41add31b8c43.zip
Merge branch 'master' of github.com:lifo/docrails
-rw-r--r--Gemfile4
-rw-r--r--RAILS_VERSION2
-rw-r--r--actionmailer/CHANGELOG10
-rw-r--r--actionmailer/lib/action_mailer/version.rb2
-rw-r--r--actionpack/CHANGELOG551
-rw-r--r--actionpack/lib/action_dispatch/http/mime_negotiation.rb4
-rw-r--r--actionpack/lib/action_dispatch/railtie.rb1
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb53
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb4
-rw-r--r--actionpack/lib/action_pack/version.rb2
-rw-r--r--actionpack/lib/action_view/base.rb7
-rw-r--r--actionpack/lib/action_view/helpers.rb9
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb27
-rw-r--r--actionpack/lib/action_view/helpers/form_tag_helper.rb4
-rw-r--r--actionpack/lib/action_view/helpers/number_helper.rb8
-rw-r--r--actionpack/lib/action_view/helpers/url_helper.rb52
-rw-r--r--actionpack/lib/action_view/render/partials.rb4
-rw-r--r--actionpack/lib/action_view/template.rb9
-rw-r--r--actionpack/lib/action_view/test_case.rb7
-rw-r--r--actionpack/test/abstract_unit.rb20
-rw-r--r--actionpack/test/dispatch/routing_test.rb51
-rw-r--r--actionpack/test/template/active_model_helper_test.rb9
-rw-r--r--actionpack/test/template/asset_tag_helper_test.rb26
-rw-r--r--actionpack/test/template/erb/helper.rb11
-rw-r--r--actionpack/test/template/form_helper_test.rb18
-rw-r--r--actionpack/test/template/form_tag_helper_test.rb20
-rw-r--r--actionpack/test/template/number_helper_test.rb9
-rw-r--r--actionpack/test/template/prototype_helper_test.rb25
-rw-r--r--actionpack/test/template/render_test.rb8
-rw-r--r--actionpack/test/template/scriptaculous_helper_test.rb33
-rw-r--r--actionpack/test/template/url_helper_test.rb419
-rw-r--r--activemodel/CHANGELOG17
-rw-r--r--activemodel/activemodel.gemspec25
-rw-r--r--activemodel/lib/active_model/dirty.rb24
-rw-r--r--activemodel/lib/active_model/errors.rb2
-rw-r--r--activemodel/lib/active_model/version.rb2
-rw-r--r--activemodel/test/cases/dirty_test.rb1
-rw-r--r--activemodel/test/cases/validations/i18n_validation_test.rb10
-rw-r--r--activerecord/CHANGELOG10
-rw-r--r--activerecord/activerecord.gemspec1
-rwxr-xr-xactiverecord/lib/active_record/associations.rb73
-rw-r--r--activerecord/lib/active_record/associations/through_association_scope.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb3
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb6
-rw-r--r--activerecord/lib/active_record/named_scope.rb133
-rw-r--r--activerecord/lib/active_record/railties/databases.rake2
-rw-r--r--activerecord/lib/active_record/reflection.rb11
-rw-r--r--activerecord/lib/active_record/relation.rb21
-rw-r--r--activerecord/lib/active_record/relation/finder_methods.rb20
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder.rb6
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb25
-rw-r--r--activerecord/lib/active_record/relation/spawn_methods.rb15
-rw-r--r--activerecord/lib/active_record/version.rb2
-rw-r--r--activerecord/test/cases/column_definition_test.rb17
-rw-r--r--activerecord/test/cases/relations_test.rb16
-rw-r--r--activerecord/test/models/post.rb6
-rw-r--r--activeresource/CHANGELOG2
-rw-r--r--activeresource/activeresource.gemspec1
-rw-r--r--activeresource/lib/active_resource/version.rb2
-rw-r--r--activesupport/CHANGELOG9
-rw-r--r--activesupport/activesupport.gemspec1
-rw-r--r--activesupport/lib/active_support/core_ext/class/attribute.rb2
-rw-r--r--activesupport/lib/active_support/values/time_zone.rb90
-rw-r--r--activesupport/lib/active_support/version.rb2
-rw-r--r--activesupport/test/core_ext/class/attribute_test.rb6
-rw-r--r--activesupport/test/time_zone_test.rb8
-rw-r--r--rails.gemspec17
-rw-r--r--rails3b.gemspec27
-rw-r--r--railties/CHANGELOG16
-rw-r--r--railties/guides/assets/images/belongs_to.png (renamed from railties/guides/images/belongs_to.png)bin34017 -> 34017 bytes
-rw-r--r--railties/guides/assets/images/book_icon.gif (renamed from railties/guides/images/book_icon.gif)bin337 -> 337 bytes
-rw-r--r--railties/guides/assets/images/bullet.gif (renamed from railties/guides/images/bullet.gif)bin60 -> 60 bytes
-rw-r--r--railties/guides/assets/images/challenge.png (renamed from railties/guides/images/challenge.png)bin54134 -> 54134 bytes
-rw-r--r--railties/guides/assets/images/chapters_icon.gif (renamed from railties/guides/images/chapters_icon.gif)bin628 -> 628 bytes
-rw-r--r--railties/guides/assets/images/check_bullet.gif (renamed from railties/guides/images/check_bullet.gif)bin384 -> 384 bytes
-rw-r--r--railties/guides/assets/images/credits_pic_blank.gif (renamed from railties/guides/images/credits_pic_blank.gif)bin613 -> 613 bytes
-rw-r--r--railties/guides/assets/images/csrf.png (renamed from railties/guides/images/csrf.png)bin41996 -> 41996 bytes
-rw-r--r--railties/guides/assets/images/customized_error_messages.png (renamed from railties/guides/images/customized_error_messages.png)bin5055 -> 5055 bytes
-rw-r--r--railties/guides/assets/images/edge_badge.png (renamed from railties/guides/images/edge_badge.png)bin7945 -> 7945 bytes
-rw-r--r--railties/guides/assets/images/error_messages.png (renamed from railties/guides/images/error_messages.png)bin14645 -> 14645 bytes
-rw-r--r--railties/guides/assets/images/feature_tile.gif (renamed from railties/guides/images/feature_tile.gif)bin43 -> 43 bytes
-rw-r--r--railties/guides/assets/images/footer_tile.gif (renamed from railties/guides/images/footer_tile.gif)bin44 -> 44 bytes
-rw-r--r--railties/guides/assets/images/fxn.png (renamed from railties/guides/images/fxn.png)bin20664 -> 20664 bytes
-rw-r--r--railties/guides/assets/images/grey_bullet.gif (renamed from railties/guides/images/grey_bullet.gif)bin45 -> 45 bytes
-rw-r--r--railties/guides/assets/images/habtm.png (renamed from railties/guides/images/habtm.png)bin63801 -> 63801 bytes
-rw-r--r--railties/guides/assets/images/has_many.png (renamed from railties/guides/images/has_many.png)bin38582 -> 38582 bytes
-rw-r--r--railties/guides/assets/images/has_many_through.png (renamed from railties/guides/images/has_many_through.png)bin100220 -> 100220 bytes
-rw-r--r--railties/guides/assets/images/has_one.png (renamed from railties/guides/images/has_one.png)bin39022 -> 39022 bytes
-rw-r--r--railties/guides/assets/images/has_one_through.png (renamed from railties/guides/images/has_one_through.png)bin92594 -> 92594 bytes
-rw-r--r--railties/guides/assets/images/header_backdrop.png (renamed from railties/guides/images/header_backdrop.png)bin882 -> 882 bytes
-rw-r--r--railties/guides/assets/images/header_tile.gif (renamed from railties/guides/images/header_tile.gif)bin44 -> 44 bytes
-rw-r--r--railties/guides/assets/images/i18n/demo_localized_pirate.png (renamed from railties/guides/images/i18n/demo_localized_pirate.png)bin15027 -> 15027 bytes
-rw-r--r--railties/guides/assets/images/i18n/demo_translated_en.png (renamed from railties/guides/images/i18n/demo_translated_en.png)bin12057 -> 12057 bytes
-rw-r--r--railties/guides/assets/images/i18n/demo_translated_pirate.png (renamed from railties/guides/images/i18n/demo_translated_pirate.png)bin13392 -> 13392 bytes
-rw-r--r--railties/guides/assets/images/i18n/demo_translation_missing.png (renamed from railties/guides/images/i18n/demo_translation_missing.png)bin13143 -> 13143 bytes
-rw-r--r--railties/guides/assets/images/i18n/demo_untranslated.png (renamed from railties/guides/images/i18n/demo_untranslated.png)bin11925 -> 11925 bytes
-rw-r--r--railties/guides/assets/images/icons/README (renamed from railties/guides/images/icons/README)0
-rw-r--r--railties/guides/assets/images/icons/callouts/1.png (renamed from railties/guides/images/icons/callouts/1.png)bin329 -> 329 bytes
-rw-r--r--railties/guides/assets/images/icons/callouts/10.png (renamed from railties/guides/images/icons/callouts/10.png)bin361 -> 361 bytes
-rw-r--r--railties/guides/assets/images/icons/callouts/11.png (renamed from railties/guides/images/icons/callouts/11.png)bin565 -> 565 bytes
-rw-r--r--railties/guides/assets/images/icons/callouts/12.png (renamed from railties/guides/images/icons/callouts/12.png)bin617 -> 617 bytes
-rw-r--r--railties/guides/assets/images/icons/callouts/13.png (renamed from railties/guides/images/icons/callouts/13.png)bin623 -> 623 bytes
-rw-r--r--railties/guides/assets/images/icons/callouts/14.png (renamed from railties/guides/images/icons/callouts/14.png)bin411 -> 411 bytes
-rw-r--r--railties/guides/assets/images/icons/callouts/15.png (renamed from railties/guides/images/icons/callouts/15.png)bin640 -> 640 bytes
-rw-r--r--railties/guides/assets/images/icons/callouts/2.png (renamed from railties/guides/images/icons/callouts/2.png)bin353 -> 353 bytes
-rw-r--r--railties/guides/assets/images/icons/callouts/3.png (renamed from railties/guides/images/icons/callouts/3.png)bin350 -> 350 bytes
-rw-r--r--railties/guides/assets/images/icons/callouts/4.png (renamed from railties/guides/images/icons/callouts/4.png)bin345 -> 345 bytes
-rw-r--r--railties/guides/assets/images/icons/callouts/5.png (renamed from railties/guides/images/icons/callouts/5.png)bin348 -> 348 bytes
-rw-r--r--railties/guides/assets/images/icons/callouts/6.png (renamed from railties/guides/images/icons/callouts/6.png)bin355 -> 355 bytes
-rw-r--r--railties/guides/assets/images/icons/callouts/7.png (renamed from railties/guides/images/icons/callouts/7.png)bin344 -> 344 bytes
-rw-r--r--railties/guides/assets/images/icons/callouts/8.png (renamed from railties/guides/images/icons/callouts/8.png)bin357 -> 357 bytes
-rw-r--r--railties/guides/assets/images/icons/callouts/9.png (renamed from railties/guides/images/icons/callouts/9.png)bin357 -> 357 bytes
-rw-r--r--railties/guides/assets/images/icons/caution.png (renamed from railties/guides/images/icons/caution.png)bin2554 -> 2554 bytes
-rw-r--r--railties/guides/assets/images/icons/example.png (renamed from railties/guides/images/icons/example.png)bin2354 -> 2354 bytes
-rw-r--r--railties/guides/assets/images/icons/home.png (renamed from railties/guides/images/icons/home.png)bin1340 -> 1340 bytes
-rw-r--r--railties/guides/assets/images/icons/important.png (renamed from railties/guides/images/icons/important.png)bin2657 -> 2657 bytes
-rw-r--r--railties/guides/assets/images/icons/next.png (renamed from railties/guides/images/icons/next.png)bin1302 -> 1302 bytes
-rw-r--r--railties/guides/assets/images/icons/note.png (renamed from railties/guides/images/icons/note.png)bin2730 -> 2730 bytes
-rw-r--r--railties/guides/assets/images/icons/prev.png (renamed from railties/guides/images/icons/prev.png)bin1348 -> 1348 bytes
-rw-r--r--railties/guides/assets/images/icons/tip.png (renamed from railties/guides/images/icons/tip.png)bin2602 -> 2602 bytes
-rw-r--r--railties/guides/assets/images/icons/up.png (renamed from railties/guides/images/icons/up.png)bin1320 -> 1320 bytes
-rw-r--r--railties/guides/assets/images/icons/warning.png (renamed from railties/guides/images/icons/warning.png)bin2828 -> 2828 bytes
-rw-r--r--railties/guides/assets/images/jaimeiniesta.jpgbin0 -> 11913 bytes
-rw-r--r--railties/guides/assets/images/nav_arrow.gif (renamed from railties/guides/images/nav_arrow.gif)bin427 -> 427 bytes
-rw-r--r--railties/guides/assets/images/polymorphic.png (renamed from railties/guides/images/polymorphic.png)bin85248 -> 85248 bytes
-rw-r--r--railties/guides/assets/images/posts_index.png (renamed from railties/guides/images/posts_index.png)bin60846 -> 60846 bytes
-rw-r--r--railties/guides/assets/images/rails_guides_logo.gif (renamed from railties/guides/images/rails_guides_logo.gif)bin5114 -> 5114 bytes
-rw-r--r--railties/guides/assets/images/rails_logo_remix.gif (renamed from railties/guides/images/rails_logo_remix.gif)bin8533 -> 8533 bytes
-rw-r--r--railties/guides/assets/images/rails_welcome.png (renamed from railties/guides/images/rails_welcome.png)bin106417 -> 106417 bytes
-rw-r--r--railties/guides/assets/images/session_fixation.png (renamed from railties/guides/images/session_fixation.png)bin47860 -> 47860 bytes
-rw-r--r--railties/guides/assets/images/tab_grey.gif (renamed from railties/guides/images/tab_grey.gif)bin4924 -> 4924 bytes
-rw-r--r--railties/guides/assets/images/tab_info.gif (renamed from railties/guides/images/tab_info.gif)bin4762 -> 4762 bytes
-rw-r--r--railties/guides/assets/images/tab_note.gif (renamed from railties/guides/images/tab_note.gif)bin4807 -> 4807 bytes
-rw-r--r--railties/guides/assets/images/tab_red.gif (renamed from railties/guides/images/tab_red.gif)bin4753 -> 4753 bytes
-rw-r--r--railties/guides/assets/images/tab_yellow.gif (renamed from railties/guides/images/tab_yellow.gif)bin4759 -> 4759 bytes
-rw-r--r--railties/guides/assets/images/tab_yellow.png (renamed from railties/guides/images/tab_yellow.png)bin1611 -> 1611 bytes
-rw-r--r--railties/guides/assets/images/validation_error_messages.png (renamed from railties/guides/images/validation_error_messages.png)bin1107 -> 1107 bytes
-rwxr-xr-xrailties/guides/assets/javascripts/code_highlighter.js (renamed from railties/guides/files/javascripts/code_highlighter.js)0
-rwxr-xr-xrailties/guides/assets/javascripts/guides.js (renamed from railties/guides/files/javascripts/guides.js)0
-rw-r--r--railties/guides/assets/javascripts/highlighters.js (renamed from railties/guides/files/javascripts/highlighters.js)0
-rw-r--r--railties/guides/assets/stylesheets/main.css (renamed from railties/guides/files/stylesheets/main.css)39
-rwxr-xr-xrailties/guides/assets/stylesheets/print.css (renamed from railties/guides/files/stylesheets/print.css)0
-rwxr-xr-xrailties/guides/assets/stylesheets/reset.css (renamed from railties/guides/files/stylesheets/reset.css)0
-rwxr-xr-xrailties/guides/assets/stylesheets/style.css (renamed from railties/guides/files/stylesheets/style.css)0
-rw-r--r--railties/guides/assets/stylesheets/syntax.css (renamed from railties/guides/files/stylesheets/syntax.css)0
-rw-r--r--railties/guides/rails_guides/generator.rb101
-rw-r--r--railties/guides/source/action_view_overview.textile4
-rw-r--r--railties/guides/source/active_support_core_extensions.textile6
-rw-r--r--railties/guides/source/association_basics.textile2
-rw-r--r--railties/guides/source/contribute.textile2
-rw-r--r--railties/guides/source/credits.html.erb66
-rw-r--r--railties/guides/source/credits.textile.erb60
-rw-r--r--railties/guides/source/debugging_rails_applications.textile3
-rw-r--r--railties/guides/source/form_helpers.textile2
-rw-r--r--railties/guides/source/getting_started.textile5
-rw-r--r--railties/guides/source/index.html.erb150
-rw-r--r--railties/guides/source/index.textile.erb139
-rw-r--r--railties/guides/source/layout.html.erb22
-rw-r--r--railties/guides/source/layouts_and_rendering.textile5
-rw-r--r--railties/guides/source/performance_testing.textile8
-rw-r--r--railties/guides/source/plugins.textile29
-rw-r--r--railties/guides/source/routing.textile151
-rw-r--r--railties/guides/source/security.textile10
-rw-r--r--railties/guides/source/testing.textile3
-rw-r--r--railties/lib/rails/application/configuration.rb2
-rw-r--r--railties/lib/rails/generators/rails/app/app_generator.rb5
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/application.rb5
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/boot.rb12
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt3
-rw-r--r--railties/lib/rails/generators/rails/app/templates/public/index.html3
-rw-r--r--railties/lib/rails/version.rb2
-rw-r--r--railties/test/application/middleware_test.rb6
-rw-r--r--version.rb2
173 files changed, 1525 insertions, 1364 deletions
diff --git a/Gemfile b/Gemfile
index 7c6720ac7f..d516abe111 100644
--- a/Gemfile
+++ b/Gemfile
@@ -2,7 +2,7 @@ path File.dirname(__FILE__)
source 'http://rubygems.org'
gem "arel", :git => "git://github.com/rails/arel.git"
-gem "rails", "3.0.0.beta1"
+gem "rails", "3.0.0.beta2"
gem "rake", ">= 0.8.7"
gem "mocha", ">= 0.9.8"
@@ -11,7 +11,7 @@ group :mri do
if RUBY_VERSION < '1.9'
gem "system_timer"
gem "ruby-debug", ">= 0.10.3"
- elsif RUBY_VERSION < '1.9.2'
+ elsif RUBY_VERSION < '1.9.2' && !ENV['CI']
gem "ruby-debug19"
end
end
diff --git a/RAILS_VERSION b/RAILS_VERSION
index efcd59e268..90a578314f 100644
--- a/RAILS_VERSION
+++ b/RAILS_VERSION
@@ -1 +1 @@
-3.0.0.beta1
+3.0.0.beta2
diff --git a/actionmailer/CHANGELOG b/actionmailer/CHANGELOG
index 0018a2ed5d..605b18d7e9 100644
--- a/actionmailer/CHANGELOG
+++ b/actionmailer/CHANGELOG
@@ -1,7 +1,15 @@
-*Rails 3.0 (pending)*
+*Rails 3.0.0 [beta 2] (April 1st, 2010)*
+
+* Added interceptors and observers from Mail [ML]
+
+ ActionMailer::Base.register_interceptor calls Mail.register_interceptor
+ ActionMailer::Base.register_observer calls Mail.register_observer
* Whole new API added with tests. See base.rb for full details. Old API is deprecated.
+
+*Rails 3.0.0 [beta 1] (February 4, 2010)*
+
* The Mail::Message class has helped methods for all the field types that return 'common' defaults for the common use case, so to get the subject, mail.subject will give you a string, mail.date will give you a DateTime object, mail.from will give you an array of address specs (mikel@test.lindsaar.net) etc. If you want to access the field object itself, call mail[:field_name] which will return the field object you want, which you can then chain, like mail[:from].formatted
* Mail#content_type now returns the content_type field as a string. If you want the mime type of a mail, then you call Mail#mime_type (eg, text/plain), if you want the parameters of the content type field, you call Mail#content_type_parameters which gives you a hash, eg {'format' => 'flowed', 'charset' => 'utf-8'}
diff --git a/actionmailer/lib/action_mailer/version.rb b/actionmailer/lib/action_mailer/version.rb
index 7328a7dc80..5954cfcede 100644
--- a/actionmailer/lib/action_mailer/version.rb
+++ b/actionmailer/lib/action_mailer/version.rb
@@ -3,7 +3,7 @@ module ActionMailer
MAJOR = 3
MINOR = 0
TINY = 0
- BUILD = "beta1"
+ BUILD = "beta2"
STRING = [MAJOR, MINOR, TINY, BUILD].join('.')
end
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index 014a501080..7c2cebcff1 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,4 +1,35 @@
-*Edge*
+*Rails 3.0.0 [beta 2] (April 1st, 2010)*
+
+* #concat is now deprecated in favor of using <%= %> helpers [YK]
+
+* Block helpers now return Strings, so you can use <%= form_for @foo do |f| %>.
+ <% form_for do |f| %> still works with deprecation notices [YK]
+
+* Add a new #mount method on the router that does not anchor the PATH_INFO
+ at the end [YK & CL]
+
+* Create a new LookupContext object that is responsible for performantly
+ finding a template for a given pattern [JV]
+
+* Removed relative_url_for in favor of respecting SCRIPT_NAME [YK & CL]
+
+* Changed file streaming to use Rack::Sendfile middleware [YK]
+
+* ActionDispatch::Request#content_type returns a String to be compatible with
+ Rack::Request. Use #content_mime_type for the Mime::Type instance [YK]
+
+* Updated Prototype to 1.6.1 and Scriptaculous to 1.8.3 [ML]
+
+* Change the preferred way that URL helpers are included into a class[YK & CL]
+
+ # for all helpers including named routes
+ include Rails.application.router.url_helpers
+
+ # for just url_for
+ include Rails.application.router.url_for
+
+
+*Rails 3.0.0 [beta 1] (February 4, 2010)*
* Fixed that PrototypeHelper#update_page should return html_safe [DHH]
@@ -14,9 +45,9 @@
flash[:notice] = 'Post was created'
redirect_to(@post)
-
+
...becomes:
-
+
redirect_to(@post, :notice => 'Post was created')
* Added ActionController::Base#notice/= and ActionController::Base#alert/= as a convenience accessors in both the controller and the view for flash[:notice]/= and flash[:alert]/= [DHH]
@@ -147,14 +178,14 @@
# Instead of <%= render :partial => "account" %>
<%= render "account" %>
-
+
# Instead of <%= render :partial => "account", :locals => { :account => @buyer } %>
<%= render "account", :account => @buyer %>
-
+
# @account is an Account instance, so it uses the RecordIdentifier to replace
# <%= render :partial => "accounts/account", :locals => { :account => @account } %>
<%= render(@account) %>
-
+
# @posts is an array of Post instances, so it uses the RecordIdentifier to replace
# <%= render :partial => "posts/post", :collection => @posts %>
<%= render(@posts) %>
@@ -245,7 +276,7 @@
* Make PrototypeHelper#submit_to_remote a wrapper around PrototypeHelper#button_to_remote. [Tarmo Tänav]
-* Set HttpOnly for the cookie session store's cookie. #1046
+* Set HttpOnly for the cookie session store's cookie. #1046
* Added FormTagHelper#image_submit_tag confirm option #784 [Alastair Brunton]
@@ -262,7 +293,7 @@
Completed in 0.10000 (4 reqs/sec) | Rendering: 0.04000 (40%) | DB: 0.00400 (4%) | 200 OK [http://example.com]
...to:
-
+
Completed in 100ms (View: 40, DB: 4) | 200 OK [http://example.com]
* Add support for shallow nesting of routes. #838 [S. Brent Faulkner]
@@ -347,7 +378,7 @@
* Deprecated TemplateHandler line offset [Josh Peek]
* Allow caches_action to accept cache store options. #416. [José Valim]. Example:
-
+
caches_action :index, :redirected, :if => Proc.new { |c| !c.request.format.json? }, :expires_in => 1.hour
* Remove define_javascript_functions, javascript_include_tag and friends are far superior. [Michael Koziarski]
@@ -357,7 +388,7 @@
* Add :as option to render a collection of partials with a custom local variable name. #509 [Simon Jefford, Pratik Naik]
render :partial => 'other_people', :collection => @people, :as => :person
-
+
This will let you access objects of @people as 'person' local variable inside 'other_people' partial template.
* time_zone_select: support for regexp matching of priority zones. Resolves #195 [Ernie Miller]
@@ -511,7 +542,7 @@
* Remove support for multivalued (e.g., '&'-delimited) cookies. [Jamis Buck]
-* Fix problem with render :partial collections, records, and locals. #11057 [lotswholetime]
+* Fix problem with render :partial collections, records, and locals. #11057 [lotswholetime]
* Added support for naming concrete classes in sweeper declarations [David Heinemeier Hansson]
@@ -534,7 +565,7 @@
* Make assert_routing aware of the HTTP method used. #8039 [mpalmer]
e.g. assert_routing({ :method => 'put', :path => '/product/321' }, { :controller => "product", :action => "update", :id => "321" })
-* Make map.root accept a single symbol as an argument to declare an alias. #10818 [bscofield]
+* Make map.root accept a single symbol as an argument to declare an alias. #10818 [bscofield]
e.g. map.dashboard '/dashboard', :controller=>'dashboard'
map.root :dashboard
@@ -543,7 +574,7 @@
* Add label_tag helper for generating elements. #10802 [DefV]
-* Introduce TemplateFinder to handle view paths and lookups. #10800 [Pratik Naik]
+* Introduce TemplateFinder to handle view paths and lookups. #10800 [Pratik Naik]
* Performance: optimize route recognition. Large speedup for apps with many resource routes. #10835 [oleganza]
@@ -768,7 +799,7 @@
* ActionController::Routing::DynamicSegment#interpolation_chunk should call #to_s on all values before calling URI.escape. [Rick Olson]
-* Only accept session ids from cookies, prevents session fixation attacks. [bradediger]
+* Only accept session ids from cookies, prevents session fixation attacks. [bradediger]
*2.0.0 [Preview Release]* (September 29th, 2007) [Includes duplicates of changes from 1.12.2 - 1.13.3]
@@ -827,7 +858,7 @@
def index
@posts = Post.find(:all)
-
+
respond_to do |format|
format.html # => renders index.html.erb and uses "text/html" as the content type
format.iphone # => renders index.iphone.erb and uses "text/html" as the content type
@@ -921,7 +952,7 @@
After filters will *no longer* be run if an around_filter fails to yield, users relying on
this behaviour are advised to put the code in question after a yield statement in an around filter.
-
+
* Allow you to delete cookies with options. Closes #3685 [Josh Peek, Chris Wanstrath]
@@ -1021,13 +1052,13 @@
* Update to Prototype 1.5.1. [Sam Stephenson]
-* Allow routes to be decalred under namespaces [Tobias Lütke]:
-
+* Allow routes to be decalred under namespaces [Tobias Lütke]:
+
map.namespace :admin do |admin|
- admin.root :controller => "products"
+ admin.root :controller => "products"
admin.feed 'feed.xml', :controller => 'products', :action => 'feed', :format => 'xml'
end
-
+
* Update to script.aculo.us 1.7.1_beta3. [Thomas Fuchs]
* observe_form always sends the serialized form. #5271 [Manfred Stienstra, normelton@gmail.com]
@@ -1039,7 +1070,7 @@
* Added url_for usage on render :location, which allows for record identification [David Heinemeier Hansson]. Example:
render :xml => person, :status => :created, :location => person
-
+
...expands the location to person_url(person).
* Introduce the request.body stream. Lazy-read to parse parameters rather than always setting RAW_POST_DATA. Reduces the memory footprint of large binary PUT requests. [Jeremy Kemper]
@@ -1067,21 +1098,21 @@
<% form_for(@post) do |f| %>
...
<% end %>
-
+
This will expand to be the same as:
-
+
<% form_for :post, @post, :url => post_path(@post), :html => { :method => :put, :class => "edit_post", :id => "edit_post_45" } do |f| %>
...
<% end %>
-
+
And for new records:
-
+
<% form_for(Post.new) do |f| %>
...
<% end %>
-
+
This will expand to be the same as:
-
+
<% form_for :post, @post, :url => posts_path, :html => { :class => "new_post", :id => "new_post" } do |f| %>
...
<% end %>
@@ -1093,7 +1124,7 @@
redirect_to(post) # => redirect_to(posts_url(post)) => Location: http://example.com/posts/1
link_to(post.title, post) # => link_to(post.title, posts_url(post)) => <a href="/posts/1">Hello world</a>
- Any method that calls url_for on its parameters will automatically benefit from this.
+ Any method that calls url_for on its parameters will automatically benefit from this.
* Removed deprecated parameters_for_method_reference concept (legacy from before named routes) [David Heinemeier Hansson]
@@ -1137,14 +1168,14 @@
* Added map.namespace to deal with the common situation of admin sections and the like [David Heinemeier Hansson]
Before:
-
+
map.resources :products, :path_prefix => "admin", :controller => "admin/products", :collection => { :inventory => :get }, :member => { :duplicate => :post }
map.resources :tags, :name_prefix => 'admin_product_', :path_prefix => "admin/products/:product_id", :controller => "admin/product_tags"
map.resources :images, :name_prefix => 'admin_product_', :path_prefix => "admin/products/:product_id", :controller => "admin/product_images"
map.resources :variants, :name_prefix => 'admin_product_', :path_prefix => "admin/products/:product_id", :controller => "admin/product_variants"
After:
-
+
map.namespace(:admin) do |admin|
admin.resources :products,
:collection => { :inventory => :get },
@@ -1160,28 +1191,28 @@
emails.resources :comments, :name_prefix => "email_"
emails.resources :attachments, :name_prefix => "email_"
end
-
+
After:
map.resources :emails do |emails|
emails.resources :comments
emails.resources :attachments
end
-
+
This does mean that if you intended to have comments_url go to /emails/5/comments, then you'll have to set :name_prefix to nil explicitly.
* Added :has_many and :has_one for declaring plural and singular resources beneath the current [David Heinemeier Hansson]
Before:
-
+
map.resources :notes do |notes|
notes.resources :comments
notes.resources :attachments
notes.resource :author
end
-
+
After:
-
+
map.resources :notes, :has_many => [ :comments, :attachments ], :has_one => :author
* Added that render :xml will try to call to_xml if it can [David Heinemeier Hansson]. Makes these work:
@@ -1209,9 +1240,9 @@
* Default xml template goes from #{action_name}.rxml => #{action_name}.xml.builder.
* Default rjs template goes from #{action_name}.rjs => #{action_name}.js.rjs.
-
+
You can still specify your old templates:
-
+
respond_to do |format|
format.xml do
render :action => "#{action_name}.rxml"
@@ -1239,8 +1270,8 @@
* Allow configuration of the default action cache path for #caches_action calls. [Rick Olson]
class ListsController < ApplicationController
- caches_action :index, :cache_path => Proc.new { |controller|
- controller.params[:user_id] ?
+ caches_action :index, :cache_path => Proc.new { |controller|
+ controller.params[:user_id] ?
controller.send(:user_lists_url, c.params[:user_id]) :
controller.send(:lists_url) }
end
@@ -1313,7 +1344,7 @@ Roos]
<link href="/stylesheets/style1.css" media="screen" rel="Stylesheet" type="text/css" />
<link href="/stylesheets/styleB.css" media="screen" rel="Stylesheet" type="text/css" />
<link href="/stylesheets/styleX2.css" media="screen" rel="Stylesheet" type="text/css" />
-
+
stylesheet_link_tag :all, :cache => true # when ActionController::Base.perform_caching is true =>
<link href="/stylesheets/all.css" media="screen" rel="Stylesheet" type="text/css" />
@@ -1469,7 +1500,7 @@ superclass' view_paths. [Rick Olson]
* Add singleton resources. [Rick Olson]
map.resource :account
-
+
GET /account
GET /account;edit
UPDATE /account
@@ -1508,7 +1539,7 @@ superclass' view_paths. [Rick Olson]
* Added the option for extension aliases to mime type registration [David Heinemeier Hansson]. Example (already in the default routes):
Mime::Type.register "text/html", :html, %w( application/xhtml+xml ), %w( xhtml )
-
+
...will respond on both .html and .xhtml.
* @response.redirect_url works with 201 Created responses: just return headers['Location'] rather than checking the response status. [Jeremy Kemper]
@@ -1577,7 +1608,7 @@ superclass' view_paths. [Rick Olson]
<% content_tag :div, :class => "strong" %>
Hello world!
<% end %>
-
+
Will output:
<div class="strong">Hello world!</div>
@@ -1636,7 +1667,7 @@ superclass' view_paths. [Rick Olson]
Gives:
<script defer="true" type="text/javascript">...</script>
-
+
Which is needed for dealing with the IE6 DOM when it's not yet fully loaded.
* Fixed that rescue template path shouldn't be hardcoded, then it's easier to hook in your own #6295 [Mike Naberezny]
@@ -1693,9 +1724,9 @@ superclass' view_paths. [Rick Olson]
* Added proper getters and setters for content type and charset [David Heinemeier Hansson]. Example of what we used to do:
response.headers["Content-Type"] = "application/atom+xml; charset=utf-8"
-
+
...now:
-
+
response.content_type = Mime::ATOM
response.charset = "utf-8"
@@ -1738,7 +1769,7 @@ superclass' view_paths. [Rick Olson]
* Fixed JavaScriptHelper#link_to_function and JavaScriptHelper#button_to_function to have the script argument be optional [David Heinemeier Hansson]. So what used to require a nil, like this:
link_to("Hider", nil, :class => "hider_link") { |p| p[:something].hide }
-
+
...can be written like this:
link_to("Hider", :class => "hider_link") { |p| p[:something].hide }
@@ -1756,7 +1787,7 @@ superclass' view_paths. [Rick Olson]
* Fixed that AssetTagHelper#image_tag and others using compute_public_path should not modify the incoming source argument (closes #5102) [eule@space.ch]
-* Deprecated the auto-appending of .png to AssetTagHelper#image_tag calls that doesn't have an extension [David Heinemeier Hansson]
+* Deprecated the auto-appending of .png to AssetTagHelper#image_tag calls that doesn't have an extension [David Heinemeier Hansson]
* Fixed FormOptionsHelper#select to respect :selected value #5813
@@ -1953,7 +1984,7 @@ superclass' view_paths. [Rick Olson]
class WeblogController < ActionController::Base
def index
@posts = Post.find :all
-
+
respond_to do |format|
format.html
format.xml { render :xml => @posts.to_xml }
@@ -1961,26 +1992,26 @@ superclass' view_paths. [Rick Olson]
end
end
end
-
+
# returns HTML when requested by a browser, since the browser
# has the HTML mimetype at the top of its priority list
Accept: text/html
- GET /weblog
-
- # returns the XML
+ GET /weblog
+
+ # returns the XML
Accept: application/xml
- GET /weblog
+ GET /weblog
- # returns the HTML
+ # returns the HTML
Accept: application/xml
GET /weblog.html
# returns the XML
Accept: text/html
GET /weblog.xml
-
+
All this relies on the fact that you have a route that includes .:format.
-
+
* Expanded :method option in FormTagHelper#form_tag, FormHelper#form_for, PrototypeHelper#remote_form_for, PrototypeHelper#remote_form_tag, and PrototypeHelper#link_to_remote to allow for verbs other than GET and POST by automatically creating a hidden form field named _method, which will simulate the other verbs over post [David Heinemeier Hansson]
* Added :method option to UrlHelper#link_to, which allows for using other verbs than GET for the link. This replaces the :post option, which is now deprecated. Example: link_to "Destroy", person_url(:id => person), :method => :delete [David Heinemeier Hansson]
@@ -2016,12 +2047,12 @@ superclass' view_paths. [Rick Olson]
* Fixes bad rendering of JavaScriptMacrosHelper rdoc (closes #4910) [Frederick Ros]
* Allow error_messages_for to report errors for multiple objects, as well as support for customizing the name of the object in the error summary header. Closes #4186. [andrew@redlinesoftware.com, Marcel Molina Jr.]
-
+
error_messages_for :account, :user, :subscription, :object_name => :account
* Enhance documentation for setting headers in integration tests. Skip auto HTTP prepending when its already there. Closes #4079. [Rick Olson]
-* Documentation for AbstractRequest. Closes #4895. [Kevin Clark]
+* Documentation for AbstractRequest. Closes #4895. [Kevin Clark]
* Refactor various InstanceTag instance method to class methods. Closes #4800. [Stefan Kaes]
@@ -2054,8 +2085,8 @@ superclass' view_paths. [Rick Olson]
* Modify routing so that you can say :require => { :method => :post } for a route, and the route will never be selected unless the request method is POST. Only works for route recognition, not for route generation. [Jamis Buck]
* Added :add_headers option to verify which merges a hash of name/value pairs into the response's headers hash if the prerequisites cannot be satisfied. [Sam Stephenson]
- ex. verify :only => :speak, :method => :post,
- :render => { :status => 405, :text => "Must be post" },
+ ex. verify :only => :speak, :method => :post,
+ :render => { :status => 405, :text => "Must be post" },
:add_headers => { "Allow" => "POST" }
* Added ActionController.filter_parameter_logging that makes it easy to remove passwords, credit card numbers, and other sensitive information from being logged when a request is handled #1897 [jeremye@bsa.ca.gov]
@@ -2221,7 +2252,7 @@ superclass' view_paths. [Rick Olson]
<% content_tag :div, :class => "strong" %>
Hello world!
<% end %>
-
+
Will output:
<div class="strong">Hello world!</div>
@@ -2274,7 +2305,7 @@ superclass' view_paths. [Rick Olson]
Gives:
<script defer="true" type="text/javascript">...</script>
-
+
Which is needed for dealing with the IE6 DOM when it's not yet fully loaded.
* Fixed that rescue template path shouldn't be hardcoded, then it's easier to hook in your own #6295 [Mike Naberezny]
@@ -2329,9 +2360,9 @@ superclass' view_paths. [Rick Olson]
* Added proper getters and setters for content type and charset [David Heinemeier Hansson]. Example of what we used to do:
response.headers["Content-Type"] = "application/atom+xml; charset=utf-8"
-
+
...now:
-
+
response.content_type = Mime::ATOM
response.charset = "utf-8"
@@ -2366,7 +2397,7 @@ superclass' view_paths. [Rick Olson]
* Fixed JavaScriptHelper#link_to_function and JavaScriptHelper#button_to_function to have the script argument be optional [David Heinemeier Hansson]. So what used to require a nil, like this:
link_to("Hider", nil, :class => "hider_link") { |p| p[:something].hide }
-
+
...can be written like this:
link_to("Hider", :class => "hider_link") { |p| p[:something].hide }
@@ -2380,7 +2411,7 @@ superclass' view_paths. [Rick Olson]
* Fixed that AssetTagHelper#image_tag and others using compute_public_path should not modify the incoming source argument (closes #5102) [eule@space.ch]
-* Deprecated the auto-appending of .png to AssetTagHelper#image_tag calls that doesn't have an extension [David Heinemeier Hansson]
+* Deprecated the auto-appending of .png to AssetTagHelper#image_tag calls that doesn't have an extension [David Heinemeier Hansson]
* Fixed FormOptionsHelper#select to respect :selected value #5813
@@ -2546,7 +2577,7 @@ superclass' view_paths. [Rick Olson]
class WeblogController < ActionController::Base
def index
@posts = Post.find :all
-
+
respond_to do |format|
format.html
format.xml { render :xml => @posts.to_xml }
@@ -2554,26 +2585,26 @@ superclass' view_paths. [Rick Olson]
end
end
end
-
+
# returns HTML when requested by a browser, since the browser
# has the HTML mimetype at the top of its priority list
Accept: text/html
- GET /weblog
-
- # returns the XML
+ GET /weblog
+
+ # returns the XML
Accept: application/xml
- GET /weblog
+ GET /weblog
- # returns the HTML
+ # returns the HTML
Accept: application/xml
GET /weblog.html
# returns the XML
Accept: text/html
GET /weblog.xml
-
+
All this relies on the fact that you have a route that includes .:format.
-
+
* Expanded :method option in FormTagHelper#form_tag, FormHelper#form_for, PrototypeHelper#remote_form_for, PrototypeHelper#remote_form_tag, and PrototypeHelper#link_to_remote to allow for verbs other than GET and POST by automatically creating a hidden form field named _method, which will simulate the other verbs over post [David Heinemeier Hansson]
* Added :method option to UrlHelper#link_to, which allows for using other verbs than GET for the link. This replaces the :post option, which is now deprecated. Example: link_to "Destroy", person_url(:id => person), :method => :delete [David Heinemeier Hansson]
@@ -2595,7 +2626,7 @@ superclass' view_paths. [Rick Olson]
* Use #flush between switching from #write to #syswrite. Closes #4907. [Blair Zajac <blair@orcaware.com>]
* Allow error_messages_for to report errors for multiple objects, as well as support for customizing the name of the object in the error summary header. Closes #4186. [andrew@redlinesoftware.com, Marcel Molina Jr.]
-
+
error_messages_for :account, :user, :subscription, :object_name => :account
* Fix assert_redirected_to tests according to real-world usage. Also, don't fail if you add an extra :controller option: [Rick Olson]
@@ -2617,8 +2648,8 @@ superclass' view_paths. [Rick Olson]
* Modify routing so that you can say :require => { :method => :post } for a route, and the route will never be selected unless the request method is POST. Only works for route recognition, not for route generation. [Jamis Buck]
* Added :add_headers option to verify which merges a hash of name/value pairs into the response's headers hash if the prerequisites cannot be satisfied. [Sam Stephenson]
- ex. verify :only => :speak, :method => :post,
- :render => { :status => 405, :text => "Must be post" },
+ ex. verify :only => :speak, :method => :post,
+ :render => { :status => 405, :text => "Must be post" },
:add_headers => { "Allow" => "POST" }
@@ -2683,7 +2714,7 @@ superclass' view_paths. [Rick Olson]
* Added automated timestamping to AssetTagHelper methods for stylesheets, javascripts, and images when Action Controller is run under Rails [David Heinemeier Hansson]. Example:
image_tag("rails.png") # => '<img alt="Rails" src="/images/rails.png?1143664135" />'
-
+
...to avoid frequent stats (not a problem for most people), you can set RAILS_ASSET_ID in the ENV to avoid stats:
ENV["RAILS_ASSET_ID"] = "2345"
@@ -2703,9 +2734,9 @@ superclass' view_paths. [Rick Olson]
* Change #form_for and #fields_for so that the second argument is not required [Dave Thomas]
<% form_for :post, @post, :url => { :action => 'create' } do |f| -%>
-
+
becomes...
-
+
<% form_for :post, :url => { :action => 'create' } do |f| -%>
* Update to script.aculo.us 1.6 [Thomas Fuchs]
@@ -2723,11 +2754,11 @@ superclass' view_paths. [Rick Olson]
* Added nicer message for assert_redirected_to (closes #4294) [court3nay]
assert_redirected_to :action => 'other_host', :only_path => false
-
+
when it was expecting...
-
+
redirected_to :action => 'other_host', :only_path => true, :host => 'other.test.host'
-
+
gives the error message...
response is not a redirection to all of the options supplied (redirection is <{:only_path=>false, :host=>"other.test.host", :action=>"other_host"}>), difference: <{:only_path=>"true", :host=>"other.test.host"}>
@@ -2774,11 +2805,11 @@ superclass' view_paths. [Rick Olson]
* CHANGED DEFAULT: The default content type for .rxml is now application/xml instead of type/xml, see http://www.xml.com/pub/a/2004/07/21/dive.html for reason [David Heinemeier Hansson]
* Added option to render action/template/file of a specific extension (and here by template type). This means you can have multiple templates with the same name but a different extension [David Heinemeier Hansson]. Example:
-
+
class WeblogController < ActionController::Base
def index
@posts = Post.find :all
-
+
respond_to do |type|
type.html # using defaults, which will render weblog/index.rhtml
type.xml { render :action => "index.rxml" }
@@ -2792,7 +2823,7 @@ superclass' view_paths. [Rick Olson]
class WeblogController < ActionController::Base
def create
@post = Post.create(params[:post])
-
+
respond_to do |type|
type.js { render } # renders create.rjs
type.html { redirect_to :action => "index" }
@@ -2818,16 +2849,16 @@ superclass' view_paths. [Rick Olson]
* Added plugin support for parameter parsers, which allows for better support for REST web services. By default, posts submitted with the application/xml content type is handled by creating a XmlSimple hash with the same name as the root element of the submitted xml. More handlers can easily be registered like this:
# Assign a new param parser to a new content type
- ActionController::Base.param_parsers['application/atom+xml'] = Proc.new do |data|
- node = REXML::Document.new(post)
+ ActionController::Base.param_parsers['application/atom+xml'] = Proc.new do |data|
+ node = REXML::Document.new(post)
{ node.root.name => node.root }
end
# Assign the default XmlSimple to a new content type
ActionController::Base.param_parsers['application/backpack+xml'] = :xml_simple
-
+
Default YAML web services were retired, ActionController::Base.param_parsers carries an example which shows how to get this functionality back. As part of this new plugin support, request.[formatted_post?, xml_post?, yaml_post? and post_format] were all deprecated in favor of request.content_type [Tobias Lütke]
-
+
* Fixed Effect.Appear in effects.js to work with floats in Safari #3524, #3813, #3044 [Thomas Fuchs]
* Fixed that default image extension was not appended when using a full URL with AssetTagHelper#image_tag #4032, #3728 [rubyonrails@beautifulpixel.com]
@@ -2865,7 +2896,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
page['blank_slate'] # => $('blank_slate');
page['blank_slate'].show # => $('blank_slate').show();
page['blank_slate'].show('first').up # => $('blank_slate').show('first').up();
-
+
page.select('p') # => $$('p');
page.select('p.welcome b').first # => $$('p.welcome b').first();
page.select('p.welcome b').first.hide # => $$('p.welcome b').first().hide();
@@ -3003,7 +3034,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Add session ID to default logging, but remove the verbose description of every step [David Heinemeier Hansson]
* Add the following RJS methods: [Sam Stephenson]
-
+
* alert - Displays an alert() dialog
* redirect_to - Changes window.location.href to simulate a browser redirect
* call - Calls a JavaScript function
@@ -3085,13 +3116,13 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
page.visual_effect :highlight, 'list'
page.hide 'status-indicator', 'cancel-link'
end
-
+
generates the following JavaScript:
-
+
new Insertion.Bottom("list", "<li>Last item</li>");
new Effect.Highlight("list");
["status-indicator", "cancel-link"].each(Element.hide);
-
+
* Refactored JavaScriptHelper into PrototypeHelper and ScriptaculousHelper [Sam Stephenson]
* Update to latest script.aculo.us version (as of [3031])
@@ -3114,12 +3145,12 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
<% form_for :person, person, :url => { :action => "update" } do |person_form| %>
First name: <%= person_form.text_field :first_name %>
Last name : <%= person_form.text_field :last_name %>
-
+
<% fields_for :permission => person.permission do |permission_fields| %>
Admin? : <%= permission_fields.check_box :admin %>
<% end %>
<% end %>
-
+
* options_for_select allows any objects which respond_to? :first and :last rather than restricting to Array and Range. #2824 [Jacob Robbins <jrobbins@cmj.com>, Jeremy Kemper]
* The auto_link text helper accepts an optional block to format the link text for each url and email address. Example: auto_link(post.body) { |text| truncate(text, 10) } [Jeremy Kemper]
@@ -3150,11 +3181,11 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
class ApplicationController < ActionController::Base
before_filter :authenticate
end
-
+
class WeblogController < ApplicationController
# will run the :authenticate filter
end
-
+
class SignupController < ActionController::Base
# will not run the :authenticate filter
skip_before_filter :authenticate
@@ -3300,7 +3331,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Added easy assignment of fragment cache store through use of symbols for included stores (old way still works too)
Before:
- ActionController::Base.fragment_cache_store =
+ ActionController::Base.fragment_cache_store =
ActionController::Base::Caching::Fragments::FileStore.new("/path/to/cache/directory")
After:
@@ -3463,7 +3494,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Added incremental and local autocompleting and loads of documentation to controls.js [Ivan Krstic]
* Extended the auto_complete_field helper to accept tokens option
* Changed object extension mechanism to favor Object.extend to make script.aculo.us easily adaptable to support 3rd party libs like IE7.js [David Zülke]
-
+
* Fixed that named routes didn't use the default values for action and possible other parameters #1534 [Nicholas Seckar]
* Fixed JavascriptHelper#visual_effect to use camelize such that :blind_up will work #1639 [pelletierm@eastmedia.net]
@@ -3519,13 +3550,13 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Added support for graceful error handling of Ajax calls #1217 [Jamis Buck/Thomas Fuchs]. Example:
link_to_remote(
- "test",
- :url => { :action => "faulty" },
+ "test",
+ :url => { :action => "faulty" },
:update => { :success => "good", :failure => "bad" },
403 => "alert('Forbidden- got ya!')",
- 404 => "alert('Nothing there...?')",
+ 404 => "alert('Nothing there...?')",
:failure => "alert('Unkown error ' + request.status)")
-
+
* Attempt to explicitly flush the output at the end of CgiProcess#out
* Fixed assert_redirected_to to handle absolute controller paths properly #1472 [Rick Olson/Nicholas Seckar]
@@ -3536,7 +3567,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Fixed prototype to consider all fields it doesn't know as text (such as Safari's search) just like the browser in its serialization #1497 [Sean Treadway]
-* Improved performance of Routes generation by a factor of 5 #1434 [Nicholas Seckar]
+* Improved performance of Routes generation by a factor of 5 #1434 [Nicholas Seckar]
* Added named routes (NEEDS BETTER DESCRIPTION) #1434 [Nicholas Seckar]
@@ -3567,8 +3598,8 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Correct distance_of_time_in_words for integer arguments and make the second arg optional, treating the first arg as a duration in seconds. #1458 [madrobby <thomas@fesch.at>]
-* Fixed query parser to deal gracefully with equal signs inside keys and values #1345 [gorou].
- Example: /?sig=abcdef=:foobar=&x=y will pass now.
+* Fixed query parser to deal gracefully with equal signs inside keys and values #1345 [gorou].
+ Example: /?sig=abcdef=:foobar=&x=y will pass now.
* Added Cuba to country list #1351 [todd]
@@ -3588,7 +3619,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Ensure that helpers are only available to the controllers where they are defined and their subclasses. #1394 [kdole@tamu.edu]
-* render("foo/bar") works with a layout again
+* render("foo/bar") works with a layout again
* Fixed double-singularization on scaffolded pagination call (Address would be turned into Addres) #1216, #1404 [nilsga]
@@ -3636,7 +3667,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
| render_text "hello world!" | render :text => "hello world!" |
| render_partial_collection "person", @people, nil, :a => 1 | render :partial => "person", :collection => @people, |
| | :locals => { :a => 1 } |
- +---------------------------------------------------------------+-------------------------------------------------------+
+ +---------------------------------------------------------------+-------------------------------------------------------+
* Deprecated redirect_to_path and redirect_to_url in favor of letting redirect_to do the right thing when passed either a path or url.
@@ -3664,7 +3695,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
Content-Type: application/xml
<request><item><content>HelloWorld</content></item></request>
-
+
...is the same as:
Content-Type: application/x-yaml
@@ -3673,11 +3704,11 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
content: HelloWorld
...is the same as:
-
+
item[content]=HelloWorld
-
+
Which in the end turns into { "item" => { "content" => "HelloWorld" } }. This makes it a lot easier to publish REST web services on top of your regular actions (as they won't care).
-
+
Example Curl call:
curl -H 'Content-Type: application/xml' -d '<request><item><content>KillMeMore</content></item></request>' http://www.example.com/service
@@ -3721,11 +3752,11 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Removed dumping of template assigns on the rescue page as it would very easily include a ton of data making page loads take seconds (and the information was rarely helpful) #1222
* Added BenchmarkHelper that can measure the execution time of a block in a template and reports the result to the log. Example:
-
+
<% benchmark "Notes section" do %>
<%= expensive_notes_operation %>
<% end %>
-
+
Will add something like "Notes section (0.345234)" to the log.
* Added ActionController::Caching::Sweeper as an improved an easier to use sweeper. The new sweepers work on a single-step approach instead of two-steps like the old ones. Before
@@ -3733,7 +3764,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
def after_save(record)
@list = record.is_a?(List) ? record : record.list
end
-
+
def filter(controller)
controller.expire_page(:controller => "lists", :action => %w( show public feed ), :id => @list.id)
controller.expire_action(:controller => "lists", :action => "all")
@@ -3750,7 +3781,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
end
The new sweepers can also observe on the actions themselves by implementing methods according to (before|after)_$controller_$action. Example of a callback that'll be called after PagesController#update_title has been performed:
-
+
def after_pages_update_title
expire_fragment(%r{pages/#{controller.assigns["page"].id}/.*})
end
@@ -3789,16 +3820,16 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Added a wide range of new Javascript effects:
* Effect.Puff zooms the element out and makes it smoothly transparent at the same time, giving a "puff" illusion #996 [thomas@fesch.at]
- After the animation is completed, the display property will be set to none.
+ After the animation is completed, the display property will be set to none.
This effect will work on relative and absolute positioned elements.
-
+
* Effect.Appear as the opposite of Effect.Fade #990 [thomas@fesch.at]
You should return elements with style="display:none;" or a like class for this to work best and have no chance of flicker.
-
+
* Effect.Squish for scaling down an element and making it disappear at the end #972 [thomas@fesch.at]
-
+
* Effect.Scale for smoothly scaling images or text up and down #972 [thomas@fesch.at]
-
+
* Effect.Fade which smoothly turns opacity from 100 to 0 and then hides the element #960 [thomas@fesch.at]
* Added Request#xml_http_request? (and an alias xhr?) to that'll return true when the request came from one of the Javascript helper methods (Ajax). This can be used to give one behavior for modern browsers supporting Ajax, another to old browsers #1127 [Sam Stephenson]
@@ -3806,11 +3837,11 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Changed render_partial to take local assigns as the second parameter instead of an explicit object and then the assigns. So the API changes from:
<%= render_partial "account", person, "rules" => regulations.rules %>
-
+
...to:
-
+
<%= render_partial "account", :account => person, :rules => regulations.rules %>
-
+
The old API will still work, though, and render_partial "account" will still assume :account => @account.
* Added support for web servers that use PATH_INFO instead of REQUEST_URI like IIS #1014 [BradG/Nicholas Seckar]
@@ -3951,7 +3982,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
flash.now[:message] = 'Save failed, review'
render_action 'edit'
end
- end
+ end
end
* Added to_param call for parameters when composing an url using url_for from something else than strings #812 [Sam Stephenson]. Example:
@@ -3989,7 +4020,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
A request for /categories/top-level-cat, would give @params[:path_info] with "top-level-cat".
A request for /categories/top-level-cat/level-1-cat, would give @params[:path_info] with "top-level-cat/level-1-cat" and so forth.
-
+
The @params[:path_info] return is really an array, but where to_s has been overwritten to do join("/").
* Fixed options_for_select on selected line issue #624 [Florian Weber]
@@ -4110,11 +4141,11 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
def test_create_post
post :create, "post" => { "title" => "Exciting!" }
assert_redirected_to :action => "show"
-
+
follow_redirect
assert_rendered_file "post/show"
end
-
+
Limitation: Only works for redirects to other actions within the same controller.
* Fixed double requiring of models with the same name as the controller
@@ -4139,9 +4170,9 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
<%= text_field "student[]", "last_name" %>
<%= text_field "student[]", "grade", :size => "5" %>
<% end %>
-
+
...would produce, for say David Black with id 123 and a grace of C+:
-
+
<input id="student_123_first_name" name="student[123][first_name]" size="20" size="30" type="text" value="David" />
<input id="student_123_last_name" name="student[123][last_name]" size="30" type="text" value="Black" />
<input id="student_123_grade" name="student[123][grade]" size="5" type="text" value="C+" />
@@ -4171,7 +4202,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
class WeblogController
before_filter { |c| c.send(:redirect_to_url("http://www.farfaraway.com")}) }
-
+
def hello
render_text "I will never be called"
end
@@ -4184,7 +4215,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
redirect_to :action => "elsewhere"
render_action "overthere"
end
-
+
Only the redirect happens. The rendering call is simply ignored.
@@ -4194,12 +4225,12 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Added assert_cookie_equal to assert the contents of a named cookie
-* Fixed bug in page caching that prevented it from working at all
+* Fixed bug in page caching that prevented it from working at all
*1.3.0* (January 17th, 2005)
-* Added an extensive caching module that offers three levels of granularity (page, action, fragment) and a variety of stores.
+* Added an extensive caching module that offers three levels of granularity (page, action, fragment) and a variety of stores.
Read more in ActionController::Caching.
* Added the option of passing a block to ActiveRecordHelper#form in order to add more to the auto-generated form #469 [dom@sisna.com]
@@ -4238,9 +4269,9 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Fixed three issues with retrying breakpoints #417 [Florian Gross]
- 1. Don't screw up pages that use multiple values for the same parameter (?foo=bar&foo=qux was converted to ?foo=barqux)
- 2. Don't screw up all forms when you click the "Retry with Breakpoint" link multiple times instead of reloading
- (This caused the parameters to be added multiple times for GET forms leading to trouble.)
+ 1. Don't screw up pages that use multiple values for the same parameter (?foo=bar&foo=qux was converted to ?foo=barqux)
+ 2. Don't screw up all forms when you click the "Retry with Breakpoint" link multiple times instead of reloading
+ (This caused the parameters to be added multiple times for GET forms leading to trouble.)
3. Don't add ?BP-RETRY=1 multiple times
* Added that all renders and redirects now return false, so they can be used as the last line in before_filters to stop execution.
@@ -4252,7 +4283,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
return false
end
end
-
+
After:
def authenticate
redirect_to(:controller => "account", :action => "login") unless @session[:authenticated]
@@ -4263,7 +4294,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
class JournalController < ActionController::Base
# only require authentication if the current action is edit or delete
before_filter :authorize, :only_on => [ :edit, :delete ]
-
+
private
def authorize
# redirect to login unless authenticated
@@ -4307,7 +4338,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Added more informative exception when using helper :some_helper and the helper requires another file that fails, you'll get an
error message tells you what file actually failed to load, rather than falling back on assuming it was the helper file itself #346 [dblack]
-* Added use of *_before_type_cast for all input and text fields. This is helpful for getting "100,000" back on a integer-based
+* Added use of *_before_type_cast for all input and text fields. This is helpful for getting "100,000" back on a integer-based
validation where the value would normally be "100".
* Added Request#port_string to get something like ":8080" back on 8080 and "" on 80 (or 443 with https).
@@ -4354,15 +4385,15 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
scaffold :<%= singular_name %>
<% end %>
helper :post
-
+
...produces this on post as singular_name:
class SomeController < ApplicationController
-
+
scaffold :post
-
+
helper :post
-
+
...where as:
class SomeController < ApplicationController
@@ -4370,18 +4401,18 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
scaffold :<%= singular_name %>
<% end -%>
helper :post
-
+
...produces:
class SomeController < ApplicationController
scaffold :post
helper :post
-
+
[This undocumented gem for ERb was uncovered by bitsweat]
* Fixed CgiRequest so that it'll now accept session options with Symbols as keys (as the documentation points out) [Suggested by Andreas]
-* Added that render_partial will always by default include a counter with value 1 unless there is a counter passed in via the
+* Added that render_partial will always by default include a counter with value 1 unless there is a counter passed in via the
local_assigns hash that overrides it. As a result, render_collection_of_partials can still be written in terms of render_partial
and partials that make use of a counter can be called without problems from both render_collection_of_partials as well as
render_partial #295 [Marcel Molina Jr.]
@@ -4396,12 +4427,12 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
link:classes/ActionController/Base.html#M000021. It's also possible to pass a string instead of an options hash to
get a link tag that just points without consideration. The <tt>html_options</tt> works jointly for the image and ahref tag by
letting the following special values enter the options on the image and the rest goes to the ahref:
-
+
::alt: If no alt text is given, the file name part of the +src+ is used (capitalized and without the extension)
::size: Supplied as "XxY", so "30x45" becomes width="30" and height="45"
::align: Sets the alignment, no special features
-
- The +src+ can be supplied as a...
+
+ The +src+ can be supplied as a...
* full path, like "/my_images/image.gif"
* file name, like "rss.gif", that gets expanded to "/images/rss.gif"
* file name without extension, like "logo", that gets expanded to "/images/logo.png"
@@ -4416,10 +4447,10 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
# Calls Controller#miletone with a GET request
process :milestone
-
+
# Calls Controller#miletone with a POST request that has parameters
post :milestone, { "name" => "David" }
-
+
# Calls Controller#milestone with a HEAD request that has both parameters and session data
head :milestone, { "id" => 1 }, { "user_id" => 23 }
@@ -4429,7 +4460,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Added indifference to whether @headers["Content-Type"], @headers["Content-type"], or @headers["content-type"] is used.
-* Added TestSession#session_id that returns an empty string to make it easier to functional test applications that doesn't use
+* Added TestSession#session_id that returns an empty string to make it easier to functional test applications that doesn't use
cookie-based sessions #275 [jcf]
* Fixed that cached template loading would still check the file system to see if the file existed #258 [Andreas Schwarz]
@@ -4444,9 +4475,9 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
cookies["user_name"] = "david" # => Will set a simple session cookie
cookies["login"] = { "value" => "XJ-122", "expires" => Time.now + 360} # => Will set a cookie that expires in 1 hour
-
+
Examples for reading:
-
+
cookies["user_name"] # => "david"
cookies.size # => 2
@@ -4481,14 +4512,14 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
class MsgController < ApplicationController
helper :msg
end
-
+
...you can just do:
-
+
class MsgController < ApplicationController
end
* Added dependencies_on(layer) to query the dependencies of a controller. Examples:
-
+
MsgController.dependencies_on(:model) # => [ :post, :comment, :attachment ]
MsgController.dependencies_on(:service) # => [ :notification_service ]
MsgController.dependencies_on(:observer) # => [ :comment_observer ]
@@ -4543,7 +4574,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
class WeblogController < ActionController::Base
include WeblogHelper
end
-
+
After:
module WeblogHelper
@@ -4579,10 +4610,10 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Changed scaffolding of forms to use <label> tags instead of <b> to please W3C [evl]
-* Added DateHelper#distance_of_time_in_words_to_now(from_time) that works like distance_of_time_in_words,
+* Added DateHelper#distance_of_time_in_words_to_now(from_time) that works like distance_of_time_in_words,
but where <tt>to_time</tt> is fixed to <tt>Time.now</tt>.
-* Added assert_flash_equal(expected, key, message), assert_session_equal(expected, key, message),
+* Added assert_flash_equal(expected, key, message), assert_session_equal(expected, key, message),
assert_assigned_equal(expected, key, message) to test the contents of flash, session, and template assigns.
* Improved the failure report on assert_success when the action triggered a redirection [alexey].
@@ -4607,7 +4638,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
xml.description "Basecamp: Recent items"
xml.language "en-us"
xml.ttl "40"
-
+
for item in @recent_items
xml.item do
xml.title(item_title(item))
@@ -4615,7 +4646,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
xml.pubDate(item_pubDate(item))
xml.guid(@person.firm.account.url + @recent_items.url(item))
xml.link(@person.firm.account.url + @recent_items.url(item))
-
+
xml.tag!("dc:creator", item.author_name) if item_has_creator?(item)
end
end
@@ -4652,12 +4683,12 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
of the tag you want. Options for the tag can be specified as a hash parameter to that method.
Builder-based templates can be mixed and matched with the regular ERb ones. The only thing that differentiates them is the extension.
- No new methods have been added to the public interface to handle them.
-
+ No new methods have been added to the public interface to handle them.
+
Action Pack ships with a version of Builder, but it will use the RubyGems version if you have one installed.
-
+
Read more about Builder on: http://onestepback.org/index.cgi/Tech/Ruby/StayingSimple.rdoc
-
+
[Builder is created by Jim Weirich]
* Added much improved support for functional testing [what-a-day].
@@ -4668,9 +4699,9 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
@request.action = "authenticate"
@request.request_parameters["user_name"] = "nop"
@request.request_parameters["password"] = ""
-
+
response = LoginController.process_test(@request)
-
+
assert_equal "The username and/or password you entered is invalid.", response.session["flash"]["alert"]
assert_equal "http://37signals.basecamp.com/login/", response.headers["location"]
end
@@ -4684,7 +4715,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
See a full example on http://codepaste.org/view/paste/334
-* Increased performance by up to 100% with a revised cookie class that fixes the performance problems with the
+* Increased performance by up to 100% with a revised cookie class that fixes the performance problems with the
default one that ships with 1.8.1 and below. It replaces the inheritance on SimpleDelegator with DelegateClass(Array)
following the suggestion from Matz on:
http://groups.google.com/groups?th=e3a4e68ba042f842&seekm=c3sioe%241qvm%241%40news.cybercity.dk#link14
@@ -4694,9 +4725,9 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Added implicit counter variable to render_collection_of_partials [Marcel Molina Jr.]. From the docs:
<%= render_collection_of_partials "ad", @advertisements %>
-
+
This will render "advertiser/_ad.rhtml" and pass the local variable +ad+ to the template for display. An iteration counter
- will automatically be made available to the template with a name of the form +partial_name_counter+. In the case of the
+ will automatically be made available to the template with a name of the form +partial_name_counter+. In the case of the
example above, the template would be fed +ad_counter+.
* Fixed problems with two sessions being maintained on reset_session that would particularly screw up ActiveRecordStore.
@@ -4712,15 +4743,15 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Added JavaScript confirm feature to link_to. Documentation:
- The html_options have a special feature for creating javascript confirm alerts where if you pass
+ The html_options have a special feature for creating javascript confirm alerts where if you pass
:confirm => 'Are you sure?', the link will be guarded with a JS popup asking that question.
If the user accepts, the link is processed, otherwise not.
* Added link_to_unless_current as a UrlHelper method [Sam Stephenson]. Documentation:
- Creates a link tag of the given +name+ using an URL created by the set of +options+, unless the current
+ Creates a link tag of the given +name+ using an URL created by the set of +options+, unless the current
controller, action, and id are the same as the link's, in which case only the name is returned (or the
- given block is yielded, if one exists). This is useful for creating link bars where you don't want to link
+ given block is yielded, if one exists). This is useful for creating link bars where you don't want to link
to the page currently being viewed.
* Fixed that UrlRewriter (the driver for url_for, link_to, etc) would blow up when the anchor was an integer [alexey]
@@ -4740,9 +4771,9 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Added the possibility for shared partials. Example:
<%= render_partial "advertisement/ad", ad %>
-
+
This will render the partial "advertisement/_ad.rhtml" regardless of which controller this is being called from.
-
+
[Jacob Fugal]
* Fixed crash when encountering forms that have empty-named fields [James Prudente]
@@ -4768,7 +4799,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
...can now be as:
before_filter { |controller| return false if controller.params["stop_action"] }
-
+
[Jeremy Kemper]
* Made the following methods public (was protected): url_for, controller_class_name, controller_name, action_name
@@ -4781,7 +4812,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Changed base class setup from AbstractTemplate/ERbTemplate to ActionView::Base. This change should be harmless unless you were
accessing Action View directly in which case you now need to reference the Base class.\
-* Added that render_collection_of_partials returns nil if the collection is empty. This makes showing a “no items” message easier.
+* Added that render_collection_of_partials returns nil if the collection is empty. This makes showing a “no items” message easier.
For example: <%= render_collection_of_partials("message", @messages) || "No messages found." %> [Sam Stephenson]
* Added :month_before_year as an option to date_select to get the month select before the year. Especially useful for credit card forms.
@@ -4809,42 +4840,42 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Introduced passing of locally scoped variables between templates:
- You can pass local variables to sub templates by using a hash of with the variable
+ You can pass local variables to sub templates by using a hash of with the variable
names as keys and the objects as values:
-
+
<%= render "shared/header", { "headline" => "Welcome", "person" => person } %>
-
+
These can now be accessed in shared/header with:
-
+
Headline: <%= headline %>
First name: <%= person.first_name %>
-
+
* Introduced the concept of partials as a certain type of sub templates:
- There's also a convenience method for rendering sub templates within the current
- controller that depends on a single object (we call this kind of sub templates for
+ There's also a convenience method for rendering sub templates within the current
+ controller that depends on a single object (we call this kind of sub templates for
partials). It relies on the fact that partials should follow the naming convention
of being prefixed with an underscore -- as to separate them from regular templates
that could be rendered on their own. In the template for Advertiser#buy, we could have:
-
+
<% for ad in @advertisements %>
<%= render_partial "ad", ad %>
<% end %>
-
- This would render "advertiser/_ad.rhtml" and pass the local variable +ad+
+
+ This would render "advertiser/_ad.rhtml" and pass the local variable +ad+
for the template to display.
-
+
== Rendering a collection of partials
-
+
The example of partial use describes a familar pattern where a template needs
- to iterate over a array and render a sub template for each of the elements.
- This pattern has been implemented as a single method that accepts an array and
- renders a partial by the same name of as the elements contained within. So the
+ to iterate over a array and render a sub template for each of the elements.
+ This pattern has been implemented as a single method that accepts an array and
+ renders a partial by the same name of as the elements contained within. So the
three-lined example in "Using partials" can be rewritten with a single line:
-
+
<%= render_collection_of_partials "ad", @advertisements %>
-
- So this will render "advertiser/_ad.rhtml" and pass the local variable +ad+ for
+
+ So this will render "advertiser/_ad.rhtml" and pass the local variable +ad+ for
the template to display.
* Improved send_file by allowing a wide range of options to be applied [Jeremy Kemper]:
@@ -4852,36 +4883,36 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
Sends the file by streaming it 4096 bytes at a time. This way the
whole file doesn't need to be read into memory at once. This makes
it feasible to send even large files.
-
+
Be careful to sanitize the path parameter if it coming from a web
page. send_file(@params['path'] allows a malicious user to
download any file on your server.
-
+
Options:
- * <tt>:filename</tt> - specifies the filename the browser will see.
+ * <tt>:filename</tt> - specifies the filename the browser will see.
Defaults to File.basename(path).
- * <tt>:type</tt> - specifies an HTTP content type.
+ * <tt>:type</tt> - specifies an HTTP content type.
Defaults to 'application/octet-stream'.
- * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded.
+ * <tt>:disposition</tt> - specifies whether the file will be shown inline or downloaded.
Valid values are 'inline' and 'attachment' (default).
* <tt>:buffer_size</tt> - specifies size (in bytes) of the buffer used to stream
the file. Defaults to 4096.
-
+
The default Content-Type and Content-Disposition headers are
set to download arbitrary binary files in as many browsers as
possible. IE versions 4, 5, 5.5, and 6 are all known to have
a variety of quirks (especially when downloading over SSL).
-
+
Simple download:
send_file '/path/to.zip'
-
+
Show a JPEG in browser:
send_file '/path/to.jpeg', :type => 'image/jpeg', :disposition => 'inline'
-
+
Read about the other Content-* HTTP headers if you'd like to
provide the user with more information (such as Content-Description).
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.11
-
+
Also be aware that the document may be cached by proxies and browsers.
The Pragma and Cache-Control headers declare how the file may be cached
by intermediaries. They default to require clients to validate with
@@ -4908,74 +4939,74 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Added select, collection_select, and country_select to make it easier for Active Records to set attributes through
drop-down lists of options. Example:
-
+
<%= select "person", "gender", %w( Male Female ) %>
-
+
...would give the following:
-
+
<select name="person[gender]" id="person_gender"><option>Male</option><option>Female</option></select>
* Added an option for getting multiple values on a single form name into an array instead of having the last one overwrite.
This is especially useful for groups of checkboxes, which can now be written as:
-
+
<input type="checkbox" name="rights[]" value="CREATE" />
<input type="checkbox" name="rights[]" value="UPDATE" />
<input type="checkbox" name="rights[]" value="DELETE" />
-
+
...and retrieved in the controller action with:
-
+
@params["rights"] # => [ "CREATE", "UPDATE", "DELETE" ]
-
- The old behavior (where the last one wins, "DELETE" in the example) is still available. Just don't add "[]" to the
+
+ The old behavior (where the last one wins, "DELETE" in the example) is still available. Just don't add "[]" to the
end of the name. [Scott Baron]
-
+
* Added send_file which uses the new render_text block acceptance to make it feasible to send large files.
- The files is sent with a bunch of voodoo HTTP headers required to get arbitrary files to download as
+ The files is sent with a bunch of voodoo HTTP headers required to get arbitrary files to download as
expected in as many browsers as possible (eg, IE hacks). Example:
-
+
def play_movie
send_file "/movies/that_movie.avi"
end
-
+
[Jeremy Kemper]
-* render_text now accepts a block for deferred rendering. Useful for streaming large files, displaying
+* render_text now accepts a block for deferred rendering. Useful for streaming large files, displaying
a “please wait” message during a complex search, etc. Streaming example:
-
+
render_text do |response|
File.open(path, 'rb') do |file|
while buf = file.read(1024)
- print buf
- end
+ print buf
+ end
end
end
-
+
[Jeremy Kemper]
* Added a new Tag Helper that can generate generic tags programmatically insted of through HTML. Example:
-
+
tag("br", "clear" => "all") => <br clear="all" />
-
- ...that's usually not terribly interesting (unless you have a lot of options already in a hash), but it
+
+ ...that's usually not terribly interesting (unless you have a lot of options already in a hash), but it
gives way for more specific tags, like the new form tag:
-
+
form_tag({ :controller => "weblog", :action => "update" }, { :multipart => "true", "style" => "width: 200px"}) =>
<form action="/weblog/update" enctype="multipart/formdata" style="width: 200px">
-
+
There's even a "pretty" version for people who don't like to open tags in code and close them in HTML:
-
+
<%= start_form_tag :action => "update" %>
# all the input fields
<%= end_form_tag %>
-
+
(end_form_tag just returns "</form>")
-* The selected parameter in options_for_select may now also an array of values to be selected when
+* The selected parameter in options_for_select may now also an array of values to be selected when
using a multiple select. Example:
options_for_select([ "VISA", "Mastercard", "Discover" ], ["VISA", "Discover"]) =>
<option selected>VISA</option>\n<option>Mastercard</option>\n<option selected>Discover</option>
-
+
[Scott Baron]
* Changed the URL rewriter so controller_prefix and action_prefix can be used in isolation. You can now do:
@@ -4983,7 +5014,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
url_for(:controller_prefix => "clients")
...or:
-
+
url_for(:action_prefix => "category/messages")
Neither would have worked in isolation before (:controller_prefix required a :controller and :action_prefix required an :action)
@@ -4991,7 +5022,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Started process of a cleaner separation between Action Controller and ERb-based Action Views by introducing an
abstract base class for views. And Amita adapter could be fitted in more easily now.
-* The date helper methods date_select and datetime_select now also use the field error wrapping
+* The date helper methods date_select and datetime_select now also use the field error wrapping
(div with class fieldWithErrors by default).
* The date helper methods date_select and datetime_select can now discard selects
@@ -5003,7 +5034,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
end
...would give the following on a Post#title (text field) error:
-
+
<p>Title can't be empty</p>
<div style='background-color: red'>
<input id="post_title" name="post[title]" size="30" type="text" value="Hello World" />
@@ -5036,18 +5067,18 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
layout "layouts/weblog"
scaffold :post
end
-
+
[Suggested by Scott]
* Changed url_for (and all the that drives, like redirect_to, link_to, link_for) so you can pass it a symbol instead of a hash.
This symbol is a method reference which is then called to calculate the url. Example:
-
+
class WeblogController < ActionController::Base
def update
# do some update
redirect_to :dashboard_url
end
-
+
protected
def dashboard_url
if @project.active?
@@ -5057,23 +5088,23 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
end
end
end
-
+
* Added default_url_options to specialize behavior for all url_for (and friends) calls:
- Overwrite to implement a number of default options that all url_for-based methods will use.
- The default options should come in form of a hash, just like the one you would use for
+ Overwrite to implement a number of default options that all url_for-based methods will use.
+ The default options should come in form of a hash, just like the one you would use for
url_for directly. Example:
-
+
def default_url_options(options)
{ :controller_prefix => @project.active? ? "projects/" : "accounts/" }
end
-
- As you can infer from the example, this is mostly useful for situations where you want to
+
+ As you can infer from the example, this is mostly useful for situations where you want to
centralize dynamic dissions about the urls as they stem from the business domain. Please note
that any individual url_for call can always override the defaults set by this method.
-
-* Changed url_for so that an "id" passed in the :params is not treated special. You need to use the dedicated :id to get
+
+* Changed url_for so that an "id" passed in the :params is not treated special. You need to use the dedicated :id to get
the special auto path-params treatment. Considering the url http://localhost:81/friends/list
url_for(:action => "show", :params => { "id" => 5 })
@@ -5091,7 +5122,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
*0.7.8*
-* Fixed session bug where you couldn't store any objects that didn't exist in the standard library
+* Fixed session bug where you couldn't store any objects that didn't exist in the standard library
(such as Active Record objects).
* Added reset_session method for Action Controller objects to clear out all objects in the session.
@@ -5102,22 +5133,22 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
class WeblogController < ActionController::Base
around_filter BenchmarkingFilter.new
-
+
# Before this action is performed, BenchmarkingFilter#before(controller) is executed
def index
end
# After this action has been performed, BenchmarkingFilter#after(controller) is executed
end
-
+
class BenchmarkingFilter
def initialize
@runtime
end
-
+
def before
start_timer
end
-
+
def after
stop_timer
report_result
@@ -5128,7 +5159,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
text_field "post", "title"
...just gives: <input id="post_title" name="post[title]" size="30" type="text" value="" />
-
+
text_field "post", "title", "id" => "title_for_post", "name" => "first_post_title"
...can now give: <input id="title_for_post" name="first_post_title" size="30" type="text" value="" />
@@ -5156,7 +5187,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
* Included ERB::Util so all templates can easily escape HTML content with <%=h @person.content %>
* All requests are now considered local by default, so everyone will be exposed to detailed debugging screens on errors.
- When the application is ready to go public, set ActionController::Base.consider_all_requests_local to false,
+ When the application is ready to go public, set ActionController::Base.consider_all_requests_local to false,
and implement the protected method local_request? in the controller to determine when debugging screens should be shown.
* Fixed three bugs with the url_for/redirect_to/link_to handling. Considering the url http://localhost:81/friends/show/1
@@ -5164,7 +5195,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
url_for(:action => "list")
...used to give http://localhost:81/friends/list/1
......now gives http://localhost:81/friends/list
-
+
url_for(:controller => "friends", :action => "destroy", :id => 5)
...used to give http://localhost:81/friends/destroy
......now gives http://localhost:81/friends/destroy/5
@@ -5174,7 +5205,7 @@ Default YAML web services were retired, ActionController::Base.param_parsers car
url_for(:action => "list", :id => 5)
...used to give http://localhost:81/5eachers/list/t
......now gives http://localhost:81/teachers/list/5
-
+
[Reported by David Morton & Radsaq]
* Logs exception to logfile in addition to showing them for local requests
diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
index be89924015..4082770b85 100644
--- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb
+++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
@@ -48,7 +48,7 @@ module ActionDispatch
@env["action_dispatch.request.formats"] ||=
if parameters[:format]
Array(Mime[parameters[:format]])
- elsif xhr? || (accept && !accept.include?(?,))
+ elsif xhr? || (accept && accept !~ /,\s*\*\/\*/)
accepts
else
[Mime::HTML]
@@ -87,4 +87,4 @@ module ActionDispatch
end
end
end
-end \ No newline at end of file
+end
diff --git a/actionpack/lib/action_dispatch/railtie.rb b/actionpack/lib/action_dispatch/railtie.rb
index 563df0f256..004c254e55 100644
--- a/actionpack/lib/action_dispatch/railtie.rb
+++ b/actionpack/lib/action_dispatch/railtie.rb
@@ -6,6 +6,7 @@ module ActionDispatch
config.action_dispatch = ActiveSupport::OrderedOptions.new
config.action_dispatch.x_sendfile_header = ""
config.action_dispatch.ip_spoofing_check = true
+ config.action_dispatch.show_exceptions = true
# Prepare dispatcher callbacks and run 'prepare' callbacks
initializer "action_dispatch.prepare_dispatcher" do |app|
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 74d0297898..2c7ee7dad0 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -194,6 +194,21 @@ module ActionDispatch
self
end
+ def mount(app, options = nil)
+ if options
+ path = options.delete(:at)
+ else
+ options = app
+ app, path = options.find { |k, v| k.respond_to?(:call) }
+ options.delete(app) if app
+ end
+
+ raise "A rack application must be specified" unless path
+
+ match(path, options.merge(:to => app, :anchor => false))
+ self
+ end
+
def default_url_options=(options)
@set.default_url_options = options
end
@@ -380,14 +395,13 @@ module ActionDispatch
[:index, :create, :new, :show, :update, :destroy, :edit]
end
- attr_reader :plural, :singular, :options
+ attr_reader :controller, :path, :options
def initialize(entities, options = {})
- @name = entities.to_s
- @options = options
-
- @plural = @name.pluralize
- @singular = @name.singularize
+ @name = entities.to_s
+ @path = options.delete(:path) || @name
+ @controller = options.delete(:controller) || @name.to_s.pluralize
+ @options = options
end
def default_actions
@@ -417,8 +431,12 @@ module ActionDispatch
options[:as] || @name
end
- def controller
- options[:controller] || plural
+ def plural
+ name.to_s.pluralize
+ end
+
+ def singular
+ name.to_s.singularize
end
def member_name
@@ -509,7 +527,7 @@ module ActionDispatch
resource = SingletonResource.new(resources.pop, options)
- scope(:path => resource.name.to_s, :controller => resource.controller) do
+ scope(:path => resource.path, :controller => resource.controller) do
with_scope_level(:resource, resource) do
scope(:name_prefix => resource.name.to_s, :as => "") do
@@ -539,7 +557,7 @@ module ActionDispatch
resource = Resource.new(resources.pop, options)
- scope(:path => resource.name.to_s, :controller => resource.controller) do
+ scope(:path => resource.path, :controller => resource.controller) do
with_scope_level(:resources, resource) do
yield if block_given?
@@ -603,21 +621,6 @@ module ActionDispatch
end
end
- def mount(app, options = nil)
- if options
- path = options.delete(:at)
- else
- options = app
- app, path = options.find { |k, v| k.respond_to?(:call) }
- options.delete(app) if app
- end
-
- raise "A rack application must be specified" unless path
-
- match(path, options.merge(:to => app, :anchor => false))
- self
- end
-
def match(*args)
options = args.extract_options!
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index 621d63c5e2..031fa1dfb4 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -263,9 +263,7 @@ module ActionDispatch
"HTTP_HOST" => host,
"REMOTE_ADDR" => remote_addr,
"CONTENT_TYPE" => "application/x-www-form-urlencoded",
- "HTTP_ACCEPT" => accept,
-
- "action_dispatch.show_exceptions" => false
+ "HTTP_ACCEPT" => accept
}
(rack_environment || {}).each do |key, value|
diff --git a/actionpack/lib/action_pack/version.rb b/actionpack/lib/action_pack/version.rb
index 72a1cd30ad..0b40465a79 100644
--- a/actionpack/lib/action_pack/version.rb
+++ b/actionpack/lib/action_pack/version.rb
@@ -3,7 +3,7 @@ module ActionPack
MAJOR = 3
MINOR = 0
TINY = 0
- BUILD = "beta1"
+ BUILD = "beta2"
STRING = [MAJOR, MINOR, TINY, BUILD].join('.')
end
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index a9b0715b2e..fde61e9df9 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -168,6 +168,8 @@ module ActionView #:nodoc:
remove_method :helpers
attr_reader :helpers
+ class_attribute :_router
+
class << self
delegate :erb_trim_mode=, :to => 'ActionView::Template::Handlers::ERB'
delegate :logger, :to => 'ActionController::Base', :allow_nil => true
@@ -204,7 +206,10 @@ module ActionView #:nodoc:
@assigns = assigns_for_first_render.each { |key, value| instance_variable_set("@#{key}", value) }
@helpers = self.class.helpers || Module.new
- @_controller = controller
+ if @_controller = controller
+ @_request = controller.request if controller.respond_to?(:request)
+ end
+
@_config = ActiveSupport::InheritableOptions.new(controller.config) if controller && controller.respond_to?(:config)
@_content_for = Hash.new { |h,k| h[k] = ActiveSupport::SafeBuffer.new }
@_virtual_path = nil
diff --git a/actionpack/lib/action_view/helpers.rb b/actionpack/lib/action_view/helpers.rb
index a50c180f63..ba3bdd0d18 100644
--- a/actionpack/lib/action_view/helpers.rb
+++ b/actionpack/lib/action_view/helpers.rb
@@ -29,16 +29,13 @@ module ActionView #:nodoc:
autoload :TranslationHelper
autoload :UrlHelper
- def self.included(base)
- base.extend(ClassMethods)
- end
+ extend ActiveSupport::Concern
- module ClassMethods
- include SanitizeHelper::ClassMethods
+ included do
+ extend SanitizeHelper::ClassMethods
end
include ActiveSupport::Benchmarkable
-
include ActiveModelHelper
include AssetTagHelper
include AtomFeedHelper
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index 89560d0b49..9467a0912a 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -96,6 +96,7 @@ module ActionView
extend ActiveSupport::Concern
include FormTagHelper
+ include UrlHelper
# Creates a form and a scope around a specific model object that is used
# as a base for questioning about values for the fields.
@@ -120,7 +121,7 @@ module ActionView
# The generic way to call +form_for+ yields a form builder around a
# model:
#
- # <%= form_for :person, :url => { :action => "update" } do |f| %>
+ # <%= form_for :person, :url => { :action => "create" } do |f| %>
# <%= f.error_messages %>
# First name: <%= f.text_field :first_name %><br />
# Last name : <%= f.text_field :last_name %><br />
@@ -144,7 +145,7 @@ module ActionView
# If the instance variable is not <tt>@person</tt> you can pass the actual
# record as the second argument:
#
- # <%= form_for :person, person, :url => { :action => "update" } do |f| %>
+ # <%= form_for :person, person, :url => { :action => "create" } do |f| %>
# ...
# <% end %>
#
@@ -176,7 +177,7 @@ module ActionView
# possible to use both the stand-alone FormHelper methods and methods
# from FormTagHelper. For example:
#
- # <%= form_for :person, @person, :url => { :action => "update" } do |f| %>
+ # <%= form_for :person, @person, :url => { :action => "create" } do |f| %>
# First name: <%= f.text_field :first_name %>
# Last name : <%= f.text_field :last_name %>
# Biography : <%= text_area :person, :biography %>
@@ -264,7 +265,7 @@ module ActionView
# custom builder. For example, let's say you made a helper to
# automatically add labels to form inputs.
#
- # <%= form_for :person, @person, :url => { :action => "update" }, :builder => LabellingFormBuilder do |f| %>
+ # <%= form_for :person, @person, :url => { :action => "create" }, :builder => LabellingFormBuilder do |f| %>
# <%= f.text_field :first_name %>
# <%= f.text_field :last_name %>
# <%= text_area :person, :biography %>
@@ -341,7 +342,7 @@ module ActionView
#
# === Generic Examples
#
- # <%= form_for @person, :url => { :action => "update" } do |person_form| %>
+ # <%= form_for @person do |person_form| %>
# First name: <%= person_form.text_field :first_name %>
# Last name : <%= person_form.text_field :last_name %>
#
@@ -353,13 +354,13 @@ module ActionView
# ...or if you have an object that needs to be represented as a different
# parameter, like a Client that acts as a Person:
#
- # <%= fields_for :person, @client do |permission_fields| %>
+ # <%= fields_for :person, @client, :url => { :action => "create" } do |permission_fields| %>
# Admin?: <%= permission_fields.check_box :admin %>
# <% end %>
#
# ...or if you don't have an object, just a name of the parameter:
#
- # <%= fields_for :person do |permission_fields| %>
+ # <%= fields_for :person, :url => { :action => "create" } do |permission_fields| %>
# Admin?: <%= permission_fields.check_box :admin %>
# <% end %>
#
@@ -403,7 +404,7 @@ module ActionView
#
# This model can now be used with a nested fields_for, like so:
#
- # <%= form_for @person, :url => { :action => "update" } do |person_form| %>
+ # <%= form_for @person do |person_form| %>
# ...
# <%= person_form.fields_for :address do |address_fields| %>
# Street : <%= address_fields.text_field :street %>
@@ -432,7 +433,7 @@ module ActionView
# with a value that evaluates to +true+, you will destroy the associated
# model (eg. 1, '1', true, or 'true'):
#
- # <%= form_for @person, :url => { :action => "update" } do |person_form| %>
+ # <%= form_for @person do |person_form| %>
# ...
# <%= person_form.fields_for :address do |address_fields| %>
# ...
@@ -460,7 +461,7 @@ module ActionView
# the nested fields_for call will be repeated for each instance in the
# collection:
#
- # <%= form_for @person, :url => { :action => "update" } do |person_form| %>
+ # <%= form_for @person do |person_form| %>
# ...
# <%= person_form.fields_for :projects do |project_fields| %>
# <% if project_fields.object.active? %>
@@ -471,7 +472,7 @@ module ActionView
#
# It's also possible to specify the instance to be used:
#
- # <%= form_for @person, :url => { :action => "update" } do |person_form| %>
+ # <%= form_for @person do |person_form| %>
# ...
# <% @person.projects.each do |project| %>
# <% if project.active? %>
@@ -484,7 +485,7 @@ module ActionView
#
# Or a collection to be used:
#
- # <%= form_for @person, :url => { :action => "update" } do |person_form| %>
+ # <%= form_for @person do |person_form| %>
# ...
# <%= person_form.fields_for :projects, @active_projects do |project_fields| %>
# Name: <%= project_fields.text_field :name %>
@@ -513,7 +514,7 @@ module ActionView
# parameter with a value that evaluates to +true+
# (eg. 1, '1', true, or 'true'):
#
- # <%= form_for @person, :url => { :action => "update" } do |person_form| %>
+ # <%= form_for @person do |person_form| %>
# ...
# <%= person_form.fields_for :projects do |project_fields| %>
# Delete: <%= project_fields.check_box :_destroy %>
diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb
index ca100e102e..0d47c6eecb 100644
--- a/actionpack/lib/action_view/helpers/form_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb
@@ -93,6 +93,10 @@ module ActionView
# # => <select disabled="disabled" id="destination" name="destination"><option>NYC</option>
# # <option>Paris</option><option>Rome</option></select>
def select_tag(name, option_tags = nil, options = {})
+ if Array === option_tags
+ ActiveSupport::Deprecation.warn 'Passing an array of option_tags to select_tag implicitly joins them without marking them as HTML-safe. Pass option_tags.join.html_safe instead.', caller
+ end
+
html_name = (options[:multiple] == true && !name.to_s.ends_with?("[]")) ? "#{name}[]" : name
if blank = options.delete(:include_blank)
if blank.kind_of?(String)
diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb
index 605e5d5873..01fecc0f23 100644
--- a/actionpack/lib/action_view/helpers/number_helper.rb
+++ b/actionpack/lib/action_view/helpers/number_helper.rb
@@ -273,8 +273,12 @@ module ActionView
strip_insignificant_zeros = options.delete :strip_insignificant_zeros
if significant and precision > 0
- digits = (Math.log10(number) + 1).floor
- rounded_number = BigDecimal.new((number / 10 ** (digits - precision)).to_s).round.to_f * 10 ** (digits - precision)
+ if number == 0
+ digits, rounded_number = 1, 0
+ else
+ digits = (Math.log10(number) + 1).floor
+ rounded_number = BigDecimal.new((number / 10 ** (digits - precision)).to_s).round.to_f * 10 ** (digits - precision)
+ end
precision = precision - digits
precision = precision > 0 ? precision : 0 #don't let it be negative
else
diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb
index b23d5fcb68..1415966869 100644
--- a/actionpack/lib/action_view/helpers/url_helper.rb
+++ b/actionpack/lib/action_view/helpers/url_helper.rb
@@ -13,14 +13,15 @@ module ActionView
extend ActiveSupport::Concern
include ActionDispatch::Routing::UrlFor
- include JavaScriptHelper
+ include TagHelper
# Need to map default url options to controller one.
- def default_url_options(*args) #:nodoc:
- controller.send(:default_url_options, *args)
- end
-
+ # def default_url_options(*args) #:nodoc:
+ # controller.send(:default_url_options, *args)
+ # end
+ #
def url_options
+ return super unless controller.respond_to?(:url_options)
controller.url_options
end
@@ -97,7 +98,7 @@ module ActionView
when Hash
options = { :only_path => options[:host].nil? }.update(options.symbolize_keys)
escape = options.key?(:escape) ? options.delete(:escape) : false
- controller.send(:url_for, options)
+ super
when :back
escape = false
controller.request.env["HTTP_REFERER"] || 'javascript:history.back()'
@@ -119,13 +120,24 @@ module ActionView
#
# ==== Signatures
#
- # link_to(name, options = {}, html_options = nil)
- # link_to(options = {}, html_options = nil) do
+ # link_to(body, url, html_options = {})
+ # # url is a String; you can use URL helpers like
+ # # posts_path
+ #
+ # link_to(body, url_options = {}, html_options = {})
+ # # url_options, except :confirm or :method,
+ # # is passed to url_for
+ #
+ # link_to(options = {}, html_options = {}) do
+ # # name
+ # end
+ #
+ # link_to(url, html_options = {}) do
# # name
# end
#
# ==== Options
- # * <tt>:confirm => 'question?'</tt> - This will allow the unobtrusive JavaScript
+ # * <tt>:confirm => 'question?'</tt> - This will allow the unobtrusive JavaScript
# driver to prompt with the question specified. If the user accepts, the link is
# processed normally, otherwise no action is taken.
# * <tt>:method => symbol of HTTP verb</tt> - This modifier will dynamically
@@ -138,7 +150,11 @@ module ActionView
# disabled clicking the link will have no effect. If you are relying on the
# POST behavior, you should check for it in your controller's action by using
# the request object's methods for <tt>post?</tt>, <tt>delete?</tt> or <tt>put?</tt>.
- # * The +html_options+ will accept a hash of html attributes for the link tag.
+ # * <tt>:remote => true</tt> - This will allow the unobtrusive JavaScript
+ # driver to make an Ajax request to the URL in question instead of following
+ # the link. The drivers each provide mechanisms for listening for the
+ # completion of the Ajax request and performing JavaScript operations once
+ # they're complete
#
# ==== Examples
# Because it relies on +url_for+, +link_to+ supports both older-style controller/action/id arguments
@@ -220,8 +236,8 @@ module ActionView
options = args[1] || {}
html_options = args[2]
- url = url_for(options)
html_options = convert_options_to_data_attributes(options, html_options)
+ url = url_for(options)
if html_options
html_options = html_options.stringify_keys
@@ -259,10 +275,10 @@ module ActionView
# There are a few special +html_options+:
# * <tt>:method</tt> - Specifies the anchor name to be appended to the path.
# * <tt>:disabled</tt> - Specifies the anchor name to be appended to the path.
- # * <tt>:confirm</tt> - This will use the unobtrusive JavaScript driver to
+ # * <tt>:confirm</tt> - This will use the unobtrusive JavaScript driver to
# prompt with the question specified. If the user accepts, the link is
# processed normally, otherwise no action is taken.
- # * <tt>:remote</tt> - If set to true, will allow the Unobtrusive JavaScript drivers to control the
+ # * <tt>:remote</tt> - If set to true, will allow the Unobtrusive JavaScript drivers to control the
# submit behaviour. By default this behaviour is an ajax submit.
#
# ==== Examples
@@ -282,7 +298,7 @@ module ActionView
# # </form>"
#
#
- # <%= button_to('Destroy', 'http://www.example.com', :confirm => 'Are you sure?',
+ # <%= button_to('Destroy', 'http://www.example.com', :confirm => 'Are you sure?',
# :method => "delete", :remote => true, :disable_with => 'loading...') %>
# # => "<form class='button-to' method='post' action='http://www.example.com' data-remote='true'>
# # <div>
@@ -546,8 +562,14 @@ module ActionView
# current_page?(:controller => 'library', :action => 'checkout')
# # => false
def current_page?(options)
+ unless request
+ raise "You cannot use helpers that need to determine the current " \
+ "page unless your view context provides a Request object " \
+ "in a #request method"
+ end
+
url_string = CGI.unescapeHTML(url_for(options))
- request = controller.request
+
# We ignore any extra parameters in the request_uri if the
# submitted url doesn't have any either. This lets the function
# work with things like ?order=asc
diff --git a/actionpack/lib/action_view/render/partials.rb b/actionpack/lib/action_view/render/partials.rb
index f04a89c1ac..4d23d55687 100644
--- a/actionpack/lib/action_view/render/partials.rb
+++ b/actionpack/lib/action_view/render/partials.rb
@@ -179,7 +179,7 @@ module ActionView
def initialize(view_context, options, block)
@view = view_context
- @partial_names = PARTIAL_NAMES[@view.controller.class]
+ @partial_names = PARTIAL_NAMES[@view.controller.class.name]
setup(options, block)
end
@@ -300,7 +300,7 @@ module ActionView
end
def partial_path(object = @object)
- @partial_names[object.class] ||= begin
+ @partial_names[object.class.name] ||= begin
object = object.to_model if object.respond_to?(:to_model)
object.class.model_name.partial_path.dup.tap do |partial|
diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb
index 8abc1633ff..3df2bd8eed 100644
--- a/actionpack/lib/action_view/template.rb
+++ b/actionpack/lib/action_view/template.rb
@@ -18,6 +18,14 @@ module ActionView
attr_reader :source, :identifier, :handler, :virtual_path, :formats
+ def self.finalizer_for(method_name)
+ proc do
+ ActionView::CompiledTemplates.module_eval do
+ remove_possible_method method_name
+ end
+ end
+ end
+
def initialize(source, identifier, handler, details)
@source = source
@identifier = identifier
@@ -98,6 +106,7 @@ module ActionView
begin
ActionView::CompiledTemplates.module_eval(source, identifier, line)
+ ObjectSpace.define_finalizer(self, self.class.finalizer_for(method_name))
method_name
rescue Exception => e # errors from template code
if logger = (view && view.logger)
diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb
index 23b0c6e121..ddea9cfd92 100644
--- a/actionpack/lib/action_view/test_case.rb
+++ b/actionpack/lib/action_view/test_case.rb
@@ -142,8 +142,13 @@ module ActionView
end
end
+ def _router
+ @controller._router if @controller.respond_to?(:_router)
+ end
+
def method_missing(selector, *args)
- if @controller._router.named_routes.helpers.include?(selector)
+ if @controller.respond_to?(:_router) &&
+ @controller._router.named_routes.helpers.include?(selector)
@controller.__send__(selector, *args)
else
super
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index 143491a640..fe78b8ec1f 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -57,6 +57,18 @@ module RackTestUtils
extend self
end
+module RenderERBUtils
+ def render_erb(string)
+ template = ActionView::Template.new(
+ string.strip,
+ "test template",
+ ActionView::Template::Handlers::ERB,
+ {})
+
+ template.render(self, {}).strip
+ end
+end
+
module SetupOnce
extend ActiveSupport::Concern
@@ -225,6 +237,14 @@ class Rack::TestCase < ActionController::IntegrationTest
end
end
+class ActionController::Base
+ def self.test_routes(&block)
+ router = ActionDispatch::Routing::RouteSet.new
+ router.draw(&block)
+ include router.url_helpers
+ end
+end
+
class ::ApplicationController < ActionController::Base
end
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index e58653cb8c..19538cb88b 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -58,8 +58,9 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
get 'admin/accounts' => "queenbee#accounts"
end
- scope 'es' do
- resources :projects, :path_names => { :edit => 'cambiar' }, :as => 'projeto'
+ scope 'pt', :name_prefix => 'pt' do
+ resources :projects, :path_names => { :edit => 'editar' }, :path => 'projetos'
+ resource :admin, :path_names => { :new => 'novo' }, :path => 'administrador'
end
resources :projects, :controller => :project do
@@ -74,10 +75,14 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
resource :avatar, :controller => :avatar
end
- resources :images do
+ resources :images, :as => :funny_images do
post :revise, :on => :member
end
+ resource :manager, :as => :super_manager do
+ post :fire
+ end
+
resources :people do
nested do
scope "/:access_token" do
@@ -144,7 +149,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
namespace :forum do
- resources :products, :as => '' do
+ resources :products, :path => '' do
resources :questions
end
end
@@ -430,15 +435,35 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
end
end
+ def test_project_manager
+ with_test_routes do
+ get '/projects/1/manager'
+ assert_equal 'managers#show', @response.body
+ assert_equal '/projects/1/manager', project_super_manager_path(:project_id => '1')
+
+ get '/projects/1/manager/new'
+ assert_equal 'managers#new', @response.body
+ assert_equal '/projects/1/manager/new', new_project_super_manager_path(:project_id => '1')
+
+ post '/projects/1/manager/fire'
+ assert_equal 'managers#fire', @response.body
+ assert_equal '/projects/1/manager/fire', fire_project_super_manager_path(:project_id => '1')
+ end
+ end
+
def test_project_images
with_test_routes do
get '/projects/1/images'
assert_equal 'images#index', @response.body
- assert_equal '/projects/1/images', project_images_path(:project_id => '1')
+ assert_equal '/projects/1/images', project_funny_images_path(:project_id => '1')
+
+ get '/projects/1/images/new'
+ assert_equal 'images#new', @response.body
+ assert_equal '/projects/1/images/new', new_project_funny_image_path(:project_id => '1')
post '/projects/1/images/1/revise'
assert_equal 'images#revise', @response.body
- assert_equal '/projects/1/images/1/revise', revise_project_image_path(:project_id => '1', :id => '1')
+ assert_equal '/projects/1/images/1/revise', revise_project_funny_image_path(:project_id => '1', :id => '1')
end
end
@@ -552,11 +577,21 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
def test_path_names
with_test_routes do
- get '/es/projeto'
+ get '/pt/projetos'
assert_equal 'projects#index', @response.body
+ assert_equal '/pt/projetos', pt_projects_path
- get '/es/projeto/1/cambiar'
+ get '/pt/projetos/1/editar'
assert_equal 'projects#edit', @response.body
+ assert_equal '/pt/projetos/1/editar', edit_pt_project_path(1)
+
+ get '/pt/administrador'
+ assert_equal 'admins#show', @response.body
+ assert_equal '/pt/administrador', pt_admin_path
+
+ get '/pt/administrador/novo'
+ assert_equal 'admins#new', @response.body
+ assert_equal '/pt/administrador/novo', new_pt_admin_path
end
end
diff --git a/actionpack/test/template/active_model_helper_test.rb b/actionpack/test/template/active_model_helper_test.rb
index 1a5316a689..47eb620f7a 100644
--- a/actionpack/test/template/active_model_helper_test.rb
+++ b/actionpack/test/template/active_model_helper_test.rb
@@ -118,13 +118,12 @@ class ActiveModelHelperTest < ActionView::TestCase
setup_user
@response = ActionController::TestResponse.new
+ end
- @controller = Object.new
- def @controller.url_for(options)
- options = options.symbolize_keys
+ def url_for(options)
+ options = options.symbolize_keys
- [options[:action], options[:id].to_param].compact.join('/')
- end
+ [options[:action], options[:id].to_param].compact.join('/')
end
def test_generic_input_tag
diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb
index fbd504ae7d..223a430f92 100644
--- a/actionpack/test/template/asset_tag_helper_test.rb
+++ b/actionpack/test/template/asset_tag_helper_test.rb
@@ -34,9 +34,7 @@ class AssetTagHelperTest < ActionView::TestCase
)
end
- @controller = Class.new(BasicController) do
- def url_for(*args) "http://www.example.com" end
- end.new
+ @controller = BasicController.new
@request = Class.new do
def protocol() 'http://' end
@@ -49,6 +47,10 @@ class AssetTagHelperTest < ActionView::TestCase
ActionView::Helpers::AssetTagHelper::reset_javascript_include_default
end
+ def url_for(*args)
+ "http://www.example.com"
+ end
+
def teardown
config.perform_caching = false
ENV.delete('RAILS_ASSET_ID')
@@ -893,25 +895,19 @@ class AssetTagHelperNonVhostTest < ActionView::TestCase
def setup
super
- @controller = Class.new(BasicController) do
- def url_for(options)
- "http://www.example.com/collaboration/hieraki"
- end
- end.new
-
+ @controller = BasicController.new
@controller.config.relative_url_root = "/collaboration/hieraki"
- @request = Class.new do
- def protocol
- 'gopher://'
- end
- end.new
-
+ @request = Struct.new(:protocol).new("gopher://")
@controller.request = @request
ActionView::Helpers::AssetTagHelper::reset_javascript_include_default
end
+ def url_for(options)
+ "http://www.example.com/collaboration/hieraki"
+ end
+
def test_should_compute_proper_path
assert_dom_equal(%(<link href="http://www.example.com/collaboration/hieraki" rel="alternate" title="RSS" type="application/rss+xml" />), auto_discovery_link_tag)
assert_dom_equal(%(/collaboration/hieraki/javascripts/xmlhr.js), javascript_path("xmlhr"))
diff --git a/actionpack/test/template/erb/helper.rb b/actionpack/test/template/erb/helper.rb
index 7147178849..799f9e4036 100644
--- a/actionpack/test/template/erb/helper.rb
+++ b/actionpack/test/template/erb/helper.rb
@@ -1,20 +1,13 @@
module ERBTest
class ViewContext
- mock_controller = Class.new do
- include SharedTestRoutes.url_helpers
- end
-
+ include SharedTestRoutes.url_helpers
include ActionView::Helpers::TagHelper
include ActionView::Helpers::JavaScriptHelper
include ActionView::Helpers::FormHelper
- attr_accessor :output_buffer
+ attr_accessor :output_buffer, :controller
def protect_against_forgery?() false end
-
- define_method(:controller) do
- mock_controller.new
- end
end
class BlockTestCase < ActiveSupport::TestCase
diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb
index 7c5ccfd6ed..4af38e52dd 100644
--- a/actionpack/test/template/form_helper_test.rb
+++ b/actionpack/test/template/form_helper_test.rb
@@ -63,15 +63,15 @@ class FormHelperTest < ActionView::TestCase
@post.body = "Back to the hill and over it again!"
@post.secret = 1
@post.written_on = Date.new(2004, 6, 15)
+ end
- @controller = Class.new do
- attr_reader :url_for_options
- def url_for(options)
- @url_for_options = options
- "http://www.example.com"
- end
+ def url_for(object)
+ @url_for_options = object
+ if object.is_a?(Hash)
+ "http://www.example.com"
+ else
+ super
end
- @controller = @controller.new
end
def test_label
@@ -1348,8 +1348,8 @@ class FormHelperTest < ActionView::TestCase
def test_form_for_with_hash_url_option
form_for(:post, @post, :url => {:controller => 'controller', :action => 'action'}) do |f| end
- assert_equal 'controller', @controller.url_for_options[:controller]
- assert_equal 'action', @controller.url_for_options[:action]
+ assert_equal 'controller', @url_for_options[:controller]
+ assert_equal 'action', @url_for_options[:action]
end
def test_form_for_with_record_url_option
diff --git a/actionpack/test/template/form_tag_helper_test.rb b/actionpack/test/template/form_tag_helper_test.rb
index 868a35c476..3b8760351e 100644
--- a/actionpack/test/template/form_tag_helper_test.rb
+++ b/actionpack/test/template/form_tag_helper_test.rb
@@ -8,11 +8,15 @@ class FormTagHelperTest < ActionView::TestCase
def setup
super
- @controller = Class.new(BasicController) do
- def url_for(options)
- "http://www.example.com"
- end
- end.new
+ @controller = BasicController.new
+ end
+
+ def url_for(options)
+ if options.is_a?(Hash)
+ "http://www.example.com"
+ else
+ super
+ end
end
VALID_HTML_ID = /^[A-Za-z][-_:.A-Za-z0-9]*$/ # see http://www.w3.org/TR/html4/types.html#type-name
@@ -158,6 +162,12 @@ class FormTagHelperTest < ActionView::TestCase
assert_dom_equal expected, actual
end
+ def test_select_tag_with_array_options
+ assert_deprecated /array/ do
+ select_tag "people", ["<option>david</option>"]
+ end
+ end
+
def test_text_area_tag_size_string
actual = text_area_tag "body", "hello world", "size" => "20x40"
expected = %(<textarea cols="20" id="body" name="body" rows="40">hello world</textarea>)
diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb
index 50c57a5588..a21a1a68e4 100644
--- a/actionpack/test/template/number_helper_test.rb
+++ b/actionpack/test/template/number_helper_test.rb
@@ -102,6 +102,9 @@ class NumberHelperTest < ActionView::TestCase
assert_equal("3268", number_with_precision((32.6751 * 100.00), :precision => 0))
assert_equal("112", number_with_precision(111.50, :precision => 0))
assert_equal("1234567892", number_with_precision(1234567891.50, :precision => 0))
+ assert_equal("0", number_with_precision(0, :precision => 0))
+ assert_equal("0.00100", number_with_precision(0.001, :precision => 5))
+ assert_equal("0.001", number_with_precision(0.00111, :precision => 3))
end
def test_number_with_precision_with_custom_delimiter_and_separator
@@ -122,11 +125,17 @@ class NumberHelperTest < ActionView::TestCase
assert_equal "53", number_with_precision(52.7923, :precision => 2, :significant => true )
assert_equal "9775.00", number_with_precision(9775, :precision => 6, :significant => true )
assert_equal "5.392900", number_with_precision(5.3929, :precision => 7, :significant => true )
+ assert_equal "0.0", number_with_precision(0, :precision => 2, :significant => true )
+ assert_equal "0", number_with_precision(0, :precision => 1, :significant => true )
+ assert_equal "0.0001", number_with_precision(0.0001, :precision => 1, :significant => true )
+ assert_equal "0.000100", number_with_precision(0.0001, :precision => 3, :significant => true )
+ assert_equal "0.0001", number_with_precision(0.0001111, :precision => 1, :significant => true )
end
def test_number_with_precision_with_strip_insignificant_zeros
assert_equal "9775.43", number_with_precision(9775.43, :precision => 4, :strip_insignificant_zeros => true )
assert_equal "9775.2", number_with_precision(9775.2, :precision => 6, :significant => true, :strip_insignificant_zeros => true )
+ assert_equal "0", number_with_precision(0, :precision => 6, :significant => true, :strip_insignificant_zeros => true )
end
def test_number_with_precision_with_significant_true_and_zero_precision
diff --git a/actionpack/test/template/prototype_helper_test.rb b/actionpack/test/template/prototype_helper_test.rb
index 619293dc43..0ff37f44c2 100644
--- a/actionpack/test/template/prototype_helper_test.rb
+++ b/actionpack/test/template/prototype_helper_test.rb
@@ -47,19 +47,18 @@ class PrototypeHelperBaseTest < ActionView::TestCase
def setup
super
@template = self
- @controller = Class.new do
- def url_for(options)
- if options.is_a?(String)
- options
- else
- url = "http://www.example.com/"
- url << options[:action].to_s if options and options[:action]
- url << "?a=#{options[:a]}" if options && options[:a]
- url << "&b=#{options[:b]}" if options && options[:a] && options[:b]
- url
- end
- end
- end.new
+ end
+
+ def url_for(options)
+ if options.is_a?(String)
+ options
+ else
+ url = "http://www.example.com/"
+ url << options[:action].to_s if options and options[:action]
+ url << "?a=#{options[:a]}" if options && options[:a]
+ url << "&b=#{options[:b]}" if options && options[:a] && options[:b]
+ url
+ end
end
protected
diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb
index e54ebfbf8d..5f33c933db 100644
--- a/actionpack/test/template/render_test.rb
+++ b/actionpack/test/template/render_test.rb
@@ -281,6 +281,10 @@ class CachedViewRenderTest < ActiveSupport::TestCase
assert_equal ActionView::FileSystemResolver, view_paths.first.class
setup_view(view_paths)
end
+
+ def teardown
+ GC.start
+ end
end
class LazyViewRenderTest < ActiveSupport::TestCase
@@ -294,4 +298,8 @@ class LazyViewRenderTest < ActiveSupport::TestCase
assert_equal ActionView::FileSystemResolver.new(FIXTURE_LOAD_PATH), view_paths.first
setup_view(view_paths)
end
+
+ def teardown
+ GC.start
+ end
end
diff --git a/actionpack/test/template/scriptaculous_helper_test.rb b/actionpack/test/template/scriptaculous_helper_test.rb
index bebc3cb9f4..233012bfdd 100644
--- a/actionpack/test/template/scriptaculous_helper_test.rb
+++ b/actionpack/test/template/scriptaculous_helper_test.rb
@@ -3,21 +3,16 @@ require 'abstract_unit'
class ScriptaculousHelperTest < ActionView::TestCase
tests ActionView::Helpers::ScriptaculousHelper
- def setup
- super
- @controller = Class.new do
- def url_for(options)
- url = "http://www.example.com/"
- url << options[:action].to_s if options and options[:action]
- url
- end
- end.new
+ def url_for(options)
+ url = "http://www.example.com/"
+ url << options[:action].to_s if options and options[:action]
+ url
end
-
+
def test_effect
assert_equal "new Effect.Highlight(\"posts\",{});", visual_effect(:highlight, "posts")
assert_equal "new Effect.Highlight(\"posts\",{});", visual_effect("highlight", :posts)
- assert_equal "new Effect.Highlight(\"posts\",{});", visual_effect(:highlight, :posts)
+ assert_equal "new Effect.Highlight(\"posts\",{});", visual_effect(:highlight, :posts)
assert_equal "new Effect.Fade(\"fademe\",{duration:4.0});", visual_effect(:fade, "fademe", :duration => 4.0)
assert_equal "new Effect.Shake(element,{});", visual_effect(:shake)
assert_equal "new Effect.DropOut(\"dropme\",{queue:'end'});", visual_effect(:drop_out, 'dropme', :queue => :end)
@@ -43,7 +38,7 @@ class ScriptaculousHelperTest < ActionView::TestCase
assert ve[2].include?("scope:'test'")
assert ve[2].include?("position:'end'")
end
-
+
def test_toggle_effects
assert_equal "Effect.toggle(\"posts\",'appear',{});", visual_effect(:toggle_appear, "posts")
assert_equal "Effect.toggle(\"posts\",'slide',{});", visual_effect(:toggle_slide, "posts")
@@ -52,26 +47,26 @@ class ScriptaculousHelperTest < ActionView::TestCase
assert_equal "Effect.toggle(\"posts\",'slide',{});", visual_effect("toggle_slide", "posts")
assert_equal "Effect.toggle(\"posts\",'blind',{});", visual_effect("toggle_blind", "posts")
end
-
+
def test_sortable_element
- assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nSortable.create(\"mylist\", {onUpdate:function(){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(\"mylist\")})}})\n//]]>\n</script>),
+ assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nSortable.create(\"mylist\", {onUpdate:function(){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(\"mylist\")})}})\n//]]>\n</script>),
sortable_element("mylist", :url => { :action => "order" })
- assert_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nSortable.create(\"mylist\", {constraint:'horizontal', onUpdate:function(){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(\"mylist\")})}, tag:'div'})\n//]]>\n</script>),
+ assert_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nSortable.create(\"mylist\", {constraint:'horizontal', onUpdate:function(){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(\"mylist\")})}, tag:'div'})\n//]]>\n</script>),
sortable_element("mylist", :tag => "div", :constraint => "horizontal", :url => { :action => "order" })
- assert_dom_equal %|<script type=\"text/javascript\">\n//<![CDATA[\nSortable.create(\"mylist\", {constraint:'horizontal', containment:['list1','list2'], onUpdate:function(){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(\"mylist\")})}})\n//]]>\n</script>|,
+ assert_dom_equal %|<script type=\"text/javascript\">\n//<![CDATA[\nSortable.create(\"mylist\", {constraint:'horizontal', containment:['list1','list2'], onUpdate:function(){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(\"mylist\")})}})\n//]]>\n</script>|,
sortable_element("mylist", :containment => ['list1','list2'], :constraint => "horizontal", :url => { :action => "order" })
- assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nSortable.create(\"mylist\", {constraint:'horizontal', containment:'list1', onUpdate:function(){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(\"mylist\")})}})\n//]]>\n</script>),
+ assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nSortable.create(\"mylist\", {constraint:'horizontal', containment:'list1', onUpdate:function(){new Ajax.Request('http://www.example.com/order', {asynchronous:true, evalScripts:true, parameters:Sortable.serialize(\"mylist\")})}})\n//]]>\n</script>),
sortable_element("mylist", :containment => 'list1', :constraint => "horizontal", :url => { :action => "order" })
end
-
+
def test_draggable_element
assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Draggable(\"product_13\", {})\n//]]>\n</script>),
draggable_element("product_13")
assert_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Draggable(\"product_13\", {revert:true})\n//]]>\n</script>),
draggable_element("product_13", :revert => true)
end
-
+
def test_drop_receiving_element
assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nDroppables.add(\"droptarget1\", {onDrop:function(element){new Ajax.Request('http://www.example.com/', {asynchronous:true, evalScripts:true, parameters:'id=' + encodeURIComponent(element.id)})}})\n//]]>\n</script>),
drop_receiving_element("droptarget1")
diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb
index 87b2e59255..35e73fbf1e 100644
--- a/actionpack/test/template/url_helper_test.rb
+++ b/actionpack/test/template/url_helper_test.rb
@@ -3,58 +3,73 @@ require 'abstract_unit'
require 'active_support/ordered_options'
require 'controller/fake_controllers'
-class UrlHelperTest < ActionView::TestCase
-
- def setup
- super
- @controller = Class.new(BasicController) do
- attr_accessor :url
- def url_for(options)
- url
- end
- end
+class UrlHelperTest < ActiveSupport::TestCase
+
+ # In a few cases, the helper proxies to 'controller'
+ # or request.
+ #
+ # In those cases, we'll set up a simple mock
+ attr_accessor :controller, :request
+
+ routes = ActionDispatch::Routing::RouteSet.new
+ routes.draw do
+ match "/" => "foo#bar"
+ match "/other" => "foo#other"
+ end
+
+ include routes.url_helpers
+
+ include ActionView::Helpers::UrlHelper
+ include ActionDispatch::Assertions::DomAssertions
+ include ActionView::Context
+ include RenderERBUtils
+
+ # self.default_url_options = {:host => "www.example.com"}
+
+ # TODO: This shouldn't be needed (see template.rb:53)
+ def assigns
+ {}
+ end
- @controller = @controller.new
- @request = @controller.request = ActionDispatch::TestRequest.new
- @controller.url = "http://www.example.com"
+ def abcd(hash = {})
+ hash_for(:a => :b, :c => :d).merge(hash)
end
+ def hash_for(opts = {})
+ {:controller => "foo", :action => "bar"}.merge(opts)
+ end
+ alias url_hash hash_for
+
def test_url_for_escapes_urls
- @controller.url = "http://www.example.com?a=b&c=d"
- assert_equal "http://www.example.com?a=b&c=d", url_for(:a => 'b', :c => 'd')
- assert_equal "http://www.example.com?a=b&amp;c=d", url_for(:a => 'b', :c => 'd', :escape => true)
- assert_equal "http://www.example.com?a=b&c=d", url_for(:a => 'b', :c => 'd', :escape => false)
+ assert_equal "/?a=b&c=d", url_for(abcd)
+ assert_equal "/?a=b&amp;c=d", url_for(abcd(:escape => true))
+ assert_equal "/?a=b&c=d", url_for(abcd(:escape => false))
end
def test_url_for_escaping_is_safety_aware
- assert url_for(:a => 'b', :c => 'd', :escape => true).html_safe?, "escaped urls should be html_safe?"
- assert !url_for(:a => 'b', :c => 'd', :escape => false).html_safe?, "non-escaped urls shouldn't be safe"
+ assert url_for(abcd(:escape => true)).html_safe?, "escaped urls should be html_safe?"
+ assert !url_for(abcd(:escape => false)).html_safe?, "non-escaped urls should not be html_safe?"
end
def test_url_for_escapes_url_once
- @controller.url = "http://www.example.com?a=b&amp;c=d"
- assert_equal "http://www.example.com?a=b&amp;c=d", url_for("http://www.example.com?a=b&amp;c=d")
+ assert_equal "/?a=b&amp;c=d", url_for("/?a=b&amp;c=d")
end
def test_url_for_with_back
- @request.env['HTTP_REFERER'] = 'http://www.example.com/referer'
+ referer = 'http://www.example.com/referer'
+ @controller = Struct.new(:request).new(Struct.new(:env).new({"HTTP_REFERER" => referer}))
+
assert_equal 'http://www.example.com/referer', url_for(:back)
end
def test_url_for_with_back_and_no_referer
- @request.env['HOST_NAME'] = 'www.example.com'
- @request.env['PATH_INFO'] = '/weblog/show'
+ @controller = Struct.new(:request).new(Struct.new(:env).new({}))
assert_equal 'javascript:history.back()', url_for(:back)
end
def test_url_for_from_hash_doesnt_escape_ampersand
- @controller = TestController.new
- @view = ActionView::Base.new
- @view.controller = @controller
-
- path = @view.url_for(:controller => :cheeses, :foo => :bar, :baz => :quux)
-
- assert_equal '/cheeses?baz=quux&foo=bar', sort_query_string_params(path)
+ path = url_for(hash_for(:foo => :bar, :baz => :quux))
+ assert_equal '/?baz=quux&foo=bar', sort_query_string_params(path)
end
# todo: missing test cases
@@ -118,65 +133,54 @@ class UrlHelperTest < ActionView::TestCase
end
def test_link_tag_without_host_option
- ActionController::Base.class_eval { attr_accessor :url }
- url = {:controller => 'weblog', :action => 'show'}
- @controller = ActionController::Base.new
- @controller.request = ActionController::TestRequest.new
- assert_dom_equal(%q{<a href="/weblog/show">Test Link</a>}, link_to('Test Link', url))
+ assert_dom_equal(%q{<a href="/">Test Link</a>}, link_to('Test Link', url_hash))
end
def test_link_tag_with_host_option
- ActionController::Base.class_eval { attr_accessor :url }
- url = {:controller => 'weblog', :action => 'show', :host => 'www.example.com'}
- @controller = ActionController::Base.new
- @controller.request = ActionController::TestRequest.new
- assert_dom_equal(%q{<a href="http://www.example.com/weblog/show">Test Link</a>}, link_to('Test Link', url))
+ hash = hash_for(:host => "www.example.com")
+ expected = %q{<a href="http://www.example.com/">Test Link</a>}
+ assert_dom_equal(expected, link_to('Test Link', hash))
end
def test_link_tag_with_query
- assert_dom_equal "<a href=\"http://www.example.com?q1=v1&amp;q2=v2\">Hello</a>", link_to("Hello", "http://www.example.com?q1=v1&amp;q2=v2")
+ expected = %{<a href="http://www.example.com?q1=v1&amp;q2=v2">Hello</a>}
+ assert_dom_equal expected, link_to("Hello", "http://www.example.com?q1=v1&amp;q2=v2")
end
def test_link_tag_with_query_and_no_name
- assert_dom_equal "<a href=\"http://www.example.com?q1=v1&amp;q2=v2\">http://www.example.com?q1=v1&amp;q2=v2</a>", link_to(nil, "http://www.example.com?q1=v1&amp;q2=v2")
+ link = link_to(nil, "http://www.example.com?q1=v1&amp;q2=v2")
+ expected = %{<a href="http://www.example.com?q1=v1&amp;q2=v2">http://www.example.com?q1=v1&amp;q2=v2</a>}
+ assert_dom_equal expected, link
end
def test_link_tag_with_back
- @request.env['HOST_NAME'] = 'www.example.com'
- @request.env['PATH_INFO'] = '/weblog/show'
- @request.env['HTTP_REFERER'] = 'http://www.example.com/referer'
- assert_dom_equal "<a href=\"http://www.example.com/referer\">go back</a>", link_to('go back', :back)
+ env = {"HTTP_REFERER" => "http://www.example.com/referer"}
+ @controller = Struct.new(:request).new(Struct.new(:env).new(env))
+ expected = %{<a href="#{env["HTTP_REFERER"]}">go back</a>}
+ assert_dom_equal expected, link_to('go back', :back)
end
def test_link_tag_with_back_and_no_referer
- @request.env['HOST_NAME'] = 'www.example.com'
- @request.env['PATH_INFO'] = '/weblog/show'
- assert_dom_equal "<a href=\"javascript:history.back()\">go back</a>", link_to('go back', :back)
- end
-
- def test_link_tag_with_back
- @request.env['HOST_NAME'] = 'www.example.com'
- @request.env['PATH_INFO'] = '/weblog/show'
- @request.env['HTTP_REFERER'] = 'http://www.example.com/referer'
- assert_dom_equal "<a href=\"http://www.example.com/referer\">go back</a>", link_to('go back', :back)
- end
-
- def test_link_tag_with_back_and_no_referer
- @request.env['HOST_NAME'] = 'www.example.com'
- @request.env['PATH_INFO'] = '/weblog/show'
- assert_dom_equal "<a href=\"javascript:history.back()\">go back</a>", link_to('go back', :back)
+ @controller = Struct.new(:request).new(Struct.new(:env).new({}))
+ link = link_to('go back', :back)
+ assert_dom_equal %{<a href="javascript:history.back()">go back</a>}, link
end
def test_link_tag_with_img
- assert_dom_equal "<a href=\"http://www.example.com\"><img src='/favicon.jpg' alt=\"Favicon\" /></a>", link_to(image_tag("/favicon.jpg"), "http://www.example.com")
+ link = link_to("<img src='/favicon.jpg' />".html_safe, "/")
+ expected = %{<a href="/"><img src='/favicon.jpg' /></a>}
+ assert_dom_equal expected, link
end
def test_link_with_nil_html_options
- assert_dom_equal "<a href=\"http://www.example.com\">Hello</a>", link_to("Hello", {:action => 'myaction'}, nil)
+ link = link_to("Hello", url_hash, nil)
+ assert_dom_equal %{<a href="/">Hello</a>}, link
end
def test_link_tag_with_custom_onclick
- assert_dom_equal "<a href=\"http://www.example.com\" onclick=\"alert('yay!')\">Hello</a>", link_to("Hello", "http://www.example.com", :onclick => "alert('yay!')")
+ link = link_to("Hello", "http://www.example.com", :onclick => "alert('yay!')")
+ expected = %{<a href="http://www.example.com" onclick="alert('yay!')">Hello</a>}
+ assert_dom_equal expected, link
end
def test_link_tag_with_javascript_confirm
@@ -238,91 +242,106 @@ class UrlHelperTest < ActionView::TestCase
end
def test_link_tag_using_block_in_erb
- output_buffer = link_to("http://example.com") { concat("Example site") }
- assert_equal '<a href="http://example.com">Example site</a>', output_buffer
+ out = render_erb %{<%= link_to('/') do %>Example site<% end %>}
+ assert_equal '<a href="/">Example site</a>', out
end
def test_link_to_unless
- assert_equal "Showing", link_to_unless(true, "Showing", :action => "show", :controller => "weblog")
- assert_dom_equal "<a href=\"http://www.example.com\">Listing</a>", link_to_unless(false, "Listing", :action => "list", :controller => "weblog")
- assert_equal "Showing", link_to_unless(true, "Showing", :action => "show", :controller => "weblog", :id => 1)
- assert_equal "<strong>Showing</strong>", link_to_unless(true, "Showing", :action => "show", :controller => "weblog", :id => 1) { |name, options, html_options|
- "<strong>#{name}</strong>"
- }
- assert_equal "<strong>Showing</strong>", link_to_unless(true, "Showing", :action => "show", :controller => "weblog", :id => 1) { |name|
- "<strong>#{name}</strong>"
- }
- assert_equal "test", link_to_unless(true, "Showing", :action => "show", :controller => "weblog", :id => 1) {
- "test"
- }
+ assert_equal "Showing", link_to_unless(true, "Showing", url_hash)
+
+ assert_dom_equal %{<a href="/">Listing</a>},
+ link_to_unless(false, "Listing", url_hash)
+
+ assert_equal "Showing", link_to_unless(true, "Showing", url_hash)
+
+ assert_equal "<strong>Showing</strong>",
+ link_to_unless(true, "Showing", url_hash) { |name|
+ "<strong>#{name}</strong>"
+ }
+
+ assert_equal "<strong>Showing</strong>",
+ link_to_unless(true, "Showing", url_hash) { |name|
+ "<strong>#{name}</strong>"
+ }
+
+ assert_equal "test",
+ link_to_unless(true, "Showing", url_hash) {
+ "test"
+ }
end
def test_link_to_if
- assert_equal "Showing", link_to_if(false, "Showing", :action => "show", :controller => "weblog")
- assert_dom_equal "<a href=\"http://www.example.com\">Listing</a>", link_to_if(true, "Listing", :action => "list", :controller => "weblog")
- assert_equal "Showing", link_to_if(false, "Showing", :action => "show", :controller => "weblog", :id => 1)
+ assert_equal "Showing", link_to_if(false, "Showing", url_hash)
+ assert_dom_equal %{<a href="/">Listing</a>}, link_to_if(true, "Listing", url_hash)
+ assert_equal "Showing", link_to_if(false, "Showing", url_hash)
+ end
+
+ def request_for_url(url)
+ env = Rack::MockRequest.env_for("http://www.example.com#{url}")
+ ActionDispatch::Request.new(env)
end
def test_current_page_with_simple_url
- @request.env['HTTP_HOST'] = 'www.example.com'
- @request.env['PATH_INFO'] = '/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")
+ @request = request_for_url("/")
+ assert current_page?(url_hash)
+ assert current_page?("http://www.example.com/")
end
def test_current_page_ignoring_params
- @request.env['HTTP_HOST'] = 'www.example.com'
- @request.env['PATH_INFO'] = '/weblog/show'
- @request.env['QUERY_STRING'] = '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")
+ @request = request_for_url("/?order=desc&page=1")
+
+ assert current_page?(url_hash)
+ assert current_page?("http://www.example.com/")
end
def test_current_page_with_params_that_match
- @request.env['HTTP_HOST'] = 'www.example.com'
- @request.env['PATH_INFO'] = '/weblog/show'
- @request.env['QUERY_STRING'] = '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&amp;page=1")
+ @request = request_for_url("/?order=desc&page=1")
+
+ assert current_page?(hash_for(:order => "desc", :page => "1"))
+ assert current_page?("http://www.example.com/?order=desc&amp;page=1")
end
def test_link_unless_current
- @request.env['HTTP_HOST'] = 'www.example.com'
- @request.env['PATH_INFO'] = '/weblog/show'
- @controller.url = "http://www.example.com/weblog/show"
- 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")
-
- @request.env['QUERY_STRING'] = 'order=desc'
- @controller.url = "http://www.example.com/weblog/show"
- 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")
-
- @request.env['QUERY_STRING'] = '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")
-
- @request.env['QUERY_STRING'] = 'order=desc'
- @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", "http://www.example.com/weblog/show?order=asc")
-
- @request.env['QUERY_STRING'] = '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&amp;page=2\">Showing</a>", link_to_unless_current("Showing", "http://www.example.com/weblog/show?order=desc&page=2")
-
- @request.env['QUERY_STRING'] = ''
- @controller.url = "http://www.example.com/weblog/list"
- assert_equal "<a href=\"http://www.example.com/weblog/list\">Listing</a>",
- link_to_unless_current("Listing", :action => "list", :controller => "weblog")
- assert_equal "<a href=\"http://www.example.com/weblog/list\">Listing</a>",
- link_to_unless_current("Listing", "http://www.example.com/weblog/list")
+ @request = request_for_url("/")
+
+ assert_equal "Showing",
+ link_to_unless_current("Showing", url_hash)
+ assert_equal "Showing",
+ link_to_unless_current("Showing", "http://www.example.com/")
+
+ @request = request_for_url("/?order=desc")
+
+ assert_equal "Showing",
+ link_to_unless_current("Showing", url_hash)
+ assert_equal "Showing",
+ link_to_unless_current("Showing", "http://www.example.com/")
+
+ @request = request_for_url("/?order=desc&page=1")
+
+ assert_equal "Showing",
+ link_to_unless_current("Showing", hash_for(:order=>'desc', :page=>'1'))
+ assert_equal "Showing",
+ link_to_unless_current("Showing", "http://www.example.com/?order=desc&page=1")
+
+ @request = request_for_url("/?order=desc")
+
+ assert_equal %{<a href="/?order=asc">Showing</a>},
+ link_to_unless_current("Showing", hash_for(:order => :asc))
+ assert_equal %{<a href="http://www.example.com/?order=asc">Showing</a>},
+ link_to_unless_current("Showing", "http://www.example.com/?order=asc")
+
+ @request = request_for_url("/?order=desc")
+ assert_equal %{<a href="/?order=desc&page=2\">Showing</a>},
+ link_to_unless_current("Showing", hash_for(:order => "desc", :page => 2))
+ assert_equal %{<a href="http://www.example.com/?order=desc&amp;page=2">Showing</a>},
+ link_to_unless_current("Showing", "http://www.example.com/?order=desc&page=2")
+
+ @request = request_for_url("/show")
+
+ assert_equal %{<a href="/">Listing</a>},
+ link_to_unless_current("Listing", url_hash)
+ assert_equal %{<a href="http://www.example.com/">Listing</a>},
+ link_to_unless_current("Listing", "http://www.example.com/")
end
def test_mail_to
@@ -352,7 +371,8 @@ class UrlHelperTest < ActionView::TestCase
end
def test_mail_to_with_img
- assert_dom_equal %(<a href="mailto:feedback@example.com"><img src="/feedback.png" /></a>), mail_to('feedback@example.com', '<img src="/feedback.png" />'.html_safe)
+ assert_dom_equal %(<a href="mailto:feedback@example.com"><img src="/feedback.png" /></a>),
+ mail_to('feedback@example.com', '<img src="/feedback.png" />'.html_safe)
end
def test_mail_to_with_hex
@@ -369,6 +389,7 @@ class UrlHelperTest < ActionView::TestCase
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
+ # TODO: button_to looks at this ... why?
def protect_against_forgery?
false
end
@@ -383,6 +404,15 @@ end
class UrlHelperControllerTest < ActionController::TestCase
class UrlHelperController < ActionController::Base
+ test_routes do |map|
+ match 'url_helper_controller_test/url_helper/show_named_route',
+ :to => 'url_helper_controller_test/url_helper#show_named_route',
+ :as => :show_named_route
+
+ map.connect ":controller/:action/:id"
+ # match "/:controller(/:action(/:id))"
+ end
+
def show_url_for
render :inline => "<%= url_for :controller => 'url_helper_controller_test/url_helper', :action => 'show_url_for' %>"
end
@@ -406,17 +436,14 @@ class UrlHelperControllerTest < ActionController::TestCase
end
def test_named_route_url_shows_host_and_path
- with_url_helper_routing do
- get :show_named_route, :kind => 'url'
- assert_equal 'http://test.host/url_helper_controller_test/url_helper/show_named_route', @response.body
- end
+ get :show_named_route, :kind => 'url'
+ assert_equal 'http://test.host/url_helper_controller_test/url_helper/show_named_route',
+ @response.body
end
def test_named_route_path_shows_only_path
- with_url_helper_routing do
- get :show_named_route, :kind => 'path'
- assert_equal '/url_helper_controller_test/url_helper/show_named_route', @response.body
- end
+ get :show_named_route, :kind => 'path'
+ assert_equal '/url_helper_controller_test/url_helper/show_named_route', @response.body
end
def test_url_for_nil_returns_current_path
@@ -431,24 +458,16 @@ class UrlHelperControllerTest < ActionController::TestCase
end
end
- with_url_helper_routing do
- get :show_named_route, :kind => 'url'
- assert_equal 'http://testtwo.host/url_helper_controller_test/url_helper/show_named_route', @response.body
- end
+ get :show_named_route, :kind => 'url'
+ assert_equal 'http://testtwo.host/url_helper_controller_test/url_helper/show_named_route', @response.body
end
-
- protected
- def with_url_helper_routing
- with_routing do |set|
- set.draw do |map|
- match 'url_helper_controller_test/url_helper/show_named_route', :to => 'url_helper_controller_test/url_helper#show_named_route', :as => :show_named_route
- end
- yield
- end
- end
end
class TasksController < ActionController::Base
+ test_routes do
+ resources :tasks
+ end
+
def index
render_default
end
@@ -468,36 +487,19 @@ class TasksController < ActionController::Base
end
class LinkToUnlessCurrentWithControllerTest < ActionController::TestCase
- def setup
- super
- @controller = TasksController.new
- end
+ tests TasksController
def test_link_to_unless_current_to_current
- with_restful_routing do
- get :index
- assert_equal "tasks\ntasks", @response.body
- end
+ get :index
+ assert_equal "tasks\ntasks", @response.body
end
def test_link_to_unless_current_shows_link
- with_restful_routing do
- get :show, :id => 1
- assert_equal "<a href=\"/tasks\">tasks</a>\n" +
- "<a href=\"#{@request.protocol}#{@request.host_with_port}/tasks\">tasks</a>",
- @response.body
- end
+ get :show, :id => 1
+ assert_equal "<a href=\"/tasks\">tasks</a>\n" +
+ "<a href=\"#{@request.protocol}#{@request.host_with_port}/tasks\">tasks</a>",
+ @response.body
end
-
- protected
- def with_restful_routing
- with_routing do |set|
- set.draw do |map|
- resources :tasks
- end
- yield
- end
- end
end
class Workshop
@@ -537,6 +539,12 @@ class Session
end
class WorkshopsController < ActionController::Base
+ test_routes do
+ resources :workshops do
+ resources :sessions
+ end
+ end
+
def index
@workshop = Workshop.new(nil)
render :inline => "<%= url_for(@workshop) %>\n<%= link_to('Workshop', @workshop) %>"
@@ -551,6 +559,12 @@ class WorkshopsController < ActionController::Base
end
class SessionsController < ActionController::Base
+ test_routes do
+ resources :workshops do
+ resources :sessions
+ end
+ end
+
def index
@workshop = Workshop.new(params[:workshop_id])
@session = Session.new(nil)
@@ -567,56 +581,31 @@ class SessionsController < ActionController::Base
end
class PolymorphicControllerTest < ActionController::TestCase
- def setup
- super
- @response = ActionController::TestResponse.new
- end
-
def test_new_resource
@controller = WorkshopsController.new
- with_restful_routing do
- get :index
- assert_equal "/workshops\n<a href=\"/workshops\">Workshop</a>", @response.body
- end
+ get :index
+ assert_equal "/workshops\n<a href=\"/workshops\">Workshop</a>", @response.body
end
def test_existing_resource
@controller = WorkshopsController.new
- with_restful_routing do
- get :show, :id => 1
- assert_equal "/workshops/1\n<a href=\"/workshops/1\">Workshop</a>", @response.body
- end
+ get :show, :id => 1
+ assert_equal "/workshops/1\n<a href=\"/workshops/1\">Workshop</a>", @response.body
end
def test_new_nested_resource
@controller = SessionsController.new
- with_restful_routing do
- get :index, :workshop_id => 1
- assert_equal "/workshops/1/sessions\n<a href=\"/workshops/1/sessions\">Session</a>", @response.body
- end
+ get :index, :workshop_id => 1
+ assert_equal "/workshops/1/sessions\n<a href=\"/workshops/1/sessions\">Session</a>", @response.body
end
-
+
def test_existing_nested_resource
@controller = SessionsController.new
-
- with_restful_routing do
- get :show, :workshop_id => 1, :id => 1
- assert_equal "/workshops/1/sessions/1\n<a href=\"/workshops/1/sessions/1\">Session</a>", @response.body
- end
+
+ get :show, :workshop_id => 1, :id => 1
+ assert_equal "/workshops/1/sessions/1\n<a href=\"/workshops/1/sessions/1\">Session</a>", @response.body
end
-
- protected
- def with_restful_routing
- with_routing do |set|
- set.draw do |map|
- resources :workshops do
- resources :sessions
- end
- end
- yield
- end
- end
end
diff --git a/activemodel/CHANGELOG b/activemodel/CHANGELOG
index eae337e737..8c458b6091 100644
--- a/activemodel/CHANGELOG
+++ b/activemodel/CHANGELOG
@@ -1,4 +1,19 @@
-*Edge*
+*Rails 3.0.0 [beta 2] (April 1st, 2010)*
+
+* #new_record? and #destroyed? were removed from ActiveModel::Lint. Use
+ persisted? instead. A model is persisted if it's not a new_record? and it was
+ not destroyed? [MG]
+
+* Added validations reflection in ActiveModel::Validations [JV]
+
+ Model.validators
+ Model.validators_on(:field)
+
+* #to_key was added to ActiveModel::Lint so we can generate DOM IDs for
+ AMo objects with composite keys [MG]
+
+
+*Rails 3.0.0 [beta 1] (February 4, 2010)*
* ActiveModel::Observer#add_observer!
diff --git a/activemodel/activemodel.gemspec b/activemodel/activemodel.gemspec
index eb9ef7b7c0..9695911398 100644
--- a/activemodel/activemodel.gemspec
+++ b/activemodel/activemodel.gemspec
@@ -1,22 +1,23 @@
-version = File.read(File.expand_path("../../RAILS_VERSION", __FILE__)).strip
+version = File.read(File.expand_path('../../RAILS_VERSION', __FILE__)).strip
Gem::Specification.new do |s|
- s.platform = Gem::Platform::RUBY
- s.name = 'activemodel'
- s.version = version
- s.summary = 'A toolkit for building modeling frameworks (part of Rails).'
+ s.platform = Gem::Platform::RUBY
+ s.name = 'activemodel'
+ s.version = version
+ s.summary = 'A toolkit for building modeling frameworks (part of Rails).'
s.description = 'A toolkit for building modeling frameworks like Active Record and Active Resource. Rich support for attributes, callbacks, validations, observers, serialization, internationalization, and testing.'
+
s.required_ruby_version = '>= 1.8.7'
- s.author = "David Heinemeier Hansson"
- s.email = "david@loudthinking.com"
- s.rubyforge_project = "activemodel"
- s.homepage = "http://www.rubyonrails.org"
+ s.author = 'David Heinemeier Hansson'
+ s.email = 'david@loudthinking.com'
+ s.homepage = 'http://www.rubyonrails.org'
+ s.rubyforge_project = 'activemodel'
+
+ s.files = Dir['CHANGELOG', 'MIT-LICENSE', 'README', 'lib/**/*']
+ s.require_path = 'lib'
s.has_rdoc = true
s.add_dependency('activesupport', version)
-
- s.require_path = 'lib'
- s.files = Dir["CHANGELOG", "MIT-LICENSE", "README", "lib/**/*"]
end
diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb
index 2d5acdfced..a7ee15a7f6 100644
--- a/activemodel/lib/active_model/dirty.rb
+++ b/activemodel/lib/active_model/dirty.rb
@@ -91,17 +91,12 @@ module ActiveModel
attribute_method_affix :prefix => 'reset_', :suffix => '!'
end
- def initialize(*)
- @changed_attributes = {}
- super
- end
-
# Do any attributes have unsaved changes?
# person.changed? # => false
# person.name = 'bob'
# person.changed? # => true
def changed?
- !@changed_attributes.empty?
+ !changed_attributes.empty?
end
# List of attributes with unsaved changes.
@@ -109,7 +104,7 @@ module ActiveModel
# person.name = 'bob'
# person.changed # => ['name']
def changed
- @changed_attributes.keys
+ changed_attributes.keys
end
# Map of changed attrs => [original value, new value].
@@ -130,19 +125,24 @@ module ActiveModel
end
private
+ # Map of change <tt>attr => original value</tt>.
+ def changed_attributes
+ @changed_attributes ||= {}
+ end
+
# Handle <tt>*_changed?</tt> for +method_missing+.
def attribute_changed?(attr)
- @changed_attributes.include?(attr)
+ changed_attributes.include?(attr)
end
# Handle <tt>*_change</tt> for +method_missing+.
def attribute_change(attr)
- [@changed_attributes[attr], __send__(attr)] if attribute_changed?(attr)
+ [changed_attributes[attr], __send__(attr)] if attribute_changed?(attr)
end
# Handle <tt>*_was</tt> for +method_missing+.
def attribute_was(attr)
- attribute_changed?(attr) ? @changed_attributes[attr] : __send__(attr)
+ attribute_changed?(attr) ? changed_attributes[attr] : __send__(attr)
end
# Handle <tt>*_will_change!</tt> for +method_missing+.
@@ -153,12 +153,12 @@ module ActiveModel
rescue TypeError, NoMethodError
end
- @changed_attributes[attr] = value
+ changed_attributes[attr] = value
end
# Handle <tt>reset_*!</tt> for +method_missing+.
def reset_attribute!(attr)
- __send__("#{attr}=", @changed_attributes[attr]) if attribute_changed?(attr)
+ __send__("#{attr}=", changed_attributes[attr]) if attribute_changed?(attr)
end
end
end
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index 8d28040c32..64b28f6def 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
require 'active_support/core_ext/array/wrap'
require 'active_support/core_ext/string/inflections'
require 'active_support/core_ext/object/blank'
diff --git a/activemodel/lib/active_model/version.rb b/activemodel/lib/active_model/version.rb
index 85d0eed180..a33657626f 100644
--- a/activemodel/lib/active_model/version.rb
+++ b/activemodel/lib/active_model/version.rb
@@ -3,7 +3,7 @@ module ActiveModel
MAJOR = 3
MINOR = 0
TINY = 0
- BUILD = "beta1"
+ BUILD = "beta2"
STRING = [MAJOR, MINOR, TINY, BUILD].join('.')
end
diff --git a/activemodel/test/cases/dirty_test.rb b/activemodel/test/cases/dirty_test.rb
index 0883363baf..c910cb43d4 100644
--- a/activemodel/test/cases/dirty_test.rb
+++ b/activemodel/test/cases/dirty_test.rb
@@ -6,7 +6,6 @@ class DirtyTest < ActiveModel::TestCase
define_attribute_methods [:name]
def initialize
- super
@name = nil
end
diff --git a/activemodel/test/cases/validations/i18n_validation_test.rb b/activemodel/test/cases/validations/i18n_validation_test.rb
index 38844bb1fa..7dd82e711d 100644
--- a/activemodel/test/cases/validations/i18n_validation_test.rb
+++ b/activemodel/test/cases/validations/i18n_validation_test.rb
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
require "cases/helper"
require 'cases/tests_database'
require 'models/person'
@@ -41,6 +43,14 @@ class I18nValidationTest < ActiveModel::TestCase
@person.errors.add_on_blank :title, 'custom'
end
+ def test_full_message_encoding
+ I18n.backend.store_translations('en', :errors => {
+ :messages => { :too_short => '猫舌' }})
+ Person.validates_length_of :title, :within => 3..5
+ @person.valid?
+ assert_equal ['Title 猫舌'], @person.errors.full_messages
+ end
+
def test_errors_full_messages_translates_human_attribute_name_for_model_attributes
@person.errors.add(:name, 'not found')
Person.expects(:human_attribute_name).with(:name, :default => 'Name').returns("Person's name")
diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG
index e379f4f967..e0625c3dbb 100644
--- a/activerecord/CHANGELOG
+++ b/activerecord/CHANGELOG
@@ -1,5 +1,15 @@
*Rails 3.0.0 [Beta 2] (pending)*
+* Add Relation extensions. [Pratik Naik]
+
+ users = User.where(:admin => true).extending(User::AdminPowers)
+
+ latest_users = User.order('created_at DESC') do
+ def posts_count
+ Post.count(:user_id => to_a.map(&:id))
+ end
+ end
+
* To prefix the table names of all models in a module, define self.table_name_prefix on the module. #4032 [Andrew White]
* Silenced "SHOW FIELDS" and "SET SQL_AUTO_IS_NULL=0" statements from the MySQL driver to improve log signal to noise ration in development [DHH]
diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec
index 8121530ab3..59caa53be0 100644
--- a/activerecord/activerecord.gemspec
+++ b/activerecord/activerecord.gemspec
@@ -6,6 +6,7 @@ Gem::Specification.new do |s|
s.version = version
s.summary = 'Object-relational mapper framework (part of Rails).'
s.description = 'Databases on Rails. Build a persistent domain model by mapping database tables to Ruby classes. Strong conventions for associations, validations, aggregations, migrations, and testing come baked-in.'
+
s.required_ruby_version = '>= 1.8.7'
s.author = 'David Heinemeier Hansson'
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 7406daf837..20a8754b7c 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1495,14 +1495,6 @@ module ActiveRecord
# finder conditions.
def configure_dependency_for_has_many(reflection, extra_conditions = nil)
if reflection.options.include?(:dependent)
- # Add polymorphic type if the :as option is present
- dependent_conditions = []
- dependent_conditions << "#{reflection.primary_key_name} = \#{record.#{reflection.name}.send(:owner_quoted_id)}"
- dependent_conditions << "#{reflection.options[:as]}_type = '#{base_class.name}'" if reflection.options[:as]
- dependent_conditions << sanitize_sql(reflection.options[:conditions], reflection.table_name) if reflection.options[:conditions]
- dependent_conditions << extra_conditions if extra_conditions
- dependent_conditions = dependent_conditions.collect {|where| "(#{where})" }.join(" AND ")
- dependent_conditions = dependent_conditions.gsub('@', '\@')
case reflection.options[:dependent]
when :destroy
method_name = "has_many_dependent_destroy_for_#{reflection.name}".to_sym
@@ -1511,51 +1503,30 @@ module ActiveRecord
end
before_destroy method_name
when :delete_all
- # before_destroy do |record|
- # self.class.send(:delete_all_has_many_dependencies,
- # record,
- # "posts",
- # Post,
- # %@...@) # this is a string literal like %(...)
- # end
- # end
- module_eval <<-CALLBACK
- before_destroy do |record|
- self.class.send(:delete_all_has_many_dependencies,
- record,
- "#{reflection.name}",
- #{reflection.class_name},
- %@#{dependent_conditions}@)
- end
- CALLBACK
+ before_destroy do |record|
+ self.class.send(:delete_all_has_many_dependencies,
+ record,
+ reflection.name,
+ reflection.klass,
+ reflection.dependent_conditions(record, self.class, extra_conditions))
+ end
when :nullify
- # before_destroy do |record|
- # self.class.send(:nullify_has_many_dependencies,
- # record,
- # "posts",
- # Post,
- # "user_id",
- # %@...@) # this is a string literal like %(...)
- # end
- # end
- module_eval <<-CALLBACK
- before_destroy do |record|
- self.class.send(:nullify_has_many_dependencies,
- record,
- "#{reflection.name}",
- #{reflection.class_name},
- "#{reflection.primary_key_name}",
- %@#{dependent_conditions}@)
- end
- CALLBACK
- when :restrict
- method_name = "has_many_dependent_restrict_for_#{reflection.name}".to_sym
- define_method(method_name) do
- unless send(reflection.name).empty?
- raise DeleteRestrictionError.new(reflection)
- end
+ before_destroy do |record|
+ self.class.send(:nullify_has_many_dependencies,
+ record,
+ reflection.name,
+ reflection.klass,
+ reflection.primary_key_name,
+ reflection.dependent_conditions(record, self.class, extra_conditions))
+ end
+ when :restrict
+ method_name = "has_many_dependent_restrict_for_#{reflection.name}".to_sym
+ define_method(method_name) do
+ unless send(reflection.name).empty?
+ raise DeleteRestrictionError.new(reflection)
end
- before_destroy method_name
+ end
+ before_destroy method_name
else
raise ArgumentError, "The :dependent option expects either :destroy, :delete_all, :nullify or :restrict (#{reflection.options[:dependent].inspect})"
end
diff --git a/activerecord/lib/active_record/associations/through_association_scope.rb b/activerecord/lib/active_record/associations/through_association_scope.rb
index 6f0f698f1e..1d2f323112 100644
--- a/activerecord/lib/active_record/associations/through_association_scope.rb
+++ b/activerecord/lib/active_record/associations/through_association_scope.rb
@@ -135,7 +135,7 @@ module ActiveRecord
def build_through_conditions
conditions = @reflection.through_reflection.options[:conditions]
if conditions.is_a?(Hash)
- interpolate_sql(sanitize_sql(conditions)).gsub(
+ interpolate_sql(@reflection.through_reflection.klass.send(:sanitize_sql, conditions)).gsub(
@reflection.quoted_table_name,
@reflection.through_reflection.quoted_table_name)
elsif conditions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
index 046825d43f..6c477e48ce 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
@@ -23,7 +23,8 @@ module ActiveRecord
#
# +name+ is the column's name, such as <tt>supplier_id</tt> in <tt>supplier_id int(11)</tt>.
# +default+ is the type-casted default value, such as +new+ in <tt>sales_stage varchar(20) default 'new'</tt>.
- # +sql_type+ is only used to extract the column's length, if necessary. For example +60+ in <tt>company_name varchar(60)</tt>.
+ # +sql_type+ is used to extract the column's length, if necessary. For example +60+ in <tt>company_name varchar(60)</tt>.
+ # It will be mapped to one of the standard Rails SQL types in the <tt>type</tt> attribute.
# +null+ determines if this column allows +NULL+ values.
def initialize(name, default, sql_type = nil, null = true)
@name, @sql_type, @null = name, sql_type, null
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index a6042e1382..2395a744a3 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -114,6 +114,12 @@ module ActiveRecord
# Object identifier types
when /^oid$/
:integer
+ # UUID type
+ when /^uuid$/
+ :string
+ # Small and big integer types
+ when /^(?:small|big)int$/
+ :integer
# Pass through all types that are not specific to PostgreSQL.
else
super
diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb
index 9abf979cd0..632322b517 100644
--- a/activerecord/lib/active_record/named_scope.rb
+++ b/activerecord/lib/active_record/named_scope.rb
@@ -8,16 +8,15 @@ module ActiveRecord
extend ActiveSupport::Concern
module ClassMethods
- # Returns a relation if invoked without any arguments.
+ # Returns an anonymous scope.
#
# posts = Post.scoped
# posts.size # Fires "select count(*) from posts" and returns the count
# posts.each {|p| puts p.name } # Fires "select * from posts" and loads post objects
#
- # Returns an anonymous named scope if any options are supplied.
- #
- # shirts = Shirt.scoped(:conditions => {:color => 'red'})
- # shirts = shirts.scoped(:include => :washing_instructions)
+ # fruits = Fruit.scoped
+ # fruits = fruits.where(:colour => 'red') if options[:red_only]
+ # fruits = fruits.limit(10) if limited?
#
# Anonymous \scopes tend to be useful when procedurally generating complex queries, where passing
# intermediate values (scopes) around as first-class objects is convenient.
@@ -25,7 +24,8 @@ module ActiveRecord
# You can define a scope that applies to all finders using ActiveRecord::Base.default_scope.
def scoped(options = {}, &block)
if options.present?
- Scope.init(self, options, &block)
+ relation = scoped.apply_finder_options(options)
+ block_given? ? relation.extending(Module.new(&block)) : relation
else
current_scoped_methods ? unscoped.merge(current_scoped_methods) : unscoped.clone
end
@@ -36,21 +36,21 @@ module ActiveRecord
end
# Adds a class method for retrieving and querying objects. A scope represents a narrowing of a database query,
- # such as <tt>:conditions => {:color => :red}, :select => 'shirts.*', :include => :washing_instructions</tt>.
+ # such as <tt>where(:color => :red).select('shirts.*').includes(:washing_instructions)</tt>.
#
# class Shirt < ActiveRecord::Base
- # scope :red, :conditions => {:color => 'red'}
- # scope :dry_clean_only, :joins => :washing_instructions, :conditions => ['washing_instructions.dry_clean_only = ?', true]
+ # scope :red, where(:color => 'red')
+ # scope :dry_clean_only, joins(:washing_instructions).where('washing_instructions.dry_clean_only = ?', true)
# end
#
# The above calls to <tt>scope</tt> define class methods Shirt.red and Shirt.dry_clean_only. Shirt.red,
- # in effect, represents the query <tt>Shirt.find(:all, :conditions => {:color => 'red'})</tt>.
+ # in effect, represents the query <tt>Shirt.where(:color => 'red')</tt>.
#
# Unlike <tt>Shirt.find(...)</tt>, however, the object returned by Shirt.red is not an Array; it resembles the association object
- # constructed by a <tt>has_many</tt> declaration. For instance, you can invoke <tt>Shirt.red.find(:first)</tt>, <tt>Shirt.red.count</tt>,
- # <tt>Shirt.red.find(:all, :conditions => {:size => 'small'})</tt>. Also, just
- # as with the association objects, named \scopes act like an Array, implementing Enumerable; <tt>Shirt.red.each(&block)</tt>,
- # <tt>Shirt.red.first</tt>, and <tt>Shirt.red.inject(memo, &block)</tt> all behave as if Shirt.red really was an Array.
+ # constructed by a <tt>has_many</tt> declaration. For instance, you can invoke <tt>Shirt.red.first</tt>, <tt>Shirt.red.count</tt>,
+ # <tt>Shirt.red.where(:size => 'small')</tt>. Also, just as with the association objects, named \scopes act like an Array,
+ # implementing Enumerable; <tt>Shirt.red.each(&block)</tt>, <tt>Shirt.red.first</tt>, and <tt>Shirt.red.inject(memo, &block)</tt>
+ # all behave as if Shirt.red really was an Array.
#
# These named \scopes are composable. For instance, <tt>Shirt.red.dry_clean_only</tt> will produce all shirts that are both red and dry clean only.
# Nested finds and calculations also work with these compositions: <tt>Shirt.red.dry_clean_only.count</tt> returns the number of garments
@@ -69,9 +69,7 @@ module ActiveRecord
# Named \scopes can also be procedural:
#
# class Shirt < ActiveRecord::Base
- # scope :colored, lambda { |color|
- # { :conditions => { :color => color } }
- # }
+ # scope :colored, lambda {|color| where(:color => color) }
# end
#
# In this example, <tt>Shirt.colored('puce')</tt> finds all puce shirts.
@@ -79,26 +77,13 @@ module ActiveRecord
# Named \scopes can also have extensions, just as with <tt>has_many</tt> declarations:
#
# class Shirt < ActiveRecord::Base
- # scope :red, :conditions => {:color => 'red'} do
+ # scope :red, where(:color => 'red') do
# def dom_id
# 'red_shirts'
# end
# end
# end
- #
- #
- # For testing complex named \scopes, you can examine the scoping options using the
- # <tt>proxy_options</tt> method on the proxy itself.
- #
- # class Shirt < ActiveRecord::Base
- # scope :colored, lambda { |color|
- # { :conditions => { :color => color } }
- # }
- # end
- #
- # expected_options = { :conditions => { :colored => 'red' } }
- # assert_equal expected_options, Shirt.colored('red').proxy_options
- def scope(name, options = {}, &block)
+ def scope(name, scope_options = {}, &block)
name = name.to_sym
if !scopes[name] && respond_to?(name, true)
@@ -106,17 +91,17 @@ module ActiveRecord
"Overwriting existing method #{self.name}.#{name}."
end
- scopes[name] = lambda do |parent_scope, *args|
- Scope.init(parent_scope, case options
- when Hash, Relation
- options
- when Proc
- options.call(*args)
- end, &block)
+ scopes[name] = lambda do |*args|
+ options = scope_options.is_a?(Proc) ? scope_options.call(*args) : scope_options
+
+ relation = scoped
+ relation = options.is_a?(Hash) ? relation.apply_finder_options(options) : scoped.merge(options) if options
+ block_given? ? relation.extending(Module.new(&block)) : relation
end
+
singleton_class.instance_eval do
define_method name do |*args|
- scopes[name].call(self, *args)
+ scopes[name].call(*args)
end
end
end
@@ -127,73 +112,5 @@ module ActiveRecord
end
end
- class Scope < Relation
- attr_accessor :current_scoped_methods_when_defined
-
- delegate :scopes, :with_scope, :with_exclusive_scope, :scoped_methods, :scoped, :to => :klass
-
- def self.init(klass, options, &block)
- relation = new(klass, klass.arel_table)
-
- scope = if options.is_a?(Hash)
- klass.scoped.apply_finder_options(options.except(:extend))
- else
- options ? klass.scoped.merge(options) : klass.scoped
- end
-
- relation = relation.merge(scope)
-
- Array.wrap(options[:extend]).each {|extension| relation.send(:extend, extension) } if options.is_a?(Hash)
- relation.send(:extend, Module.new(&block)) if block_given?
-
- relation.current_scoped_methods_when_defined = klass.send(:current_scoped_methods)
- relation
- end
-
- def first(*args)
- if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash))
- to_a.first(*args)
- else
- args.first.present? ? apply_finder_options(args.first).first : super
- end
- end
-
- def last(*args)
- if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash))
- to_a.last(*args)
- else
- args.first.present? ? apply_finder_options(args.first).last : super
- end
- end
-
- def ==(other)
- case other
- when Scope
- to_sql == other.to_sql
- when Relation
- other == self
- when Array
- to_a == other.to_a
- end
- end
-
- private
-
- def method_missing(method, *args, &block)
- if klass.respond_to?(method)
- with_scope(self) do
- if current_scoped_methods_when_defined && !scoped_methods.include?(current_scoped_methods_when_defined) && !scopes.include?(method)
- with_scope(current_scoped_methods_when_defined) { klass.send(method, *args, &block) }
- else
- klass.send(method, *args, &block)
- end
- end
- else
- super
- end
- end
-
- end
-
end
end
diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake
index 06485b9033..a107befef3 100644
--- a/activerecord/lib/active_record/railties/databases.rake
+++ b/activerecord/lib/active_record/railties/databases.rake
@@ -84,7 +84,7 @@ namespace :db do
end
end
when 'postgresql'
- @encoding = config[:encoding] || ENV['CHARSET'] || 'utf8'
+ @encoding = config['encoding'] || ENV['CHARSET'] || 'utf8'
schema_search_path = config['schema_search_path'] || 'public'
first_in_schema_search_path = schema_search_path.split(',').first.strip
begin
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb
index 5e8fc104cb..0e48e229b3 100644
--- a/activerecord/lib/active_record/reflection.rb
+++ b/activerecord/lib/active_record/reflection.rb
@@ -277,6 +277,17 @@ module ActiveRecord
!options[:validate].nil? ? options[:validate] : (options[:autosave] == true || macro == :has_many)
end
+ def dependent_conditions(record, base_class, extra_conditions)
+ dependent_conditions = []
+ dependent_conditions << "#{primary_key_name} = #{record.send(name).send(:owner_quoted_id)}"
+ dependent_conditions << "#{options[:as]}_type = '#{base_class.name}'" if options[:as]
+ dependent_conditions << klass.send(:sanitize_sql, options[:conditions]) if options[:conditions]
+ dependent_conditions << extra_conditions if extra_conditions
+ dependent_conditions = dependent_conditions.collect {|where| "(#{where})" }.join(" AND ")
+ dependent_conditions = dependent_conditions.gsub('@', '\@')
+ dependent_conditions
+ end
+
private
def derive_class_name
class_name = name.to_s.camelize
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index 8577ec58f7..4e62187449 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -13,8 +13,9 @@ module ActiveRecord
delegate :insert, :to => :arel
attr_reader :table, :klass
+ attr_accessor :extensions
- def initialize(klass, table)
+ def initialize(klass, table, &block)
@klass, @table = klass, table
@implicit_readonly = nil
@@ -22,6 +23,9 @@ module ActiveRecord
SINGLE_VALUE_METHODS.each {|v| instance_variable_set(:"@#{v}_value", nil)}
(ASSOCIATION_METHODS + MULTI_VALUE_METHODS).each {|v| instance_variable_set(:"@#{v}_values", [])}
+ @extensions = []
+
+ apply_modules(Module.new(&block)) if block_given?
end
def new(*args, &block)
@@ -307,11 +311,26 @@ module ActiveRecord
@should_eager_load ||= (@eager_load_values.any? || (@includes_values.any? && references_eager_loaded_tables?))
end
+ def ==(other)
+ case other
+ when Relation
+ other.to_sql == to_sql
+ when Array
+ to_a == other.to_a
+ end
+ end
+
+ def inspect
+ to_a.inspect
+ end
+
protected
def method_missing(method, *args, &block)
if Array.method_defined?(method)
to_a.send(method, *args, &block)
+ elsif @klass.scopes[method]
+ merge(@klass.send(method, *args, &block))
elsif @klass.respond_to?(method)
@klass.send(:with_scope, self) { @klass.send(method, *args, &block) }
elsif arel.respond_to?(method)
diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb
index 37aaac0894..a26f1c0ac8 100644
--- a/activerecord/lib/active_record/relation/finder_methods.rb
+++ b/activerecord/lib/active_record/relation/finder_methods.rb
@@ -106,13 +106,29 @@ module ActiveRecord
# A convenience wrapper for <tt>find(:first, *args)</tt>. You can pass in all the
# same arguments to this method as you can to <tt>find(:first)</tt>.
def first(*args)
- args.any? ? apply_finder_options(args.first).first : find_first
+ if args.any?
+ if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash))
+ to_a.first(*args)
+ else
+ apply_finder_options(args.first).first
+ end
+ else
+ find_first
+ end
end
# A convenience wrapper for <tt>find(:last, *args)</tt>. You can pass in all the
# same arguments to this method as you can to <tt>find(:last)</tt>.
def last(*args)
- args.any? ? apply_finder_options(args.first).last : find_last
+ if args.any?
+ if args.first.kind_of?(Integer) || (loaded? && !args.first.kind_of?(Hash))
+ to_a.last(*args)
+ else
+ apply_finder_options(args.first).last
+ end
+ else
+ find_last
+ end
end
# A convenience wrapper for <tt>find(:all, *args)</tt>. You can pass in all the
diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb
index 711df16bf1..d0efa2189d 100644
--- a/activerecord/lib/active_record/relation/predicate_builder.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder.rb
@@ -20,10 +20,12 @@ module ActiveRecord
table = Arel::Table.new(table_name, :engine => @engine)
end
- attribute = table[column]
+ unless attribute = table[column]
+ raise StatementInvalid, "No attribute named `#{column}` exists for table `#{table.name}`"
+ end
case value
- when Array, ActiveRecord::Associations::AssociationCollection, ActiveRecord::NamedScope::Scope
+ when Array, ActiveRecord::Associations::AssociationCollection, ActiveRecord::Relation
values = value.to_a
attribute.in(values)
when Range
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index e224781016..b5e8b7570a 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -10,8 +10,9 @@ module ActiveRecord
next if [:where, :having].include?(query_method)
class_eval <<-CEVAL
- def #{query_method}(*args)
+ def #{query_method}(*args, &block)
new_relation = clone
+ new_relation.send(:apply_modules, Module.new(&block)) if block_given?
value = Array.wrap(args.flatten).reject {|x| x.blank? }
new_relation.#{query_method}_values += value if value.present?
new_relation
@@ -21,8 +22,9 @@ module ActiveRecord
[:where, :having].each do |query_method|
class_eval <<-CEVAL
- def #{query_method}(*args)
+ def #{query_method}(*args, &block)
new_relation = clone
+ new_relation.send(:apply_modules, Module.new(&block)) if block_given?
value = build_where(*args)
new_relation.#{query_method}_values += [*value] if value.present?
new_relation
@@ -34,8 +36,9 @@ module ActiveRecord
attr_accessor :"#{query_method}_value"
class_eval <<-CEVAL
- def #{query_method}(value = true)
+ def #{query_method}(value = true, &block)
new_relation = clone
+ new_relation.send(:apply_modules, Module.new(&block)) if block_given?
new_relation.#{query_method}_value = value
new_relation
end
@@ -43,8 +46,16 @@ module ActiveRecord
end
end
- def lock(locks = true)
+ def extending(*modules)
+ new_relation = clone
+ new_relation.send :apply_modules, *modules
+ new_relation
+ end
+
+ def lock(locks = true, &block)
relation = clone
+ relation.send(:apply_modules, Module.new(&block)) if block_given?
+
case locks
when String, TrueClass, NilClass
clone.tap {|new_relation| new_relation.lock_value = locks || true }
@@ -191,6 +202,12 @@ module ActiveRecord
private
+ def apply_modules(modules)
+ values = Array.wrap(modules)
+ @extensions += values if values.present?
+ values.each {|extension| extend(extension) }
+ end
+
def reverse_sql_order(order_query)
order_query.to_s.split(/,/).each { |s|
if s.match(/\s(asc|ASC)$/)
diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb
index a17de1bdbb..8fdd64afcc 100644
--- a/activerecord/lib/active_record/relation/spawn_methods.rb
+++ b/activerecord/lib/active_record/relation/spawn_methods.rb
@@ -6,10 +6,9 @@ module ActiveRecord
merged_relation = clone
return merged_relation unless r
- (ActiveRecord::Relation::ASSOCIATION_METHODS + ActiveRecord::Relation::MULTI_VALUE_METHODS).reject {|m| [:joins, :where].include?(m)}.each do |method|
- unless (value = r.send(:"#{method}_values")).blank?
- merged_relation.send(:"#{method}_values=", value)
- end
+ (Relation::ASSOCIATION_METHODS + Relation::MULTI_VALUE_METHODS).reject {|m| [:joins, :where].include?(m)}.each do |method|
+ value = r.send(:"#{method}_values")
+ merged_relation.send(:"#{method}_values=", value) if value.present?
end
merged_relation = merged_relation.joins(r.joins_values)
@@ -26,7 +25,7 @@ module ActiveRecord
merged_relation.where_values = merged_wheres
- ActiveRecord::Relation::SINGLE_VALUE_METHODS.reject {|m| m == :lock}.each do |method|
+ Relation::SINGLE_VALUE_METHODS.reject {|m| m == :lock}.each do |method|
unless (value = r.send(:"#{method}_value")).nil?
merged_relation.send(:"#{method}_value=", value)
end
@@ -34,6 +33,9 @@ module ActiveRecord
merged_relation.lock_value = r.lock_value unless merged_relation.lock_value
+ # Apply scope extension modules
+ merged_relation.send :apply_modules, r.extensions
+
merged_relation
end
@@ -69,7 +71,7 @@ module ActiveRecord
result
end
- VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset,
+ VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, :extend,
:order, :select, :readonly, :group, :having, :from, :lock ]
def apply_finder_options(options)
@@ -84,6 +86,7 @@ module ActiveRecord
relation = relation.where(options[:conditions]) if options.has_key?(:conditions)
relation = relation.includes(options[:include]) if options.has_key?(:include)
+ relation = relation.extending(options[:extend]) if options.has_key?(:extend)
relation
end
diff --git a/activerecord/lib/active_record/version.rb b/activerecord/lib/active_record/version.rb
index eaf5dc6545..cf78ec6e12 100644
--- a/activerecord/lib/active_record/version.rb
+++ b/activerecord/lib/active_record/version.rb
@@ -3,7 +3,7 @@ module ActiveRecord
MAJOR = 3
MINOR = 0
TINY = 0
- BUILD = "beta1"
+ BUILD = "beta2"
STRING = [MAJOR, MINOR, TINY, BUILD].join('.')
end
diff --git a/activerecord/test/cases/column_definition_test.rb b/activerecord/test/cases/column_definition_test.rb
index fc9a0ac96e..8b6c019d50 100644
--- a/activerecord/test/cases/column_definition_test.rb
+++ b/activerecord/test/cases/column_definition_test.rb
@@ -67,4 +67,21 @@ class ColumnDefinitionTest < ActiveRecord::TestCase
assert !text_column.has_default?
end
end
+
+ if current_adapter?(:PostgreSQLAdapter)
+ def test_bigint_column_should_map_to_integer
+ bigint_column = ActiveRecord::ConnectionAdapters::PostgreSQLColumn.new('number', nil, "bigint")
+ assert_equal bigint_column.type, :integer
+ end
+
+ def test_smallint_column_should_map_to_integer
+ smallint_column = ActiveRecord::ConnectionAdapters::PostgreSQLColumn.new('number', nil, "smallint")
+ assert_equal smallint_column.type, :integer
+ end
+
+ def test_uuid_column_should_map_to_string
+ uuid_column = ActiveRecord::ConnectionAdapters::PostgreSQLColumn.new('unique_id', nil, "uuid")
+ assert_equal uuid_column.type, :string
+ end
+ end
end
diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb
index 1e345399f5..7b9e680c02 100644
--- a/activerecord/test/cases/relations_test.rb
+++ b/activerecord/test/cases/relations_test.rb
@@ -572,4 +572,20 @@ class RelationTest < ActiveRecord::TestCase
assert_equal Post.all, all_posts.all
end
+ def test_anonymous_extension
+ relation = Post.where(:author_id => 1).order('id ASC') do
+ def author
+ 'lifo'
+ end
+ end
+
+ assert_equal "lifo", relation.author
+ assert_equal "lifo", relation.limit(1).author
+ end
+
+ def test_named_extension
+ relation = Post.where(:author_id => 1).order('id ASC').extending(Post::NamedExtension)
+ assert_equal "lifo", relation.author
+ assert_equal "lifo", relation.limit(1).author
+ end
end
diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb
index 704313649a..d092c4bf09 100644
--- a/activerecord/test/models/post.rb
+++ b/activerecord/test/models/post.rb
@@ -1,4 +1,10 @@
class Post < ActiveRecord::Base
+ module NamedExtension
+ def author
+ 'lifo'
+ end
+ end
+
scope :containing_the_letter_a, where("body LIKE '%a%'")
scope :ranked_by_comments, order("comments_count DESC")
scope :limit_by, lambda {|l| limit(l) }
diff --git a/activeresource/CHANGELOG b/activeresource/CHANGELOG
index 113694e895..27bf99a8ee 100644
--- a/activeresource/CHANGELOG
+++ b/activeresource/CHANGELOG
@@ -1,4 +1,4 @@
-*Edge*
+*Rails 3.0.0 [beta 1] (February 4, 2010)*
* Add support for errors in JSON format. #1956 [Fabien Jakimowicz]
diff --git a/activeresource/activeresource.gemspec b/activeresource/activeresource.gemspec
index 3718bb4f2e..ca74c0dd7d 100644
--- a/activeresource/activeresource.gemspec
+++ b/activeresource/activeresource.gemspec
@@ -6,6 +6,7 @@ Gem::Specification.new do |s|
s.version = version
s.summary = 'REST modeling framework (part of Rails).'
s.description = 'REST on Rails. Wrap your RESTful web app with Ruby classes and work with them like Active Record models.'
+
s.required_ruby_version = '>= 1.8.7'
s.author = 'David Heinemeier Hansson'
diff --git a/activeresource/lib/active_resource/version.rb b/activeresource/lib/active_resource/version.rb
index bb60954e05..d01ebd017f 100644
--- a/activeresource/lib/active_resource/version.rb
+++ b/activeresource/lib/active_resource/version.rb
@@ -3,7 +3,7 @@ module ActiveResource
MAJOR = 3
MINOR = 0
TINY = 0
- BUILD = "beta1"
+ BUILD = "beta2"
STRING = [MAJOR, MINOR, TINY, BUILD].join('.')
end
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index 3822abcab6..b9f565c71d 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,4 +1,9 @@
-*Rails 3.0 (pending)*
+*Rails 3.0.0 [beta 2] (April 1st, 2010)*
+
+* Reduced load time by deferring configuration of classes using
+ ActiveSupport::on_load(:component_name) [YK]
+
+* Rename #metaclass to #singleton_class now that ruby-core has decided [JK]
* New assertions assert_blank and assert_present. #4299 [Juanjo Bazan]
@@ -7,7 +12,7 @@
* JSON backend for YAJL. Preferred if available. #2666 [Brian Lopez]
-*Rails 3.0.0 [beta] (February 4, 2010)*
+*Rails 3.0.0 [beta 1] (February 4, 2010)*
* Introduce class_attribute to declare inheritable class attributes. Writing an attribute on a subclass behaves just like overriding the superclass reader method. Unifies and replaces most usage of cattr_accessor, class_inheritable_attribute, superclass_delegating_attribute, and extlib_inheritable_attribute. [Jeremy Kemper, Yehuda Katz]
diff --git a/activesupport/activesupport.gemspec b/activesupport/activesupport.gemspec
index bfb1e83002..ad1401bfa9 100644
--- a/activesupport/activesupport.gemspec
+++ b/activesupport/activesupport.gemspec
@@ -6,6 +6,7 @@ Gem::Specification.new do |s|
s.version = version
s.summary = 'A toolkit of support libraries and Ruby core extensions extracted from the Rails framework.'
s.description = 'A toolkit of support libraries and Ruby core extensions extracted from the Rails framework. Rich support for multibyte strings, internationalization, time zones, and testing.'
+
s.required_ruby_version = '>= 1.8.7'
s.author = 'David Heinemeier Hansson'
diff --git a/activesupport/lib/active_support/core_ext/class/attribute.rb b/activesupport/lib/active_support/core_ext/class/attribute.rb
index 9631a7d242..577d5cbf45 100644
--- a/activesupport/lib/active_support/core_ext/class/attribute.rb
+++ b/activesupport/lib/active_support/core_ext/class/attribute.rb
@@ -50,7 +50,7 @@ class Class
singleton_class.send(:define_method, attr) { value }
end
- define_method(attr) { self.class.send(attr) }
+ define_method(attr) { self.singleton_class.send(attr) }
define_method(:"#{attr}?") { !!send(attr) }
define_method(:"#{attr}=") do |value|
singleton_class.remove_possible_method(attr)
diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb
index 945cdd5278..03b324764b 100644
--- a/activesupport/lib/active_support/values/time_zone.rb
+++ b/activesupport/lib/active_support/values/time_zone.rb
@@ -194,7 +194,7 @@ module ActiveSupport
# offset is the number of seconds that this time zone is offset from UTC
# (GMT). Seconds were chosen as the offset unit because that is the unit that
# Ruby uses to represent time zone offsets (see Time#utc_offset).
- def initialize(name, utc_offset, tzinfo = nil)
+ def initialize(name, utc_offset = nil, tzinfo = nil)
@name = name
@utc_offset = utc_offset
@tzinfo = tzinfo
@@ -202,8 +202,12 @@ module ActiveSupport
end
def utc_offset
- @current_period ||= tzinfo.current_period
- @current_period.utc_offset
+ if @utc_offset
+ @utc_offset
+ else
+ @current_period ||= tzinfo.current_period
+ @current_period.utc_offset
+ end
end
# Returns the offset of this time zone as a formatted string, of the
@@ -305,75 +309,29 @@ module ActiveSupport
tzinfo.period_for_local(time, dst)
end
- # TODO: Preload instead of lazy load for thread safety
def tzinfo
+ @tzinfo ||= TimeZone.find_tzinfo(name)
+ end
+
+ # TODO: Preload instead of lazy load for thread safety
+ def self.find_tzinfo(name)
require 'tzinfo' unless defined?(::TZInfo)
- @tzinfo ||= ::TZInfo::Timezone.get(MAPPING[name])
+ ::TZInfo::Timezone.get(MAPPING[name] || name)
+ rescue TZInfo::InvalidTimezoneIdentifier
+ nil
end
unless const_defined?(:ZONES)
ZONES = []
ZONES_MAP = {}
- [[-39_600, "International Date Line West", "Midway Island", "Samoa" ],
- [-36_000, "Hawaii" ],
- [-32_400, "Alaska" ],
- [-28_800, "Pacific Time (US & Canada)", "Tijuana" ],
- [-25_200, "Mountain Time (US & Canada)", "Chihuahua", "Mazatlan",
- "Arizona" ],
- [-21_600, "Central Time (US & Canada)", "Saskatchewan", "Guadalajara",
- "Mexico City", "Monterrey", "Central America" ],
- [-18_000, "Eastern Time (US & Canada)", "Indiana (East)", "Bogota",
- "Lima", "Quito" ],
- [-16_200, "Caracas" ],
- [-14_400, "Atlantic Time (Canada)", "Georgetown", "La Paz", "Santiago" ],
- [-12_600, "Newfoundland" ],
- [-10_800, "Brasilia", "Buenos Aires", "Greenland" ],
- [ -7_200, "Mid-Atlantic" ],
- [ -3_600, "Azores", "Cape Verde Is." ],
- [ 0, "Dublin", "Edinburgh", "Lisbon", "London", "Casablanca",
- "Monrovia", "UTC" ],
- [ 3_600, "Belgrade", "Bratislava", "Budapest", "Ljubljana", "Prague",
- "Sarajevo", "Skopje", "Warsaw", "Zagreb", "Brussels",
- "Copenhagen", "Madrid", "Paris", "Amsterdam", "Berlin",
- "Bern", "Rome", "Stockholm", "Vienna",
- "West Central Africa" ],
- [ 7_200, "Bucharest", "Cairo", "Helsinki", "Kyiv", "Riga", "Sofia",
- "Tallinn", "Vilnius", "Athens", "Istanbul", "Minsk",
- "Jerusalem", "Harare", "Pretoria" ],
- [ 10_800, "Moscow", "St. Petersburg", "Volgograd", "Kuwait", "Riyadh",
- "Nairobi", "Baghdad" ],
- [ 12_600, "Tehran" ],
- [ 14_400, "Abu Dhabi", "Muscat", "Baku", "Tbilisi", "Yerevan" ],
- [ 16_200, "Kabul" ],
- [ 18_000, "Ekaterinburg", "Islamabad", "Karachi", "Tashkent" ],
- [ 19_800, "Chennai", "Kolkata", "Mumbai", "New Delhi", "Sri Jayawardenepura" ],
- [ 20_700, "Kathmandu" ],
- [ 21_600, "Astana", "Dhaka", "Almaty",
- "Novosibirsk" ],
- [ 23_400, "Rangoon" ],
- [ 25_200, "Bangkok", "Hanoi", "Jakarta", "Krasnoyarsk" ],
- [ 28_800, "Beijing", "Chongqing", "Hong Kong", "Urumqi",
- "Kuala Lumpur", "Singapore", "Taipei", "Perth", "Irkutsk",
- "Ulaan Bataar" ],
- [ 32_400, "Seoul", "Osaka", "Sapporo", "Tokyo", "Yakutsk" ],
- [ 34_200, "Darwin", "Adelaide" ],
- [ 36_000, "Canberra", "Melbourne", "Sydney", "Brisbane", "Hobart",
- "Vladivostok", "Guam", "Port Moresby" ],
- [ 39_600, "Magadan", "Solomon Is.", "New Caledonia" ],
- [ 43_200, "Fiji", "Kamchatka", "Marshall Is.", "Auckland",
- "Wellington" ],
- [ 46_800, "Nuku'alofa" ]].
- each do |offset, *places|
- places.each do |place|
- place.freeze
- zone = new(place, offset)
- ZONES << zone
- ZONES_MAP[place] = zone
- end
+ MAPPING.each_key do |place|
+ place.freeze
+ zone = new(place)
+ ZONES << zone
+ ZONES_MAP[place] = zone
end
ZONES.sort!
ZONES.freeze
- ZONES_MAP.freeze
US_ZONES = ZONES.find_all { |z| z.name =~ /US|Arizona|Indiana|Hawaii|Alaska/ }
US_ZONES.freeze
@@ -404,7 +362,7 @@ module ActiveSupport
def [](arg)
case arg
when String
- ZONES_MAP[arg]
+ ZONES_MAP[arg] ||= lookup(arg)
when Numeric, ActiveSupport::Duration
arg *= 3600 if arg.abs <= 13
all.find { |z| z.utc_offset == arg.to_i }
@@ -418,6 +376,12 @@ module ActiveSupport
def us_zones
US_ZONES
end
+
+ private
+
+ def lookup(name)
+ (tzinfo = find_tzinfo(name)) && create(tzinfo.name.freeze)
+ end
end
end
end
diff --git a/activesupport/lib/active_support/version.rb b/activesupport/lib/active_support/version.rb
index 831204693f..3ce11e59d2 100644
--- a/activesupport/lib/active_support/version.rb
+++ b/activesupport/lib/active_support/version.rb
@@ -3,7 +3,7 @@ module ActiveSupport
MAJOR = 3
MINOR = 0
TINY = 0
- BUILD = "beta1"
+ BUILD = "beta2"
STRING = [MAJOR, MINOR, TINY, BUILD].join('.')
end
diff --git a/activesupport/test/core_ext/class/attribute_test.rb b/activesupport/test/core_ext/class/attribute_test.rb
index 06b4cf075f..24aa5c0eba 100644
--- a/activesupport/test/core_ext/class/attribute_test.rb
+++ b/activesupport/test/core_ext/class/attribute_test.rb
@@ -59,4 +59,10 @@ class ClassAttributeTest < ActiveSupport::TestCase
object = Class.new { class_attribute :setting, :instance_writer => false }.new
assert_raise(NoMethodError) { object.setting = 'boom' }
end
+
+ test 'works well with singleton classes' do
+ object = @klass.new
+ object.singleton_class.setting = 'foo'
+ assert_equal 'foo', object.setting
+ end
end
diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb
index ce43c6507d..68027f7c94 100644
--- a/activesupport/test/time_zone_test.rb
+++ b/activesupport/test/time_zone_test.rb
@@ -75,6 +75,14 @@ class TimeZoneTest < Test::Unit::TestCase
end
end
+ def test_unknown_timezones_delegation_to_tzinfo
+ zone = ActiveSupport::TimeZone['America/Montevideo']
+ assert_equal ActiveSupport::TimeZone, zone.class
+ assert_equal zone.object_id, ActiveSupport::TimeZone['America/Montevideo'].object_id
+ assert_equal Time.utc(2010, 1, 31, 22), zone.utc_to_local(Time.utc(2010, 2)) # daylight saving offset -0200
+ assert_equal Time.utc(2010, 3, 31, 21), zone.utc_to_local(Time.utc(2010, 4)) # standard offset -0300
+ end
+
def test_today
Time.stubs(:now).returns(Time.utc(2000, 1, 1, 4, 59, 59)) # 1 sec before midnight Jan 1 EST
assert_equal Date.new(1999, 12, 31), ActiveSupport::TimeZone['Eastern Time (US & Canada)'].today
diff --git a/rails.gemspec b/rails.gemspec
index 8b9a374e25..9c3204242f 100644
--- a/rails.gemspec
+++ b/rails.gemspec
@@ -6,7 +6,8 @@ Gem::Specification.new do |s|
s.version = version
s.summary = 'Full-stack web application framework.'
s.description = 'Ruby on Rails is a full-stack web framework optimized for programmer happiness and sustainable productivity. It encourages beautiful code by favoring convention over configuration.'
- s.required_ruby_version = '>= 1.8.7'
+
+ s.required_ruby_version = '>= 1.8.7'
s.required_rubygems_version = ">= 1.3.6"
s.author = 'David Heinemeier Hansson'
@@ -17,11 +18,11 @@ Gem::Specification.new do |s|
s.files = []
s.require_path = []
- s.add_dependency('activesupport', version)
- s.add_dependency('actionpack', version)
- s.add_dependency('activerecord', version)
- s.add_dependency('activeresource', version)
- s.add_dependency('actionmailer', version)
- s.add_dependency('railties', version)
- s.add_dependency('bundler', '>= 0.9.8')
+ s.add_dependency('activesupport', version)
+ s.add_dependency('actionpack', version)
+ s.add_dependency('activerecord', version)
+ s.add_dependency('activeresource', version)
+ s.add_dependency('actionmailer', version)
+ s.add_dependency('railties', version)
+ s.add_dependency('bundler', '>= 0.9.14')
end
diff --git a/rails3b.gemspec b/rails3b.gemspec
deleted file mode 100644
index 613a248ef7..0000000000
--- a/rails3b.gemspec
+++ /dev/null
@@ -1,27 +0,0 @@
-Gem::Specification.new do |s|
- s.platform = Gem::Platform::RUBY
- s.name = 'rails3b'
- s.version = '3.0.1'
- s.summary = 'Just the Rails 3 beta dependencies. Works around prerelease RubyGems bug in versions before 1.3.6.'
- s.required_ruby_version = '>= 1.8.7'
-
- s.author = 'Jeremy Kemper'
- s.email = 'jeremy@bitsweat.net'
-
- s.files = []
- s.require_path = []
-
- s.add_dependency('mail', '~> 2.1.2')
- s.add_dependency('text-format', '~> 1.0.0')
- s.add_dependency('rack', '~> 1.1.0')
- s.add_dependency('rack-test', '~> 0.5.0')
- s.add_dependency('rack-mount', '= 0.4.7')
- s.add_dependency('erubis', '~> 2.6.5')
- s.add_dependency('i18n', '~> 0.3.0')
- s.add_dependency('tzinfo', '~> 0.3.16')
- s.add_dependency('builder', '~> 2.1.2')
- s.add_dependency('memcache-client', '~> 1.7.5')
- s.add_dependency('bundler', '>= 0.9.8')
- s.add_dependency('rake', '>= 0.8.3')
- s.add_dependency('thor', '~> 0.13')
-end
diff --git a/railties/CHANGELOG b/railties/CHANGELOG
index 0b67479742..24ba378efe 100644
--- a/railties/CHANGELOG
+++ b/railties/CHANGELOG
@@ -1,4 +1,18 @@
-*Edge*
+*Rails 3.0.0 [beta 2] (April 1st, 2010)*
+
+* Session store configuration has changed [YK & CL]
+
+ config.session_store :cookie_store, {:key => "..."}
+ config.cookie_secret = "fdsfhisdghfidugnfdlg"
+
+* railtie_name and engine_name are deprecated. You can now add any object to
+ the configuration object: config.your_plugin = {} [JK]
+
+* Added config.generators.templates to provide alternative paths for the generators
+ to look for templates [JV]
+
+
+*Rails 3.0.0 [beta 1] (February 4, 2010)*
* Added "rake about" as a replacement for script/about [DHH]
diff --git a/railties/guides/images/belongs_to.png b/railties/guides/assets/images/belongs_to.png
index 44243edbca..44243edbca 100644
--- a/railties/guides/images/belongs_to.png
+++ b/railties/guides/assets/images/belongs_to.png
Binary files differ
diff --git a/railties/guides/images/book_icon.gif b/railties/guides/assets/images/book_icon.gif
index c81d5db520..c81d5db520 100644
--- a/railties/guides/images/book_icon.gif
+++ b/railties/guides/assets/images/book_icon.gif
Binary files differ
diff --git a/railties/guides/images/bullet.gif b/railties/guides/assets/images/bullet.gif
index 95a26364a4..95a26364a4 100644
--- a/railties/guides/images/bullet.gif
+++ b/railties/guides/assets/images/bullet.gif
Binary files differ
diff --git a/railties/guides/images/challenge.png b/railties/guides/assets/images/challenge.png
index d163748640..d163748640 100644
--- a/railties/guides/images/challenge.png
+++ b/railties/guides/assets/images/challenge.png
Binary files differ
diff --git a/railties/guides/images/chapters_icon.gif b/railties/guides/assets/images/chapters_icon.gif
index 06fb415f4a..06fb415f4a 100644
--- a/railties/guides/images/chapters_icon.gif
+++ b/railties/guides/assets/images/chapters_icon.gif
Binary files differ
diff --git a/railties/guides/images/check_bullet.gif b/railties/guides/assets/images/check_bullet.gif
index 1fcfeba250..1fcfeba250 100644
--- a/railties/guides/images/check_bullet.gif
+++ b/railties/guides/assets/images/check_bullet.gif
Binary files differ
diff --git a/railties/guides/images/credits_pic_blank.gif b/railties/guides/assets/images/credits_pic_blank.gif
index f6f654fc65..f6f654fc65 100644
--- a/railties/guides/images/credits_pic_blank.gif
+++ b/railties/guides/assets/images/credits_pic_blank.gif
Binary files differ
diff --git a/railties/guides/images/csrf.png b/railties/guides/assets/images/csrf.png
index ab73baafe8..ab73baafe8 100644
--- a/railties/guides/images/csrf.png
+++ b/railties/guides/assets/images/csrf.png
Binary files differ
diff --git a/railties/guides/images/customized_error_messages.png b/railties/guides/assets/images/customized_error_messages.png
index fa676991e3..fa676991e3 100644
--- a/railties/guides/images/customized_error_messages.png
+++ b/railties/guides/assets/images/customized_error_messages.png
Binary files differ
diff --git a/railties/guides/images/edge_badge.png b/railties/guides/assets/images/edge_badge.png
index cddd46c4b8..cddd46c4b8 100644
--- a/railties/guides/images/edge_badge.png
+++ b/railties/guides/assets/images/edge_badge.png
Binary files differ
diff --git a/railties/guides/images/error_messages.png b/railties/guides/assets/images/error_messages.png
index 428892194a..428892194a 100644
--- a/railties/guides/images/error_messages.png
+++ b/railties/guides/assets/images/error_messages.png
Binary files differ
diff --git a/railties/guides/images/feature_tile.gif b/railties/guides/assets/images/feature_tile.gif
index 75469361db..75469361db 100644
--- a/railties/guides/images/feature_tile.gif
+++ b/railties/guides/assets/images/feature_tile.gif
Binary files differ
diff --git a/railties/guides/images/footer_tile.gif b/railties/guides/assets/images/footer_tile.gif
index bb33fc1ff0..bb33fc1ff0 100644
--- a/railties/guides/images/footer_tile.gif
+++ b/railties/guides/assets/images/footer_tile.gif
Binary files differ
diff --git a/railties/guides/images/fxn.png b/railties/guides/assets/images/fxn.png
index 9b531ee584..9b531ee584 100644
--- a/railties/guides/images/fxn.png
+++ b/railties/guides/assets/images/fxn.png
Binary files differ
diff --git a/railties/guides/images/grey_bullet.gif b/railties/guides/assets/images/grey_bullet.gif
index e75e8e93a1..e75e8e93a1 100644
--- a/railties/guides/images/grey_bullet.gif
+++ b/railties/guides/assets/images/grey_bullet.gif
Binary files differ
diff --git a/railties/guides/images/habtm.png b/railties/guides/assets/images/habtm.png
index fea78b0b5c..fea78b0b5c 100644
--- a/railties/guides/images/habtm.png
+++ b/railties/guides/assets/images/habtm.png
Binary files differ
diff --git a/railties/guides/images/has_many.png b/railties/guides/assets/images/has_many.png
index 6cff58460d..6cff58460d 100644
--- a/railties/guides/images/has_many.png
+++ b/railties/guides/assets/images/has_many.png
Binary files differ
diff --git a/railties/guides/images/has_many_through.png b/railties/guides/assets/images/has_many_through.png
index 85d7599925..85d7599925 100644
--- a/railties/guides/images/has_many_through.png
+++ b/railties/guides/assets/images/has_many_through.png
Binary files differ
diff --git a/railties/guides/images/has_one.png b/railties/guides/assets/images/has_one.png
index a70ddaaa86..a70ddaaa86 100644
--- a/railties/guides/images/has_one.png
+++ b/railties/guides/assets/images/has_one.png
Binary files differ
diff --git a/railties/guides/images/has_one_through.png b/railties/guides/assets/images/has_one_through.png
index 89a7617a30..89a7617a30 100644
--- a/railties/guides/images/has_one_through.png
+++ b/railties/guides/assets/images/has_one_through.png
Binary files differ
diff --git a/railties/guides/images/header_backdrop.png b/railties/guides/assets/images/header_backdrop.png
index ff2982175e..ff2982175e 100644
--- a/railties/guides/images/header_backdrop.png
+++ b/railties/guides/assets/images/header_backdrop.png
Binary files differ
diff --git a/railties/guides/images/header_tile.gif b/railties/guides/assets/images/header_tile.gif
index e2c878d492..e2c878d492 100644
--- a/railties/guides/images/header_tile.gif
+++ b/railties/guides/assets/images/header_tile.gif
Binary files differ
diff --git a/railties/guides/images/i18n/demo_localized_pirate.png b/railties/guides/assets/images/i18n/demo_localized_pirate.png
index 9134709573..9134709573 100644
--- a/railties/guides/images/i18n/demo_localized_pirate.png
+++ b/railties/guides/assets/images/i18n/demo_localized_pirate.png
Binary files differ
diff --git a/railties/guides/images/i18n/demo_translated_en.png b/railties/guides/assets/images/i18n/demo_translated_en.png
index ecdd878d38..ecdd878d38 100644
--- a/railties/guides/images/i18n/demo_translated_en.png
+++ b/railties/guides/assets/images/i18n/demo_translated_en.png
Binary files differ
diff --git a/railties/guides/images/i18n/demo_translated_pirate.png b/railties/guides/assets/images/i18n/demo_translated_pirate.png
index 41c580923a..41c580923a 100644
--- a/railties/guides/images/i18n/demo_translated_pirate.png
+++ b/railties/guides/assets/images/i18n/demo_translated_pirate.png
Binary files differ
diff --git a/railties/guides/images/i18n/demo_translation_missing.png b/railties/guides/assets/images/i18n/demo_translation_missing.png
index af9e2d0427..af9e2d0427 100644
--- a/railties/guides/images/i18n/demo_translation_missing.png
+++ b/railties/guides/assets/images/i18n/demo_translation_missing.png
Binary files differ
diff --git a/railties/guides/images/i18n/demo_untranslated.png b/railties/guides/assets/images/i18n/demo_untranslated.png
index 3603f43463..3603f43463 100644
--- a/railties/guides/images/i18n/demo_untranslated.png
+++ b/railties/guides/assets/images/i18n/demo_untranslated.png
Binary files differ
diff --git a/railties/guides/images/icons/README b/railties/guides/assets/images/icons/README
index f12b2a730c..f12b2a730c 100644
--- a/railties/guides/images/icons/README
+++ b/railties/guides/assets/images/icons/README
diff --git a/railties/guides/images/icons/callouts/1.png b/railties/guides/assets/images/icons/callouts/1.png
index 7d473430b7..7d473430b7 100644
--- a/railties/guides/images/icons/callouts/1.png
+++ b/railties/guides/assets/images/icons/callouts/1.png
Binary files differ
diff --git a/railties/guides/images/icons/callouts/10.png b/railties/guides/assets/images/icons/callouts/10.png
index 997bbc8246..997bbc8246 100644
--- a/railties/guides/images/icons/callouts/10.png
+++ b/railties/guides/assets/images/icons/callouts/10.png
Binary files differ
diff --git a/railties/guides/images/icons/callouts/11.png b/railties/guides/assets/images/icons/callouts/11.png
index ce47dac3f5..ce47dac3f5 100644
--- a/railties/guides/images/icons/callouts/11.png
+++ b/railties/guides/assets/images/icons/callouts/11.png
Binary files differ
diff --git a/railties/guides/images/icons/callouts/12.png b/railties/guides/assets/images/icons/callouts/12.png
index 31daf4e2f2..31daf4e2f2 100644
--- a/railties/guides/images/icons/callouts/12.png
+++ b/railties/guides/assets/images/icons/callouts/12.png
Binary files differ
diff --git a/railties/guides/images/icons/callouts/13.png b/railties/guides/assets/images/icons/callouts/13.png
index 14021a89c2..14021a89c2 100644
--- a/railties/guides/images/icons/callouts/13.png
+++ b/railties/guides/assets/images/icons/callouts/13.png
Binary files differ
diff --git a/railties/guides/images/icons/callouts/14.png b/railties/guides/assets/images/icons/callouts/14.png
index 64014b75fe..64014b75fe 100644
--- a/railties/guides/images/icons/callouts/14.png
+++ b/railties/guides/assets/images/icons/callouts/14.png
Binary files differ
diff --git a/railties/guides/images/icons/callouts/15.png b/railties/guides/assets/images/icons/callouts/15.png
index 0d65765fcf..0d65765fcf 100644
--- a/railties/guides/images/icons/callouts/15.png
+++ b/railties/guides/assets/images/icons/callouts/15.png
Binary files differ
diff --git a/railties/guides/images/icons/callouts/2.png b/railties/guides/assets/images/icons/callouts/2.png
index 5d09341b2f..5d09341b2f 100644
--- a/railties/guides/images/icons/callouts/2.png
+++ b/railties/guides/assets/images/icons/callouts/2.png
Binary files differ
diff --git a/railties/guides/images/icons/callouts/3.png b/railties/guides/assets/images/icons/callouts/3.png
index ef7b700471..ef7b700471 100644
--- a/railties/guides/images/icons/callouts/3.png
+++ b/railties/guides/assets/images/icons/callouts/3.png
Binary files differ
diff --git a/railties/guides/images/icons/callouts/4.png b/railties/guides/assets/images/icons/callouts/4.png
index adb8364eb5..adb8364eb5 100644
--- a/railties/guides/images/icons/callouts/4.png
+++ b/railties/guides/assets/images/icons/callouts/4.png
Binary files differ
diff --git a/railties/guides/images/icons/callouts/5.png b/railties/guides/assets/images/icons/callouts/5.png
index 4d7eb46002..4d7eb46002 100644
--- a/railties/guides/images/icons/callouts/5.png
+++ b/railties/guides/assets/images/icons/callouts/5.png
Binary files differ
diff --git a/railties/guides/images/icons/callouts/6.png b/railties/guides/assets/images/icons/callouts/6.png
index 0ba694af6c..0ba694af6c 100644
--- a/railties/guides/images/icons/callouts/6.png
+++ b/railties/guides/assets/images/icons/callouts/6.png
Binary files differ
diff --git a/railties/guides/images/icons/callouts/7.png b/railties/guides/assets/images/icons/callouts/7.png
index 472e96f8ac..472e96f8ac 100644
--- a/railties/guides/images/icons/callouts/7.png
+++ b/railties/guides/assets/images/icons/callouts/7.png
Binary files differ
diff --git a/railties/guides/images/icons/callouts/8.png b/railties/guides/assets/images/icons/callouts/8.png
index 5e60973c21..5e60973c21 100644
--- a/railties/guides/images/icons/callouts/8.png
+++ b/railties/guides/assets/images/icons/callouts/8.png
Binary files differ
diff --git a/railties/guides/images/icons/callouts/9.png b/railties/guides/assets/images/icons/callouts/9.png
index a0676d26cc..a0676d26cc 100644
--- a/railties/guides/images/icons/callouts/9.png
+++ b/railties/guides/assets/images/icons/callouts/9.png
Binary files differ
diff --git a/railties/guides/images/icons/caution.png b/railties/guides/assets/images/icons/caution.png
index cb9d5ea0df..cb9d5ea0df 100644
--- a/railties/guides/images/icons/caution.png
+++ b/railties/guides/assets/images/icons/caution.png
Binary files differ
diff --git a/railties/guides/images/icons/example.png b/railties/guides/assets/images/icons/example.png
index bba1c0010d..bba1c0010d 100644
--- a/railties/guides/images/icons/example.png
+++ b/railties/guides/assets/images/icons/example.png
Binary files differ
diff --git a/railties/guides/images/icons/home.png b/railties/guides/assets/images/icons/home.png
index 37a5231bac..37a5231bac 100644
--- a/railties/guides/images/icons/home.png
+++ b/railties/guides/assets/images/icons/home.png
Binary files differ
diff --git a/railties/guides/images/icons/important.png b/railties/guides/assets/images/icons/important.png
index 1096c23295..1096c23295 100644
--- a/railties/guides/images/icons/important.png
+++ b/railties/guides/assets/images/icons/important.png
Binary files differ
diff --git a/railties/guides/images/icons/next.png b/railties/guides/assets/images/icons/next.png
index 64e126bdda..64e126bdda 100644
--- a/railties/guides/images/icons/next.png
+++ b/railties/guides/assets/images/icons/next.png
Binary files differ
diff --git a/railties/guides/images/icons/note.png b/railties/guides/assets/images/icons/note.png
index 841820f7c4..841820f7c4 100644
--- a/railties/guides/images/icons/note.png
+++ b/railties/guides/assets/images/icons/note.png
Binary files differ
diff --git a/railties/guides/images/icons/prev.png b/railties/guides/assets/images/icons/prev.png
index 3e8f12fe24..3e8f12fe24 100644
--- a/railties/guides/images/icons/prev.png
+++ b/railties/guides/assets/images/icons/prev.png
Binary files differ
diff --git a/railties/guides/images/icons/tip.png b/railties/guides/assets/images/icons/tip.png
index a3a029d898..a3a029d898 100644
--- a/railties/guides/images/icons/tip.png
+++ b/railties/guides/assets/images/icons/tip.png
Binary files differ
diff --git a/railties/guides/images/icons/up.png b/railties/guides/assets/images/icons/up.png
index 2db1ce62fa..2db1ce62fa 100644
--- a/railties/guides/images/icons/up.png
+++ b/railties/guides/assets/images/icons/up.png
Binary files differ
diff --git a/railties/guides/images/icons/warning.png b/railties/guides/assets/images/icons/warning.png
index 0b0c419df2..0b0c419df2 100644
--- a/railties/guides/images/icons/warning.png
+++ b/railties/guides/assets/images/icons/warning.png
Binary files differ
diff --git a/railties/guides/assets/images/jaimeiniesta.jpg b/railties/guides/assets/images/jaimeiniesta.jpg
new file mode 100644
index 0000000000..445f048d92
--- /dev/null
+++ b/railties/guides/assets/images/jaimeiniesta.jpg
Binary files differ
diff --git a/railties/guides/images/nav_arrow.gif b/railties/guides/assets/images/nav_arrow.gif
index c4f57658d7..c4f57658d7 100644
--- a/railties/guides/images/nav_arrow.gif
+++ b/railties/guides/assets/images/nav_arrow.gif
Binary files differ
diff --git a/railties/guides/images/polymorphic.png b/railties/guides/assets/images/polymorphic.png
index ff2fd9f76d..ff2fd9f76d 100644
--- a/railties/guides/images/polymorphic.png
+++ b/railties/guides/assets/images/polymorphic.png
Binary files differ
diff --git a/railties/guides/images/posts_index.png b/railties/guides/assets/images/posts_index.png
index f6cd2f9b80..f6cd2f9b80 100644
--- a/railties/guides/images/posts_index.png
+++ b/railties/guides/assets/images/posts_index.png
Binary files differ
diff --git a/railties/guides/images/rails_guides_logo.gif b/railties/guides/assets/images/rails_guides_logo.gif
index a24683a34e..a24683a34e 100644
--- a/railties/guides/images/rails_guides_logo.gif
+++ b/railties/guides/assets/images/rails_guides_logo.gif
Binary files differ
diff --git a/railties/guides/images/rails_logo_remix.gif b/railties/guides/assets/images/rails_logo_remix.gif
index 58960ee4f9..58960ee4f9 100644
--- a/railties/guides/images/rails_logo_remix.gif
+++ b/railties/guides/assets/images/rails_logo_remix.gif
Binary files differ
diff --git a/railties/guides/images/rails_welcome.png b/railties/guides/assets/images/rails_welcome.png
index 0e02cf5a8c..0e02cf5a8c 100644
--- a/railties/guides/images/rails_welcome.png
+++ b/railties/guides/assets/images/rails_welcome.png
Binary files differ
diff --git a/railties/guides/images/session_fixation.png b/railties/guides/assets/images/session_fixation.png
index 6b084508db..6b084508db 100644
--- a/railties/guides/images/session_fixation.png
+++ b/railties/guides/assets/images/session_fixation.png
Binary files differ
diff --git a/railties/guides/images/tab_grey.gif b/railties/guides/assets/images/tab_grey.gif
index e9680b7136..e9680b7136 100644
--- a/railties/guides/images/tab_grey.gif
+++ b/railties/guides/assets/images/tab_grey.gif
Binary files differ
diff --git a/railties/guides/images/tab_info.gif b/railties/guides/assets/images/tab_info.gif
index 458fea9a61..458fea9a61 100644
--- a/railties/guides/images/tab_info.gif
+++ b/railties/guides/assets/images/tab_info.gif
Binary files differ
diff --git a/railties/guides/images/tab_note.gif b/railties/guides/assets/images/tab_note.gif
index 1d5c171ed6..1d5c171ed6 100644
--- a/railties/guides/images/tab_note.gif
+++ b/railties/guides/assets/images/tab_note.gif
Binary files differ
diff --git a/railties/guides/images/tab_red.gif b/railties/guides/assets/images/tab_red.gif
index daf140b5a8..daf140b5a8 100644
--- a/railties/guides/images/tab_red.gif
+++ b/railties/guides/assets/images/tab_red.gif
Binary files differ
diff --git a/railties/guides/images/tab_yellow.gif b/railties/guides/assets/images/tab_yellow.gif
index dc961c99dd..dc961c99dd 100644
--- a/railties/guides/images/tab_yellow.gif
+++ b/railties/guides/assets/images/tab_yellow.gif
Binary files differ
diff --git a/railties/guides/images/tab_yellow.png b/railties/guides/assets/images/tab_yellow.png
index cceea6581f..cceea6581f 100644
--- a/railties/guides/images/tab_yellow.png
+++ b/railties/guides/assets/images/tab_yellow.png
Binary files differ
diff --git a/railties/guides/images/validation_error_messages.png b/railties/guides/assets/images/validation_error_messages.png
index 622d35da5d..622d35da5d 100644
--- a/railties/guides/images/validation_error_messages.png
+++ b/railties/guides/assets/images/validation_error_messages.png
Binary files differ
diff --git a/railties/guides/files/javascripts/code_highlighter.js b/railties/guides/assets/javascripts/code_highlighter.js
index ce983dad52..ce983dad52 100755
--- a/railties/guides/files/javascripts/code_highlighter.js
+++ b/railties/guides/assets/javascripts/code_highlighter.js
diff --git a/railties/guides/files/javascripts/guides.js b/railties/guides/assets/javascripts/guides.js
index c4e4d459ea..c4e4d459ea 100755
--- a/railties/guides/files/javascripts/guides.js
+++ b/railties/guides/assets/javascripts/guides.js
diff --git a/railties/guides/files/javascripts/highlighters.js b/railties/guides/assets/javascripts/highlighters.js
index 4f5f0779d7..4f5f0779d7 100644
--- a/railties/guides/files/javascripts/highlighters.js
+++ b/railties/guides/assets/javascripts/highlighters.js
diff --git a/railties/guides/files/stylesheets/main.css b/railties/guides/assets/stylesheets/main.css
index d377628d73..7ccae2c87e 100644
--- a/railties/guides/files/stylesheets/main.css
+++ b/railties/guides/assets/stylesheets/main.css
@@ -92,7 +92,7 @@ body {
}
#header {
- background: #c52f24 url(../../images/header_tile.gif) repeat-x;
+ background: #c52f24 url(../images/header_tile.gif) repeat-x;
color: #FFF;
padding: 1.5em 0;
position: relative;
@@ -100,7 +100,7 @@ body {
}
#feature {
- background: #d5e9f6 url(../../images/feature_tile.gif) repeat-x;
+ background: #d5e9f6 url(../images/feature_tile.gif) repeat-x;
color: #333;
padding: 0.5em 0 1.5em;
}
@@ -132,7 +132,7 @@ body {
#footer {
padding: 2em 0;
- background: url(../../images/footer_tile.gif) repeat-x;
+ background: url(../images/footer_tile.gif) repeat-x;
}
#footer .wrapper {
padding-left: 2em;
@@ -179,7 +179,7 @@ a, a:link, a:visited {
}
#header .nav .index a {
- background: #980905 url(../../images/nav_arrow.gif) no-repeat right top;
+ background: #980905 url(../images/nav_arrow.gif) no-repeat right top;
padding-right: 1em;
position: relative;
z-index: 15;
@@ -285,7 +285,7 @@ h6 {
#header h1 {
float: left;
- background: url(../../images/rails_guides_logo.gif) no-repeat;
+ background: url(../images/rails_guides_logo.gif) no-repeat;
width: 297px;
text-indent: -9999em;
margin: 0;
@@ -306,7 +306,7 @@ h6 {
#feature ul {margin-left: 0;}
#feature ul li {
list-style: none;
- background: url(../../images/check_bullet.gif) no-repeat left 0.5em;
+ 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;
@@ -325,12 +325,12 @@ h6 {
font-size: 1.2857em;
padding: 0.125em 0 0.25em 0;
margin-bottom: 0;
- /*background: url(../../images/book_icon.gif) no-repeat left top;
+ /*background: url(../images/book_icon.gif) no-repeat left top;
padding: 0.125em 0 0.25em 28px;*/
}
#mainCol dd.ticket, #subCol dd.ticket {
- background: #fff9d8 url(../../images/tab_yellow.gif) no-repeat left top;
+ background: #fff9d8 url(../images/tab_yellow.gif) no-repeat left top;
border: none;
padding: 1.25em 1em 1.25em 48px;
margin-left: 0;
@@ -338,7 +338,7 @@ h6 {
}
#mainCol div.warning, #subCol dd.warning {
- background: #f9d9d8 url(../../images/tab_red.gif) no-repeat left top;
+ background: #f9d9d8 url(../images/tab_red.gif) no-repeat left top;
border: none;
padding: 1.25em 1.25em 1.25em 48px;
margin-left: 0;
@@ -355,7 +355,7 @@ h6 {
#subCol .chapters ul li {
list-style: none;
padding: 0 0 0 1em;
- background: url(../../images/bullet.gif) no-repeat left 0.45em;
+ background: url(../images/bullet.gif) no-repeat left 0.45em;
margin-left: 0;
font-size: 1em;
font-weight: normal;
@@ -366,7 +366,7 @@ tt {
}
div.code_container {
- background: #EEE url(../../images/tab_grey.gif) no-repeat left top;
+ background: #EEE url(../images/tab_grey.gif) no-repeat left top;
padding: 0.25em 1em 0.5em 48px;
}
@@ -378,14 +378,14 @@ code {
}
.note {
- background: #fff9d8 url(../../images/tab_note.gif) no-repeat left top;
+ background: #fff9d8 url(../images/tab_note.gif) no-repeat left top;
border: none;
padding: 1em 1em 0.25em 48px;
margin: 0.25em 0 1.5em 0;
}
.info {
- background: #d5e9f6 url(../../images/tab_info.gif) no-repeat left top;
+ background: #d5e9f6 url(../images/tab_info.gif) no-repeat left top;
border: none;
padding: 1em 1em 0.25em 48px;
margin: 0.25em 0 1.5em 0;
@@ -395,7 +395,7 @@ code {
#mainCol ul li {
list-style:none;
- background: url(../../images/grey_bullet.gif) no-repeat left 0.5em;
+ background: url(../images/grey_bullet.gif) no-repeat left 0.5em;
padding-left: 1em;
margin-left: 0;
}
@@ -439,3 +439,14 @@ 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;
}
+
+/* Edge Badge
+--------------------------------------- */
+
+#edge-badge {
+ position: fixed;
+ right: 0px;
+ top: 0px;
+ z-index: 100;
+ border: none;
+}
diff --git a/railties/guides/files/stylesheets/print.css b/railties/guides/assets/stylesheets/print.css
index 628da105d4..628da105d4 100755
--- a/railties/guides/files/stylesheets/print.css
+++ b/railties/guides/assets/stylesheets/print.css
diff --git a/railties/guides/files/stylesheets/reset.css b/railties/guides/assets/stylesheets/reset.css
index cb14fbcc55..cb14fbcc55 100755
--- a/railties/guides/files/stylesheets/reset.css
+++ b/railties/guides/assets/stylesheets/reset.css
diff --git a/railties/guides/files/stylesheets/style.css b/railties/guides/assets/stylesheets/style.css
index 89b2ab885a..89b2ab885a 100755
--- a/railties/guides/files/stylesheets/style.css
+++ b/railties/guides/assets/stylesheets/style.css
diff --git a/railties/guides/files/stylesheets/syntax.css b/railties/guides/assets/stylesheets/syntax.css
index 55fc5b209f..55fc5b209f 100644
--- a/railties/guides/files/stylesheets/syntax.css
+++ b/railties/guides/assets/stylesheets/syntax.css
diff --git a/railties/guides/rails_guides/generator.rb b/railties/guides/rails_guides/generator.rb
index e30dd2d5f7..f577182f5f 100644
--- a/railties/guides/rails_guides/generator.rb
+++ b/railties/guides/rails_guides/generator.rb
@@ -1,3 +1,49 @@
+# ---------------------------------------------------------------------------
+#
+# This script generates the guides. It can be invoked either directly or via the
+# generate_guides rake task within the railties directory.
+#
+# Guides are taken from the source directory, and the resulting HTML goes into the
+# output directory. Assets are stored under files, and copied to output/files as
+# part of the generation process.
+#
+# Some arguments may be passed via environment variables:
+#
+# WARNINGS
+# If you are writing a guide, please work always with WARNINGS=1. Users can
+# generate the guides, and thus this flag is off by default.
+#
+# Internal links (anchors) are checked. If a reference is broken levenshtein
+# distance is used to suggest an existing one. This is useful since IDs are
+# generated by Textile from headers and thus edits alter them.
+#
+# Also detects duplicated IDs. They happen if there are headers with the same
+# text. Please do resolve them, if any, so guides are valid XHTML.
+#
+# ALL
+# Set to "1" to force the generation of all guides.
+#
+# ONLY
+# Use ONLY if you want to generate only one or a set of guides. Prefixes are
+# enough:
+#
+# # generates only association_basics.html
+# ONLY=assoc ruby rails_guides.rb
+#
+# Separate many using commas:
+#
+# # generates only
+# ONLY=assoc,migrations ruby rails_guides.rb
+#
+# Note that if you are working on a guide generation will by default process
+# only that one, so ONLY is rarely used nowadays.
+#
+# EDGE
+# Set to "1" to indicate generated guides should be marked as edge. This
+# inserts a badge and changes the preamble of the home page.
+#
+# ---------------------------------------------------------------------------
+
require 'set'
require 'fileutils'
@@ -11,11 +57,14 @@ require 'rails_guides/levenshtein'
module RailsGuides
class Generator
- attr_reader :guides_dir, :source_dir, :output_dir
+ attr_reader :guides_dir, :source_dir, :output_dir, :edge
+
+ GUIDES_RE = /\.(?:textile|html\.erb)$/
def initialize(output=nil)
initialize_dirs(output)
create_output_dir_if_needed
+ set_edge
end
def generate
@@ -32,7 +81,11 @@ module RailsGuides
def create_output_dir_if_needed
FileUtils.mkdir_p(output_dir)
- end
+ end
+
+ def set_edge
+ @edge = ENV['EDGE'] == '1'
+ end
def generate_guides
guides_to_generate.each do |guide|
@@ -42,24 +95,23 @@ module RailsGuides
end
def guides_to_generate
- guides = Dir.entries(source_dir).grep(/\.textile(?:\.erb)?$/)
- ENV.key?("ONLY") ? select_only(guides) : guides
+ guides = Dir.entries(source_dir).grep(GUIDES_RE)
+ ENV.key?('ONLY') ? select_only(guides) : guides
end
def select_only(guides)
- prefixes = ENV["ONLY"].split(",").map(&:strip)
+ prefixes = ENV['ONLY'].split(",").map(&:strip)
guides.select do |guide|
prefixes.any? {|p| guide.start_with?(p)}
end
end
def copy_assets
- FileUtils.cp_r(File.join(guides_dir, 'images'), File.join(output_dir, 'images'))
- FileUtils.cp_r(File.join(guides_dir, 'files'), File.join(output_dir, 'files'))
+ FileUtils.cp_r(Dir.glob("#{guides_dir}/assets/*"), output_dir)
end
def output_file_for(guide)
- guide.sub(/\.textile(?:\.erb)?$/, '.html')
+ guide.sub(GUIDES_RE, '.html')
end
def generate?(source_file, output_file)
@@ -71,13 +123,12 @@ module RailsGuides
def generate_guide(guide, output_file)
puts "Generating #{output_file}"
File.open(File.join(output_dir, output_file), 'w') do |f|
- view = ActionView::Base.new(source_dir)
+ view = ActionView::Base.new(source_dir, :edge => edge)
view.extend(Helpers)
-
- if guide =~ /\.textile\.erb$/
- # Generate the erb pages with textile formatting - e.g. index/authors
+
+ if guide =~ /\.html\.erb$/
+ # Generate the special pages like the home.
result = view.render(:layout => 'layout', :file => guide)
- result = textile(result)
else
body = File.read(File.join(source_dir, guide))
body = set_header_section(body, view)
@@ -85,14 +136,9 @@ module RailsGuides
result = view.render(:layout => 'layout', :text => textile(body))
- warn_about_broken_links(result) if ENV.key?("WARN_BROKEN_LINKS")
+ warn_about_broken_links(result) if ENV['WARNINGS'] == '1'
end
-
- # FIXME: If the doctype is in the layout textile escapes it.
- # Things should be set up in a way that prevents that, a doctype
- # belongs to the layout.
- result = insert_doctype(result)
- result = insert_edge_badge(result) if ENV.key?('INSERT_EDGE_BADGE')
+
f.write result
end
end
@@ -130,7 +176,7 @@ module RailsGuides
view.content_tag(:li, l.html_safe)
end
- children_ul = view.content_tag(:ul, children.join(" ").html_safe)
+ children_ul = children.empty? ? "" : view.content_tag(:ul, children.join(" ").html_safe)
index << view.content_tag(:li, link.html_safe + children_ul.html_safe)
end
@@ -181,7 +227,7 @@ module RailsGuides
anchors = Set.new
html.scan(/<h\d\s+id="([^"]+)/).flatten.each do |anchor|
if anchors.member?(anchor)
- puts "*** DUPLICATE HEADER ID: #{anchor}, please consider rewording" if ENV.key?("WARN_DUPLICATE_HEADERS")
+ puts "*** DUPLICATE ID: #{anchor}, please put and explicit ID, e.g. h4(#explicit-id), or consider rewording"
else
anchors << anchor
end
@@ -203,16 +249,5 @@ module RailsGuides
end
end
end
-
- def insert_doctype(html)
- <<EOS + html
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-EOS
- end
-
- def insert_edge_badge(html)
- html.sub(/<body[^>]*>/, '\&<img src="images/edge_badge.png" style="position:fixed; right:0px; top:0px; border:none; z-index:100"/>')
- end
end
end
diff --git a/railties/guides/source/action_view_overview.textile b/railties/guides/source/action_view_overview.textile
index a517193cea..842a8408ad 100644
--- a/railties/guides/source/action_view_overview.textile
+++ b/railties/guides/source/action_view_overview.textile
@@ -1079,7 +1079,7 @@ h4. JavaScriptHelper
Provides functionality for working with JavaScript in your views.
-Rails includes the Prototype JavaScript framework and the Scriptaculous JavaScript controls and visual effects library. If you wish to use these libraries and their helpers, make sure +<%= javascript_include_tag :defaults, :cache => true %>+ is in the HEAD section of your page. This function will include the necessary JavaScript files Rails generated in the public/javascripts directory.
+Rails includes the Prototype JavaScript framework and the Scriptaculous JavaScript controls and visual effects library. If you wish to use these libraries and their helpers, make sure +&lt;%= javascript_include_tag :defaults, :cache => true %&gt;+ is in the HEAD section of your page. This function will include the necessary JavaScript files Rails generated in the public/javascripts directory.
h5. button_to_function
@@ -1414,7 +1414,7 @@ Replaces the inner HTML of the DOM element with the given id.
page.replace_html 'person-45', :partial => 'person', :object => @person
</ruby>
-h5. select
+h5(#prototype-select). select
Returns a collection reference by finding it through a CSS pattern in the DOM.
diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile
index a8410a8dd2..b41b16b728 100644
--- a/railties/guides/source/active_support_core_extensions.textile
+++ b/railties/guides/source/active_support_core_extensions.textile
@@ -866,7 +866,7 @@ WARNING: Note that in that case +parent+ returns +Object+.
NOTE: Defined in +active_support/core_ext/module/introspection.rb+.
-h5. +parents+
+h5(#module-parents). +parents+
The method +parents+ calls +parent+ on the receiver and upwards until +Object+ is reached. The chain is returned in an array, from bottom to top:
@@ -2191,9 +2191,9 @@ NOTE: Defined in +active_support/core_ext/array/grouping.rb+.
h3. Extensions to +Hash+
-h4. Conversions
+h4(#hash-conversions). Conversions
-h5. +to_xml+
+h5(#hash-to-xml). +to_xml+
The method +to_xml+ returns a string containing an XML representation of its receiver:
diff --git a/railties/guides/source/association_basics.textile b/railties/guides/source/association_basics.textile
index 757dce1f4e..4256466bec 100644
--- a/railties/guides/source/association_basics.textile
+++ b/railties/guides/source/association_basics.textile
@@ -417,7 +417,7 @@ h5. Creating Join Tables for +has_and_belongs_to_many+ Associations
If you create a +has_and_belongs_to_many+ association, you need to explicitly create the joining table. Unless the name of the join table is explicitly specified by using the +:join_table+ option, Active Record creates the name by using the lexical order of the class names. So a join between customer and order models will give the default join table name of "customers_orders" because "c" outranks "o" in lexical ordering.
-WARNING: The precedence between model names is calculated using the +<+ operator for +String+. This means that if the strings are of different lengths, and the strings are equal when compared up to the shortest length, then the longer string is considered of higher lexical precedence than the shorter one. For example, one would expect the tables "paper_boxes" and "papers" to generate a join table name of "papers_paper_boxes" because of the length of the name "paper_boxes", but it in fact generates a join table name of "paper_boxes_papers" (because the underscore '_' is lexicographically _less_ than 's' in common encodings).
+WARNING: The precedence between model names is calculated using the +&lt;+ operator for +String+. This means that if the strings are of different lengths, and the strings are equal when compared up to the shortest length, then the longer string is considered of higher lexical precedence than the shorter one. For example, one would expect the tables "paper_boxes" and "papers" to generate a join table name of "papers_paper_boxes" because of the length of the name "paper_boxes", but it in fact generates a join table name of "paper_boxes_papers" (because the underscore '_' is lexicographically _less_ than 's' in common encodings).
Whatever the name, you must manually generate the join table with an appropriate migration. For example, consider these associations:
diff --git a/railties/guides/source/contribute.textile b/railties/guides/source/contribute.textile
index 1203e38a4e..8c64df5362 100644
--- a/railties/guides/source/contribute.textile
+++ b/railties/guides/source/contribute.textile
@@ -9,7 +9,7 @@ h3. How to Contribute?
* We have an open commit policy: anyone is welcome to contribute, but you'll need to ask for commit access.
* PM lifo at "GitHub":http://github.com asking for "docrails":http://github.com/lifo/docrails/tree/master commit access.
* Guides are written in Textile, and reside at railties/guides/source in the docrails project.
-* All images are in the railties/guides/images directory.
+* Assets are stored in the +railties/guides/assets+ directory.
* Sample format : "Active Record Associations":http://github.com/lifo/docrails/blob/3e56a3832415476fdd1cb963980d0ae390ac1ed3/railties/guides/source/association_basics.textile
* Sample output : "Active Record Associations":association_basics.html
* You can build the Guides during testing by running +rake generate_guides+ in the +railties+ directory.
diff --git a/railties/guides/source/credits.html.erb b/railties/guides/source/credits.html.erb
new file mode 100644
index 0000000000..9851702df9
--- /dev/null
+++ b/railties/guides/source/credits.html.erb
@@ -0,0 +1,66 @@
+<% content_for :header_section do %>
+<h2>Credits</h2>
+
+<p>We'd like to thank the following people for their tireless contributions to this project.</p>
+
+<% end %>
+
+<h3 class="section">Rails Documentation Team</h3>
+
+<%= author('Mike Gunderloy', 'mgunderloy') do %>
+ Mike Gunderloy is a consultant with <a href="http://www.actionrails.com">ActionRails</a>. He brings 25 years of experience in a variety of languages to bear on his current work with Rails. His near-daily links and other blogging can be found at <a href="http://afreshcup.com">A Fresh Cup</a> and he <a href="http://twitter.com/MikeG1">twitters</a> too much.
+<% end %>
+
+<%= author('Pratik Naik', 'lifo') do %>
+ Pratik Naik is a Ruby on Rails consultant with <a href="http://www.actionrails.com">ActionRails</a> and also a member of the <a href="http://rubyonrails.org/core">Rails core team</a>. He maintains a blog at <a href="http://m.onkey.org">has_many :bugs, :through =&gt; :rails</a> and has an active <a href="http://twitter.com/lifo">twitter account</a>.
+<% end %>
+
+<%= author('Xavier Noria', 'fxn', 'fxn.png') do %>
+ Xavier has been into Rails since 2005, he is currently a Rails consultant. Xavier is Rails committer and enjoys combining his passion for Rails and his past life as a proofreader of math textbooks. Oh, he also <a href="http://twitter.com/fxn">tweets</a> and can be found everywhere as &quot;fxn&quot;.
+<% end %>
+
+<h3 class="section">Rails Guides Designers</h3>
+
+<%= author('Jason Zimdars', 'jz') do %>
+ Jason Zimdars is an experienced creative director and web designer who has lead UI and UX design for numerous websites and web applications. You can see more of his design and writing at <a href="http://www.thinkcage.com/">Thinkcage.com</a> or follow him on <a href="http://twitter.com/JZ">Twitter</a>.
+<% end %>
+
+<h3 class="section">Rails Guides Authors</h3>
+
+<%= author('Frederick Cheung', 'fcheung') do %>
+ Frederick Cheung is Chief Wizard at Texperts where he has been using Rails since 2006. He is based in Cambridge (UK) and when not consuming fine ales he blogs at <a href="http://www.spacevatican.org">spacevatican.org</a>.
+<% end %>
+
+<%= author('Tore Darell', 'toretore') do %>
+ Tore Darell is an independent developer based in Menton, France who specialises in cruft-free web applications using Ruby, Rails and unobtrusive JavaScript. His home on the internet is his blog <a href="http://tore.darell.no">Sneaky Abstractions</a>.
+<% end %>
+
+<%= author('Jeff Dean', 'zilkey') do %>
+ Jeff Dean is a software engineer with <a href="http://pivotallabs.com">Pivotal Labs</a>.
+<% end %>
+
+<%= author('Cássio Marques', 'cmarques') do %>
+ Cássio Marques is a Brazilian software developer working with different programming languages such as Ruby, JavaScript, CPP and Java, as an independent consultant. He blogs at <a href="http://cassiomarques.wordpress.com">/* CODIFICANDO */</a>, which is mainly written in Portuguese, but will soon get a new section for posts with English translation.
+<% end %>
+
+<%= author('James Miller', 'bensie') do %>
+ James Miller is a software developer for <a href="http://www.jk-tech.com">JK Tech</a> in San Diego, CA. Find me on GitHub, Gmail, Twitter, and Freenode as &quot;bensie&quot;.
+<% end %>
+
+<%= author('Emilio Tagua', 'miloops') do %>
+ Emilio Tagua &mdash;a.k.a. miloops&mdash; is an Argentinian entrepreneur, developer, open source contributor and Rails evangelist. Cofounder of <a href="http://eventioz.com">Eventioz</a>. He has been using Rails since 2006 and contributing since early 2008. Can be found at gmail, twitter, freenode, everywhere as &quot;miloops&quot;.
+<% end %>
+
+<%= author('Heiko Webers', 'hawe') do %>
+ Heiko Webers is the founder of <a href="http://www.bauland42.de">bauland42</a>, a German web application security consulting and development company focused on Ruby on Rails. He blogs at the <a href="http://www.rorsecurity.info">Ruby on Rails Security Project</a>. After 10 years of desktop application development, Heiko has rarely looked back.
+<% end %>
+
+<%= author('Mikel Lindsaar', 'raasdnil') do %>
+ Mikel Lindsaar has been working with Rails since 2006 and is the author of the Ruby Mail gem and core contributor (he helped re-write Action Mailer's API). Mikel has a <a href="http://lindsaar.net/">blog</a> and <a href="http://twitter.com/raasdnil">tweets</a>.
+<% end %>
+
+<h3 class="section">Rails Guides Reviewers</h3>
+
+<%= author('Jaime Iniesta', 'jaimeiniesta', 'jaimeiniesta.jpg') do %>
+ Jaime Iniesta works as a Ruby on Rails freelance developer since 2005. He's a member of <a href="http://www.prorubyteam.com">ProRuby</a>, co-founder of the <a href="http://srug.org">Spanish Ruby Users Group</a>, member of <a href="http://spainrb.org">Spain.rb</a>, and organizer of <a href="http://conferenciarails.org">Conferencia Rails</a> and <a href="http://euruko2009.org">EuRuKo 2009</a>. Jaime has a <a href="http://jaimeiniesta.com">blog</a> and <a href="http://twitter.com/jaimeiniesta">tweets</a>.
+<% end %>
diff --git a/railties/guides/source/credits.textile.erb b/railties/guides/source/credits.textile.erb
deleted file mode 100644
index 0c54049e1c..0000000000
--- a/railties/guides/source/credits.textile.erb
+++ /dev/null
@@ -1,60 +0,0 @@
-<% content_for :header_section do %>
-h2. Credits
-
-p. We'd like to thank the following people for their tireless contributions to this project.
-
-<% end %>
-
-<h3 class="section">Rails Documentation Team</h3>
-
-<%= author('Mike Gunderloy', 'mgunderloy') do %>
- Mike Gunderloy is a consultant with "ActionRails":http://www.actionrails.com. He brings 25 years of experience in a variety of languages to bear on his current work with Rails. His near-daily links and other blogging can be found at "A Fresh Cup":http://afreshcup.com and he "twitters":http://twitter.com/MikeG1 too much.
-<% end %>
-
-<%= author('Pratik Naik', 'lifo') do %>
- Pratik Naik is a Ruby on Rails consultant with "ActionRails":http://www.actionrails.com and also a member of the "Rails core team":http://rubyonrails.org/core. He maintains a blog at "has_many :bugs, :through => :rails":http://m.onkey.org and has an active "twitter account":http://twitter.com/lifo.
-<% end %>
-
-<%= author('Xavier Noria', 'fxn', 'fxn.png') do %>
- Xavier has been into Rails since 2005, he is currently a Rails consultant. Xavier is president of the <a href="http://www.srug.org/">Spanish Ruby Users Group</a> and has been involved in Rails in several ways. He enjoys combining his passion for Rails and his past life as a proofreader of math textbooks. Oh, he also "tweets":http://twitter.com/fxn!
-<% end %>
-
-<h3 class="section">Rails Guides Designers</h3>
-
-<%= author('Jason Zimdars', 'jz') do %>
- Jason Zimdars is an experienced creative director and web designer who has lead UI and UX design for numerous websites and web applications. You can see more of his design and writing at <a href="http://www.thinkcage.com/">Thinkcage.com</a> or follow him on <a href="http://twitter.com/JZ">Twitter</a>.
-<% end %>
-
-<h3 class="section">Rails Guides Authors</h3>
-
-<%= author('Frederick Cheung', 'fcheung') do %>
- Frederick Cheung is Chief Wizard at Texperts where he has been using Rails since 2006. He is based in Cambridge (UK) and when not consuming fine ales he blogs at "spacevatican.org":http://www.spacevatican.org.
-<% end %>
-
-<%= author('Tore Darell', 'toretore') do %>
- Tore Darell is an independent developer based in Menton, France who specialises in cruft-free web applications using Ruby, Rails and unobtrusive JavaScript. His home on the internet is his blog "Sneaky Abstractions":http://tore.darell.no.
-<% end %>
-
-<%= author('Jeff Dean', 'zilkey') do %>
- Jeff Dean is a software engineer with "Pivotal Labs":http://pivotallabs.com.
-<% end %>
-
-<%= author('Cássio Marques', 'cmarques') do %>
- Cássio Marques is a Brazilian software developer working with different programming languages such as Ruby, JavaScript, CPP and Java, as an independent consultant. He blogs at "/* CODIFICANDO */":http://cassiomarques.wordpress.com, which is mainly written in Portuguese, but will soon get a new section for posts with English translation.
-<% end %>
-
-<%= author('James Miller', 'bensie') do %>
- James Miller is a software developer for "JK Tech":http://www.jk-tech.com in San Diego, CA. Find me on GitHub, Gmail, Twitter, and Freenode as bensie.
-<% end %>
-
-<%= author('Emilio Tagua', 'miloops') do %>
- Emilio Tagua -- a.k.a. miloops -- is an Argentinian entrepreneur, developer, open source contributor and Rails evangelist. Cofounder of "Eventioz":http://eventioz.com. He has been using Rails since 2006 and contributing since early 2008. Can be found at gmail, twitter, freenode, everywhere as miloops.
-<% end %>
-
-<%= author('Heiko Webers', 'hawe') do %>
- Heiko Webers is the founder of "bauland42":http://www.bauland42.de, a German web application security consulting and development company focused on Ruby on Rails. He blogs at the "Ruby on Rails Security Project":http://www.rorsecurity.info. After 10 years of desktop application development, Heiko has rarely looked back.
-<% end %>
-
-<%= author('Mikel Lindsaar', 'raasdnil') do %>
- Mikel Lindsaar has been working with Rails since 2006 and is the author of the Ruby Mail gem and core contributor (he helped re-write ActionMailer's API). Mikel has a "blog":http://lindsaar.net/ and "tweets":http://twitter.com/raasdnil.
-<% end %>
diff --git a/railties/guides/source/debugging_rails_applications.textile b/railties/guides/source/debugging_rails_applications.textile
index cd0098d686..3eddf1a2b1 100644
--- a/railties/guides/source/debugging_rails_applications.textile
+++ b/railties/guides/source/debugging_rails_applications.textile
@@ -286,7 +286,7 @@ condition down finish list ps save thread var
continue edit frame method putl set tmate where
</shell>
-TIP: To view the help menu for any command use +help <command-name>+ in active debug mode. For example: _+help var+_
+TIP: To view the help menu for any command use +help &lt;command-name&gt;+ in active debug mode. For example: _+help var+_
The next command to learn is one of the most useful: +list+. You can also abbreviate ruby-debug commands by supplying just enough letters to distinguish them from other commands, so you can also use +l+ for the +list+ command.
@@ -704,6 +704,7 @@ h3. Changelog
"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/5
+* April 4, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":credits.html#jaimeiniesta
* November 3, 2008: Accepted for publication. Added RJS, memory leaks and plugins chapters by "Emilio Tagua":credits.html#miloops
* October 19, 2008: Copy editing pass by "Mike Gunderloy":credits.html#mgunderloy
* September 16, 2008: initial version by "Emilio Tagua":credits.html#miloops
diff --git a/railties/guides/source/form_helpers.textile b/railties/guides/source/form_helpers.textile
index d33bb4b4ff..fe0f8f1ac9 100644
--- a/railties/guides/source/form_helpers.textile
+++ b/railties/guides/source/form_helpers.textile
@@ -501,7 +501,7 @@ Date.civil(params[:start_date][:year].to_i, params[:start_date][:month].to_i, pa
The +:prefix+ option is the key used to retrieve the hash of date components from the +params+ hash. Here it was set to +start_date+, if omitted it will default to +date+.
-h4. Model Object Helpers
+h4(#select-model-object-helpers). Model Object Helpers
+select_date+ does not work well with forms that update or create Active Record objects as Active Record expects each element of the +params+ hash to correspond to one attribute.
The model object helpers for dates and times submit parameters with special names, when Active Record sees parameters with such names it knows they must be combined with the other parameters and given to a constructor appropriate to the column type. For example:
diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile
index c479c2fb20..9669f7f155 100644
--- a/railties/guides/source/getting_started.textile
+++ b/railties/guides/source/getting_started.textile
@@ -545,7 +545,7 @@ This view iterates over the contents of the +@posts+ array to display content an
* +link_to+ builds a hyperlink to a particular destination
* +edit_post_path+ is a helper that Rails provides as part of RESTful routing. You'll see a variety of these helpers for the different actions that the controller includes.
-NOTE. In previous versions of Rails, you had to use +<%=h post.name %>+ so that any HTML would be escaped before being inserted into the page. In Rails 3.0, this is now the default. To get unescaped HTML, you now use +<%= raw post.name %>+.
+NOTE. In previous versions of Rails, you had to use +&lt;%=h post.name %&gt;+ so that any HTML would be escaped before being inserted into the page. In Rails 3.0, this is now the default. To get unescaped HTML, you now use +&lt;%= raw post.name %&gt;+.
TIP: For more details on the rendering process, see "Layouts and Rendering in Rails":layouts_and_rendering.html.
@@ -597,7 +597,7 @@ The +new.html.erb+ view displays this empty Post to the user:
<%= link_to 'Back', posts_path %>
</erb>
-The +<%= render 'form' %>+ line is our first introduction to _partials_ in Rails. A partial is a snippet of HTML and Ruby code that can be reused in multiple locations. In this case, the form used to make a new post, is basically identical to a form used to edit a post, both have text fields for the name and title and a text area for the content with a button to make a new post or update the existing post.
+The +&lt;%= render 'form' %&gt;+ line is our first introduction to _partials_ in Rails. A partial is a snippet of HTML and Ruby code that can be reused in multiple locations. In this case, the form used to make a new post, is basically identical to a form used to edit a post, both have text fields for the name and title and a text area for the content with a button to make a new post or update the existing post.
If you take a look at +views/posts/_form.html.erb+ file, you will see the following:
@@ -1432,6 +1432,7 @@ h3. Changelog
"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/2
+* April 1, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":credits.html#jaimeiniesta
* February 8, 2010: Full re-write for Rails 3.0-beta, added helpers and before_filters, refactored code by "Mikel Lindsaar":credits:html#raasdnil
* January 24, 2010: Re-write for Rails 3.0 by "Mikel Lindsaar":credits:html#raasdnil
* July 18, 2009: Minor cleanup in anticipation of Rails 2.3.3 by "Mike Gunderloy":credits.html#mgunderloy
diff --git a/railties/guides/source/index.html.erb b/railties/guides/source/index.html.erb
new file mode 100644
index 0000000000..8864b52325
--- /dev/null
+++ b/railties/guides/source/index.html.erb
@@ -0,0 +1,150 @@
+<% content_for :header_section do %>
+<h2>Ruby on Rails Guides</h2>
+
+<% if @edge %>
+<p>
+ These are <b>Edge Guides</b>, based on the current
+ <a href="http://github.com/rails/rails/tree/master">master branch</a>.
+</p>
+<p>
+ If you are looking for the ones for the stable version please check
+ <a href="http://guides.rubyonrails.org">http://guides.rubyonrails.org</a> instead.
+</p>
+<% end %>
+
+<p>
+ These guides are designed to make you immediately productive with Rails,
+ and to help you understand how all of the pieces fit together.
+</p>
+
+<% end %>
+
+<% content_for :index_section do %>
+<div id="subCol">
+ <dl>
+ <dd class="warning">Rails Guides are a result of the ongoing <a href="http://hackfest.rubyonrails.org">Guides hackfest</a>, and a work in progress.</dd>
+ <dd class="ticket">Guides marked with this icon are currently being worked on. While they might still be useful to you, they may contain incomplete information and even errors. You can help by reviewing them and posting your comments and corrections at the respective Lighthouse ticket.</dd>
+ </dl>
+</div>
+<% end %>
+
+<h3>Start Here</h3>
+
+<dl>
+<%= guide('Getting Started with Rails', 'getting_started.html') do %>
+ <p>Everything you need to know to install Rails and create your first application.</p>
+<% end %>
+</dl>
+
+<h3>Models</h3>
+
+<dl>
+<%= guide("Rails Database Migrations", 'migrations.html') do %>
+ <p>This guide covers how you can use Active Record migrations to alter your database in a structured and organized manner.</p>
+<% end %>
+
+<%= guide("Active Record Validations and Callbacks", 'activerecord_validations_callbacks.html') do %>
+ <p>This guide covers how you can use Active Record validations and callbacks.</p>
+<% end %>
+
+<%= guide("Active Record Associations", 'association_basics.html') do %>
+ <p>This guide covers all the associations provided by Active Record.</p>
+<% end %>
+
+<%= guide("Active Record Query Interface", 'active_record_querying.html') do %>
+ <p>This guide covers the database query interface provided by Active Record.</p>
+<% end %>
+</dl>
+
+<h3>Views</h3>
+
+<dl>
+<%= guide("Layouts and Rendering in Rails", 'layouts_and_rendering.html') do %>
+ <p>This guide covers the basic layout features of Action Controller and Action View, including rendering and redirecting, using content_for blocks, and working with partials.</p>
+<% end %>
+
+<%= guide("Action View Form Helpers", 'form_helpers.html', :ticket => 1) do %>
+ <p>Guide to using built in Form helpers.</p>
+<% end %>
+</dl>
+
+<h3>Controllers</h3>
+
+<dl>
+<%= guide("Action Controller Overview", 'action_controller_overview.html') do %>
+ <p>This guide covers how controllers work and how they fit into the request cycle in your application. It includes sessions, filters, and cookies, data streaming, and dealing with exceptions raised by a request, among other topics.</p>
+<% end %>
+
+<%= guide("Rails Routing from the Outside In", 'routing.html') do %>
+ <p>This guide covers the user-facing features of Rails routing. If you want to understand how to use routing in your own Rails applications, start here.</p>
+<% end %>
+</dl>
+
+<h3>Digging Deeper</h3>
+
+<dl>
+
+<%= guide("Rails on Rack", 'rails_on_rack.html') do %>
+ <p>This guide covers Rails integration with Rack and interfacing with other Rack components.</p>
+<% end %>
+
+<%= guide("Rails Internationalization API", 'i18n.html') do %>
+ <p>This guide covers how to add internationalization to your applications. Your application will be able to translate content to different languages, change pluralization rules, use correct date formats for each country and so on.</p>
+<% end %>
+
+<%= guide("Action Mailer Basics", 'action_mailer_basics.html', :ticket => 25) do %>
+ <p>This guide describes how to use Action Mailer to send and receive emails.</p>
+<% end %>
+
+<%= guide("Testing Rails Applications", 'testing.html', :ticket => 8) do %>
+ <p>This is a rather comprehensive guide to doing both unit and functional tests in Rails. It covers everything from &quot;What is a test?&quot; to the testing APIs. Enjoy.</p>
+<% end %>
+
+<%= guide("Securing Rails Applications", 'security.html') do %>
+ <p>This guide describes common security problems in web applications and how to avoid them with Rails.</p>
+<% end %>
+
+<%= guide("Debugging Rails Applications", 'debugging_rails_applications.html') do %>
+ <p>This guide describes how to debug Rails applications. It covers the different ways of achieving this and how to understand what is happening "behind the scenes" of your code.</p>
+<% end %>
+
+<%= guide("Performance Testing Rails Applications", 'performance_testing.html') do %>
+ <p>This guide covers the various ways of performance testing a Ruby on Rails application.</p>
+<% end %>
+
+<%= guide("The Basics of Creating Rails Plugins", 'plugins.html', :ticket => 32) do %>
+ <p>This guide covers how to build a plugin to extend the functionality of Rails.</p>
+<% end %>
+
+<%= guide("Configuring Rails Applications", 'configuring.html') do %>
+ <p>This guide covers the basic configuration settings for a Rails application.</p>
+<% end %>
+
+<%= guide("Rails Command Line Tools and Rake tasks", 'command_line.html', :ticket => 29) do %>
+ <p>This guide covers the command line tools and rake tasks provided by Rails.</p>
+<% end %>
+
+<%= guide("Caching with Rails", 'caching_with_rails.html', :ticket => 10) do %>
+ <p>Various caching techniques provided by Rails.</p>
+<% end %>
+
+<%= guide("Contributing to Rails", 'contributing_to_rails.html') do %>
+ <p>Rails is not &quot;somebody else's framework.&quot; This guide covers a variety of ways that you can get involved in the ongoing development of Rails.</p>
+<% end %>
+</dl>
+
+<h3>Release Notes</h3>
+
+<dl>
+<%= guide("Ruby on Rails 3.0 Release Notes", '3_0_release_notes.html') do %>
+ <p>Release notes for Rails 3.0.</p>
+<% end %>
+
+<%= guide("Ruby on Rails 2.3 Release Notes", '2_3_release_notes.html') do %>
+ <p>Release notes for Rails 2.3.</p>
+<% end %>
+
+<%= guide("Ruby on Rails 2.2 Release Notes", '2_2_release_notes.html') do %>
+ <p>Release notes for Rails 2.2.</p>
+<% end %>
+</dl>
diff --git a/railties/guides/source/index.textile.erb b/railties/guides/source/index.textile.erb
deleted file mode 100644
index 538fe48a38..0000000000
--- a/railties/guides/source/index.textile.erb
+++ /dev/null
@@ -1,139 +0,0 @@
-<% content_for :header_section do %>
-h2. Ruby on Rails Guides
-
-These guides are designed to make you immediately productive with Rails, and to help you understand how all of the pieces fit together. There are two different versions of the Guides site, and you should be sure to use the one that applies to your situation:
-
-* "Current Release version":http://guides.rubyonrails.org - based on Rails 2.3
-* "Edge version":http://edgeguides.rubyonrails.org - based on the current Rails "master branch":http://github.com/rails/rails/tree/master
-
-<% end %>
-
-<% content_for :index_section do %>
-<div id="subCol">
- <dl>
- <dd class="warning">Rails Guides are a result of the ongoing "Guides hackfest":http://hackfest.rubyonrails.org and a work in progress.</dd>
- <dd class="ticket">Guides marked with this icon are currently being worked on. While they might still be useful to you, they may contain incomplete information and even errors. You can help by reviewing them and posting your comments and corrections at the respective Lighthouse ticket.</dd>
- </dl>
-</div>
-<% end %>
-
-h3. Start Here
-
-<dl>
-<%= guide('Getting Started with Rails', 'getting_started.html') do %>
- Everything you need to know to install Rails and create your first application.
-<% end %>
-</dl>
-
-h3. Models
-
-<dl>
-<%= guide("Rails Database Migrations", 'migrations.html') do %>
- This guide covers how you can use Active Record migrations to alter your database in a structured and organized manner.
-<% end %>
-
-<%= guide("Active Record Validations and Callbacks", 'activerecord_validations_callbacks.html') do %>
- This guide covers how you can use Active Record validations and callbacks.
-<% end %>
-
-<%= guide("Active Record Associations", 'association_basics.html') do %>
- This guide covers all the associations provided by Active Record.
-<% end %>
-
-<%= guide("Active Record Query Interface", 'active_record_querying.html') do %>
- This guide covers the database query interface provided by Active Record.
-<% end %>
-</dl>
-
-h3. Views
-
-<dl>
-<%= guide("Layouts and Rendering in Rails", 'layouts_and_rendering.html') do %>
- This guide covers the basic layout features of Action Controller and Action View, including rendering and redirecting, using content_for blocks, and working with partials.
-<% end %>
-
-<%= guide("Action View Form Helpers", 'form_helpers.html', :ticket => 1) do %>
- Guide to using built in Form helpers.
-<% end %>
-</dl>
-
-h3. Controllers
-
-<dl>
-<%= guide("Action Controller Overview", 'action_controller_overview.html') do %>
- This guide covers how controllers work and how they fit into the request cycle in your application. It includes sessions, filters, and cookies, data streaming, and dealing with exceptions raised by a request, among other topics.
-<% end %>
-
-<%= guide("Rails Routing from the Outside In", 'routing.html') do %>
- This guide covers the user-facing features of Rails routing. If you want to understand how to use routing in your own Rails applications, start here.
-<% end %>
-</dl>
-
-h3. Digging Deeper
-
-<dl>
-
-<%= guide("Rails on Rack", 'rails_on_rack.html') do %>
- This guide covers Rails integration with Rack and interfacing with other Rack components.
-<% end %>
-
-<%= guide("Rails Internationalization API", 'i18n.html') do %>
- This guide covers how to add internationalization to your applications. Your application will be able to translate content to different languages, change pluralization rules, use correct date formats for each country and so on.
-<% end %>
-
-<%= guide("Action Mailer Basics", 'action_mailer_basics.html', :ticket => 25) do %>
- This guide describes how to use Action Mailer to send and receive emails.
-<% end %>
-
-<%= guide("Testing Rails Applications", 'testing.html', :ticket => 8) do %>
- This is a rather comprehensive guide to doing both unit and functional tests in Rails. It covers everything from “What is a test?” to the testing APIs. Enjoy.
-<% end %>
-
-<%= guide("Securing Rails Applications", 'security.html') do %>
- This guide describes common security problems in web applications and how to avoid them with Rails.
-<% end %>
-
-<%= guide("Debugging Rails Applications", 'debugging_rails_applications.html') do %>
- This guide describes how to debug Rails applications. It covers the different ways of achieving this and how to understand what is happening "behind the scenes" of your code.
-<% end %>
-
-<%= guide("Performance Testing Rails Applications", 'performance_testing.html') do %>
- This guide covers the various ways of performance testing a Ruby on Rails application.
-<% end %>
-
-<%= guide("The Basics of Creating Rails Plugins", 'plugins.html', :ticket => 32) do %>
- This guide covers how to build a plugin to extend the functionality of Rails.
-<% end %>
-
-<%= guide("Configuring Rails Applications", 'configuring.html') do %>
- This guide covers the basic configuration settings for a Rails application.
-<% end %>
-
-<%= guide("Rails Command Line Tools and Rake tasks", 'command_line.html', :ticket => 29) do %>
- This guide covers the command line tools and rake tasks provided by Rails.
-<% end %>
-
-<%= guide("Caching with Rails", 'caching_with_rails.html', :ticket => 10) do %>
- Various caching techniques provided by Rails.
-<% end %>
-
-<%= guide("Contributing to Rails", 'contributing_to_rails.html') do %>
- Rails is not "somebody else's framework." This guide covers a variety of ways that you can get involved in the ongoing development of Rails.
-<% end %>
-</dl>
-
-h3. Release Notes
-
-<dl>
-<%= guide("Ruby on Rails 3.0 Release Notes", '3_0_release_notes.html') do %>
- Release notes for Rails 3.0.
-<% end %>
-
-<%= guide("Ruby on Rails 2.3 Release Notes", '2_3_release_notes.html') do %>
- Release notes for Rails 2.3.
-<% end %>
-
-<%= guide("Ruby on Rails 2.2 Release Notes", '2_2_release_notes.html') do %>
- Release notes for Rails 2.2.
-<% end %>
-</dl>
diff --git a/railties/guides/source/layout.html.erb b/railties/guides/source/layout.html.erb
index a21f1bbeed..b280101d25 100644
--- a/railties/guides/source/layout.html.erb
+++ b/railties/guides/source/layout.html.erb
@@ -1,19 +1,27 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title><%= yield(:page_title) || 'Ruby on Rails guides' %></title>
-<link rel="stylesheet" type="text/css" href="files/stylesheets/style.css" />
-<link rel="stylesheet" type="text/css" href="files/stylesheets/syntax.css" />
-<link rel="stylesheet" type="text/css" href="files/stylesheets/print.css" media="print" />
+<link rel="stylesheet" type="text/css" href="stylesheets/style.css" />
+<link rel="stylesheet" type="text/css" href="stylesheets/syntax.css" />
+<link rel="stylesheet" type="text/css" href="stylesheets/print.css" media="print" />
-<script type="text/javascript" src="files/javascripts/guides.js"></script>
-<script type="text/javascript" src="files/javascripts/code_highlighter.js"></script>
-<script type="text/javascript" src="files/javascripts/highlighters.js"></script>
+<script type="text/javascript" src="javascripts/guides.js"></script>
+<script type="text/javascript" src="javascripts/code_highlighter.js"></script>
+<script type="text/javascript" src="javascripts/highlighters.js"></script>
</head>
<body class="guide">
+ <% if @edge %>
+ <div>
+ <img src="images/edge_badge.png" alt="edge-badge" id="edge-badge" />
+ </div>
+ <% end %>
<div id="topNav">
<div class="wrapper">
<strong>More at <a href="http://rubyonrails.org/">rubyonrails.org:</a> </strong>
@@ -101,7 +109,7 @@
<hr class="hide" />
<div id="footer">
<div class="wrapper">
- <p>This work is licensed under a <a href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-Share Alike 3.0</a> License</a></p>
+ <p>This work is licensed under a <a href="http://creativecommons.org/licenses/by-sa/3.0/">Creative Commons Attribution-Share Alike 3.0</a> License</p>
<p>"Rails", "Ruby on Rails", and the Rails logo are trademarks of David Heinemeier Hansson. All rights reserved.</p>
</div>
</div>
diff --git a/railties/guides/source/layouts_and_rendering.textile b/railties/guides/source/layouts_and_rendering.textile
index 2cb98e9ee6..d9781fc966 100644
--- a/railties/guides/source/layouts_and_rendering.textile
+++ b/railties/guides/source/layouts_and_rendering.textile
@@ -510,7 +510,7 @@ def show
end
</ruby>
-Make sure you use +and return+ and not +&& return+ because while the former will work, the latter will not due to operator precedence in the Ruby Language.
+Make sure you use +and return+ and not +&amp;&amp; return+ because while the former will work, the latter will not due to operator precedence in the Ruby Language.
Note that the implicit render done by ActionController detects if +render+ has been called, and thus avoids this error. Therefore, the following will work without errors:
@@ -747,7 +747,7 @@ You can even use dynamic paths such as +cache/#{current_site}/main/display+.
h5. Linking to CSS Files with +stylesheet_link_tag+
-The +stylesheet_link_tag+ helper returns an HTML +<link>+ tag for each source provided. Rails looks in +public/stylesheets+ for these files by default, but you can specify a full path relative to the document root, or a URL, if you prefer. For example, to include +public/stylesheets/main.cs+:
+The +stylesheet_link_tag+ helper returns an HTML +&lt;link&gt;+ tag for each source provided. Rails looks in +public/stylesheets+ for these files by default, but you can specify a full path relative to the document root, or a URL, if you prefer. For example, to include +public/stylesheets/main.cs+:
<erb>
<%= stylesheet_link_tag "main" %>
@@ -1197,6 +1197,7 @@ h3. Changelog
"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/15
+* April 4, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":credits.html#jaimeiniesta
* January 25, 2010: Rails 3.0 Update by "Mikel Lindsaar":credits.html#raasdnil
* December 27, 2008: Merge patch from Rodrigo Rosenfeld Rosas covering subtemplates
* December 27, 2008: Information on new rendering defaults by "Mike Gunderloy":credits.html#mgunderloy
diff --git a/railties/guides/source/performance_testing.textile b/railties/guides/source/performance_testing.textile
index 5c760a5966..f74b68b0ef 100644
--- a/railties/guides/source/performance_testing.textile
+++ b/railties/guides/source/performance_testing.textile
@@ -213,11 +213,11 @@ h4. Understanding the Output
Performance tests generate different outputs inside +tmp/performance+ directory depending on their mode and metric.
-h5. Benchmarking
+h5(#output-benchmarking). Benchmarking
In benchmarking mode, performance tests generate two types of outputs:
-h6. Command Line
+h6(#output-command-line). Command Line
This is the primary form of output in benchmarking mode. Example:
@@ -258,7 +258,7 @@ measurement,created_at,app,rails,ruby,platform
0.00771250000000012,2009-01-09T15:46:03Z,,2.3.0.master.859e150,ruby-1.8.6.110,i686-darwin9.0.0
</shell>
-h5. Profiling
+h5(#output-profiling). Profiling
In profiling mode, you can choose from four types of output.
@@ -330,7 +330,7 @@ h5. Apply the Patch
h5. Configure and Install
-The following will install ruby in your home directory's +/rubygc+ directory. Make sure to replace +<homedir>+ with a full patch to your actual home directory.
+The following will install ruby in your home directory's +/rubygc+ directory. Make sure to replace +&lt;homedir&gt;+ with a full patch to your actual home directory.
<shell>
[lifo@null ruby-version]$ ./configure --prefix=/<homedir>/rubygc
diff --git a/railties/guides/source/plugins.textile b/railties/guides/source/plugins.textile
index 2db421aa91..74c8ee2df9 100644
--- a/railties/guides/source/plugins.textile
+++ b/railties/guides/source/plugins.textile
@@ -35,14 +35,14 @@ h4. Create the Basic Application
The examples in this guide require that you have a working rails application. To create a simple rails app execute:
-<pre>
+<shell>
gem install rails
rails yaffle_guide
cd yaffle_guide
rails generate scaffold bird name:string
rake db:migrate
rails server
-</pre>
+</shell>
Then navigate to http://localhost:3000/birds. Make sure you have a functioning rails app before continuing.
@@ -56,22 +56,22 @@ Rails ships with a plugin generator which creates a basic plugin skeleton. Pass
This creates a plugin in 'vendor/plugins' including an 'init.rb' and 'README' as well as standard 'lib', 'task', and 'test' directories.
Examples:
-<pre>
+<shell>
rails generate plugin yaffle
rails generate plugin yaffle --with-generator
-</pre>
+</shell>
To get more detailed help on the plugin generator, type +rails generate plugin+.
Later on this guide will describe how to work with generators, so go ahead and generate your plugin with the +--with-generator+ option now:
-<pre>
+<shell>
rails generate plugin yaffle --with-generator
-</pre>
+</shell>
You should see the following output:
-<pre>
+<shell>
create vendor/plugins/yaffle/lib
create vendor/plugins/yaffle/tasks
create vendor/plugins/yaffle/test
@@ -89,20 +89,20 @@ create vendor/plugins/yaffle/generators/yaffle
create vendor/plugins/yaffle/generators/yaffle/templates
create vendor/plugins/yaffle/generators/yaffle/yaffle_generator.rb
create vendor/plugins/yaffle/generators/yaffle/USAGE
-</pre>
+</shell>
h4. Organize Your Files
To make it easy to organize your files and to make the plugin more compatible with GemPlugins, start out by altering your file system to look like this:
-<pre>
+<shell>
|-- lib
| |-- yaffle
| `-- yaffle.rb
`-- rails
|
`-- init.rb
-</pre>
+</shell>
*vendor/plugins/yaffle/init.rb*
@@ -124,7 +124,7 @@ h4. Test Setup
*vendor/plugins/yaffle/test/database.yml:*
-<pre>
+<yaml>
sqlite:
:adapter: sqlite
:dbfile: vendor/plugins/yaffle/test/yaffle_plugin.sqlite.db
@@ -146,7 +146,7 @@ mysql:
:username: root
:password: password
:database: yaffle_plugin_test
-</pre>
+</yaml>
For this guide you'll need 2 tables/models, Hickwalls and Wickwalls, so add the following:
@@ -239,10 +239,10 @@ end
To run this, go to the plugin directory and run +rake+:
-<pre>
+<shell>
cd vendor/plugins/yaffle
rake
-</pre>
+</shell>
You should see output like:
@@ -1511,4 +1511,5 @@ h3. Changelog
"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213/tickets/32-update-plugins-guide
+* April 4, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":credits.html#jaimeiniesta
* November 17, 2008: Major revision by Jeff Dean
diff --git a/railties/guides/source/routing.textile b/railties/guides/source/routing.textile
index 8cf084494b..0cf8c45761 100644
--- a/railties/guides/source/routing.textile
+++ b/railties/guides/source/routing.textile
@@ -65,7 +65,7 @@ RESTful routes take advantage of the built-in REST orientation of Rails to wrap
resources :books
</ruby>
-h4. Named Routes
+h4(#quick-tour-named-routes). Named Routes
Named routes give you very readable links in your code, as well as handling incoming requests. Here's a typical named route:
@@ -79,7 +79,7 @@ If you're coming from Rails 2, this route will be equivalent to:
map.login '/login', :controller => 'sessions', :action => 'new'
</ruby>
-You will also notice that +sessions#new+ is a shorthand for +:controller => 'sessions', :action => 'new'+. By declaring a named route such as this, you can use +login_path+ or +login_url+ in your controllers and views to generate the URLs for this route.
+You will also notice that +sessions#new+ is a shorthand for +:controller => 'sessions', :action => 'new'+. By declaring a named route such as this, you can use +login_path+ or +login_url+ in your controllers and views to generate the URLs for this route. A RESTful generates named routes without the need to explicitly generate a named route via +as+ key.
h4. Nested Routes
@@ -91,7 +91,7 @@ resources :assemblies do
end
</ruby>
-h4. Regular Routes
+h4(#quick-tour-regular-routes). Regular Routes
In many applications, you'll also see non-RESTful routing, which explicitly connects the parts of a URL to a particular action. For example,
@@ -215,8 +215,7 @@ Although the conventions of RESTful routing are likely to be sufficient for many
* +:controller+
* +:singular+
-* +:requirements+
-* +:conditions+
+* +:constraints+
* +:as+
* +:path_names+
* +:only+
@@ -257,13 +256,7 @@ If you use controller namespaces, you need to be aware of a subtlety in the Rail
TIP: If you want to guarantee that a link goes to a top-level controller, use a preceding slash to anchor the controller name: +&lt;%= link_to "show", {:controller => "/photos", :action => "show"} %&gt;+
-You can also specify a controller namespace with the +:namespace+ option instead of a path:
-
-<ruby>
-resources :adminphotos, :namespace => "admin", :controller => "photos"
-</ruby>
-
-This can be especially useful when map multiple namespaced routes together using +namespace+ block by:
+You can also specify a controller namespace with the +namespace+ method instead of a path. This can be especially useful when mapping multiple namespaced routes together:
<ruby>
namespace :admin do
@@ -285,20 +278,16 @@ resources :teeth, :singular => "tooth"
TIP: Depending on the other code in your application, you may prefer to add additional rules to the +Inflector+ class instead.
-h5. Using +:requirements+
+h5. Using +:constraints+
-You can use the +:requirements+ option in a RESTful route to impose a format on the implied +:id+ parameter in the singular routes. For example:
+You can use the +:constraints+ option in a RESTful route to impose a format on the implied parameter in routes. For example:
<ruby>
-resources :photos, :requirements => {:id => /[A-Z][A-Z][0-9]+/}
+resources :photos, :constraints => {:id => /[A-Z][A-Z][0-9]+/}
</ruby>
This declaration constrains the +:id+ parameter to match the supplied regular expression. So, in this case, +/photos/1+ would no longer be recognized by this route, but +/photos/RR27+ would.
-h5. Using +:conditions+
-
-Conditions in Rails routing are currently used only to set the HTTP verb for individual routes. Although in theory you can set this for RESTful routes, in practice there is no good reason to do so. (You'll learn more about conditions in the discussion of classic routing later in this guide.)
-
h5. Using +:as+
The +:as+ option lets you override the normal naming for the actual generated paths. For example:
@@ -343,37 +332,15 @@ TIP: If you find yourself wanting to change this option uniformly for all of you
config.action_controller.resources_path_names = { :new => 'make', :edit => 'change' }
</ruby>
-h5. Using +:path_prefix+
-
-The +:path_prefix+ option lets you add additional parameters that will be prefixed to the recognized paths. For example, suppose each photo in your application belongs to a particular photographer. In that case, you might declare this route:
-
-<ruby>
-resources :photos, :path_prefix => '/photographers/:photographer_id'
-</ruby>
-
-Routes recognized by this entry would include:
-
-<pre>
-/photographers/1/photos/2
-/photographers/1/photos
-</pre>
-
-NOTE: In most cases, it's simpler to recognize URLs of this sort by creating nested resources, as discussed in the next section.
-
-NOTE: You can also use +:path_prefix+ with non-RESTful routes.
-
h5. Using +:name_prefix+
You can use the :name_prefix option to avoid collisions between routes. This is most useful when you have two resources with the same name that use +:path_prefix+ to map differently. For example:
<ruby>
-resources :photos, :path_prefix => '/photographers/:photographer_id',
- :name_prefix => 'photographer_'
-resources :photos, :path_prefix => '/agencies/:agency_id',
- :name_prefix => 'agency_'
+resources :photos :name_prefix => 'photographer'
</ruby>
-This combination will give you route helpers such as +photographer_photos_path+ and +agency_edit_photo_path+ to use in your code.
+This combination will give you route helpers such as +photographer_photos_path+ to use in your code.
NOTE: You can also use +:name_prefix+ with non-RESTful routes.
@@ -395,8 +362,6 @@ resources :photos, :except => :destroy
In this case, all of the normal routes except the route for +destroy+ (a +DELETE+ request to +/photos/<em>id</em>+) will be generated.
-In addition to an action or a list of actions, you can also supply the special symbols +:all+ or +:none+ to the +:only+ and +:except+ options.
-
TIP: If your application has many RESTful routes, using +:only+ and +:except+ to generate only the routes that you actually need can cut down on memory use and speed up the routing process.
h4. Nested Resources
@@ -421,8 +386,6 @@ resources :magazines do
end
</ruby>
-TIP: Further below you'll learn about a convenient shortcut for this construct:<br/>+resources :magazines, :has_many => :ads+
-
In addition to the routes for magazines, this declaration will also create routes for ads, each of which requires the specification of a magazine in the URL:
|_.HTTP verb|_.URL |_.controller|_.action |_.used for|
@@ -437,7 +400,7 @@ In addition to the routes for magazines, this declaration will also create route
This will also create routing helpers such as +magazine_ads_url+ and +edit_magazine_ad_path+.
-h5. Using +:name_prefix+
+h5(#nested-name-prefix). Using +:name_prefix+
The +:name_prefix+ option overrides the automatically-generated prefix in nested route helpers. For example,
@@ -447,38 +410,7 @@ resources :magazines do
end
</ruby>
-This will create routing helpers such as +periodical_ads_url+ and +periodical_edit_ad_path+. You can even use +:name_prefix+ to suppress the prefix entirely:
-
-<ruby>
-resources :magazines do
- resources :ads, :name_prefix => nil
-end
-</ruby>
-
-This will create routing helpers such as +ads_url+ and +edit_ad_path+. Note that calling these will still require supplying an article id:
-
-<ruby>
-ads_url(@magazine)
-edit_ad_path(@magazine, @ad)
-</ruby>
-
-h5. Using +:has_one+ and +:has_many+
-
-The +:has_one+ and +:has_many+ options provide a succinct notation for simple nested routes. Use +:has_one+ to nest a singleton resource, or +:has_many+ to nest a plural resource:
-
-<ruby>
-resources :photos, :has_one => :photographer, :has_many => [:publications, :versions]
-</ruby>
-
-This has the same effect as this set of declarations:
-
-<ruby>
-resources :photos do
- resource :photographer
- resources :publications
- resources :versions
-end
-</ruby>
+This will create routing helpers such as +periodical_ads_url+ and +periodical_edit_ad_path+.
h5. Limits to Nesting
@@ -492,7 +424,7 @@ resources :publishers do
end
</ruby>
-However, without the use of +name_prefix => nil+, deeply-nested resources quickly become cumbersome. In this case, for example, the application would recognize URLs such as
+Deeply-nested resources quickly become cumbersome. In this case, for example, the application would recognize URLs such as
<pre>
/publishers/1/magazines/2/photos/3
@@ -524,11 +456,7 @@ This will enable recognition of (among others) these routes:
/photos/3 ==> photo_path(3)
</pre>
-With shallow nesting, you need only supply enough information to uniquely identify the resource that you want to work with. If you like, you can combine shallow nesting with the +:has_one+ and +:has_many+ options:
-
-<ruby>
-resources :publishers, :has_many => { :magazines => :photos }, :shallow => true
-</ruby>
+With shallow nesting, you need only supply enough information to uniquely identify the resource that you want to work with.
h4. Route Generation from Arrays
@@ -556,19 +484,25 @@ This format is especially useful when you might not know until runtime which of
h4. Namespaced Resources
-It's possible to do some quite complex things by combining +:path_prefix+ and +:name_prefix+. For example, you can use the combination of these two options to move administrative resources to their own folder in your application:
+It's possible to do some quite complex things by combining +scope+ and +:name_prefix+. For example, you can use the combination of these two options to move administrative resources to their own folder in your application:
<ruby>
-resources :photos, :path_prefix => 'admin', :controller => 'admin/photos'
-resources :tags, :name_prefix => 'admin_photo_', :path_prefix => 'admin/photos/:photo_id', :controller => 'admin/photo_tags'
-resources :ratings, :name_prefix => 'admin_photo_', :path_prefix => 'admin/photos/:photo_id', :controller => 'admin/photo_ratings'
+scope 'admin' do
+ resources :photos, :name_prefix => "admin", :controller => 'admin/photos'
+ scope 'photos' do
+ resources :tags, :name_prefix => 'admin_photo', :controller => 'admin/photo_tags'
+ resources :ratings, :name_prefix => 'admin_photo', :controller => 'admin/photo_ratings'
+ end
+end
</ruby>
The good news is that if you find yourself using this level of complexity, you can stop. Rails supports _namespaced resources_ to make placing resources in their own folder a snap. Here's the namespaced version of those same three routes:
<ruby>
namespace :admin do
- resources :photos, :has_many => { :tags, :ratings }
+ resources :photos do
+ resources :tags, :ratings
+ end
end
</ruby>
@@ -592,7 +526,7 @@ end
This will enable Rails to recognize URLs such as +/photos/1/preview+ using the GET HTTP verb, and route them to the preview action of the Photos controller. It will also create the +preview_photo_url+ and +preview_photo_path+ route helpers.
-Within the block of member routes, each route name specifies the HTTP verb that it will recognize. You can use +get+, +put+, +post+, +delete+, or +any+ here. If you don't have multiple +member+ route, you can also passing +:on+ to the routing.
+Within the block of member routes, each route name specifies the HTTP verb that it will recognize. You can use +get+, +put+, +post+, or +delete+ here. If you don't have multiple +member+ route, you can also passing +:on+ to the routing.
<ruby>
resources :photos do
@@ -649,7 +583,7 @@ When you set up a regular route, you supply a series of symbols that Rails maps
match ':controller(/:action(/:id))'
</ruby>
-If an incoming request of +/photos/show/1+ is processed by this route (because it hasn't matched any previous route in the file), then the result will be to invoke the +show+ action of the +Photos+ controller, and to make the final parameter (1) available as +params[:id]+.
+If an incoming request of +/photos/show/1+ is processed by this route (because it hasn't matched any previous route in the file), then the result will be to invoke the +show+ action of the +Photos+ controller, and to make the final parameter (1) available as +params[:id]+. This route will also route the incoming request of +/photos+ to PhotosController, since +:action+ and +:id+ are optional parameters, denoted by parenthesis.
h4. Wildcard Components
@@ -709,12 +643,12 @@ match 'logout' => 'sessions#destroy', :as => :logout
This will do two things. First, requests to +/logout+ will be sent to the +destroy+ action of the +Sessions+ controller. Second, Rails will maintain the +logout_path+ and +logout_url+ helpers for use within your code.
-h4. Route Requirements
+h4. Route Constraints
-You can use the +:requirements+ option to enforce a format for any parameter in a route:
+You can use the +:constraints+ option to enforce a format for any parameter in a route:
<ruby>
-match 'photo/:id' => 'photos#show', :requirements => { :id => /[A-Z]\d{5}/ }
+match 'photo/:id' => 'photos#show', :constraints => { :id => /[A-Z]\d{5}/ }
</ruby>
This route would respond to URLs such as +/photo/A12345+. You can more succinctly express the same route this way:
@@ -723,16 +657,6 @@ This route would respond to URLs such as +/photo/A12345+. You can more succinctl
match 'photo/:id' => 'photos#show', :id => /[A-Z]\d{5}/
</ruby>
-h4. Route Conditions
-
-Route conditions (introduced with the +:conditions+ option) are designed to implement restrictions on routes. Currently, the only supported restriction is +:method+:
-
-<ruby>
-match 'photo/:id' => 'photos#show', :conditions => { :method => :get }
-</ruby>
-
-As with conditions in RESTful routes, you can specify +:get+, +:post+, +:put+, +:delete+, or +:any+ for the acceptable method.
-
h4. Route Globbing
Route globbing is a way to specify that a particular parameter should be matched to all the remaining parts of a route. For example
@@ -743,20 +667,6 @@ match 'photo/*other' => 'photos#unknown'
This route would match +photo/12+ or +/photo/long/path/to/12+ equally well, creating an array of path segments as the value of +params[:other]+.
-h4. Route Options
-
-You can use +:with_options+ to simplify defining groups of similar routes:
-
-<ruby>
-map.with_options :controller => 'photo' do |photo|
- photo.list '', :action => 'index'
- photo.delete ':id/delete', :action => 'delete'
- photo.edit ':id/edit', :action => 'edit'
-end
-</ruby>
-
-The importance of +map.with_options+ has declined with the introduction of RESTful routes.
-
h3. Formats and +respond_to+
There's one more way in which routing can do different things depending on differences in the incoming HTTP request: by issuing a response that corresponds to what the request specifies that it will accept. In Rails routing, you can control this with the special +:format+ parameter in the route.
@@ -899,6 +809,7 @@ h3. Changelog
"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/3
+* April 2, 2010: Updated guide to match new Routing DSL in Rails 3, by Rizwan Reza
* Febuary 1, 2010: Modifies the routing documentation to match new routing DSL in Rails 3, by Prem Sichanugrist
* October 4, 2008: Added additional detail on specifying verbs for resource member/collection routes, by "Mike Gunderloy":credits.html#mgunderloy
* September 23, 2008: Added section on namespaced controllers and routing, by "Mike Gunderloy":credits.html#mgunderloy
diff --git a/railties/guides/source/security.textile b/railties/guides/source/security.textile
index b62ff8cb38..1ddf094d18 100644
--- a/railties/guides/source/security.textile
+++ b/railties/guides/source/security.textile
@@ -611,7 +611,7 @@ h4. SQL Injection
-- _Thanks to clever methods, this is hardly a problem in most Rails applications. However, this is a very devastating and common attack in web applications, so it is important to understand the problem._
-h5. Introduction
+h5(#sql-injection-introduction). Introduction
SQL injection attacks aim at influencing database queries by manipulating web application parameters. A popular goal of SQL injection attacks is to bypass authorization. Another goal is to carry out data manipulation or reading arbitrary data. Here is an example of how not to use user input data in a query:
@@ -668,7 +668,7 @@ The result won't be a list of projects (because there is no project with an empt
Also, the second query renames some columns with the AS statement so that the web application displays the values from the user table. Be sure to update your Rails "to at least 2.1.1":http://www.rorsecurity.info/2008/09/08/sql-injection-issue-in-limit-and-offset-parameter/.
-h5. Countermeasures
+h5(#sql-injection-countermeasures). Countermeasures
Ruby on Rails has a built in filter for special SQL characters, which will escape ' , " , NULL character and line breaks. <em class="highlight">Using +Model.find(id)+ or +Model.find_by_some thing(something)+ automatically applies this countermeasure</em>. But in SQL fragments, especially <em class="highlight">in conditions fragments (+:conditions => "..."+), the +connection.execute()+ or +Model.find_by_sql()+ methods, it has to be applied manually</em>.
@@ -760,7 +760,7 @@ http://www.cbsnews.com/stories/2002/02/15/weather_local/main501644.shtml?zipcode
<script src=http://www.securitylab.ru/test/sc.js></script><!--
</plain>
-h6. Countermeasures
+h6(#html-injection-countermeasures). Countermeasures
_(highlight)It is very important to filter malicious input, but it is also important to escape the output of the web application_.
@@ -850,7 +850,7 @@ In the end, he got a 4 KB worm, which he injected into his profile page.
The "moz-binding":http://www.securiteam.com/securitynews/5LP051FHPE.html CSS property proved to be another way to introduce JavaScript in CSS in Gecko-based browsers (Firefox, for example).
-h5. Countermeasures
+h5(#css-injection-countermeasures). Countermeasures
This example, again, showed that a blacklist filter is never complete. However, as custom CSS in web applications is a quite rare feature, I am not aware of a whitelist CSS filter. _(highlight)If you want to allow custom colours or images, you can allow the user to choose them and build the CSS in the web application_. Use Rails' +sanitize()+ method as a model for a whitelist CSS filter, if you really need one.
@@ -879,7 +879,7 @@ RedCloth.new("<a href='javascript:alert(1)'>hello</a>", [:filter_html]).to_html
# => "<p><a href="javascript:alert(1)">hello</a></p>"
</ruby>
-h5. Countermeasures
+h5(#textile-injection-countermeasures). Countermeasures
It is recommended to _(highlight)use RedCloth in combination with a whitelist input filter_, as described in the countermeasures against XSS section.
diff --git a/railties/guides/source/testing.textile b/railties/guides/source/testing.textile
index ac9fb4276e..b1eee0ccb9 100644
--- a/railties/guides/source/testing.textile
+++ b/railties/guides/source/testing.textile
@@ -411,7 +411,7 @@ NOTE: +assert_valid(record)+ has been deprecated. Please use +assert(record.vali
|_.Assertion |_.Purpose|
|+assert_valid(record)+ |Ensures that the passed record is valid by Active Record standards and returns any error messages if it is not.|
|+assert_difference(expressions, difference = 1, message = nil) {...}+ |Test numeric difference between the return value of an expression as a result of what is evaluated in the yielded block.|
-|+assert_no_difference(expressions, message = nil, &block)+ |Asserts that the numeric result of evaluating an expression is not changed before and after invoking the passed in block.|
+|+assert_no_difference(expressions, message = nil, &amp;block)+ |Asserts that the numeric result of evaluating an expression is not changed before and after invoking the passed in block.|
|+assert_recognizes(expected_options, path, extras={}, message=nil)+ |Asserts that the routing of the given path was handled correctly and that the parsed options (given in the expected_options hash) match path. Basically, it asserts that Rails recognizes the route given by expected_options.|
|+assert_generates(expected_path, options, defaults={}, extras = {}, message=nil)+ |Asserts that the provided options can be used to generate the provided path. This is the inverse of assert_recognizes. The extras parameter is used to tell the request the names and values of additional request parameters that would be in a query string. The message parameter allows you to specify a custom error message for assertion failures.|
|+assert_response(type, message = nil)+ |Asserts that the response comes with a specific status code. You can specify +:success+ to indicate 200, +:redirect+ to indicate 300-399, +:missing+ to indicate 404, or +:error+ to match the 500-599 range|
@@ -940,6 +940,7 @@ h3. Changelog
"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/8
+* April 4, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":credits.html#jaimeiniesta
* November 13, 2008: Revised based on feedback from Pratik Naik by "Akshay Surve":credits.html#asurve (not yet approved for publication)
* October 14, 2008: Edit and formatting pass by "Mike Gunderloy":credits.html#mgunderloy (not yet approved for publication)
* October 12, 2008: First draft by "Akshay Surve":credits.html#asurve (not yet approved for publication)
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb
index 44635ff4f6..5c7de616be 100644
--- a/railties/lib/rails/application/configuration.rb
+++ b/railties/lib/rails/application/configuration.rb
@@ -132,7 +132,7 @@ module Rails
middleware.use('::Rack::Lock', :if => lambda { !allow_concurrency })
middleware.use('::Rack::Runtime')
middleware.use('::Rails::Rack::Logger')
- middleware.use('::ActionDispatch::ShowExceptions', lambda { consider_all_requests_local })
+ middleware.use('::ActionDispatch::ShowExceptions', lambda { consider_all_requests_local }, :if => lambda { action_dispatch.show_exceptions })
middleware.use("::ActionDispatch::RemoteIp", lambda { action_dispatch.ip_spoofing_check }, lambda { action_dispatch.trusted_proxies })
middleware.use('::Rack::Sendfile', lambda { action_dispatch.x_sendfile_header })
middleware.use('::ActionDispatch::Callbacks', lambda { !cache_classes })
diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb
index fccae9190a..fbad3c9ef1 100644
--- a/railties/lib/rails/generators/rails/app/app_generator.rb
+++ b/railties/lib/rails/generators/rails/app/app_generator.rb
@@ -31,6 +31,9 @@ module Rails::Generators
class_option :edge, :type => :boolean, :default => false,
:desc => "Setup the application with Gemfile pointing to Rails repository"
+ class_option :skip_gemfile, :type => :boolean, :default => false,
+ :desc => "Don't create a Gemfile"
+
class_option :skip_activerecord, :type => :boolean, :aliases => "-O", :default => false,
:desc => "Skip ActiveRecord files"
@@ -71,7 +74,7 @@ module Rails::Generators
copy_file "gitignore", ".gitignore" unless options[:skip_git]
template "Rakefile"
template "config.ru"
- template "Gemfile"
+ template "Gemfile" unless options[:skip_gemfile]
end
def create_app_files
diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb
index dc20ffb2fa..bd4fedcdec 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/application.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb
@@ -11,8 +11,9 @@ require "active_resource/railtie"
require "rails/test_unit/railtie"
<% end -%>
-# Auto-require default libraries and those for the current Rails environment.
-Bundler.require :default, Rails.env
+# If you have a Gemfile, require the gems listed there, including any gems
+# you've limited to :test, :development, or :production.
+Bundler.require(:default, Rails.env) if defined?(Bundler)
module <%= app_const_base %>
class Application < Rails::Application
diff --git a/railties/lib/rails/generators/rails/app/templates/config/boot.rb b/railties/lib/rails/generators/rails/app/templates/config/boot.rb
index 3cb561d41f..3971a07012 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/boot.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/boot.rb
@@ -1,8 +1,14 @@
-# Use Bundler (preferred)
+# Use locked gems if present.
begin
require File.expand_path('../../.bundle/environment', __FILE__)
+
rescue LoadError
+ # Otherwise, use RubyGems.
require 'rubygems'
- require 'bundler'
- Bundler.setup
+
+ # And set up the gems listed in the Gemfile.
+ if File.exist?(File.expand_path('../../Gemfile', __FILE__))
+ require 'bundler'
+ Bundler.setup
+ end
end
diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt
index 0b87b241ec..beb28e2229 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/environments/test.rb.tt
@@ -14,6 +14,9 @@
config.consider_all_requests_local = true
config.action_controller.perform_caching = false
+ # Raise exceptions instead of rendering exception templates
+ config.action_dispatch.show_exceptions = false
+
# Disable request forgery protection in test environment
config.action_controller.allow_forgery_protection = false
diff --git a/railties/lib/rails/generators/rails/app/templates/public/index.html b/railties/lib/rails/generators/rails/app/templates/public/index.html
index 836da1b689..9fb304a66b 100644
--- a/railties/lib/rails/generators/rails/app/templates/public/index.html
+++ b/railties/lib/rails/generators/rails/app/templates/public/index.html
@@ -82,7 +82,8 @@
#about-content {
background-color: #ffd;
border: 1px solid #fc0;
- margin-left: -11px;
+ margin-left: -55px;
+ margin-right: -10px;
}
#about-content table {
margin-top: 10px;
diff --git a/railties/lib/rails/version.rb b/railties/lib/rails/version.rb
index 1dd8fa0ec7..7c47cbeabd 100644
--- a/railties/lib/rails/version.rb
+++ b/railties/lib/rails/version.rb
@@ -3,7 +3,7 @@ module Rails
MAJOR = 3
MINOR = 0
TINY = 0
- BUILD = "beta1"
+ BUILD = "beta2"
STRING = [MAJOR, MINOR, TINY, BUILD].join('.')
end
diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb
index 9a359d20b1..7f72881d55 100644
--- a/railties/test/application/middleware_test.rb
+++ b/railties/test/application/middleware_test.rb
@@ -52,6 +52,12 @@ module ApplicationTests
assert !middleware.include?("ActionDispatch::Static")
end
+ test "removes show exceptions if action_dispatch.show_exceptions is disabled" do
+ add_to_config "config.action_dispatch.show_exceptions = false"
+ boot!
+ assert !middleware.include?("ActionDispatch::ShowExceptions")
+ end
+
test "use middleware" do
use_frameworks []
add_to_config "config.middleware.use Rack::Config"
diff --git a/version.rb b/version.rb
index 1dd8fa0ec7..7c47cbeabd 100644
--- a/version.rb
+++ b/version.rb
@@ -3,7 +3,7 @@ module Rails
MAJOR = 3
MINOR = 0
TINY = 0
- BUILD = "beta1"
+ BUILD = "beta2"
STRING = [MAJOR, MINOR, TINY, BUILD].join('.')
end