aboutsummaryrefslogtreecommitdiffstats
path: root/railties
diff options
context:
space:
mode:
Diffstat (limited to 'railties')
-rwxr-xr-x[-rw-r--r--]railties/Rakefile2
-rw-r--r--railties/guides/assets/stylesheets/main.css2
-rw-r--r--railties/guides/rails_guides/helpers.rb9
-rw-r--r--railties/guides/source/3_0_release_notes.textile4
-rw-r--r--railties/guides/source/action_controller_overview.textile2
-rw-r--r--railties/guides/source/action_mailer_basics.textile2
-rw-r--r--railties/guides/source/action_view_overview.textile2
-rw-r--r--railties/guides/source/active_record_querying.textile2
-rw-r--r--railties/guides/source/active_record_validations_callbacks.textile26
-rw-r--r--railties/guides/source/active_support_core_extensions.textile8
-rw-r--r--railties/guides/source/association_basics.textile2
-rw-r--r--railties/guides/source/caching_with_rails.textile1
-rw-r--r--railties/guides/source/command_line.textile3
-rw-r--r--railties/guides/source/configuring.textile154
-rw-r--r--railties/guides/source/contribute.textile2
-rw-r--r--railties/guides/source/contributing_to_rails.textile13
-rw-r--r--railties/guides/source/debugging_rails_applications.textile2
-rw-r--r--railties/guides/source/form_helpers.textile2
-rw-r--r--railties/guides/source/generators.textile6
-rw-r--r--railties/guides/source/getting_started.textile2
-rw-r--r--railties/guides/source/i18n.textile77
-rw-r--r--railties/guides/source/index.html.erb14
-rw-r--r--railties/guides/source/layout.html.erb25
-rw-r--r--railties/guides/source/layouts_and_rendering.textile2
-rw-r--r--railties/guides/source/migrations.textile4
-rw-r--r--railties/guides/source/performance_testing.textile2
-rw-r--r--railties/guides/source/plugins.textile2
-rw-r--r--railties/guides/source/rails_application_templates.textile2
-rw-r--r--railties/guides/source/rails_on_rack.textile2
-rw-r--r--railties/guides/source/routing.textile4
-rw-r--r--railties/guides/source/security.textile4
-rw-r--r--railties/guides/source/testing.textile4
-rw-r--r--railties/lib/rails/commands.rb5
-rw-r--r--railties/lib/rails/engine.rb6
-rw-r--r--railties/lib/rails/generators.rb2
-rwxr-xr-x[-rw-r--r--]railties/lib/rails/generators/rails/app/templates/Rakefile2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/public/javascripts/prototype.js733
-rw-r--r--railties/lib/rails/generators/rails/plugin/templates/Rakefile.tt2
-rwxr-xr-x[-rw-r--r--]railties/lib/rails/generators/rails/plugin_new/templates/Rakefile4
-rw-r--r--railties/lib/rails/railtie.rb4
-rw-r--r--railties/lib/rails/test_help.rb11
-rw-r--r--railties/test/application/generators_test.rb9
-rw-r--r--railties/test/application/initializers/frameworks_test.rb60
-rw-r--r--railties/test/application/rake_test.rb16
-rw-r--r--railties/test/generators/migration_generator_test.rb12
-rw-r--r--railties/test/generators/model_generator_test.rb6
-rw-r--r--railties/test/generators_test.rb6
-rw-r--r--railties/test/railties/engine_test.rb19
48 files changed, 743 insertions, 542 deletions
diff --git a/railties/Rakefile b/railties/Rakefile
index 9504661c0e..5137bee761 100644..100755
--- a/railties/Rakefile
+++ b/railties/Rakefile
@@ -1,4 +1,4 @@
-require 'rake'
+#!/usr/bin/env rake
require 'rake/testtask'
require 'rake/gempackagetask'
diff --git a/railties/guides/assets/stylesheets/main.css b/railties/guides/assets/stylesheets/main.css
index 932ee402c4..cf6e9e5cc8 100644
--- a/railties/guides/assets/stylesheets/main.css
+++ b/railties/guides/assets/stylesheets/main.css
@@ -333,7 +333,7 @@ h6 {
padding: 0.125em 0 0.25em 28px;*/
}
-#mainCol dd.ticket, #subCol dd.ticket {
+#mainCol dd.work-in-progress, #subCol dd.work-in-progress {
background: #fff9d8 url(../images/tab_yellow.gif) no-repeat left top;
border: none;
padding: 1.25em 1em 1.25em 48px;
diff --git a/railties/guides/rails_guides/helpers.rb b/railties/guides/rails_guides/helpers.rb
index bf99538696..d466c76c7c 100644
--- a/railties/guides/rails_guides/helpers.rb
+++ b/railties/guides/rails_guides/helpers.rb
@@ -4,19 +4,14 @@ module RailsGuides
link = content_tag(:a, :href => url) { name }
result = content_tag(:dt, link)
- if ticket = options[:ticket]
- result << content_tag(:dd, lh(ticket), :class => 'ticket')
+ if options[:work_in_progress]
+ result << content_tag(:dd, 'Work in progress', :class => 'work-in-progress')
end
result << content_tag(:dd, capture(&block))
result
end
- def lh(id, label = "Lighthouse Ticket")
- url = "http://rails.lighthouseapp.com/projects/16213/tickets/#{id}"
- content_tag(:a, label, :href => url)
- end
-
def author(name, nick, image = 'credits_pic_blank.gif', &block)
image = "images/#{image}"
diff --git a/railties/guides/source/3_0_release_notes.textile b/railties/guides/source/3_0_release_notes.textile
index 9c08c9fa0a..adb1c755df 100644
--- a/railties/guides/source/3_0_release_notes.textile
+++ b/railties/guides/source/3_0_release_notes.textile
@@ -271,10 +271,10 @@ end
<ruby>
scope 'es' do
- resources :projects, :path_names => { :edit => 'cambiar' }, :path => 'projeto'
+ resources :projects, :path_names => { :edit => 'cambiar' }, :path => 'proyecto'
end
-# Gives you the edit action with /es/projeto/1/cambiar
+# Gives you the edit action with /es/proyecto/1/cambiar
</ruby>
* Added +root+ method to the router as a short cut for <tt>match '/', :to => path</tt>.
diff --git a/railties/guides/source/action_controller_overview.textile b/railties/guides/source/action_controller_overview.textile
index b39075f101..0d6c66f168 100644
--- a/railties/guides/source/action_controller_overview.textile
+++ b/railties/guides/source/action_controller_overview.textile
@@ -814,8 +814,6 @@ NOTE: Certain exceptions are only rescuable from the +ApplicationController+ cla
h3. Changelog
-"Lighthouse Ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/17
-
* February 17, 2009: Yet another proofread by Xavier Noria.
* November 4, 2008: First release version by Tore Darell
diff --git a/railties/guides/source/action_mailer_basics.textile b/railties/guides/source/action_mailer_basics.textile
index 8d2ce44e93..b75c528a33 100644
--- a/railties/guides/source/action_mailer_basics.textile
+++ b/railties/guides/source/action_mailer_basics.textile
@@ -508,6 +508,4 @@ In the test we send the email and store the returned object in the +email+ varia
h3. Changelog
-"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213/tickets/25
-
* September 30, 2010: Fixed typos and reformatted Action Mailer configuration table for better understanding. "Jaime Iniesta":http://jaimeiniesta.com
diff --git a/railties/guides/source/action_view_overview.textile b/railties/guides/source/action_view_overview.textile
index 54792600a5..051baa660c 100644
--- a/railties/guides/source/action_view_overview.textile
+++ b/railties/guides/source/action_view_overview.textile
@@ -1472,7 +1472,5 @@ You can read more about the Rails Internationalization (I18n) API "here":i18n.ht
h3. Changelog
-"Lighthouse Ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/71
-
* September 3, 2009: Continuing work by Trevor Turk, leveraging the "Action Pack docs":http://ap.rubyonrails.org/ and "What's new in Edge Rails":http://ryandaigle.com/articles/2007/8/3/what-s-new-in-edge-rails-partials-get-layouts
* April 5, 2009: Starting work by Trevor Turk, leveraging Mike Gunderloy's docs
diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile
index 6837c8b11a..328439fdb8 100644
--- a/railties/guides/source/active_record_querying.textile
+++ b/railties/guides/source/active_record_querying.textile
@@ -928,8 +928,6 @@ For options, please see the parent section, "Calculations":#calculations.
h3. Changelog
-"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/16
-
* April 7, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com
* February 3, 2010: Update to Rails 3 by "James Miller":credits.html#bensie
* February 7, 2009: Second version by "Pratik":credits.html#lifo
diff --git a/railties/guides/source/active_record_validations_callbacks.textile b/railties/guides/source/active_record_validations_callbacks.textile
index e9ff6197ec..0824ba450c 100644
--- a/railties/guides/source/active_record_validations_callbacks.textile
+++ b/railties/guides/source/active_record_validations_callbacks.textile
@@ -96,7 +96,7 @@ To verify whether or not an object is valid, Rails uses the +valid?+ method. You
<ruby>
class Person < ActiveRecord::Base
- validates_presence_of :name
+ validates :name, :presence => true
end
Person.create(:name => "John Doe").valid? # => true
@@ -109,7 +109,7 @@ Note that an object instantiated with +new+ will not report errors even if it's
<ruby>
class Person < ActiveRecord::Base
- validates_presence_of :name
+ validates :name, :presence => true
end
>> p = Person.new
@@ -141,13 +141,13 @@ end
h4(#validations_overview-errors). +errors[]+
-To verify whether or not a particular attribute of an object is valid, you can use +errors[:attribute]+ that returns an array with all attribute errors, when there are no errors on the specified attribute, an empty array is returned.
+To verify whether or not a particular attribute of an object is valid, you can use +errors[:attribute]+. It returns an array of all the errors for +:attribute+. If there are no errors on the specified attribute, an empty array is returned.
This method is only useful _after_ validations have been run, because it only inspects the errors collection and does not trigger validations itself. It's different from the +ActiveRecord::Base#invalid?+ method explained above because it doesn't verify the validity of the object as a whole. It only checks to see whether there are errors found on an individual attribute of the object.
<ruby>
class Person < ActiveRecord::Base
- validates_presence_of :name
+ validates :name, :presence => true
end
>> Person.new.errors[:name].any? # => false
@@ -355,7 +355,7 @@ This helper validates that the specified attributes are not empty. It uses the +
<ruby>
class Person < ActiveRecord::Base
- validates_presence_of :name, :login, :email
+ validates :name, :login, :email, :presence => true
end
</ruby>
@@ -505,7 +505,7 @@ class Person < ActiveRecord::Base
validates_numericality_of :age, :on => :update
# the default (validates on both create and update)
- validates_presence_of :name, :on => :save
+ validates :name, :presence => true, :on => :save
end
</ruby>
@@ -603,7 +603,7 @@ Returns an OrderedHash with all errors. Each key is the attribute name and the v
<ruby>
class Person < ActiveRecord::Base
- validates_presence_of :name
+ validates :name, :presence => true
validates_length_of :name, :minimum => 3
end
@@ -623,7 +623,7 @@ h4(#working_with_validation_errors-errors-2). +errors[]+
<ruby>
class Person < ActiveRecord::Base
- validates_presence_of :name
+ validates :name, :presence => true
validates_length_of :name, :minimum => 3
end
@@ -699,7 +699,7 @@ The +clear+ method is used when you intentionally want to clear all the messages
<ruby>
class Person < ActiveRecord::Base
- validates_presence_of :name
+ validates :name, :presence => true
validates_length_of :name, :minimum => 3
end
@@ -723,7 +723,7 @@ The +size+ method returns the total number of error messages for the object.
<ruby>
class Person < ActiveRecord::Base
- validates_presence_of :name
+ validates :name, :presence => true
validates_length_of :name, :minimum => 3
validates_presence_of :email
end
@@ -824,10 +824,10 @@ Here is a simple example where we change the Rails behaviour to always display t
ActionView::Base.field_error_proc = Proc.new do |html_tag, instance|
if instance.error_message.kind_of?(Array)
%(#{html_tag}<span class="validation-error">&nbsp;
- #{instance.error_message.join(',')}</span>)
+ #{instance.error_message.join(',')}</span>).html_safe
else
%(#{html_tag}<span class="validation-error">&nbsp;
- #{instance.error_message}</span>)
+ #{instance.error_message}</span>).html_safe
end
end
</ruby>
@@ -1160,8 +1160,6 @@ config.active_record.observers = :mailer_observer
h3. Changelog
-"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213/tickets/26-active-record-validations-and-callbacks
-
* July 20, 2010: Fixed typos and rephrased some paragraphs for clarity. "Jaime Iniesta":http://jaimeiniesta.com
* May 24, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com
* May 15, 2010: Validation Errors section updated by "Emili Parreño":http://www.eparreno.com
diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile
index dc1200812e..7333a81cf9 100644
--- a/railties/guides/source/active_support_core_extensions.textile
+++ b/railties/guides/source/active_support_core_extensions.textile
@@ -1189,6 +1189,12 @@ To insert something verbatim use the +raw+ helper rather than calling +html_safe
<%= raw @cms.current_template %> <%# inserts @cms.current_template as is %>
</erb>
+or, equivalently, use <tt><%==</tt>:
+
+<erb>
+<%== @cms.current_template %> <%# inserts @cms.current_template as is %>
+</erb>
+
The +raw+ helper calls +html_safe+ for you:
<ruby>
@@ -3401,7 +3407,5 @@ NOTE: Defined in +active_support/core_ext/load_error.rb+.
h3. Changelog
-"Lighthouse ticket":https://rails.lighthouseapp.com/projects/16213/tickets/67
-
* August 10, 2010: Starts to take shape, added to the index.
* April 18, 2009: Initial version by "Xavier Noria":credits.html#fxn
diff --git a/railties/guides/source/association_basics.textile b/railties/guides/source/association_basics.textile
index f6d61373e1..14bbe907f3 100644
--- a/railties/guides/source/association_basics.textile
+++ b/railties/guides/source/association_basics.textile
@@ -1876,8 +1876,6 @@ Extensions can refer to the internals of the association proxy using these three
h3. Changelog
-"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/11
-
* April 7, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com
* April 19, 2009: Added +:touch+ option to +belongs_to+ associations by "Mike Gunderloy":credits.html#mgunderloy
* February 1, 2009: Added +:autosave+ option "Mike Gunderloy":credits.html#mgunderloy
diff --git a/railties/guides/source/caching_with_rails.textile b/railties/guides/source/caching_with_rails.textile
index 3320b610e7..63c52da32a 100644
--- a/railties/guides/source/caching_with_rails.textile
+++ b/railties/guides/source/caching_with_rails.textile
@@ -368,7 +368,6 @@ h3. Further reading
h3. Changelog
-"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/10-guide-to-caching
* May 02, 2009: Formatting cleanups
* April 26, 2009: Clean up typos in submitted patch
diff --git a/railties/guides/source/command_line.textile b/railties/guides/source/command_line.textile
index 752b5926f7..acd105c622 100644
--- a/railties/guides/source/command_line.textile
+++ b/railties/guides/source/command_line.textile
@@ -590,6 +590,3 @@ h5. Miscellaneous Tasks
+rake routes+ will list all of your defined routes, which is useful for tracking down routing problems in your app, or giving you a good overview of the URLs in an app you're trying to get familiar with.
-h3. Changelog
-
-"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213/tickets/29
diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile
index 28fff5c11e..ca78cc0e6d 100644
--- a/railties/guides/source/configuring.textile
+++ b/railties/guides/source/configuring.textile
@@ -13,7 +13,7 @@ Rails offers (at least) four good spots to place initialization code:
* application.rb
* Environment-specific Configuration Files
-* Initializers (load_application_initializers)
+* Initializers
* After-Initializers
h3. Running Code Before Rails
@@ -23,53 +23,53 @@ To run some code before Rails itself is loaded, simply put it above the call to
h3. Configuring Rails Components
-In general, the work of configuring Rails means configuring the components of Rails, as well as configuring Rails itself. The +application.rb+ and environment-specific configuration files (such as +config/environments/production.rb+) allow you to specify the various settings that you want to pass down to all of the components. For example, the default Rails 2.3 +application.rb+ file includes one setting:
+In general, the work of configuring Rails means configuring the components of Rails, as well as configuring Rails itself. The +application.rb+ and environment-specific configuration files (such as +config/environments/production.rb+) allow you to specify the various settings that you want to pass down to all of the components. For example, the default Rails 3.0 +application.rb+ file includes this setting:
<ruby>
-config.filter_parameters << :password
+ config.filter_parameters += [:password]
</ruby>
This is a setting for Rails itself. If you want to pass settings to individual Rails components, you can do so via the same +config+ object:
<ruby>
-config.active_record.timestamped_migrations = false
+ config.active_record.timestamped_migrations = false
</ruby>
Rails will use that particular setting to configure Active Record.
h4. Rails General Configuration
-* +config.routes_configuration_file+ overrides the default path for the routes configuration file. This defaults to +config/routes.rb+.
+* +config.after_initialize+ takes a block which will be ran _after_ Rails has finished initializing. Useful for configuring values set up by other initializers:
-* +config.cache_classes+ controls whether or not application classes should be reloaded on each request.
+<ruby>
+ config.after_initialize do
+ ActionView::Base.sanitized_allowed_tags.delete 'div'
+ end
+</ruby>
-* +config.cache_store+ configures which cache store to use for Rails caching. Options include +:memory_store+, +:file_store+, +:mem_cache_store+ or the name of your own custom class.
+* +config.app_generators+ alternate name for +config.generators+. See the "Configuring Generators" section below for how to use this.
-* +config.colorize_logging+ (true by default) specifies whether or not to use ANSI color codes when logging information.
+* +config.autoload_once_paths+ accepts an array of paths from which Rails will automatically load from only once. All elements of this array must also be in +autoload_paths+.
-* +config.controller_paths+ accepts an array of paths that will be searched for controllers. Defaults to +app/controllers+.
+* +config.autoload_paths+ accepts an array of additional paths to prepend to the load path. By default, all app, lib, vendor and mock paths are included in this list.
-* +config.database_configuration_file+ overrides the default path for the database configuration file. Default to +config/database.yml+.
+* +config.cache_classes+ controls whether or not application classes should be reloaded on each request. Defaults to _true_ in development, _false_ in test and production.
-* +config.dependency_loading+ enables or disables dependency loading during the request cycle. Setting dependency_loading to _true_ will allow new classes to be loaded during a request and setting it to _false_ will disable this behavior.
+* +config.cache_store+ configures which cache store to use for Rails caching. Options include +:memory_store+, +:file_store+, +:mem_cache_store+ or the name of your own custom class.
-* +config.eager_load_paths+ accepts an array of paths from which Rails will eager load on boot if cache classes is enabled. All elements of this array must also be in +load_paths+.
+* +config.colorize_logging+ (true by default) specifies whether or not to use ANSI color codes when logging information.
-* +config.load_once_paths+ accepts an array of paths from which Rails will automatically load from only once. All elements of this array must also be in +load_paths+.
+* +config.dependency_loading+ enables or disables dependency loading during the request cycle. Setting dependency_loading to _true_ will allow new classes to be loaded during a request and setting it to _false_ will disable this behavior.
-* +config.load_paths+ accepts an array of additional paths to prepend to the load path. By default, all app, lib, vendor and mock paths are included in this list.
+* +config.eager_load_paths+ accepts an array of paths from which Rails will eager load on boot if cache classes is enabled. All elements of this array must also be in +load_paths+.
* +config.log_level+ defines the verbosity of the Rails logger. In production mode, this defaults to +:info+. In development mode, it defaults to +:debug+.
* +config.log_path+ overrides the path to the log file to use. Defaults to +log/#{environment}.log+ (e.g. log/development.log or log/production.log).
-* +config.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Action Controller. Set to nil to disable logging.
+* +config.middleware+ allows you to configure the application's middleware. This is covered in depth in the "Configuring Middleware" section below.
-* +config.plugin_loader+ overrides the class that handles loading each plugin. Defaults to +Rails::Plugin::Loader+.
-
-* +config.plugin_locators+ overrides the class that handle finding the desired plugins that you‘d like to load for your application. By default it is the +Rails::Plugin::FileSystemLocator+.
-
-* +config.plugin_paths+ overrides the path to the root of the plugins directory. Defaults to +vendor/plugins+.
+* +config.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Action Controller. Set to nil to disable logging.
* +config.plugins+ accepts the list of plugins to load. If this is set to nil, all plugins will be loaded. If this is set to [], no plugins will be loaded. Otherwise, plugins will be loaded in the order specified.
@@ -77,14 +77,85 @@ h4. Rails General Configuration
* +config.reload_plugins+ enables or disables plugin reloading.
-* +config.root_path+ configures the root path of the application.
+* +config.root+ configures the root path of the application.
-* +config.time_zone+ sets the default time zone for the application and enables time zone awareness for Active Record.
+* +config.serve_static_assets+ configures Rails to serve static assets. Defaults to _true_, but in the production environment is turned off. The server software used to run the application should be used to serve the assets instead.
-* +config.view_path+ sets the path of the root of an application's views. Defaults to +app/views+.
+* +config.time_zone+ sets the default time zone for the application and enables time zone awareness for Active Record.
* +config.whiny_nils+ enables or disabled warnings when an methods of nil are invoked. Defaults to _false_.
+h4. Configuring Generators
+
+Rails 3 allows you to alter what generators are used with the +config.generators+ method. This method takes a block:
+
+<ruby>
+ config.generators do |g|
+ g.orm :active_record
+ g.test_framework :test_unit
+ end
+</ruby>
+
+The full set of methods that can be used in this block are as follows:
+
+* +force_plural+ allows pluralized model names. Defaults to _false_.
+* +helper+ defines whether or not to generate helpers. Defaults to _true_
+* +orm+ defines which orm to use. Defaults to _nil_, so will use Active Record by default.
+* +integration_tool+ defines which integration tool to use. Defaults to _nil_
+* +performance_tool+ defines which performance tool to use. Defaults to _nil_
+* +resource_controller+ defines which generator to use for generating a controller when using +rails generate resource+. Defaults to +:controller+.
+* +scaffold_controller+ different from +resource_controller+, defines which generator to use for generating a _scaffolded_ controller when using +rails generate scaffold+. Defaults to +:scaffold_controller+
+* +stylesheets+ turns on the hook for stylesheets in generators. Used in Rails for when the +scaffold+ generator is ran, but this hook can be used in other generates as well.
+* +test_framework+ defines which test framework to use. Defaults to _nil_, so will use Test::Unit by default.
+* +template_engine+ defines which template engine to use, such as ERB or Haml. Defaults to +:erb+.
+
+h4. Configuring Middleware
+
+Every Rails application comes with a standard set of middleware which it uses in this order in the development environment:
+
+* +ActionDispatch::Static+ is used to serve static assets. Disabled if +config.serve_static_assets+ is _true_.
+* +Rack::Lock+ Will wrap the app in mutex so it can only be called by a single thread at a time. Only enabled if +config.action_controller.allow_concurrency+ is set to _false_, which it is by default.
+* +ActiveSupport::Cache::Strategy::LocalCache+ Serves as a basic memory backed cache. This cache is not thread safe and is intended only for serving as a temporary memory cache for a single thread.
+* +Rack::Runtime+ Sets an +X-Runtime+ header, containing the time (in seconds) taken to execute the request.
+* +Rails::Rack::Logger+ Will notify the logs that the request has began. After request is complete, flushes all the logs.
+* +ActionDispatch::ShowExceptions+ rescues any exception returned by the application and renders nice exception pages if the request is local or if +config.consider_all_requests_local+ is set to _true_. If +config.action_dispatch.show_exceptions+ is set to _false_, exceptions will be raised regardless.
+* +ActionDispatch::RemoteIp+ checks for IP spoofing attacks. Configurable with the +config.action_dispatch.ip_spoofing_check+ and +config.action_dispatch.trusted_proxies+ settings.
+* +Rack::Sendfile+ The Sendfile middleware intercepts responses whose body is being served from a file and replaces it with a server specific X-Sendfile header. Configurable with +config.action_dispatch_
+* +ActionDispatch::Callbacks+ Runs the prepare callbacks before serving the request.
+* +ActiveRecord::ConnectionAdapters::ConnectionManagement+ cleans active connections after each request, unless the +rack.test+ key in the request environment is set to _true_.
+* +ActiveRecord::QueryCache+ caches all +SELECT+ queries generated in a request. If an +INSERT+ or +UPDATE+ takes place then the cache is cleaned.
+* +ActionDispatch::Cookies+ sets cookies for the request.
+* +ActionDispatch::Session::CookieStore+ is responsible for storing the session in cookies. An alternate middleware can be used for this by changing the +config.action_controller.session_store+ to an alternate value. Additionally, options passed to this can be configured by using +config.action_controller.session_options+.
+* +ActionDispatch::Flash+ sets up the +flash+ keys. Only available if +config.action_controller.session_store+ is set to a value.
+* +ActionDispatch::ParamsParser+ parses out parameters from the request into +params+
+* +Rack::MethodOverride+ allows the method to be overridden if +params[:_method]+ is set. This is the middleware which supports the PUT and DELETE HTTP method types.
+* +ActionDispatch::Head+ converts HEAD requests to GET requests and serves them as so.
+* +ActionDispatch::BestStandardsSupport+ enables "best standards support" so that IE8 renders some elements correctly.
+
+Besides these usual middleware, you can add your own by using the +config.middleware.use+ method:
+
+<ruby>
+ config.middleware.use Magical::Unicorns
+</ruby>
+
+This will put the +Magical::Unicorns+ middleware on the end of the stack. If you wish to put this middleware before another use +insert_before+:
+
+<ruby>
+ config.middleware.insert_before ActionDispatch::Head, Magical::Unicorns
+</ruby>
+
+There's also +insert_after+ which will insert a middleware _after_ another:
+
+<ruby>
+ config.middleware.insert_after ActionDispatch::Head, Magical::Unicorns
+</ruby>
+
+Middlewares can also be completely swapped out and replaced with others:
+
+<ruby>
+ config.middleware.swap ActionDispatch::BestStandardsSupport, Magical::Unicorns
+</ruby>
+
h4. Configuring i18n
* +config.i18n.default_locale+ sets the default locale of an application used for i18n. Defaults to +:en+.
@@ -137,24 +208,16 @@ h4. Configuring Action Controller
WARNING: Threadsafe operation is incompatible with the normal workings of development mode Rails. In particular, automatic dependency loading and class reloading are automatically disabled when you call +config.threadsafe!+.
-* +config.action_controller.param_parsers+ provides an array of handlers that can extract information from incoming HTTP requests and add it to the +params+ hash. By default, parsers for multipart forms, URL-encoded forms, XML, and JSON are active.
-
* +config.action_controller.default_charset+ specifies the default character set for all renders. The default is "utf-8".
* +config.action_controller.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Action Controller. Set to nil to disable logging.
-* +config.action_controller.resource_path_names+ is a hash of default names for several RESTful actions. By default, the new action is named +new+ and the edit action is named +edit+.
-
* +config.action_controller.request_forgery_protection_token+ sets the token parameter name for RequestForgery. Calling +protect_from_forgery+ sets it to +:authenticity_token+ by default.
-* +config.action_controller.optimise_named_routes+ turns on some optimizations in generating the routing table. It is set to +true+ by default.
-
* +config.action_controller.allow_forgery_protection+ enables or disables CSRF protection. By default this is +false+ in test mode and +true+ in all other modes.
* +config.action_controller.relative_url_root+ can be used to tell Rails that you are deploying to a subdirectory. The default is +ENV['RAILS_RELATIVE_URL_ROOT']+.
-* +config.action_dispatch.session_store+ sets the name of the store for session data. The default is +:cookie_store+; other valid options include +:active_record_store+, +:mem_cache_store+ or the name of your own custom class.
-
The caching code adds two additional settings:
* +ActionController::Base.page_cache_directory+ sets the directory where Rails will create cached pages for your web server. The default is +Rails.public_path+ (which is usually set to +Rails.root + "/public"+).
@@ -169,14 +232,16 @@ The Active Record session store can also be configured:
* +ActiveRecord::SessionStore::Session.data_column_name+ sets the name of the column which stores marshaled session data. Defaults to +data+.
+h4. Configuring Action Dispatch
+
+* +config.action_dispatch.session_store+ sets the name of the store for session data. The default is +:cookie_store+; other valid options include +:active_record_store+, +:mem_cache_store+ or the name of your own custom class.
+
h4. Configuring Action View
There are only a few configuration options for Action View, starting with four on +ActionView::Base+:
* +config.action_view.debug_rjs+ specifies whether RJS responses should be wrapped in a try/catch block that alert()s the caught exception (and then re-raises it). The default is +false+.
-* +config.action_view.warn_cache_misses+ tells Rails to display a warning whenever an action results in a cache miss on your view paths. The default is +false+.
-
* +config.action_view.field_error_proc+ provides an HTML generator for displaying errors that come from Active Record. The default is <tt>Proc.new{ |html_tag, instance| %Q(%&lt;div class=&quot;field_with_errors&quot;&gt;#{html_tag}&lt;/div&gt;).html_safe }</tt>
* +config.action_view.default_form_builder+ tells Rails which form builder to use by default. The default is +ActionView::Helpers::FormBuilder+.
@@ -189,8 +254,6 @@ h4. Configuring Action Mailer
There are a number of settings available on +config.action_mailer+:
-* +config.action_mailer.template_root+ gives the root folder for Action Mailer templates.
-
* +config.action_mailer.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Action Mailer. Set to nil to disable logging.
* +config.action_mailer.smtp_settings+ allows detailed configuration for the +:smtp+ delivery method. It accepts a hash of options, which can include any of these options:
@@ -211,15 +274,13 @@ There are a number of settings available on +config.action_mailer+:
* +config.action_mailer.perform_deliveries+ specifies whether mail will actually be delivered. By default this is +true+; it can be convenient to set it to +false+ for testing.
-* +config.action_mailer.default_charset+ tells Action Mailer which character set to use for the body and for encoding the subject. It defaults to +utf-8+.
-
-* +config.action_mailer.default_content_type+ specifies the default content type used for the main part of the message. It defaults to "text/plain"
-
-* +config.action_mailer.default_mime_version+ is the default MIME version for the message. It defaults to +1.0+.
-
-* +config.action_mailer.default_implicit_parts_order+ - When a message is built implicitly (i.e. multiple parts are assembled from templates
-which specify the content type in their filenames) this variable controls how the parts are ordered. Defaults to +["text/html", "text/enriched", "text/plain"]+. Items that appear first in the array have higher priority in the mail client
-and appear last in the mime encoded message.
+* +config.action_mailer.default+ configures Action Mailer defaults. These default to:
+<ruby>
+ :mime_version => "1.0",
+ :charset => "UTF-8",
+ :content_type => "text/plain",
+ :parts_order => [ "text/plain", "text/enriched", "text/html" ]
+</ruby>
h4. Configuring Active Resource
@@ -273,12 +334,9 @@ Some parts of Rails can also be configured externally by supplying environment v
* +ENV["RAILS_CACHE_ID"]+ and +ENV["RAILS_APP_VERSION"]+ are used to generate expanded cache keys in Rails' caching code. This allows you to have multiple separate caches from the same application.
-* +ENV['RAILS_GEM_VERSION']+ defines the version of the Rails gems to use, if +RAILS_GEM_VERSION+ is not defined in your +environment.rb+ file.
-
h3. Changelog
-"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/28
-
+* November 26, 2010: Removed all config settings not available in Rails 3 (Ryan Bigg)
* August 13, 2009: Updated with config syntax and added general configuration options by "John Pignata"
* January 3, 2009: First reasonably complete draft by "Mike Gunderloy":credits.html#mgunderloy
* November 5, 2008: Rough outline by "Mike Gunderloy":credits.html#mgunderloy
diff --git a/railties/guides/source/contribute.textile b/railties/guides/source/contribute.textile
index 88c5c79e9d..3d4607de1d 100644
--- a/railties/guides/source/contribute.textile
+++ b/railties/guides/source/contribute.textile
@@ -1,6 +1,6 @@
h2. Contribute to the Rails Guides
-Rails Guides aim to improve the Rails documentation and to make the barrier to entry as low as possible. A reasonably experienced developer should be able to use the Guides to come up to speed on Rails quickly. You can track the overall effort at the "Rails Guides Lighthouse":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets. Our sponsors have contributed prizes for those who write an entire guide, but there are many other ways to contribute.
+Rails Guides aim to improve the Rails documentation and to make the barrier to entry as low as possible. A reasonably experienced developer should be able to use the guides to come up to speed on Rails quickly. Our sponsors have contributed prizes for those who write an entire guide, but there are many other ways to contribute.
endprologue.
diff --git a/railties/guides/source/contributing_to_rails.textile b/railties/guides/source/contributing_to_rails.textile
index 7184759610..ccb9db5eee 100644
--- a/railties/guides/source/contributing_to_rails.textile
+++ b/railties/guides/source/contributing_to_rails.textile
@@ -105,12 +105,17 @@ mysql> GRANT ALL PRIVILEGES ON activerecord_unittest2.*
to 'rails'@'localhost';
</shell>
-Then ensure you run bundle install without the +--without db+ option:
+Now you'll have to install Active Record dependencies. This step is a little tricky because just running +bundle install+ without the +--without db+ parameter won't get those dependencies installed. It turns out that bundler remembers the +--without db+ parameter between calls so you'll have to manually override this. (See the "+bundle_install+ man page":http://gembundler.com/man/bundle-install.1.html for details)
+
+The easiest way to do this is to remove bundler's config file and then run +install+ again:
<shell>
+rm .bundle/config
bundle install
</shell>
+INFO: If you don't feel comfortable deleting bundler's config file, you can achieve the same effect by manually removing the "+BUNDLE_WITHOUT: db+" line on +.bundle/config+.
+
Finally, enter this from the +activerecord+ directory to create the test databases:
<shell>
@@ -127,7 +132,7 @@ You can now run tests as you did for +sqlite3+:
rake test_mysql
</shell>
-You can also +myqsl+ with +postgresql+, +jdbcmysql+, +jdbcsqlite3+ or +jdbcpostgresql+. Check out the file +activerecord/RUNNING_UNIT_TESTS+ for information on running more targeted database tests, or the file +ci/ci_build.rb+ to see the test suite that the Rails continuous integration server runs.
+You can also replace +myqsl+ with +postgresql+, +jdbcmysql+, +jdbcsqlite3+ or +jdbcpostgresql+. Check out the file +activerecord/RUNNING_UNIT_TESTS+ for information on running more targeted database tests, or the file +ci/ci_build.rb+ to see the test suite that the Rails continuous integration server runs.
NOTE: If you're working with Active Record code, you _must_ ensure that the tests pass for at least MySQL, PostgreSQL, and SQLite 3. Subtle differences between the various Active Record database adapters have been behind the rejection of many patches that looked OK when tested only against MySQL.
@@ -189,7 +194,7 @@ h3. Contributing to the Rails Documentation
Another area where you can help out if you're not yet ready to take the plunge to writing Rails core code is with Rails documentation. You can help with the Rails Guides or the Rails API documentation.
-TIP: "docrails":http://github.com/lifo/docrails/tree/master is the documentation branch for Rails with an *open commit policy*. You can simply PM "lifo":http://github.com/lifo on Github and ask for the commit rights. Documentation changes made as part of the "docrails":http://github.com/lifo/docrails/tree/master project are merged back to the Rails master code from time to time. Check out the "original announcement":http://weblog.rubyonrails.org/2008/5/2/help-improve-rails-documentation-on-git-branch for more details.
+TIP: "docrails":http://github.com/lifo/docrails/tree/master is the documentation branch for Rails with an *open commit policy*, it has public write access. Documentation changes made as part of the "docrails":http://github.com/lifo/docrails/tree/master project are merged back to the Rails master code from time to time. Check out the "original announcement":http://weblog.rubyonrails.org/2008/5/2/help-improve-rails-documentation-on-git-branch for more details.
h4. The Rails Guides
@@ -300,8 +305,6 @@ And then...think about your next contribution!
h3. Changelog
-"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/64
-
* April 6, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com
* August 1, 2009: Updates/amplifications by "Mike Gunderloy":credits.html#mgunderloy
* March 2, 2009: Initial draft by "Mike Gunderloy":credits.html#mgunderloy
diff --git a/railties/guides/source/debugging_rails_applications.textile b/railties/guides/source/debugging_rails_applications.textile
index adf427147b..6613fad406 100644
--- a/railties/guides/source/debugging_rails_applications.textile
+++ b/railties/guides/source/debugging_rails_applications.textile
@@ -704,8 +704,6 @@ h3. References
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":http://jaimeiniesta.com
* 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
diff --git a/railties/guides/source/form_helpers.textile b/railties/guides/source/form_helpers.textile
index ded82512d3..e178a60307 100644
--- a/railties/guides/source/form_helpers.textile
+++ b/railties/guides/source/form_helpers.textile
@@ -776,8 +776,6 @@ Many apps grow beyond simple forms editing a single object. For example when cre
h3. Changelog
-"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/1
-
* April 6, 2010: Fixed document to validate XHTML 1.0 Strict. "Jaime Iniesta":http://jaimeiniesta.com
h3. Authors
diff --git a/railties/guides/source/generators.textile b/railties/guides/source/generators.textile
index 0f2cbb76dc..99c34ed30f 100644
--- a/railties/guides/source/generators.textile
+++ b/railties/guides/source/generators.textile
@@ -92,7 +92,7 @@ class InitializerGenerator < Rails::Generators::NamedBase
end
</ruby>
-First, notice that we are inheriting from +Rails::Generators::NamedBase+ instead of +Rails::Generators::Base+. This means that our generator expects at least one argument, which will be the name of the initializer.
+First, notice that we are inheriting from +Rails::Generators::NamedBase+ instead of +Rails::Generators::Base+. This means that our generator expects at least one argument, which will be the name of the initializer, and will be available in our code in the variable +name+.
We can see that by invoking the description of this new generator (don't forget to delete the old generator file):
@@ -201,7 +201,7 @@ config.generators do |g|
end
</ruby>
-If we generate another resource with the scaffold generator, we can notice that neither stylesheets nor fixtures are created anymore. If you want to customize it further, for example to use DataMapper and RSpec instead of Active Record and TestUnit, it's just a matter of adding their gems to your application and configuring your generators.
+If we generate another resource with the scaffold generator, we can see that neither stylesheets nor fixtures are created anymore. If you want to customize it further, for example to use DataMapper and RSpec instead of Active Record and TestUnit, it's just a matter of adding their gems to your application and configuring your generators.
To demonstrate this, we are going to create a new helper generator that simply adds some instance variable readers. First, we create a generator:
@@ -363,8 +363,6 @@ Fallbacks allow your generators to have a single responsibility, increasing code
h3. Changelog
-"Lighthouse Ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/102
-
* August 23, 2010: Edit pass by "Xavier Noria":credits.html#fxn
* April 30, 2010: Reviewed by José Valim
diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile
index f3420e37d1..902b7353c0 100644
--- a/railties/guides/source/getting_started.textile
+++ b/railties/guides/source/getting_started.textile
@@ -1469,8 +1469,6 @@ Two very common sources of data that are not UTF-8:
h3. Changelog
-"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/2
-
* August 30, 2010: Minor editing after Rails 3 release by "Joost Baaij":http://www.spacebabies.nl
* July 12, 2010: Fixes, editing and updating of code samples by "Jaime Iniesta":http://jaimeiniesta.com
* May 16, 2010: Added a section on configuration gotchas to address common encoding problems that people might have by "Yehuda Katz":http://www.yehudakatz.com
diff --git a/railties/guides/source/i18n.textile b/railties/guides/source/i18n.textile
index 8a7e9fcae6..25c24ac7d7 100644
--- a/railties/guides/source/i18n.textile
+++ b/railties/guides/source/i18n.textile
@@ -127,7 +127,7 @@ If you want to translate your Rails application to a *single language other than
However, you would probably like to *provide support for more locales* in your application. In such case, you need to set and pass the locale between requests.
-WARNING: You may be tempted to store the chosen locale in a _session_ or a _cookie_. *Do not do so*. The locale should be transparent and a part of the URL. This way you don't break people's basic assumptions about the web itself: if you send a URL of some page to a friend, she should see the same page, same content. A fancy word for this would be that you're being "_RESTful_":http://en.wikipedia.org/wiki/Representational_State_Transfer. Read more about the RESTful approach in "Stefan Tilkov's articles":http://www.infoq.com/articles/rest-introduction. There may be some exceptions to this rule, which are discussed below.
+WARNING: You may be tempted to store the chosen locale in a _session_ or a <em>cookie</em>. *Do not do so*. The locale should be transparent and a part of the URL. This way you don't break people's basic assumptions about the web itself: if you send a URL of some page to a friend, she should see the same page, same content. A fancy word for this would be that you're being "<em>RESTful</em>":http://en.wikipedia.org/wiki/Representational_State_Transfer. Read more about the RESTful approach in "Stefan Tilkov's articles":http://www.infoq.com/articles/rest-introduction. There may be some exceptions to this rule, which are discussed below.
The _setting part_ is easy. You can set the locale in a +before_filter+ in the +ApplicationController+ like this:
@@ -253,7 +253,7 @@ match '/:locale' => 'dashboard#index'
Do take special care about the *order of your routes*, so this route declaration does not "eat" other ones. (You may want to add it directly before the +root :to+ declaration.)
-IMPORTANT: This solution has currently one rather big *downside*. Due to the _default_url_options_ implementation, you have to pass the +:id+ option explicitly, like this: +link_to 'Show', book_url(:id => book)+ and not depend on Rails' magic in code like +link_to 'Show', book+. If this should be a problem, have a look at two plugins which simplify work with routes in this way: Sven Fuchs's "routing_filter":http://github.com/svenfuchs/routing-filter/tree/master and Raul Murciano's "translate_routes":http://github.com/raul/translate_routes/tree/master. See also the page "How to encode the current locale in the URL":http://rails-i18n.org/wiki/wikipages/how-to-encode-the-current-locale-in-the-url in the Rails i18n Wiki.
+NOTE: Have a look at two plugins which simplify work with routes in this way: Sven Fuchs's "routing_filter":http://github.com/svenfuchs/routing-filter/tree/master and Raul Murciano's "translate_routes":http://github.com/raul/translate_routes/tree/master.
h4. Setting the Locale from the Client Supplied Information
@@ -278,7 +278,7 @@ def extract_locale_from_accept_language_header
end
</ruby>
-Of course, in a production environment you would need much more robust code, and could use a plugin such as Iain Hecker's "http_accept_language":http://github.com/iain/http_accept_language/tree/master or even Rack middleware such as Ryan Tomayko's "locale":http://github.com/rtomayko/rack-contrib/blob/master/lib/rack/locale.rb.
+Of course, in a production environment you would need much more robust code, and could use a plugin such as Iain Hecker's "http_accept_language":http://github.com/iain/http_accept_language/tree/master or even Rack middleware such as Ryan Tomayko's "locale":http://github.com/rack/rack-contrib/blob/master/lib/rack/contrib/locale.rb.
h5. Using GeoIP (or Similar) Database
@@ -464,24 +464,24 @@ I18n.t 'message'
The +translate+ method also takes a +:scope+ option which can contain one or more additional keys that will be used to specify a “namespace” or scope for a translation key:
<ruby>
-I18n.t :invalid, :scope => [:activerecord, :errors, :messages]
+I18n.t :record_invalid, :scope => [:activerecord, :errors, :messages]
</ruby>
-This looks up the +:invalid+ message in the Active Record error messages.
+This looks up the +:record_invalid+ message in the Active Record error messages.
Additionally, both the key and scopes can be specified as dot-separated keys as in:
<ruby>
-I18n.translate :"activerecord.errors.messages.invalid"
+I18n.translate "activerecord.errors.messages.record_invalid"
</ruby>
Thus the following calls are equivalent:
<ruby>
-I18n.t 'activerecord.errors.messages.invalid'
-I18n.t 'errors.messages.invalid', :scope => :active_record
-I18n.t :invalid, :scope => 'activerecord.errors.messages'
-I18n.t :invalid, :scope => [:activerecord, :errors, :messages]
+I18n.t 'activerecord.errors.messages.record_invalid'
+I18n.t 'errors.messages.record_invalid', :scope => :active_record
+I18n.t :record_invalid, :scope => 'activerecord.errors.messages'
+I18n.t :record_invalid, :scope => [:activerecord, :errors, :messages]
</ruby>
h5. Defaults
@@ -672,11 +672,11 @@ Active Record validation error messages can also be translated easily. Active Re
This gives you quite powerful means to flexibly adjust your messages to your application's needs.
-Consider a User model with a +validates_presence_of+ validation for the name attribute like this:
+Consider a User model with a validation for the name attribute like this:
<ruby>
class User < ActiveRecord::Base
- validates_presence_of :name
+ validates :name, :presence => true
end
</ruby>
@@ -697,7 +697,7 @@ activerecord.errors.models.user.attributes.name.blank
activerecord.errors.models.user.blank
activerecord.errors.messages.blank
errors.attributes.name.blank
-errors.messagges.blank
+errors.messages.blank
</ruby>
When your models are additionally using inheritance then the messages are looked up in the inheritance chain.
@@ -706,7 +706,7 @@ For example, you might have an Admin model inheriting from User:
<ruby>
class Admin < User
- validates_presence_of :name
+ validates :name, :presence => true
end
</ruby>
@@ -719,7 +719,7 @@ activerecord.errors.models.user.attributes.title.blank
activerecord.errors.models.user.blank
activerecord.errors.messages.blank
errors.attributes.title.blank
-errors.messagges.blank
+errors.messages.blank
</ruby>
This way you can provide special translations for various error messages at different points in your models inheritance chain and in the attributes, models, or default scopes.
@@ -733,27 +733,27 @@ So, for example, instead of the default error message +"can not be blank"+ you c
* +count+, where available, can be used for pluralization if present:
|_. validation |_.with option |_.message |_.interpolation|
-| validates_confirmation_of | - | :confirmation | -|
-| validates_acceptance_of | - | :accepted | -|
-| validates_presence_of | - | :blank | -|
-| validates_length_of | :within, :in | :too_short | count|
-| validates_length_of | :within, :in | :too_long | count|
-| validates_length_of | :is | :wrong_length | count|
-| validates_length_of | :minimum | :too_short | count|
-| validates_length_of | :maximum | :too_long | count|
-| validates_uniqueness_of | - | :taken | -|
-| validates_format_of | - | :invalid | -|
-| validates_inclusion_of | - | :inclusion | -|
-| validates_exclusion_of | - | :exclusion | -|
-| validates_associated | - | :invalid | -|
-| validates_numericality_of | - | :not_a_number | -|
-| validates_numericality_of | :greater_than | :greater_than | count|
-| validates_numericality_of | :greater_than_or_equal_to | :greater_than_or_equal_to | count|
-| validates_numericality_of | :equal_to | :equal_to | count|
-| validates_numericality_of | :less_than | :less_than | count|
-| validates_numericality_of | :less_than_or_equal_to | :less_than_or_equal_to | count|
-| validates_numericality_of | :odd | :odd | -|
-| validates_numericality_of | :even | :even | -|
+| confirmation | - | :confirmation | -|
+| acceptance | - | :accepted | -|
+| presence | - | :blank | -|
+| length | :within, :in | :too_short | count|
+| length | :within, :in | :too_long | count|
+| length | :is | :wrong_length | count|
+| length | :minimum | :too_short | count|
+| length | :maximum | :too_long | count|
+| uniqueness | - | :taken | -|
+| format | - | :invalid | -|
+| inclusion | - | :inclusion | -|
+| exclusion | - | :exclusion | -|
+| associated | - | :invalid | -|
+| numericality | - | :not_a_number | -|
+| numericality | :greater_than | :greater_than | count|
+| numericality | :greater_than_or_equal_to | :greater_than_or_equal_to | count|
+| numericality | :equal_to | :equal_to | count|
+| numericality | :less_than | :less_than | count|
+| numericality | :less_than_or_equal_to | :less_than_or_equal_to | count|
+| numericality | :odd | :odd | -|
+| numericality | :even | :even | -|
h5. Translations for the Active Record +error_messages_for+ Helper
@@ -889,8 +889,3 @@ fn1. Or, to quote "Wikipedia":http://en.wikipedia.org/wiki/Internationalization_
fn2. Other backends might allow or require to use other formats, e.g. a GetText backend might allow to read GetText files.
fn3. One of these reasons is that we don't want to imply any unnecessary load for applications that do not need any I18n capabilities, so we need to keep the I18n library as simple as possible for English. Another reason is that it is virtually impossible to implement a one-fits-all solution for all problems related to I18n for all existing languages. So a solution that allows us to exchange the entire implementation easily is appropriate anyway. This also makes it much easier to experiment with custom features and extensions.
-
-
-h3. Changelog
-
-"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213/tickets/23
diff --git a/railties/guides/source/index.html.erb b/railties/guides/source/index.html.erb
index 6b897e3a6a..84fbc53a69 100644
--- a/railties/guides/source/index.html.erb
+++ b/railties/guides/source/index.html.erb
@@ -31,7 +31,7 @@ Ruby on Rails Guides
<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>
+ <dd class="work-in-progress">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 to the author.</dd>
</dl>
</div>
<% end %>
@@ -71,7 +71,7 @@ Ruby on Rails Guides
<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 %>
+<%= guide("Action View Form Helpers", 'form_helpers.html', :work_in_progress => true) do %>
<p>Guide to using built-in Form helpers.</p>
<% end %>
</dl>
@@ -100,11 +100,11 @@ Ruby on Rails Guides
<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 %>
+<%= guide("Action Mailer Basics", 'action_mailer_basics.html', :work_in_progress => true) 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 %>
+<%= guide("Testing Rails Applications", 'testing.html', :work_in_progress => true) 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 %>
@@ -124,11 +124,11 @@ Ruby on Rails Guides
<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 %>
+<%= guide("Rails Command Line Tools and Rake tasks", 'command_line.html', :work_in_progress => true) 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 %>
+<%= guide("Caching with Rails", 'caching_with_rails.html', :work_in_progress => true) do %>
<p>Various caching techniques provided by Rails.</p>
<% end %>
</dl>
@@ -136,7 +136,7 @@ Ruby on Rails Guides
<h3>Extending Rails</h3>
<dl>
- <%= guide("The Basics of Creating Rails Plugins", 'plugins.html', :ticket => 32) do %>
+ <%= guide("The Basics of Creating Rails Plugins", 'plugins.html', :work_in_progress => true) do %>
<p>This guide covers how to build a plugin to extend the functionality of Rails.</p>
<% end %>
diff --git a/railties/guides/source/layout.html.erb b/railties/guides/source/layout.html.erb
index d4b87dc45b..bb62506f04 100644
--- a/railties/guides/source/layout.html.erb
+++ b/railties/guides/source/layout.html.erb
@@ -106,6 +106,31 @@
<div class="wrapper">
<div id="mainCol">
<%= yield.html_safe %>
+
+ <h3>Feedback</h3>
+ <p>
+ You're encouraged to help in keeping the quality of this guide.
+ </p>
+ <p>
+ If you see any typos or factual errors you are confident to
+ patch please clone <%= link_to 'docrails', 'https://github.com/lifo/docrails' %>
+ and push the change yourself. That branch of Rails has public write access.
+ Commits are still reviewed, but that happens after you've submitted your
+ contribution. <%= link_to 'docrails', 'https://github.com/lifo/docrails' %> is
+ cross-merged with master periodically.
+ </p>
+ <p>
+ You may also find incomplete content, or stuff that is not up to date.
+ Please do add any missing documentation for master. Check the
+ <%= link_to 'Ruby on Rails Guides Guidelines', 'ruby_on_rails_guides_guidelines.html' %>
+ guide for style and conventions.
+ </p>
+ <p>
+ Issues may also be reported <%= link_to 'in Github', 'https://github.com/lifo/docrails/issues' %>.
+ </p>
+ <p>And last but not least, any kind of discussion regarding Ruby on Rails
+ documentation is very welcome in the <%= link_to 'rubyonrails-docs mailing list', 'http://groups.google.com/group/rubyonrails-docs' %>.
+ </p>
</div>
</div>
</div>
diff --git a/railties/guides/source/layouts_and_rendering.textile b/railties/guides/source/layouts_and_rendering.textile
index 4e26d152bf..80a1fdd38d 100644
--- a/railties/guides/source/layouts_and_rendering.textile
+++ b/railties/guides/source/layouts_and_rendering.textile
@@ -1194,8 +1194,6 @@ There are several ways of getting similar results with different sub-templating
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":http://jaimeiniesta.com
* January 25, 2010: Rails 3.0 Update by "Mikel Lindsaar":credits.html#raasdnil
* December 27, 2008: Merge patch from Rodrigo Rosenfeld Rosas covering subtemplates
diff --git a/railties/guides/source/migrations.textile b/railties/guides/source/migrations.textile
index 4c49a4ccbc..0d13fbc10a 100644
--- a/railties/guides/source/migrations.textile
+++ b/railties/guides/source/migrations.textile
@@ -584,13 +584,11 @@ h3. Active Record and Referential Integrity
The Active Record way claims that intelligence belongs in your models, not in the database. As such, features such as triggers or foreign key constraints, which push some of that intelligence back into the database, are not heavily used.
-Validations such as +validates_uniqueness_of+ are one way in which models can enforce data integrity. The +:dependent+ option on associations allows models to automatically destroy child objects when the parent is destroyed. Like anything which operates at the application level these cannot guarantee referential integrity and so some people augment them with foreign key constraints.
+Validations such as +validates :foreign_key, :uniqueness => true+ are one way in which models can enforce data integrity. The +:dependent+ option on associations allows models to automatically destroy child objects when the parent is destroyed. Like anything which operates at the application level these cannot guarantee referential integrity and so some people augment them with foreign key constraints.
Although Active Record does not provide any tools for working directly with such features, the +execute+ method can be used to execute arbitrary SQL. There are also a number of plugins such as "foreign_key_migrations":http://github.com/harukizaemon/redhillonrails/tree/master/foreign_key_migrations/ which add foreign key support to Active Record (including support for dumping foreign keys in +db/schema.rb+).
h3. Changelog
-"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/6
-
* July 15, 2010: minor typos corrected by "Jaime Iniesta":http://jaimeiniesta.com
* September 14, 2008: initial version by "Frederick Cheung":credits.html#fcheung
diff --git a/railties/guides/source/performance_testing.textile b/railties/guides/source/performance_testing.textile
index 9dda6d420a..41bdd27e9b 100644
--- a/railties/guides/source/performance_testing.textile
+++ b/railties/guides/source/performance_testing.textile
@@ -524,7 +524,5 @@ Rails has been lucky to have two startups dedicated to Rails specific performanc
h3. Changelog
-"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/4
-
* January 9, 2009: Complete rewrite by "Pratik":credits.html#lifo
* September 6, 2008: Initial version by Matthew Bergman
diff --git a/railties/guides/source/plugins.textile b/railties/guides/source/plugins.textile
index d32e7de564..cb43282ace 100644
--- a/railties/guides/source/plugins.textile
+++ b/railties/guides/source/plugins.textile
@@ -1513,7 +1513,5 @@ The final plugin should have a directory structure that looks something like thi
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":http://jaimeiniesta.com
* November 17, 2008: Major revision by Jeff Dean
diff --git a/railties/guides/source/rails_application_templates.textile b/railties/guides/source/rails_application_templates.textile
index bc7b151dfe..d4b887ad02 100644
--- a/railties/guides/source/rails_application_templates.textile
+++ b/railties/guides/source/rails_application_templates.textile
@@ -233,6 +233,4 @@ git :commit => "-a -m 'Initial commit'"
h3. Changelog
-"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/78
-
* April 29, 2009: Initial version by "Pratik":credits.html#lifo
diff --git a/railties/guides/source/rails_on_rack.textile b/railties/guides/source/rails_on_rack.textile
index eaebb05f17..f17e9b4798 100644
--- a/railties/guides/source/rails_on_rack.textile
+++ b/railties/guides/source/rails_on_rack.textile
@@ -237,7 +237,5 @@ h4. Understanding Middlewares
h3. Changelog
-"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/58
-
* February 7, 2009: Second version by "Pratik":credits.html#lifo
* January 11, 2009: First version by "Pratik":credits.html#lifo
diff --git a/railties/guides/source/routing.textile b/railties/guides/source/routing.textile
index cc0c3316c8..2f5c88b8c3 100644
--- a/railties/guides/source/routing.textile
+++ b/railties/guides/source/routing.textile
@@ -194,7 +194,7 @@ end
or, for a single case
<ruby>
-resources :posts, :path => "/admin"
+resources :posts, :path => "/admin/posts"
</ruby>
In each of these cases, the named routes remain the same as if you did not use +scope+. In the last case, the following paths map to +PostsController+:
@@ -853,8 +853,6 @@ assert_routing({ :path => "photos", :method => :post }, { :controller => "photos
h3. Changelog
-"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/3
-
* April 10, 2010: Updated guide to remove outdated and superfluous information, and to provide information about new features, by "Yehuda Katz":http://www.yehudakatz.com
* April 2, 2010: Updated guide to match new Routing DSL in Rails 3, by "Rizwan Reza":http://www.rizwanreza.com/
* Febuary 1, 2010: Modifies the routing documentation to match new routing DSL in Rails 3, by Prem Sichanugrist
diff --git a/railties/guides/source/security.textile b/railties/guides/source/security.textile
index 4656cf4e40..5b24d8c8e3 100644
--- a/railties/guides/source/security.textile
+++ b/railties/guides/source/security.textile
@@ -550,7 +550,7 @@ Ruby uses a slightly different approach than many other languages to match the e
<ruby>
class File < ActiveRecord::Base
- validates_format_of :name, :with => /^[\w\.\-\+]+$/
+ validates :name, :format => /^[\w\.\-\+]+$/
end
</ruby>
@@ -979,6 +979,4 @@ The security landscape shifts and it is important to keep up to date, because mi
h3. Changelog
-"Lighthouse ticket":http://rails.lighthouseapp.com/projects/16213-rails-guides/tickets/7
-
* November 1, 2008: First approved version by Heiko Webers
diff --git a/railties/guides/source/testing.textile b/railties/guides/source/testing.textile
index 043a2462b4..c292a5d83b 100644
--- a/railties/guides/source/testing.textile
+++ b/railties/guides/source/testing.textile
@@ -315,7 +315,7 @@ Now to get this test to pass we can add a model level validation for the _title_
<ruby>
class Post < ActiveRecord::Base
- validates_presence_of :title
+ validates :title, :presence => true
end
</ruby>
@@ -940,8 +940,6 @@ The built-in +test/unit+ based testing is not the only way to test Rails applica
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":http://jaimeiniesta.com
* 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)
diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb
index de5d876c18..338565247f 100644
--- a/railties/lib/rails/commands.rb
+++ b/railties/lib/rails/commands.rb
@@ -12,11 +12,8 @@ command = aliases[command] || command
case command
when 'generate', 'destroy', 'plugin'
- if command == "plugin" && ARGV.first == "new"
+ if command == 'plugin' && ARGV.first == 'new'
require "rails/commands/plugin_new"
- elsif command == 'generate' && ARGV.first == "plugin_new"
- puts "This generator should not be used directly as a generator. You should use `rails plugin new` command instead"
- exit(1)
else
require APP_PATH
Rails.application.require_environment!
diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb
index 62fb781c19..85fa4424c4 100644
--- a/railties/lib/rails/engine.rb
+++ b/railties/lib/rails/engine.rb
@@ -363,8 +363,10 @@ module Rails
_railtie
end
- define_method(:table_name_prefix) do
- "#{name}_"
+ unless mod.respond_to?(:table_name_prefix)
+ define_method(:table_name_prefix) do
+ "#{name}_"
+ end
end
end
end
diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb
index 240810b8bd..66c4088a68 100644
--- a/railties/lib/rails/generators.rb
+++ b/railties/lib/rails/generators.rb
@@ -228,6 +228,7 @@ module Rails
rails = groups.delete("rails")
rails.map! { |n| n.sub(/^rails:/, '') }
rails.delete("app")
+ rails.delete("plugin_new")
print_list("rails", rails)
hidden_namespaces.each {|n| groups.delete(n.to_s) }
@@ -301,6 +302,7 @@ module Rails
$LOAD_PATH.each do |base|
Dir[File.join(base, "{rails/generators,generators}", "**", "*_generator.rb")].each do |path|
begin
+ path = path.sub("#{base}/", "")
require path
rescue Exception => e
# No problem
diff --git a/railties/lib/rails/generators/rails/app/templates/Rakefile b/railties/lib/rails/generators/rails/app/templates/Rakefile
index d83cafc3be..4dc1023f1f 100644..100755
--- a/railties/lib/rails/generators/rails/app/templates/Rakefile
+++ b/railties/lib/rails/generators/rails/app/templates/Rakefile
@@ -1,7 +1,7 @@
+#!/usr/bin/env rake
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require File.expand_path('../config/application', __FILE__)
-require 'rake'
<%= app_const %>.load_tasks
diff --git a/railties/lib/rails/generators/rails/app/templates/public/javascripts/prototype.js b/railties/lib/rails/generators/rails/app/templates/public/javascripts/prototype.js
index 06249a6ae3..474b2231bb 100644
--- a/railties/lib/rails/generators/rails/app/templates/public/javascripts/prototype.js
+++ b/railties/lib/rails/generators/rails/app/templates/public/javascripts/prototype.js
@@ -1,4 +1,4 @@
-/* Prototype JavaScript framework, version 1.7_rc2
+/* Prototype JavaScript framework, version 1.7
* (c) 2005-2010 Sam Stephenson
*
* Prototype is freely distributable under the terms of an MIT-style license.
@@ -8,7 +8,7 @@
var Prototype = {
- Version: '1.7_rc2',
+ Version: '1.7',
Browser: (function(){
var ua = navigator.userAgent;
@@ -166,10 +166,12 @@ var Class = (function() {
NUMBER_TYPE = 'Number',
STRING_TYPE = 'String',
OBJECT_TYPE = 'Object',
+ FUNCTION_CLASS = '[object Function]',
BOOLEAN_CLASS = '[object Boolean]',
NUMBER_CLASS = '[object Number]',
STRING_CLASS = '[object String]',
ARRAY_CLASS = '[object Array]',
+ DATE_CLASS = '[object Date]',
NATIVE_JSON_STRINGIFY_SUPPORT = window.JSON &&
typeof JSON.stringify === 'function' &&
JSON.stringify(0) === '0' &&
@@ -322,7 +324,7 @@ var Class = (function() {
}
function isFunction(object) {
- return typeof object === "function";
+ return _toString.call(object) === FUNCTION_CLASS;
}
function isString(object) {
@@ -333,6 +335,10 @@ var Class = (function() {
return _toString.call(object) === NUMBER_CLASS;
}
+ function isDate(object) {
+ return _toString.call(object) === DATE_CLASS;
+ }
+
function isUndefined(object) {
return typeof object === "undefined";
}
@@ -352,6 +358,7 @@ var Class = (function() {
isFunction: isFunction,
isString: isString,
isNumber: isNumber,
+ isDate: isDate,
isUndefined: isUndefined
});
})();
@@ -1079,9 +1086,10 @@ Array.from = $A;
slice = arrayProto.slice,
_each = arrayProto.forEach; // use native browser JS 1.6 implementation if available
- function each(iterator) {
- for (var i = 0, length = this.length; i < length; i++)
- iterator(this[i]);
+ function each(iterator, context) {
+ for (var i = 0, length = this.length >>> 0; i < length; i++) {
+ if (i in this) iterator.call(context, this[i], i, this);
+ }
}
if (!_each) _each = each;
@@ -1287,8 +1295,14 @@ var Hash = Class.create(Enumerable, (function() {
var key = encodeURIComponent(pair.key), values = pair.value;
if (values && typeof values == 'object') {
- if (Object.isArray(values))
- return results.concat(values.map(toQueryPair.curry(key)));
+ if (Object.isArray(values)) {
+ var queryValues = [];
+ for (var i = 0, len = values.length, value; i < len; i++) {
+ value = values[i];
+ queryValues.push(toQueryPair(key, value));
+ }
+ return results.concat(queryValues);
+ }
} else results.push(toQueryPair(key, values));
return results;
}).join('&');
@@ -1468,9 +1482,7 @@ Ajax.Base = Class.create({
this.options.method = this.options.method.toLowerCase();
- if (Object.isString(this.options.parameters))
- this.options.parameters = this.options.parameters.toQueryParams();
- else if (Object.isHash(this.options.parameters))
+ if (Object.isHash(this.options.parameters))
this.options.parameters = this.options.parameters.toObject();
}
});
@@ -1486,22 +1498,21 @@ Ajax.Request = Class.create(Ajax.Base, {
request: function(url) {
this.url = url;
this.method = this.options.method;
- var params = Object.clone(this.options.parameters);
+ var params = Object.isString(this.options.parameters) ?
+ this.options.parameters :
+ Object.toQueryString(this.options.parameters);
if (!['get', 'post'].include(this.method)) {
- params['_method'] = this.method;
+ params += (params ? '&' : '') + "_method=" + this.method;
this.method = 'post';
}
- this.parameters = params;
-
- if (params = Object.toQueryString(params)) {
- if (this.method == 'get')
- this.url += (this.url.include('?') ? '&' : '?') + params;
- else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
- params += '&_=';
+ if (params && this.method === 'get') {
+ this.url += (this.url.include('?') ? '&' : '?') + params;
}
+ this.parameters = params.toQueryParams();
+
try {
var response = new Ajax.Response(this);
if (this.options.onCreate) this.options.onCreate(response);
@@ -1570,11 +1581,12 @@ Ajax.Request = Class.create(Ajax.Base, {
success: function() {
var status = this.getStatus();
- return !status || (status >= 200 && status < 300);
+ return !status || (status >= 200 && status < 300) || status == 304;
},
getStatus: function() {
try {
+ if (this.transport.status === 1223) return 204;
return this.transport.status || 0;
} catch (e) { return 0 }
},
@@ -1849,6 +1861,11 @@ if (!Node.ELEMENT_NODE) {
(function(global) {
+ function shouldUseCache(tagName, attributes) {
+ if (tagName === 'select') return false;
+ if ('type' in attributes) return false;
+ return true;
+ }
var HAS_EXTENDED_CREATE_ELEMENT_SYNTAX = (function(){
try {
@@ -1866,13 +1883,19 @@ if (!Node.ELEMENT_NODE) {
attributes = attributes || { };
tagName = tagName.toLowerCase();
var cache = Element.cache;
+
if (HAS_EXTENDED_CREATE_ELEMENT_SYNTAX && attributes.name) {
tagName = '<' + tagName + ' name="' + attributes.name + '">';
delete attributes.name;
return Element.writeAttribute(document.createElement(tagName), attributes);
}
+
if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
- return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
+
+ var node = shouldUseCache(tagName, attributes) ?
+ cache[tagName].cloneNode(false) : document.createElement(tagName);
+
+ return Element.writeAttribute(node, attributes);
};
Object.extend(global.Element, element || { });
@@ -1883,7 +1906,7 @@ if (!Node.ELEMENT_NODE) {
Element.idCounter = 1;
Element.cache = { };
-function purgeElement(element) {
+Element._purgeElement = function(element) {
var uid = element._prototypeUID;
if (uid) {
Element.stopObserving(element);
@@ -1948,6 +1971,21 @@ Element.Methods = {
}
})();
+ var LINK_ELEMENT_INNERHTML_BUGGY = (function() {
+ try {
+ var el = document.createElement('div');
+ el.innerHTML = "<link>";
+ var isBuggy = (el.childNodes.length === 0);
+ el = null;
+ return isBuggy;
+ } catch(e) {
+ return true;
+ }
+ })();
+
+ var ANY_INNERHTML_BUGGY = SELECT_ELEMENT_INNERHTML_BUGGY ||
+ TABLE_ELEMENT_INNERHTML_BUGGY || LINK_ELEMENT_INNERHTML_BUGGY;
+
var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
var s = document.createElement("script"),
isBuggy = false;
@@ -1962,8 +2000,10 @@ Element.Methods = {
return isBuggy;
})();
+
function update(element, content) {
element = $(element);
+ var purgeElement = Element._purgeElement;
var descendants = element.getElementsByTagName('*'),
i = descendants.length;
@@ -1984,7 +2024,7 @@ Element.Methods = {
return element;
}
- if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) {
+ if (ANY_INNERHTML_BUGGY) {
if (tagName in Element._insertionTranslations.tags) {
while (element.firstChild) {
element.removeChild(element.firstChild);
@@ -1993,6 +2033,12 @@ Element.Methods = {
.each(function(node) {
element.appendChild(node)
});
+ } else if (LINK_ELEMENT_INNERHTML_BUGGY && Object.isString(content) && content.indexOf('<link') > -1) {
+ while (element.firstChild) {
+ element.removeChild(element.firstChild);
+ }
+ var nodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts(), true);
+ nodes.each(function(node) { element.appendChild(node) });
}
else {
element.innerHTML = content.stripScripts();
@@ -2402,117 +2448,6 @@ Element.Methods = {
return element;
},
- cumulativeOffset: function(element) {
- var valueT = 0, valueL = 0;
- if (element.parentNode) {
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- element = element.offsetParent;
- } while (element);
- }
- return Element._returnOffset(valueL, valueT);
- },
-
- positionedOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- element = element.offsetParent;
- if (element) {
- if (element.tagName.toUpperCase() == 'BODY') break;
- var p = Element.getStyle(element, 'position');
- if (p !== 'static') break;
- }
- } while (element);
- return Element._returnOffset(valueL, valueT);
- },
-
- absolutize: function(element) {
- element = $(element);
- if (Element.getStyle(element, 'position') == 'absolute') return element;
-
- var offsets = Element.positionedOffset(element),
- top = offsets[1],
- left = offsets[0],
- width = element.clientWidth,
- height = element.clientHeight;
-
- element._originalLeft = left - parseFloat(element.style.left || 0);
- element._originalTop = top - parseFloat(element.style.top || 0);
- element._originalWidth = element.style.width;
- element._originalHeight = element.style.height;
-
- element.style.position = 'absolute';
- element.style.top = top + 'px';
- element.style.left = left + 'px';
- element.style.width = width + 'px';
- element.style.height = height + 'px';
- return element;
- },
-
- relativize: function(element) {
- element = $(element);
- if (Element.getStyle(element, 'position') == 'relative') return element;
-
- element.style.position = 'relative';
- var top = parseFloat(element.style.top || 0) - (element._originalTop || 0),
- left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
-
- element.style.top = top + 'px';
- element.style.left = left + 'px';
- element.style.height = element._originalHeight;
- element.style.width = element._originalWidth;
- return element;
- },
-
- cumulativeScrollOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.scrollTop || 0;
- valueL += element.scrollLeft || 0;
- element = element.parentNode;
- } while (element);
- return Element._returnOffset(valueL, valueT);
- },
-
- getOffsetParent: function(element) {
- if (element.offsetParent) return $(element.offsetParent);
- if (element == document.body) return $(element);
-
- while ((element = element.parentNode) && element != document.body)
- if (Element.getStyle(element, 'position') != 'static')
- return $(element);
-
- return $(document.body);
- },
-
- viewportOffset: function(forElement) {
- var valueT = 0,
- valueL = 0,
- element = forElement;
-
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
-
- if (element.offsetParent == document.body &&
- Element.getStyle(element, 'position') == 'absolute') break;
-
- } while (element = element.offsetParent);
-
- element = forElement;
- do {
- if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) {
- valueT -= element.scrollTop || 0;
- valueL -= element.scrollLeft || 0;
- }
- } while (element = element.parentNode);
-
- return Element._returnOffset(valueL, valueT);
- },
-
clonePosition: function(element, source) {
var options = Object.extend({
setLeft: true,
@@ -2566,8 +2501,6 @@ if (Prototype.Browser.Opera) {
Element.Methods.getStyle = Element.Methods.getStyle.wrap(
function(proceed, element, style) {
switch (style) {
- case 'left': case 'top': case 'right': case 'bottom':
- if (proceed(element, 'position') === 'static') return null;
case 'height': case 'width':
if (!Element.visible(element)) return null;
@@ -2603,37 +2536,6 @@ if (Prototype.Browser.Opera) {
}
else if (Prototype.Browser.IE) {
- Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
- function(proceed, element) {
- element = $(element);
- if (!element.parentNode) return $(document.body);
- var position = element.getStyle('position');
- if (position !== 'static') return proceed(element);
- element.setStyle({ position: 'relative' });
- var value = proceed(element);
- element.setStyle({ position: position });
- return value;
- }
- );
-
- $w('positionedOffset viewportOffset').each(function(method) {
- Element.Methods[method] = Element.Methods[method].wrap(
- function(proceed, element) {
- element = $(element);
- if (!element.parentNode) return Element._returnOffset(0, 0);
- var position = element.getStyle('position');
- if (position !== 'static') return proceed(element);
- var offsetParent = element.getOffsetParent();
- if (offsetParent && offsetParent.getStyle('position') === 'fixed')
- offsetParent.setStyle({ zoom: 1 });
- element.setStyle({ position: 'relative' });
- var value = proceed(element);
- element.setStyle({ position: position });
- return value;
- }
- );
- });
-
Element.Methods.getStyle = function(element, style) {
element = $(element);
style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
@@ -2862,20 +2764,6 @@ else if (Prototype.Browser.WebKit) {
return element;
};
-
- Element.Methods.cumulativeOffset = function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- if (element.offsetParent == document.body)
- if (Element.getStyle(element, 'position') == 'absolute') break;
-
- element = element.offsetParent;
- } while (element);
-
- return Element._returnOffset(valueL, valueT);
- };
}
if ('outerHTML' in document.documentElement) {
@@ -2914,11 +2802,20 @@ Element._returnOffset = function(l, t) {
return result;
};
-Element._getContentFromAnonymousElement = function(tagName, html) {
+Element._getContentFromAnonymousElement = function(tagName, html, force) {
var div = new Element('div'),
t = Element._insertionTranslations.tags[tagName];
- if (t) {
- div.innerHTML = t[0] + html + t[1];
+
+ var workaround = false;
+ if (t) workaround = true;
+ else if (force) {
+ workaround = true;
+ t = ['', '', 0];
+ }
+
+ if (workaround) {
+ div.innerHTML = '&nbsp;' + t[0] + html + t[1];
+ div.removeChild(div.firstChild);
for (var i = t[2]; i--; ) {
div = div.firstChild;
}
@@ -3077,7 +2974,8 @@ Element.addMethods = function(methods) {
"FORM": Object.clone(Form.Methods),
"INPUT": Object.clone(Form.Element.Methods),
"SELECT": Object.clone(Form.Element.Methods),
- "TEXTAREA": Object.clone(Form.Element.Methods)
+ "TEXTAREA": Object.clone(Form.Element.Methods),
+ "BUTTON": Object.clone(Form.Element.Methods)
});
}
@@ -3264,6 +3162,8 @@ Element.addMethods({
purge: function(element) {
if (!(element = $(element))) return;
+ var purgeElement = Element._purgeElement;
+
purgeElement(element);
var descendants = element.getElementsByTagName('*'),
@@ -3283,11 +3183,13 @@ Element.addMethods({
return (Number(match[1]) / 100);
}
- function getPixelValue(value, property) {
+ function getPixelValue(value, property, context) {
+ var element = null;
if (Object.isElement(value)) {
element = value;
value = element.getStyle(property);
}
+
if (value === null) {
return null;
}
@@ -3296,7 +3198,9 @@ Element.addMethods({
return window.parseFloat(value);
}
- if (/\d/.test(value) && element.runtimeStyle) {
+ var isPercentage = value.include('%'), isViewport = (context === document.viewport);
+
+ if (/\d/.test(value) && element && element.runtimeStyle && !(isPercentage && isViewport)) {
var style = element.style.left, rStyle = element.runtimeStyle.left;
element.runtimeStyle.left = element.currentStyle.left;
element.style.left = value || 0;
@@ -3307,18 +3211,33 @@ Element.addMethods({
return value;
}
- if (value.include('%')) {
+ if (element && isPercentage) {
+ context = context || element.parentNode;
var decimal = toDecimal(value);
- var whole;
- if (property.include('left') || property.include('right') ||
- property.include('width')) {
- whole = $(element.parentNode).measure('width');
- } else if (property.include('top') || property.include('bottom') ||
- property.include('height')) {
- whole = $(element.parentNode).measure('height');
+ var whole = null;
+ var position = element.getStyle('position');
+
+ var isHorizontal = property.include('left') || property.include('right') ||
+ property.include('width');
+
+ var isVertical = property.include('top') || property.include('bottom') ||
+ property.include('height');
+
+ if (context === document.viewport) {
+ if (isHorizontal) {
+ whole = document.viewport.getWidth();
+ } else if (isVertical) {
+ whole = document.viewport.getHeight();
+ }
+ } else {
+ if (isHorizontal) {
+ whole = $(context).measure('width');
+ } else if (isVertical) {
+ whole = $(context).measure('height');
+ }
}
- return whole * decimal;
+ return (whole === null) ? 0 : whole * decimal;
}
return 0;
@@ -3410,6 +3329,14 @@ Element.addMethods({
var position = element.getStyle('position'),
width = element.getStyle('width');
+ if (width === "0px" || width === null) {
+ element.style.display = 'block';
+ width = element.getStyle('width');
+ }
+
+ var context = (position === 'fixed') ? document.viewport :
+ element.parentNode;
+
element.setStyle({
position: 'absolute',
visibility: 'hidden',
@@ -3420,9 +3347,9 @@ Element.addMethods({
var newWidth;
if (width && (positionedWidth === width)) {
- newWidth = getPixelValue(width);
- } else if (width && (position === 'absolute' || position === 'fixed')) {
- newWidth = getPixelValue(width);
+ newWidth = getPixelValue(element, 'width', context);
+ } else if (position === 'absolute' || position === 'fixed') {
+ newWidth = getPixelValue(element, 'width', context);
} else {
var parent = element.parentNode, pLayout = $(parent).getLayout();
@@ -3453,6 +3380,7 @@ Element.addMethods({
if (!(property in COMPUTATIONS)) {
throw "Property not found.";
}
+
return this._set(property, COMPUTATIONS[property].call(this, this.element));
},
@@ -3505,7 +3433,10 @@ Element.addMethods({
if (!this._preComputing) this._begin();
var bHeight = this.get('border-box-height');
- if (bHeight <= 0) return 0;
+ if (bHeight <= 0) {
+ if (!this._preComputing) this._end();
+ return 0;
+ }
var bTop = this.get('border-top'),
bBottom = this.get('border-bottom');
@@ -3522,7 +3453,10 @@ Element.addMethods({
if (!this._preComputing) this._begin();
var bWidth = this.get('border-box-width');
- if (bWidth <= 0) return 0;
+ if (bWidth <= 0) {
+ if (!this._preComputing) this._end();
+ return 0;
+ }
var bLeft = this.get('border-left'),
bRight = this.get('border-right');
@@ -3552,11 +3486,17 @@ Element.addMethods({
},
'border-box-height': function(element) {
- return element.offsetHeight;
+ if (!this._preComputing) this._begin();
+ var height = element.offsetHeight;
+ if (!this._preComputing) this._end();
+ return height;
},
'border-box-width': function(element) {
- return element.offsetWidth;
+ if (!this._preComputing) this._begin();
+ var width = element.offsetWidth;
+ if (!this._preComputing) this._end();
+ return width;
},
'margin-box-height': function(element) {
@@ -3626,23 +3566,19 @@ Element.addMethods({
},
'border-top': function(element) {
- return Object.isNumber(element.clientTop) ? element.clientTop :
- getPixelValue(element, 'borderTopWidth');
+ return getPixelValue(element, 'borderTopWidth');
},
'border-bottom': function(element) {
- return Object.isNumber(element.clientBottom) ? element.clientBottom :
- getPixelValue(element, 'borderBottomWidth');
+ return getPixelValue(element, 'borderBottomWidth');
},
'border-left': function(element) {
- return Object.isNumber(element.clientLeft) ? element.clientLeft :
- getPixelValue(element, 'borderLeftWidth');
+ return getPixelValue(element, 'borderLeftWidth');
},
'border-right': function(element) {
- return Object.isNumber(element.clientRight) ? element.clientRight :
- getPixelValue(element, 'borderRightWidth');
+ return getPixelValue(element, 'borderRightWidth');
},
'margin-top': function(element) {
@@ -3721,23 +3657,52 @@ Element.addMethods({
}
function getDimensions(element) {
- var layout = $(element).getLayout();
- return {
- width: layout.get('width'),
- height: layout.get('height')
+ element = $(element);
+ var display = Element.getStyle(element, 'display');
+
+ if (display && display !== 'none') {
+ return { width: element.offsetWidth, height: element.offsetHeight };
+ }
+
+ var style = element.style;
+ var originalStyles = {
+ visibility: style.visibility,
+ position: style.position,
+ display: style.display
+ };
+
+ var newStyles = {
+ visibility: 'hidden',
+ display: 'block'
};
+
+ if (originalStyles.position !== 'fixed')
+ newStyles.position = 'absolute';
+
+ Element.setStyle(element, newStyles);
+
+ var dimensions = {
+ width: element.offsetWidth,
+ height: element.offsetHeight
+ };
+
+ Element.setStyle(element, originalStyles);
+
+ return dimensions;
}
function getOffsetParent(element) {
- if (isDetached(element)) return $(document.body);
+ element = $(element);
+
+ if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
+ return $(document.body);
var isInline = (Element.getStyle(element, 'display') === 'inline');
if (!isInline && element.offsetParent) return $(element.offsetParent);
- if (element === document.body) return $(element);
while ((element = element.parentNode) && element !== document.body) {
if (Element.getStyle(element, 'position') !== 'static') {
- return (element.nodeName === 'HTML') ? $(document.body) : $(element);
+ return isHtml(element) ? $(document.body) : $(element);
}
}
@@ -3746,16 +3711,21 @@ Element.addMethods({
function cumulativeOffset(element) {
+ element = $(element);
var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- element = element.offsetParent;
- } while (element);
+ if (element.parentNode) {
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ }
return new Element.Offset(valueL, valueT);
}
function positionedOffset(element) {
+ element = $(element);
+
var layout = element.getLayout();
var valueT = 0, valueL = 0;
@@ -3787,6 +3757,7 @@ Element.addMethods({
}
function viewportOffset(forElement) {
+ element = $(element);
var valueT = 0, valueL = 0, docBody = document.body;
var element = forElement;
@@ -3852,6 +3823,57 @@ Element.addMethods({
return element;
}
+ if (Prototype.Browser.IE) {
+ getOffsetParent = getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+
+ if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element))
+ return $(document.body);
+
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ }
+ );
+
+ positionedOffset = positionedOffset.wrap(function(proceed, element) {
+ element = $(element);
+ if (!element.parentNode) return new Element.Offset(0, 0);
+ var position = element.getStyle('position');
+ if (position !== 'static') return proceed(element);
+
+ var offsetParent = element.getOffsetParent();
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
+ hasLayout(offsetParent);
+
+ element.setStyle({ position: 'relative' });
+ var value = proceed(element);
+ element.setStyle({ position: position });
+ return value;
+ });
+ } else if (Prototype.Browser.Webkit) {
+ cumulativeOffset = function(element) {
+ element = $(element);
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ if (element.offsetParent == document.body)
+ if (Element.getStyle(element, 'position') == 'absolute') break;
+
+ element = element.offsetParent;
+ } while (element);
+
+ return new Element.Offset(valueL, valueT);
+ };
+ }
+
+
Element.addMethods({
getLayout: getLayout,
measure: measure,
@@ -3869,6 +3891,14 @@ Element.addMethods({
return element.nodeName.toUpperCase() === 'BODY';
}
+ function isHtml(element) {
+ return element.nodeName.toUpperCase() === 'HTML';
+ }
+
+ function isDocument(element) {
+ return element.nodeType === Node.DOCUMENT_NODE;
+ }
+
function isDetached(element) {
return element !== document.body &&
!Element.descendantOf(element, document.body);
@@ -3880,32 +3910,10 @@ Element.addMethods({
element = $(element);
if (isDetached(element)) return new Element.Offset(0, 0);
- var rect = element.getBoundingClientRect(),
+ var rect = element.getBoundingClientRect(),
docEl = document.documentElement;
return new Element.Offset(rect.left - docEl.clientLeft,
rect.top - docEl.clientTop);
- },
-
- positionedOffset: function(element) {
- element = $(element);
- var parent = element.getOffsetParent();
- if (isDetached(element)) return new Element.Offset(0, 0);
-
- if (element.offsetParent &&
- element.offsetParent.nodeName.toUpperCase() === 'HTML') {
- return positionedOffset(element);
- }
-
- var eOffset = element.viewportOffset(),
- pOffset = isBody(parent) ? viewportOffset(parent) :
- parent.viewportOffset();
- var retOffset = eOffset.relativeTo(pOffset);
-
- var layout = element.getLayout();
- var top = retOffset.top - layout.get('margin-top');
- var left = retOffset.left - layout.get('margin-left');
-
- return new Element.Offset(left, top);
}
});
}
@@ -4962,24 +4970,34 @@ var Form = {
serializeElements: function(elements, options) {
if (typeof options != 'object') options = { hash: !!options };
else if (Object.isUndefined(options.hash)) options.hash = true;
- var key, value, submitted = false, submit = options.submit;
+ var key, value, submitted = false, submit = options.submit, accumulator, initial;
+
+ if (options.hash) {
+ initial = {};
+ accumulator = function(result, key, value) {
+ if (key in result) {
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
+ result[key].push(value);
+ } else result[key] = value;
+ return result;
+ };
+ } else {
+ initial = '';
+ accumulator = function(result, key, value) {
+ return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + encodeURIComponent(value);
+ }
+ }
- var data = elements.inject({ }, function(result, element) {
+ return elements.inject(initial, function(result, element) {
if (!element.disabled && element.name) {
key = element.name; value = $(element).getValue();
if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
submit !== false && (!submit || key == submit) && (submitted = true)))) {
- if (key in result) {
- if (!Object.isArray(result[key])) result[key] = [result[key]];
- result[key].push(value);
- }
- else result[key] = value;
+ result = accumulator(result, key, value);
}
}
return result;
});
-
- return options.hash ? data : Object.toQueryString(data);
}
};
@@ -5046,7 +5064,8 @@ Form.Methods = {
focusFirstElement: function(form) {
form = $(form);
- form.findFirstElement().activate();
+ var element = form.findFirstElement();
+ if (element) element.activate();
return form;
},
@@ -5153,67 +5172,77 @@ var $F = Form.Element.Methods.getValue;
/*--------------------------------------------------------------------------*/
-Form.Element.Serializers = {
- input: function(element, value) {
+Form.Element.Serializers = (function() {
+ function input(element, value) {
switch (element.type.toLowerCase()) {
case 'checkbox':
case 'radio':
- return Form.Element.Serializers.inputSelector(element, value);
+ return inputSelector(element, value);
default:
- return Form.Element.Serializers.textarea(element, value);
+ return valueSelector(element, value);
}
- },
+ }
- inputSelector: function(element, value) {
- if (Object.isUndefined(value)) return element.checked ? element.value : null;
+ function inputSelector(element, value) {
+ if (Object.isUndefined(value))
+ return element.checked ? element.value : null;
else element.checked = !!value;
- },
+ }
- textarea: function(element, value) {
+ function valueSelector(element, value) {
if (Object.isUndefined(value)) return element.value;
else element.value = value;
- },
+ }
- select: function(element, value) {
+ function select(element, value) {
if (Object.isUndefined(value))
- return this[element.type == 'select-one' ?
- 'selectOne' : 'selectMany'](element);
- else {
- var opt, currentValue, single = !Object.isArray(value);
- for (var i = 0, length = element.length; i < length; i++) {
- opt = element.options[i];
- currentValue = this.optionValue(opt);
- if (single) {
- if (currentValue == value) {
- opt.selected = true;
- return;
- }
+ return (element.type === 'select-one' ? selectOne : selectMany)(element);
+
+ var opt, currentValue, single = !Object.isArray(value);
+ for (var i = 0, length = element.length; i < length; i++) {
+ opt = element.options[i];
+ currentValue = this.optionValue(opt);
+ if (single) {
+ if (currentValue == value) {
+ opt.selected = true;
+ return;
}
- else opt.selected = value.include(currentValue);
}
+ else opt.selected = value.include(currentValue);
}
- },
+ }
- selectOne: function(element) {
+ function selectOne(element) {
var index = element.selectedIndex;
- return index >= 0 ? this.optionValue(element.options[index]) : null;
- },
+ return index >= 0 ? optionValue(element.options[index]) : null;
+ }
- selectMany: function(element) {
+ function selectMany(element) {
var values, length = element.length;
if (!length) return null;
for (var i = 0, values = []; i < length; i++) {
var opt = element.options[i];
- if (opt.selected) values.push(this.optionValue(opt));
+ if (opt.selected) values.push(optionValue(opt));
}
return values;
- },
+ }
- optionValue: function(opt) {
- return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
+ function optionValue(opt) {
+ return Element.hasAttribute(opt, 'value') ? opt.value : opt.text;
}
-};
+
+ return {
+ input: input,
+ inputSelector: inputSelector,
+ textarea: valueSelector,
+ select: select,
+ selectOne: selectOne,
+ selectMany: selectMany,
+ optionValue: optionValue,
+ button: valueSelector
+ };
+})();
/*--------------------------------------------------------------------------*/
@@ -5324,24 +5353,53 @@ Form.EventObserver = Class.create(Abstract.EventObserver, {
var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl
&& 'onmouseleave' in docEl;
+
+
+ var isIELegacyEvent = function(event) { return false; };
+
+ if (window.attachEvent) {
+ if (window.addEventListener) {
+ isIELegacyEvent = function(event) {
+ return !(event instanceof window.Event);
+ };
+ } else {
+ isIELegacyEvent = function(event) { return true; };
+ }
+ }
+
var _isButton;
- if (Prototype.Browser.IE) {
- var buttonMap = { 0: 1, 1: 4, 2: 2 };
- _isButton = function(event, code) {
- return event.button === buttonMap[code];
- };
- } else if (Prototype.Browser.WebKit) {
- _isButton = function(event, code) {
- switch (code) {
- case 0: return event.which == 1 && !event.metaKey;
- case 1: return event.which == 1 && event.metaKey;
- default: return false;
+
+ function _isButtonForDOMEvents(event, code) {
+ return event.which ? (event.which === code + 1) : (event.button === code);
+ }
+
+ var legacyButtonMap = { 0: 1, 1: 4, 2: 2 };
+ function _isButtonForLegacyEvents(event, code) {
+ return event.button === legacyButtonMap[code];
+ }
+
+ function _isButtonForWebKit(event, code) {
+ switch (code) {
+ case 0: return event.which == 1 && !event.metaKey;
+ case 1: return event.which == 2 || (event.which == 1 && event.metaKey);
+ case 2: return event.which == 3;
+ default: return false;
+ }
+ }
+
+ if (window.attachEvent) {
+ if (!window.addEventListener) {
+ _isButton = _isButtonForLegacyEvents;
+ } else {
+ _isButton = function(event, code) {
+ return isIELegacyEvent(event) ? _isButtonForLegacyEvents(event, code) :
+ _isButtonForDOMEvents(event, code);
}
- };
+ }
+ } else if (Prototype.Browser.WebKit) {
+ _isButton = _isButtonForWebKit;
} else {
- _isButton = function(event, code) {
- return event.which ? (event.which === code + 1) : (event.button === code);
- };
+ _isButton = _isButtonForDOMEvents;
}
function isLeftClick(event) { return _isButton(event, 0) }
@@ -5371,6 +5429,7 @@ Form.EventObserver = Class.create(Abstract.EventObserver, {
function findElement(event, expression) {
var element = Event.element(event);
+
if (!expression) return element;
while (element) {
if (Object.isElement(element) && Prototype.Selector.match(element, expression)) {
@@ -5411,49 +5470,59 @@ Form.EventObserver = Class.create(Abstract.EventObserver, {
event.stopped = true;
}
+
Event.Methods = {
- isLeftClick: isLeftClick,
+ isLeftClick: isLeftClick,
isMiddleClick: isMiddleClick,
- isRightClick: isRightClick,
+ isRightClick: isRightClick,
- element: element,
+ element: element,
findElement: findElement,
- pointer: pointer,
+ pointer: pointer,
pointerX: pointerX,
pointerY: pointerY,
stop: stop
};
-
var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
m[name] = Event.Methods[name].methodize();
return m;
});
- if (Prototype.Browser.IE) {
+ if (window.attachEvent) {
function _relatedTarget(event) {
var element;
switch (event.type) {
- case 'mouseover': element = event.fromElement; break;
- case 'mouseout': element = event.toElement; break;
- default: return null;
+ case 'mouseover':
+ case 'mouseenter':
+ element = event.fromElement;
+ break;
+ case 'mouseout':
+ case 'mouseleave':
+ element = event.toElement;
+ break;
+ default:
+ return null;
}
return Element.extend(element);
}
- Object.extend(methods, {
+ var additionalMethods = {
stopPropagation: function() { this.cancelBubble = true },
preventDefault: function() { this.returnValue = false },
inspect: function() { return '[object Event]' }
- });
+ };
Event.extend = function(event, element) {
if (!event) return false;
- if (event._extendedByPrototype) return event;
+ if (!isIELegacyEvent(event)) return event;
+
+ if (event._extendedByPrototype) return event;
event._extendedByPrototype = Prototype.emptyFunction;
+
var pointer = Event.pointer(event);
Object.extend(event, {
@@ -5463,12 +5532,18 @@ Form.EventObserver = Class.create(Abstract.EventObserver, {
pageY: pointer.y
});
- return Object.extend(event, methods);
+ Object.extend(event, methods);
+ Object.extend(event, additionalMethods);
+
+ return event;
};
} else {
+ Event.extend = Prototype.K;
+ }
+
+ if (window.addEventListener) {
Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__;
Object.extend(Event.prototype, methods);
- Event.extend = Prototype.K;
}
function _createResponder(element, eventName, handler) {
@@ -5567,7 +5642,7 @@ Form.EventObserver = Class.create(Abstract.EventObserver, {
element.addEventListener("dataavailable", responder, false);
else {
element.attachEvent("ondataavailable", responder);
- element.attachEvent("onfilterchange", responder);
+ element.attachEvent("onlosecapture", responder);
}
} else {
var actualEventName = _getDOMEventName(eventName);
@@ -5605,7 +5680,13 @@ Form.EventObserver = Class.create(Abstract.EventObserver, {
return element;
}
- var responder = responders.find( function(r) { return r.handler === handler; });
+ var i = responders.length, responder;
+ while (i--) {
+ if (responders[i].handler === handler) {
+ responder = responders[i];
+ break;
+ }
+ }
if (!responder) return element;
if (eventName.include(':')) {
@@ -5613,7 +5694,7 @@ Form.EventObserver = Class.create(Abstract.EventObserver, {
element.removeEventListener("dataavailable", responder, false);
else {
element.detachEvent("ondataavailable", responder);
- element.detachEvent("onfilterchange", responder);
+ element.detachEvent("onlosecapture", responder);
}
} else {
var actualEventName = _getDOMEventName(eventName);
@@ -5640,10 +5721,10 @@ Form.EventObserver = Class.create(Abstract.EventObserver, {
var event;
if (document.createEvent) {
event = document.createEvent('HTMLEvents');
- event.initEvent('dataavailable', true, true);
+ event.initEvent('dataavailable', bubble, true);
} else {
event = document.createEventObject();
- event.eventType = bubble ? 'ondataavailable' : 'onfilterchange';
+ event.eventType = bubble ? 'ondataavailable' : 'onlosecapture';
}
event.eventName = eventName;
@@ -5677,7 +5758,7 @@ Form.EventObserver = Class.create(Abstract.EventObserver, {
},
handleEvent: function(event) {
- var element = event.findElement(this.selector);
+ var element = Event.findElement(event, this.selector);
if (element) this.callback.call(this.element, event, element);
}
});
diff --git a/railties/lib/rails/generators/rails/plugin/templates/Rakefile.tt b/railties/lib/rails/generators/rails/plugin/templates/Rakefile.tt
index 733e321c94..77149ae351 100644
--- a/railties/lib/rails/generators/rails/plugin/templates/Rakefile.tt
+++ b/railties/lib/rails/generators/rails/plugin/templates/Rakefile.tt
@@ -1,4 +1,4 @@
-require 'rake'
+#!/usr/bin/env rake
require 'rake/testtask'
require 'rake/rdoctask'
diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile b/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile
index 88f50f9f04..12350309bf 100644..100755
--- a/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile
+++ b/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile
@@ -1,12 +1,10 @@
-# encoding: UTF-8
-require 'rubygems'
+#!/usr/bin/env rake
begin
require 'bundler/setup'
rescue LoadError
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
end
-require 'rake'
require 'rake/rdoctask'
Rake::RDocTask.new(:rdoc) do |rdoc|
diff --git a/railties/lib/rails/railtie.rb b/railties/lib/rails/railtie.rb
index c76bc83377..030a838dc1 100644
--- a/railties/lib/rails/railtie.rb
+++ b/railties/lib/rails/railtie.rb
@@ -97,7 +97,7 @@ module Rails
# If your railtie has rake tasks, you can tell Rails to load them through the method
# rake tasks:
#
- # class MyRailtie < Railtie
+ # class MyRailtie < Rails::Railtie
# rake_tasks do
# load "path/to/my_railtie.tasks"
# end
@@ -107,7 +107,7 @@ module Rails
# your generators at a different location, you can specify in your Railtie a block which
# will load them during normal generators lookup:
#
- # class MyRailtie < Railtie
+ # class MyRailtie < Rails::Railtie
# generators do
# require "path/to/my_railtie_generator"
# end
diff --git a/railties/lib/rails/test_help.rb b/railties/lib/rails/test_help.rb
index 38f2f651f4..f81002328f 100644
--- a/railties/lib/rails/test_help.rb
+++ b/railties/lib/rails/test_help.rb
@@ -39,14 +39,3 @@ class ActionDispatch::IntegrationTest
@routes = Rails.application.routes
end
end
-
-begin
- require_library_or_gem 'ruby-debug'
- Debugger.start
- if Debugger.respond_to?(:settings)
- Debugger.settings[:autoeval] = true
- Debugger.settings[:autolist] = 1
- end
-rescue LoadError
- # ruby-debug wasn't available so neither can the debugging be
-end
diff --git a/railties/test/application/generators_test.rb b/railties/test/application/generators_test.rb
index 3a3e28179a..8b840fffd0 100644
--- a/railties/test/application/generators_test.rb
+++ b/railties/test/application/generators_test.rb
@@ -26,17 +26,10 @@ module ApplicationTests
end
test "allow running plugin new generator inside Rails app directory" do
- FileUtils.cd rails_root
- `./script/rails plugin new vendor/plugins/bukkits`
+ FileUtils.cd(rails_root){ `ruby script/rails plugin new vendor/plugins/bukkits` }
assert File.exist?(File.join(rails_root, "vendor/plugins/bukkits/test/dummy/config/application.rb"))
end
- test "don't allow running plugin_new generator as a generator" do
- FileUtils.cd rails_root
- output = `./script/rails g plugin_new vendor/plugins/bukkits`
- assert_match /This generator should not be used directly as a generator. You should use `rails plugin new` command instead/, output
- end
-
test "generators default values" do
with_bare_config do |c|
assert_equal(true, c.generators.colorize_logging)
diff --git a/railties/test/application/initializers/frameworks_test.rb b/railties/test/application/initializers/frameworks_test.rb
index 6970ea7b7a..475091f789 100644
--- a/railties/test/application/initializers/frameworks_test.rb
+++ b/railties/test/application/initializers/frameworks_test.rb
@@ -65,6 +65,66 @@ module ApplicationTests
assert_equal ["notify"], Foo.action_methods
end
+ test "allows to not load all helpers for controllers" do
+ add_to_config "config.action_controller.include_all_helpers = false"
+
+ app_file "app/controllers/application_controller.rb", <<-RUBY
+ class ApplicationController < ActionController::Base
+ end
+ RUBY
+
+ app_file "app/controllers/foo_controller.rb", <<-RUBY
+ class FooController < ApplicationController
+ def included_helpers
+ render :inline => "<%= from_app_helper -%> <%= from_foo_helper %>"
+ end
+
+ def not_included_helper
+ render :inline => "<%= respond_to?(:from_bar_helper) -%>"
+ end
+ end
+ RUBY
+
+ app_file "app/helpers/application_helper.rb", <<-RUBY
+ module ApplicationHelper
+ def from_app_helper
+ "from_app_helper"
+ end
+ end
+ RUBY
+
+ app_file "app/helpers/foo_helper.rb", <<-RUBY
+ module FooHelper
+ def from_foo_helper
+ "from_foo_helper"
+ end
+ end
+ RUBY
+
+ app_file "app/helpers/bar_helper.rb", <<-RUBY
+ module BarHelper
+ def from_bar_helper
+ "from_bar_helper"
+ end
+ end
+ RUBY
+
+ app_file "config/routes.rb", <<-RUBY
+ AppTemplate::Application.routes.draw do
+ match "/:controller(/:action)"
+ end
+ RUBY
+
+ require 'rack/test'
+ extend Rack::Test::Methods
+
+ get "/foo/included_helpers"
+ assert_equal "from_app_helper from_foo_helper", last_response.body
+
+ get "/foo/not_included_helper"
+ assert_equal "false", last_response.body
+ end
+
# AD
test "action_dispatch extensions are applied to ActionDispatch" do
add_to_config "config.action_dispatch.tld_length = 2"
diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb
index 719550f9d9..23cd2378c7 100644
--- a/railties/test/application/rake_test.rb
+++ b/railties/test/application/rake_test.rb
@@ -34,6 +34,22 @@ module ApplicationTests
assert_match "SuperMiddleware", Dir.chdir(app_path){ `rake middleware` }
end
+ def test_initializers_are_executed_in_rake_tasks
+ add_to_config <<-RUBY
+ initializer "do_something" do
+ puts "Doing something..."
+ end
+
+ rake_tasks do
+ task :do_nothing => :environment do
+ end
+ end
+ RUBY
+
+ output = Dir.chdir(app_path){ `rake do_nothing` }
+ assert_match "Doing something...", output
+ end
+
def test_code_statistics_sanity
assert_match "Code LOC: 5 Test LOC: 0 Code to Test Ratio: 1:0.0",
Dir.chdir(app_path){ `rake stats` }
diff --git a/railties/test/generators/migration_generator_test.rb b/railties/test/generators/migration_generator_test.rb
index f9d1e42d24..288ec30460 100644
--- a/railties/test/generators/migration_generator_test.rb
+++ b/railties/test/generators/migration_generator_test.rb
@@ -34,12 +34,12 @@ class MigrationGeneratorTest < Rails::Generators::TestCase
run_generator [migration, "title:string", "body:text"]
assert_migration "db/migrate/#{migration}.rb" do |content|
- assert_class_method :up, content do |up|
+ assert_method :up, content do |up|
assert_match /add_column :posts, :title, :string/, up
assert_match /add_column :posts, :body, :text/, up
end
- assert_class_method :down, content do |down|
+ assert_method :down, content do |down|
assert_match /remove_column :posts, :title/, down
assert_match /remove_column :posts, :body/, down
end
@@ -51,12 +51,12 @@ class MigrationGeneratorTest < Rails::Generators::TestCase
run_generator [migration, "title:string", "body:text"]
assert_migration "db/migrate/#{migration}.rb" do |content|
- assert_class_method :up, content do |up|
+ assert_method :up, content do |up|
assert_match /remove_column :posts, :title/, up
assert_match /remove_column :posts, :body/, up
end
- assert_class_method :down, content do |down|
+ assert_method :down, content do |down|
assert_match /add_column :posts, :title, :string/, down
assert_match /add_column :posts, :body, :text/, down
end
@@ -68,11 +68,11 @@ class MigrationGeneratorTest < Rails::Generators::TestCase
run_generator [migration, "title:string", "content:text"]
assert_migration "db/migrate/#{migration}.rb" do |content|
- assert_class_method :up, content do |up|
+ assert_method :up, content do |up|
assert_match /^\s*$/, up
end
- assert_class_method :down, content do |down|
+ assert_method :down, content do |down|
assert_match /^\s*$/, down
end
end
diff --git a/railties/test/generators/model_generator_test.rb b/railties/test/generators/model_generator_test.rb
index 52e08cf2dd..8a0f560bc8 100644
--- a/railties/test/generators/model_generator_test.rb
+++ b/railties/test/generators/model_generator_test.rb
@@ -99,13 +99,13 @@ class ModelGeneratorTest < Rails::Generators::TestCase
run_generator ["product", "name:string", "supplier_id:integer"]
assert_migration "db/migrate/create_products.rb" do |m|
- assert_class_method :up, m do |up|
+ assert_method :up, m do |up|
assert_match /create_table :products/, up
assert_match /t\.string :name/, up
assert_match /t\.integer :supplier_id/, up
end
- assert_class_method :down, m do |down|
+ assert_method :down, m do |down|
assert_match /drop_table :products/, down
end
end
@@ -141,7 +141,7 @@ class ModelGeneratorTest < Rails::Generators::TestCase
run_generator ["account", "--no-timestamps"]
assert_migration "db/migrate/create_accounts.rb" do |m|
- assert_class_method :up, m do |up|
+ assert_method :up, m do |up|
assert_no_match /t.timestamps/, up
end
end
diff --git a/railties/test/generators_test.rb b/railties/test/generators_test.rb
index f93800a5ae..346c9ceb9d 100644
--- a/railties/test/generators_test.rb
+++ b/railties/test/generators_test.rb
@@ -102,6 +102,12 @@ class GeneratorsTest < Rails::Generators::TestCase
assert_no_match /^ app$/, output
end
+ def test_rails_generators_help_does_not_include_app_nor_plugin_new
+ output = capture(:stdout){ Rails::Generators.help }
+ assert_no_match /app/, output
+ assert_no_match /plugin_new/, output
+ end
+
def test_rails_generators_with_others_information
output = capture(:stdout){ Rails::Generators.help }
assert_match /Fixjour:/, output
diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb
index 701b6816c8..7548c6318e 100644
--- a/railties/test/railties/engine_test.rb
+++ b/railties/test/railties/engine_test.rb
@@ -683,5 +683,24 @@ module RailtiesTest
app_generators = Rails.application.config.generators.options[:rails]
assert_equal :test_unit , app_generators[:test_framework]
end
+
+ test "do not create table_name_prefix method if it already exists" do
+ @plugin.write "lib/bukkits.rb", <<-RUBY
+ module Bukkits
+ def self.table_name_prefix
+ "foo"
+ end
+
+ class Engine < ::Rails::Engine
+ isolate_namespace(Bukkits)
+ end
+ end
+ RUBY
+
+ boot_rails
+ require "#{rails_root}/config/environment"
+
+ assert_equal "foo", Bukkits.table_name_prefix
+ end
end
end