From 45d41f0dadd9fa171f306ff356770c4492726f30 Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Thu, 19 Jun 2008 16:25:27 +0200
Subject: integrating I18n into Rails
---
actionpack/lib/action_view.rb | 2 +
.../action_view/helpers/active_record_helper.rb | 33 +-
actionpack/lib/action_view/helpers/date_helper.rb | 81 ++--
.../lib/action_view/helpers/form_options_helper.rb | 52 +-
.../lib/action_view/helpers/number_helper.rb | 18 +-
actionpack/lib/action_view/lang/en-US.rb | 93 ++++
.../template/active_record_helper_i18n_test.rb | 47 ++
actionpack/test/template/date_helper_i18n_test.rb | 99 ++++
.../test/template/form_options_helper_i18n_test.rb | 26 +
.../test/template/number_helper_i18n_test.rb | 27 ++
activerecord/lib/active_record.rb | 2 +
activerecord/lib/active_record/lang/en-US.rb | 25 +
activerecord/lib/active_record/validations.rb | 184 ++++---
activerecord/test/cases/validations_i18n_test.rb | 539 +++++++++++++++++++++
.../active_support/core_ext/array/conversions.rb | 14 +-
activesupport/lib/active_support/vendor.rb | 7 +
activesupport/lib/active_support/vendor/i18n-0.0.1 | 1 +
17 files changed, 1082 insertions(+), 168 deletions(-)
create mode 100644 actionpack/lib/action_view/lang/en-US.rb
create mode 100644 actionpack/test/template/active_record_helper_i18n_test.rb
create mode 100644 actionpack/test/template/date_helper_i18n_test.rb
create mode 100644 actionpack/test/template/form_options_helper_i18n_test.rb
create mode 100644 actionpack/test/template/number_helper_i18n_test.rb
create mode 100644 activerecord/lib/active_record/lang/en-US.rb
create mode 100644 activerecord/test/cases/validations_i18n_test.rb
create mode 160000 activesupport/lib/active_support/vendor/i18n-0.0.1
diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb
index 973020a768..33d50a61c4 100644
--- a/actionpack/lib/action_view.rb
+++ b/actionpack/lib/action_view.rb
@@ -32,6 +32,8 @@ require 'action_view/base'
require 'action_view/partials'
require 'action_view/template_error'
+require 'action_view/lang/en-US.rb'
+
ActionView::Base.class_eval do
include ActionView::Partials
diff --git a/actionpack/lib/action_view/helpers/active_record_helper.rb b/actionpack/lib/action_view/helpers/active_record_helper.rb
index f3f204cc97..5ad9d5f76d 100644
--- a/actionpack/lib/action_view/helpers/active_record_helper.rb
+++ b/actionpack/lib/action_view/helpers/active_record_helper.rb
@@ -151,12 +151,17 @@ module ActionView
# instance yourself and set it up. View the source of this method to see how easy it is.
def error_messages_for(*params)
options = params.extract_options!.symbolize_keys
+
if object = options.delete(:object)
objects = [object].flatten
else
objects = params.collect {|object_name| instance_variable_get("@#{object_name}") }.compact
end
- count = objects.inject(0) {|sum, object| sum + object.errors.count }
+
+ count = objects.inject(0) {|sum, object| sum + object.errors.count }
+ locale = options[:locale]
+ locale ||= request.locale if respond_to?(:request)
+
unless count.zero?
html = {}
[:id, :class].each do |key|
@@ -168,21 +173,29 @@ module ActionView
end
end
options[:object_name] ||= params.first
- options[:header_message] = "#{pluralize(count, 'error')} prohibited this #{options[:object_name].to_s.gsub('_', ' ')} from being saved" unless options.include?(:header_message)
- options[:message] ||= 'There were problems with the following fields:' unless options.include?(:message)
- error_messages = objects.sum {|object| object.errors.full_messages.map {|msg| content_tag(:li, msg) } }.join
- contents = ''
- contents << content_tag(options[:header_tag] || :h2, options[:header_message]) unless options[:header_message].blank?
- contents << content_tag(:p, options[:message]) unless options[:message].blank?
- contents << content_tag(:ul, error_messages)
+ I18n.with_options :locale => locale, :scope => [:active_record, :error] do |locale|
+ header_message = if options.include?(:header_message)
+ options[:header_message]
+ else
+ object_name = options[:object_name].to_s.gsub('_', ' ')
+ locale.t :header_message, :count => count, :object_name => object_name
+ end
+ message = options.include?(:message) ? options[:message] : locale.t(:message)
+ error_messages = objects.sum {|object| object.errors.full_messages.map {|msg| content_tag(:li, msg) } }.join
+
+ contents = ''
+ contents << content_tag(options[:header_tag] || :h2, header_message) unless header_message.blank?
+ contents << content_tag(:p, message) unless message.blank?
+ contents << content_tag(:ul, error_messages)
- content_tag(:div, contents, html)
+ content_tag(:div, contents, html)
+ end
else
''
end
end
-
+
private
def all_input_tags(record, record_name, options)
input_block = options[:input_block] || default_input_block
diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb
index 7ed6272898..0337be0744 100755
--- a/actionpack/lib/action_view/helpers/date_helper.rb
+++ b/actionpack/lib/action_view/helpers/date_helper.rb
@@ -58,35 +58,43 @@ module ActionView
# distance_of_time_in_words(to_time, from_time, true) # => over 6 years
# distance_of_time_in_words(Time.now, Time.now) # => less than a minute
#
- def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false)
+ def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false, options = {})
+ locale = options[:locale]
+ locale ||= request.locale if respond_to?(:request)
+
from_time = from_time.to_time if from_time.respond_to?(:to_time)
to_time = to_time.to_time if to_time.respond_to?(:to_time)
distance_in_minutes = (((to_time - from_time).abs)/60).round
distance_in_seconds = ((to_time - from_time).abs).round
- case distance_in_minutes
- when 0..1
- return (distance_in_minutes == 0) ? 'less than a minute' : '1 minute' unless include_seconds
- case distance_in_seconds
- when 0..4 then 'less than 5 seconds'
- when 5..9 then 'less than 10 seconds'
- when 10..19 then 'less than 20 seconds'
- when 20..39 then 'half a minute'
- when 40..59 then 'less than a minute'
- else '1 minute'
- end
+ I18n.with_options :locale => locale, :scope => :'datetime.distance_in_words' do |locale|
+ case distance_in_minutes
+ when 0..1
+ return distance_in_minutes == 0 ?
+ locale.t(:less_than_x_minutes, :count => 1) :
+ locale.t(:x_minutes, :count => distance_in_minutes) unless include_seconds
+
+ case distance_in_seconds
+ when 0..4 then locale.t :less_than_x_seconds, :count => 5
+ when 5..9 then locale.t :less_than_x_seconds, :count => 10
+ when 10..19 then locale.t :less_than_x_seconds, :count => 20
+ when 20..39 then locale.t :half_a_minute
+ when 40..59 then locale.t :less_than_x_minutes, :count => 1
+ else locale.t :x_minutes, :count => 1
+ end
- when 2..44 then "#{distance_in_minutes} minutes"
- when 45..89 then 'about 1 hour'
- when 90..1439 then "about #{(distance_in_minutes.to_f / 60.0).round} hours"
- when 1440..2879 then '1 day'
- when 2880..43199 then "#{(distance_in_minutes / 1440).round} days"
- when 43200..86399 then 'about 1 month'
- when 86400..525599 then "#{(distance_in_minutes / 43200).round} months"
- when 525600..1051199 then 'about 1 year'
- else "over #{(distance_in_minutes / 525600).round} years"
+ when 2..44 then locale.t :x_minutes, :count => distance_in_minutes
+ when 45..89 then locale.t :about_x_hours, :count => 1
+ when 90..1439 then locale.t :about_x_hours, :count => (distance_in_minutes.to_f / 60.0).round
+ when 1440..2879 then locale.t :x_days, :count => 1
+ when 2880..43199 then locale.t :x_days, :count => (distance_in_minutes / 1440).round
+ when 43200..86399 then locale.t :about_x_months, :count => 1
+ when 86400..525599 then locale.t :x_months, :count => (distance_in_minutes / 43200).round
+ when 525600..1051199 then locale.t :about_x_years, :count => 1
+ else locale.t :over_x_years, :count => (distance_in_minutes / 525600).round
+ end
end
- end
+ end
# Like distance_of_time_in_words, but where to_time is fixed to Time.now .
#
@@ -498,13 +506,19 @@ module ActionView
# select_month(Date.today, :use_month_names => %w(Januar Februar Marts ...))
#
def select_month(date, options = {}, html_options = {})
+ locale = options[:locale]
+ locale ||= request.locale if respond_to?(:request)
+
val = date ? (date.kind_of?(Fixnum) ? date : date.month) : ''
if options[:use_hidden]
hidden_html(options[:field_name] || 'month', val, options)
else
month_options = []
- month_names = options[:use_month_names] || (options[:use_short_month] ? Date::ABBR_MONTHNAMES : Date::MONTHNAMES)
+ month_names = options[:use_month_names] || begin
+ (options[:use_short_month] ? :'date.abbr_month_names' : :'date.month_names').t locale
+ end
month_names.unshift(nil) if month_names.size < 13
+
1.upto(12) do |month_number|
month_name = if options[:use_month_numbers]
month_number
@@ -522,7 +536,7 @@ module ActionView
end
select_html(options[:field_name] || 'month', month_options.join, options, html_options)
end
- end
+ end
# Returns a select tag with options for each of the five years on each side of the current, which is selected. The five year radius
# can be changed using the :start_year and :end_year keys in the +options+. Both ascending and descending year
@@ -612,15 +626,17 @@ module ActionView
private
def date_or_time_select(options, html_options = {})
+ locale = options[:locale]
+
defaults = { :discard_type => true }
options = defaults.merge(options)
datetime = value(object)
datetime ||= default_time_from_options(options[:default]) unless options[:include_blank]
-
+
position = { :year => 1, :month => 2, :day => 3, :hour => 4, :minute => 5, :second => 6 }
- order = (options[:order] ||= [:year, :month, :day])
-
+ order = options[:order] ||= :'date.order'.t(locale)
+
# Discard explicit and implicit by not being included in the :order
discard = {}
discard[:year] = true if options[:discard_year] or !order.include?(:year)
@@ -629,19 +645,19 @@ module ActionView
discard[:hour] = true if options[:discard_hour]
discard[:minute] = true if options[:discard_minute] or discard[:hour]
discard[:second] = true unless options[:include_seconds] && !discard[:minute]
-
+
# If the day is hidden and the month is visible, the day should be set to the 1st so all month choices are valid
# (otherwise it could be 31 and february wouldn't be a valid date)
if datetime && discard[:day] && !discard[:month]
datetime = datetime.change(:day => 1)
end
-
+
# Maintain valid dates by including hidden fields for discarded elements
[:day, :month, :year].each { |o| order.unshift(o) unless order.include?(o) }
-
+
# Ensure proper ordering of :hour, :minute and :second
[:hour, :minute, :second].each { |o| order.delete(o); order.push(o) }
-
+
date_or_time_select = ''
order.reverse.each do |param|
# Send hidden fields for discarded elements once output has started
@@ -656,9 +672,8 @@ module ActionView
when :second then options[:include_seconds] ? " : " : ""
else ""
end)
-
end
-
+
date_or_time_select
end
diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb
index b3f8e63c1b..c782c0a816 100644
--- a/actionpack/lib/action_view/helpers/form_options_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -276,16 +276,25 @@ module ActionView
# that they will be listed above the rest of the (long) list.
#
# NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag.
- def country_options_for_select(selected = nil, priority_countries = nil)
+ def country_options_for_select(*args)
+ options = args.extract_options!
+
+ locale = options[:locale]
+ locale ||= request.locale if respond_to?(:request)
+
+ selected, priority_countries = *args
+ countries = :'countries.names'.t options[:locale]
country_options = ""
if priority_countries
+ # TODO priority_countries need to be translated?
country_options += options_for_select(priority_countries, selected)
country_options += "------------- \n"
end
- return country_options + options_for_select(COUNTRIES, selected)
+ return country_options + options_for_select(countries, selected)
end
+
# Returns a string of option tags for pretty much any time zone in the
# world. Supply a TimeZone name as +selected+ to have it marked as the
@@ -340,43 +349,8 @@ module ActionView
end
# All the countries included in the country_options output.
- COUNTRIES = ["Afghanistan", "Aland Islands", "Albania", "Algeria", "American Samoa", "Andorra", "Angola",
- "Anguilla", "Antarctica", "Antigua And Barbuda", "Argentina", "Armenia", "Aruba", "Australia", "Austria",
- "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin",
- "Bermuda", "Bhutan", "Bolivia", "Bosnia and Herzegowina", "Botswana", "Bouvet Island", "Brazil",
- "British Indian Ocean Territory", "Brunei Darussalam", "Bulgaria", "Burkina Faso", "Burundi", "Cambodia",
- "Cameroon", "Canada", "Cape Verde", "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
- "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
- "Congo, the Democratic Republic of the", "Cook Islands", "Costa Rica", "Cote d'Ivoire", "Croatia", "Cuba",
- "Cyprus", "Czech Republic", "Denmark", "Djibouti", "Dominica", "Dominican Republic", "Ecuador", "Egypt",
- "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Falkland Islands (Malvinas)",
- "Faroe Islands", "Fiji", "Finland", "France", "French Guiana", "French Polynesia",
- "French Southern Territories", "Gabon", "Gambia", "Georgia", "Germany", "Ghana", "Gibraltar", "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guernsey", "Guinea",
- "Guinea-Bissau", "Guyana", "Haiti", "Heard and McDonald Islands", "Holy See (Vatican City State)",
- "Honduras", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Iran, Islamic Republic of", "Iraq",
- "Ireland", "Isle of Man", "Israel", "Italy", "Jamaica", "Japan", "Jersey", "Jordan", "Kazakhstan", "Kenya",
- "Kiribati", "Korea, Democratic People's Republic of", "Korea, Republic of", "Kuwait", "Kyrgyzstan",
- "Lao People's Democratic Republic", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libyan Arab Jamahiriya",
- "Liechtenstein", "Lithuania", "Luxembourg", "Macao", "Macedonia, The Former Yugoslav Republic Of",
- "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Martinique",
- "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia, Federated States of", "Moldova, Republic of",
- "Monaco", "Mongolia", "Montenegro", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia", "Nauru",
- "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand", "Nicaragua", "Niger",
- "Nigeria", "Niue", "Norfolk Island", "Northern Mariana Islands", "Norway", "Oman", "Pakistan", "Palau",
- "Palestinian Territory, Occupied", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines",
- "Pitcairn", "Poland", "Portugal", "Puerto Rico", "Qatar", "Reunion", "Romania", "Russian Federation",
- "Rwanda", "Saint Barthelemy", "Saint Helena", "Saint Kitts and Nevis", "Saint Lucia",
- "Saint Pierre and Miquelon", "Saint Vincent and the Grenadines", "Samoa", "San Marino",
- "Sao Tome and Principe", "Saudi Arabia", "Senegal", "Serbia", "Seychelles", "Sierra Leone", "Singapore",
- "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa",
- "South Georgia and the South Sandwich Islands", "Spain", "Sri Lanka", "Sudan", "Suriname",
- "Svalbard and Jan Mayen", "Swaziland", "Sweden", "Switzerland", "Syrian Arab Republic",
- "Taiwan, Province of China", "Tajikistan", "Tanzania, United Republic of", "Thailand", "Timor-Leste",
- "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan",
- "Turks and Caicos Islands", "Tuvalu", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom",
- "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan", "Vanuatu", "Venezuela",
- "Viet Nam", "Virgin Islands, British", "Virgin Islands, U.S.", "Wallis and Futuna", "Western Sahara",
- "Yemen", "Zambia", "Zimbabwe"] unless const_defined?("COUNTRIES")
+ # only included for backwards compatibility, please use the I18n interface
+ COUNTRIES = :'countries.names'.t 'en-US' unless const_defined?("COUNTRIES")
end
class InstanceTag #:nodoc:
diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb
index 120bb4cc1f..9d98036f2d 100644
--- a/actionpack/lib/action_view/helpers/number_helper.rb
+++ b/actionpack/lib/action_view/helpers/number_helper.rb
@@ -69,13 +69,19 @@ module ActionView
# number_to_currency(1234567890.50, :unit => "£", :separator => ",", :delimiter => "", :format => "%n %u")
# # => 1234567890,50 £
def number_to_currency(number, options = {})
- options = options.stringify_keys
- precision = options["precision"] || 2
- unit = options["unit"] || "$"
- separator = precision > 0 ? options["separator"] || "." : ""
- delimiter = options["delimiter"] || ","
- format = options["format"] || "%u%n"
+ options = options.symbolize_keys
+
+ locale = options[:locale]
+ locale ||= request.locale if respond_to?(:request)
+ defaults = :'currency.format'.t(locale) || {}
+ precision = options[:precision] || defaults[:precision]
+ unit = options[:unit] || defaults[:unit]
+ separator = options[:separator] || defaults[:separator]
+ delimiter = options[:delimiter] || defaults[:delimiter]
+ format = options[:format] || defaults[:format]
+ separator = '' if precision == 0
+
begin
parts = number_with_precision(number, precision).split('.')
format.gsub(/%n/, number_with_delimiter(parts[0], delimiter) + separator + parts[1].to_s).gsub(/%u/, unit)
diff --git a/actionpack/lib/action_view/lang/en-US.rb b/actionpack/lib/action_view/lang/en-US.rb
new file mode 100644
index 0000000000..659f96a5f3
--- /dev/null
+++ b/actionpack/lib/action_view/lang/en-US.rb
@@ -0,0 +1,93 @@
+I18n.backend.add_translations :'en-US', {
+ :date => {
+ :formats => {
+ :default => "%Y-%m-%d",
+ :short => "%b %d",
+ :long => "%B %d, %Y",
+ },
+ :day_names => Date::DAYNAMES,
+ :abbr_day_names => Date::ABBR_DAYNAMES,
+ :month_names => Date::MONTHNAMES,
+ :abbr_month_names => Date::ABBR_MONTHNAMES,
+ :order => [:year, :month, :day]
+ },
+ :time => {
+ :formats => {
+ :default => "%a, %d %b %Y %H:%M:%S %z",
+ :short => "%d %b %H:%M",
+ :long => "%B %d, %Y %H:%M",
+ },
+ :am => 'am',
+ :pm => 'pm'
+ },
+ :datetime => {
+ :distance_in_words => {
+ :half_a_minute => 'half a minute',
+ :less_than_x_seconds => ['less than 1 second', 'less than {{count}} seconds'],
+ :x_seconds => ['1 second', '{{count}} seconds'],
+ :less_than_x_minutes => ['less than a minute', 'less than {{count}} minutes'],
+ :x_minutes => ['1 minute', '{{count}} minutes'],
+ :about_x_hours => ['about 1 hour', 'about {{count}} hours'],
+ :x_days => ['1 day', '{{count}} days'],
+ :about_x_months => ['about 1 month', 'about {{count}} months'],
+ :x_months => ['1 month', '{{count}} months'],
+ :about_x_years => ['about 1 year', 'about {{count}} year'],
+ :over_x_years => ['over 1 year', 'over {{count}} years']
+ }
+ },
+ :currency => {
+ :format => {
+ :unit => '$',
+ :precision => 2,
+ :separator => '.',
+ :delimiter => ',',
+ :format => '%u%n',
+ }
+ },
+ :countries => {
+ :names => ["Afghanistan", "Aland Islands", "Albania", "Algeria", "American Samoa", "Andorra", "Angola",
+ "Anguilla", "Antarctica", "Antigua And Barbuda", "Argentina", "Armenia", "Aruba", "Australia", "Austria",
+ "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin",
+ "Bermuda", "Bhutan", "Bolivia", "Bosnia and Herzegowina", "Botswana", "Bouvet Island", "Brazil",
+ "British Indian Ocean Territory", "Brunei Darussalam", "Bulgaria", "Burkina Faso", "Burundi", "Cambodia",
+ "Cameroon", "Canada", "Cape Verde", "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
+ "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
+ "Congo, the Democratic Republic of the", "Cook Islands", "Costa Rica", "Cote d'Ivoire", "Croatia", "Cuba",
+ "Cyprus", "Czech Republic", "Denmark", "Djibouti", "Dominica", "Dominican Republic", "Ecuador", "Egypt",
+ "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Falkland Islands (Malvinas)",
+ "Faroe Islands", "Fiji", "Finland", "France", "French Guiana", "French Polynesia",
+ "French Southern Territories", "Gabon", "Gambia", "Georgia", "Germany", "Ghana", "Gibraltar", "Greece",
+ "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guernsey", "Guinea",
+ "Guinea-Bissau", "Guyana", "Haiti", "Heard and McDonald Islands", "Holy See (Vatican City State)",
+ "Honduras", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Iran, Islamic Republic of", "Iraq",
+ "Ireland", "Isle of Man", "Israel", "Italy", "Jamaica", "Japan", "Jersey", "Jordan", "Kazakhstan", "Kenya",
+ "Kiribati", "Korea, Democratic People's Republic of", "Korea, Republic of", "Kuwait", "Kyrgyzstan",
+ "Lao People's Democratic Republic", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libyan Arab Jamahiriya",
+ "Liechtenstein", "Lithuania", "Luxembourg", "Macao", "Macedonia, The Former Yugoslav Republic Of",
+ "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Martinique",
+ "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia, Federated States of", "Moldova, Republic of",
+ "Monaco", "Mongolia", "Montenegro", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia", "Nauru",
+ "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand", "Nicaragua", "Niger",
+ "Nigeria", "Niue", "Norfolk Island", "Northern Mariana Islands", "Norway", "Oman", "Pakistan", "Palau",
+ "Palestinian Territory, Occupied", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines",
+ "Pitcairn", "Poland", "Portugal", "Puerto Rico", "Qatar", "Reunion", "Romania", "Russian Federation",
+ "Rwanda", "Saint Barthelemy", "Saint Helena", "Saint Kitts and Nevis", "Saint Lucia",
+ "Saint Pierre and Miquelon", "Saint Vincent and the Grenadines", "Samoa", "San Marino",
+ "Sao Tome and Principe", "Saudi Arabia", "Senegal", "Serbia", "Seychelles", "Sierra Leone", "Singapore",
+ "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa",
+ "South Georgia and the South Sandwich Islands", "Spain", "Sri Lanka", "Sudan", "Suriname",
+ "Svalbard and Jan Mayen", "Swaziland", "Sweden", "Switzerland", "Syrian Arab Republic",
+ "Taiwan, Province of China", "Tajikistan", "Tanzania, United Republic of", "Thailand", "Timor-Leste",
+ "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan",
+ "Turks and Caicos Islands", "Tuvalu", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom",
+ "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan", "Vanuatu", "Venezuela",
+ "Viet Nam", "Virgin Islands, British", "Virgin Islands, U.S.", "Wallis and Futuna", "Western Sahara",
+ "Yemen", "Zambia", "Zimbabwe"]
+ },
+ :active_record => {
+ :error => {
+ :header_message => ["1 error prohibited this {{object_name}} from being saved", "{{count}} errors prohibited this {{object_name}} from being saved"],
+ :message => "There were problems with the following fields:"
+ }
+ }
+}
diff --git a/actionpack/test/template/active_record_helper_i18n_test.rb b/actionpack/test/template/active_record_helper_i18n_test.rb
new file mode 100644
index 0000000000..057fb9bd1a
--- /dev/null
+++ b/actionpack/test/template/active_record_helper_i18n_test.rb
@@ -0,0 +1,47 @@
+require 'abstract_unit'
+
+class ActiveRecordHelperI18nTest < Test::Unit::TestCase
+ include ActionView::Helpers::ActiveRecordHelper
+
+ attr_reader :request
+ def setup
+ @request = mock
+ @object = stub :errors => stub(:count => 1, :full_messages => ['full_messages'])
+ stubs(:content_tag).returns 'content_tag'
+
+ I18n.stubs(:t).with(:'header_message', :locale => 'en-US', :scope => [:active_record, :error], :count => 1, :object_name => '').returns "1 error prohibited this from being saved"
+ I18n.stubs(:t).with(:'message', :locale => 'en-US', :scope => [:active_record, :error]).returns 'There were problems with the following fields:'
+ end
+
+ def test_error_messages_for_given_a_locale_it_does_not_check_request_for_locale
+ request.expects(:locale).never
+ @object.errors.stubs(:count).returns 0
+ error_messages_for(:object => @object, :locale => 'en-US')
+ end
+
+ def test_error_messages_for_given_no_locale_it_checks_request_for_locale
+ request.expects(:locale).returns 'en-US'
+ @object.errors.stubs(:count).returns 0
+ error_messages_for(:object => @object)
+ end
+
+ def test_error_messages_for_given_a_header_message_option_it_does_not_translate_header_message
+ I18n.expects(:translate).with(:'header_message', :locale => 'en-US', :scope => [:active_record, :error], :count => 1, :object_name => '').never
+ error_messages_for(:object => @object, :header_message => 'header message', :locale => 'en-US')
+ end
+
+ def test_error_messages_for_given_no_header_message_option_it_translates_header_message
+ I18n.expects(:t).with(:'header_message', :locale => 'en-US', :scope => [:active_record, :error], :count => 1, :object_name => '').returns 'header message'
+ error_messages_for(:object => @object, :locale => 'en-US')
+ end
+
+ def test_error_messages_for_given_a_message_option_it_does_not_translate_message
+ I18n.expects(:t).with(:'message', :locale => 'en-US', :scope => [:active_record, :error]).never
+ error_messages_for(:object => @object, :message => 'message', :locale => 'en-US')
+ end
+
+ def test_error_messages_for_given_no_message_option_it_translates_message
+ I18n.expects(:t).with(:'message', :locale => 'en-US', :scope => [:active_record, :error]).returns 'There were problems with the following fields:'
+ error_messages_for(:object => @object, :locale => 'en-US')
+ end
+end
\ No newline at end of file
diff --git a/actionpack/test/template/date_helper_i18n_test.rb b/actionpack/test/template/date_helper_i18n_test.rb
new file mode 100644
index 0000000000..9b7c03a400
--- /dev/null
+++ b/actionpack/test/template/date_helper_i18n_test.rb
@@ -0,0 +1,99 @@
+require 'abstract_unit'
+
+class DateHelperDistanceOfTimeInWordsI18nTests < Test::Unit::TestCase
+ include ActionView::Helpers::DateHelper
+ attr_reader :request
+
+ def setup
+ @request = mock
+ @from = Time.mktime(2004, 6, 6, 21, 45, 0)
+ end
+
+ # distance_of_time_in_words
+
+ def test_distance_of_time_in_words_given_a_locale_it_does_not_check_request_for_locale
+ request.expects(:locale).never
+ distance_of_time_in_words @from, @from + 1.second, false, :locale => 'en-US'
+ end
+
+ def test_distance_of_time_in_words_given_no_locale_it_checks_request_for_locale
+ request.expects(:locale).returns 'en-US'
+ distance_of_time_in_words @from, @from + 1.second
+ end
+
+ def test_distance_of_time_in_words_calls_i18n
+ { # with include_seconds
+ [2.seconds, true] => [:'less_than_x_seconds', 5],
+ [9.seconds, true] => [:'less_than_x_seconds', 10],
+ [19.seconds, true] => [:'less_than_x_seconds', 20],
+ [30.seconds, true] => [:'half_a_minute', nil],
+ [59.seconds, true] => [:'less_than_x_minutes', 1],
+ [60.seconds, true] => [:'x_minutes', 1],
+
+ # without include_seconds
+ [29.seconds, false] => [:'less_than_x_minutes', 1],
+ [60.seconds, false] => [:'x_minutes', 1],
+ [44.minutes, false] => [:'x_minutes', 44],
+ [61.minutes, false] => [:'about_x_hours', 1],
+ [24.hours, false] => [:'x_days', 1],
+ [30.days, false] => [:'about_x_months', 1],
+ [60.days, false] => [:'x_months', 2],
+ [1.year, false] => [:'about_x_years', 1],
+ [3.years, false] => [:'over_x_years', 3]
+
+ }.each do |passed, expected|
+ assert_distance_of_time_in_words_translates_key passed, expected
+ end
+ end
+
+ def assert_distance_of_time_in_words_translates_key(passed, expected)
+ diff, include_seconds = *passed
+ key, count = *expected
+ to = @from + diff
+
+ options = {:locale => 'en-US', :scope => :'datetime.distance_in_words'}
+ options[:count] = count if count
+
+ I18n.expects(:t).with(key, options)
+ distance_of_time_in_words(@from, to, include_seconds, :locale => 'en-US')
+ end
+end
+
+class DateHelperSelectTagsI18nTests < Test::Unit::TestCase
+ include ActionView::Helpers::DateHelper
+ attr_reader :request
+
+ def setup
+ @request = mock
+ I18n.stubs(:translate).with(:'date.month_names', 'en-US').returns Date::MONTHNAMES
+ end
+
+ # select_month
+
+ def test_select_month_given_use_month_names_option_does_not_translate_monthnames
+ I18n.expects(:translate).never
+ select_month(8, :locale => 'en-US', :use_month_names => Date::MONTHNAMES)
+ end
+
+ def test_select_month_translates_monthnames
+ I18n.expects(:translate).with(:'date.month_names', 'en-US').returns Date::MONTHNAMES
+ select_month(8, :locale => 'en-US')
+ end
+
+ def test_select_month_given_use_short_month_option_translates_abbr_monthnames
+ I18n.expects(:translate).with(:'date.abbr_month_names', 'en-US').returns Date::ABBR_MONTHNAMES
+ select_month(8, :locale => 'en-US', :use_short_month => true)
+ end
+
+ # date_or_time_select
+
+ def test_date_or_time_select_given_an_order_options_does_not_translate_order
+ I18n.expects(:translate).never
+ datetime_select('post', 'updated_at', :order => [:year, :month, :day], :locale => 'en-US')
+ end
+
+ def test_date_or_time_select_given_no_order_options_translates_order
+ I18n.expects(:translate).with(:'date.order', 'en-US').returns [:year, :month, :day]
+ datetime_select('post', 'updated_at', :locale => 'en-US')
+ end
+end
\ No newline at end of file
diff --git a/actionpack/test/template/form_options_helper_i18n_test.rb b/actionpack/test/template/form_options_helper_i18n_test.rb
new file mode 100644
index 0000000000..c9fc0768bb
--- /dev/null
+++ b/actionpack/test/template/form_options_helper_i18n_test.rb
@@ -0,0 +1,26 @@
+require 'abstract_unit'
+
+class FormOptionsHelperI18nTests < Test::Unit::TestCase
+ include ActionView::Helpers::FormOptionsHelper
+ attr_reader :request
+
+ def setup
+ @request = mock
+ end
+
+ def test_country_options_for_select_given_a_locale_it_does_not_check_request_for_locale
+ request.expects(:locale).never
+ country_options_for_select :locale => 'en-US'
+ end
+
+ def test_country_options_for_select_given_no_locale_it_checks_request_for_locale
+ request.expects(:locale).returns 'en-US'
+ country_options_for_select
+ end
+
+ def test_country_options_for_select_translates_country_names
+ countries = ActionView::Helpers::FormOptionsHelper::COUNTRIES
+ I18n.expects(:translate).with(:'countries.names', 'en-US').returns countries
+ country_options_for_select :locale => 'en-US'
+ end
+end
\ No newline at end of file
diff --git a/actionpack/test/template/number_helper_i18n_test.rb b/actionpack/test/template/number_helper_i18n_test.rb
new file mode 100644
index 0000000000..47cb035f56
--- /dev/null
+++ b/actionpack/test/template/number_helper_i18n_test.rb
@@ -0,0 +1,27 @@
+require 'abstract_unit'
+
+class NumberHelperI18nTests < Test::Unit::TestCase
+ include ActionView::Helpers::NumberHelper
+
+ attr_reader :request
+ def setup
+ @request = mock
+ @defaults = {:separator => ".", :unit => "$", :format => "%u%n", :delimiter => ",", :precision => 2}
+ I18n.backend.add_translations 'en-US', :currency => {:format => @defaults}
+ end
+
+ def test_number_to_currency_given_a_locale_it_does_not_check_request_for_locale
+ request.expects(:locale).never
+ number_to_currency(1, :locale => 'en-US')
+ end
+
+ def test_number_to_currency_given_no_locale_it_checks_request_for_locale
+ request.expects(:locale).returns 'en-US'
+ number_to_currency(1)
+ end
+
+ def test_number_to_currency_translates_currency_formats
+ I18n.expects(:translate).with(:'currency.format', 'en-US').returns @defaults
+ number_to_currency(1, :locale => 'en-US')
+ end
+end
\ No newline at end of file
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index d4f7170305..b379bd26f8 100755
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -80,3 +80,5 @@ end
require 'active_record/connection_adapters/abstract_adapter'
require 'active_record/schema_dumper'
+
+require 'active_record/lang/en-US.rb'
diff --git a/activerecord/lib/active_record/lang/en-US.rb b/activerecord/lib/active_record/lang/en-US.rb
new file mode 100644
index 0000000000..7c3bcfd85e
--- /dev/null
+++ b/activerecord/lib/active_record/lang/en-US.rb
@@ -0,0 +1,25 @@
+I18n.backend.add_translations :'en-US', {
+ :active_record => {
+ :error_messages => {
+ :inclusion => "is not included in the list",
+ :exclusion => "is reserved",
+ :invalid => "is invalid",
+ :confirmation => "doesn't match confirmation",
+ :accepted => "must be accepted",
+ :empty => "can't be empty",
+ :blank => "can't be blank",
+ :too_long => "is too long (maximum is {{count}} characters)",
+ :too_short => "is too short (minimum is {{count}} characters)",
+ :wrong_length => "is the wrong length (should be {{count}} characters)",
+ :taken => "has already been taken",
+ :not_a_number => "is not a number",
+ :greater_than => "must be greater than {{count}}",
+ :greater_than_or_equal_to => "must be greater than or equal to {{count}}",
+ :equal_to => "must be equal to {{count}}",
+ :less_than => "must be less than {{count}}",
+ :less_than_or_equal_to => "must be less than or equal to {{count}}",
+ :odd => "must be odd",
+ :even => "must be even"
+ }
+ }
+}
\ No newline at end of file
diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb
index c4e370d017..f54fb80137 100755
--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -23,30 +23,30 @@ module ActiveRecord
@base, @errors = base, {}
end
- @@default_error_messages = {
- :inclusion => "is not included in the list",
- :exclusion => "is reserved",
- :invalid => "is invalid",
- :confirmation => "doesn't match confirmation",
- :accepted => "must be accepted",
- :empty => "can't be empty",
- :blank => "can't be blank",
- :too_long => "is too long (maximum is %d characters)",
- :too_short => "is too short (minimum is %d characters)",
- :wrong_length => "is the wrong length (should be %d characters)",
- :taken => "has already been taken",
- :not_a_number => "is not a number",
- :greater_than => "must be greater than %d",
- :greater_than_or_equal_to => "must be greater than or equal to %d",
- :equal_to => "must be equal to %d",
- :less_than => "must be less than %d",
- :less_than_or_equal_to => "must be less than or equal to %d",
- :odd => "must be odd",
- :even => "must be even"
- }
-
- # Holds a hash with all the default error messages that can be replaced by your own copy or localizations.
- cattr_accessor :default_error_messages
+ # @@default_error_messages = {
+ # :inclusion => "is not included in the list",
+ # :exclusion => "is reserved",
+ # :invalid => "is invalid",
+ # :confirmation => "doesn't match confirmation",
+ # :accepted => "must be accepted",
+ # :empty => "can't be empty",
+ # :blank => "can't be blank",
+ # :too_long => "is too long (maximum is %d characters)",
+ # :too_short => "is too short (minimum is %d characters)",
+ # :wrong_length => "is the wrong length (should be %d characters)",
+ # :taken => "has already been taken",
+ # :not_a_number => "is not a number",
+ # :greater_than => "must be greater than %d",
+ # :greater_than_or_equal_to => "must be greater than or equal to %d",
+ # :equal_to => "must be equal to %d",
+ # :less_than => "must be less than %d",
+ # :less_than_or_equal_to => "must be less than or equal to %d",
+ # :odd => "must be odd",
+ # :even => "must be even"
+ # }
+ #
+ # # Holds a hash with all the default error messages that can be replaced by your own copy or localizations.
+ # cattr_accessor :default_error_messages
# Adds an error to the base object instead of any particular attribute. This is used
@@ -61,27 +61,34 @@ module ActiveRecord
# for the same attribute and ensure that this error object returns false when asked if empty? . More than one
# error can be added to the same +attribute+ in which case an array will be returned on a call to on(attribute) .
# If no +msg+ is supplied, "invalid" is assumed.
- def add(attribute, msg = @@default_error_messages[:invalid])
- @errors[attribute.to_s] = [] if @errors[attribute.to_s].nil?
- @errors[attribute.to_s] << msg
- end
+ def add(attribute, message = nil)
+ message ||= :"active_record.error_messages.invalid".t
+ @errors[attribute.to_s] ||= []
+ @errors[attribute.to_s] << message
+ end
# Will add an error message to each of the attributes in +attributes+ that is empty.
- def add_on_empty(attributes, msg = @@default_error_messages[:empty])
+ def add_on_empty(attributes, custom_message = nil)
for attr in [attributes].flatten
value = @base.respond_to?(attr.to_s) ? @base.send(attr.to_s) : @base[attr.to_s]
- is_empty = value.respond_to?("empty?") ? value.empty? : false
- add(attr, msg) unless !value.nil? && !is_empty
+ is_empty = value.respond_to?("empty?") ? value.empty? : false
+ add(attr, generate_message(attr, :empty, :default => custom_message)) unless !value.nil? && !is_empty
end
end
# Will add an error message to each of the attributes in +attributes+ that is blank (using Object#blank?).
- def add_on_blank(attributes, msg = @@default_error_messages[:blank])
+ def add_on_blank(attributes, custom_message = nil)
for attr in [attributes].flatten
value = @base.respond_to?(attr.to_s) ? @base.send(attr.to_s) : @base[attr.to_s]
- add(attr, msg) if value.blank?
+ add(attr, generate_message(attr, :blank, :default => custom_message)) if value.blank?
end
end
+
+ def generate_message(attr, key, options = {})
+ scope = [:active_record, :error_messages]
+ key.t(options.merge(:scope => scope + [:custom, @base.class.name.downcase, attr])) ||
+ key.t(options.merge(:scope => scope))
+ end
# Returns true if the specified +attribute+ has errors associated with it.
#
@@ -166,22 +173,25 @@ module ActiveRecord
# company = Company.create(:address => '123 First St.')
# company.errors.full_messages # =>
# ["Name is too short (minimum is 5 characters)", "Name can't be blank", "Address can't be blank"]
- def full_messages
+ def full_messages(options = {})
full_messages = []
+ locale = options[:locale]
@errors.each_key do |attr|
- @errors[attr].each do |msg|
- next if msg.nil?
-
+ @errors[attr].each do |message|
+ next unless message
+
if attr == "base"
- full_messages << msg
+ full_messages << message
else
- full_messages << @base.class.human_attribute_name(attr) + " " + msg
+ key = :"active_record.human_attribute_names.#{@base.class.name.underscore.to_sym}.#{attr}"
+ attr_name = key.t(locale) || @base.class.human_attribute_name(attr)
+ full_messages << attr_name + " " + message
end
end
end
full_messages
- end
+ end
# Returns true if no errors have been added.
def empty?
@@ -388,15 +398,18 @@ module ActiveRecord
# not occur (e.g. :unless => :skip_validation , or :unless => Proc.new { |user| user.signup_step <= 2 } ). The
# method, proc or string should return or evaluate to a true or false value.
def validates_confirmation_of(*attr_names)
- configuration = { :message => ActiveRecord::Errors.default_error_messages[:confirmation], :on => :save }
+ configuration = { :on => :save }
configuration.update(attr_names.extract_options!)
attr_accessor(*(attr_names.map { |n| "#{n}_confirmation" }))
validates_each(attr_names, configuration) do |record, attr_name, value|
- record.errors.add(attr_name, configuration[:message]) unless record.send("#{attr_name}_confirmation").nil? or value == record.send("#{attr_name}_confirmation")
+ unless record.send("#{attr_name}_confirmation").nil? or value == record.send("#{attr_name}_confirmation")
+ message = record.errors.generate_message(attr_name, :confirmation, :default => configuration[:message])
+ record.errors.add(attr_name, message)
+ end
end
- end
+ end
# Encapsulates the pattern of wanting to validate the acceptance of a terms of service check box (or similar agreement). Example:
#
@@ -422,7 +435,7 @@ module ActiveRecord
# not occur (e.g. :unless => :skip_validation , or :unless => Proc.new { |user| user.signup_step <= 2 } ). The
# method, proc or string should return or evaluate to a true or false value.
def validates_acceptance_of(*attr_names)
- configuration = { :message => ActiveRecord::Errors.default_error_messages[:accepted], :on => :save, :allow_nil => true, :accept => "1" }
+ configuration = { :on => :save, :allow_nil => true, :accept => "1" }
configuration.update(attr_names.extract_options!)
db_cols = begin
@@ -434,7 +447,10 @@ module ActiveRecord
attr_accessor(*names)
validates_each(attr_names,configuration) do |record, attr_name, value|
- record.errors.add(attr_name, configuration[:message]) unless value == configuration[:accept]
+ unless value == configuration[:accept]
+ message = record.errors.generate_message(attr_name, :accepted, :default => configuration[:message])
+ record.errors.add(attr_name, message)
+ end
end
end
@@ -461,7 +477,7 @@ module ActiveRecord
# method, proc or string should return or evaluate to a true or false value.
#
def validates_presence_of(*attr_names)
- configuration = { :message => ActiveRecord::Errors.default_error_messages[:blank], :on => :save }
+ configuration = { :on => :save }
configuration.update(attr_names.extract_options!)
# can't use validates_each here, because it cannot cope with nonexistent attributes,
@@ -505,11 +521,7 @@ module ActiveRecord
# method, proc or string should return or evaluate to a true or false value.
def validates_length_of(*attrs)
# Merge given options with defaults.
- options = {
- :too_long => ActiveRecord::Errors.default_error_messages[:too_long],
- :too_short => ActiveRecord::Errors.default_error_messages[:too_short],
- :wrong_length => ActiveRecord::Errors.default_error_messages[:wrong_length]
- }.merge(DEFAULT_VALIDATION_OPTIONS)
+ options = {}.merge(DEFAULT_VALIDATION_OPTIONS)
options.update(attrs.extract_options!.symbolize_keys)
# Ensure that one and only one range option is specified.
@@ -531,15 +543,14 @@ module ActiveRecord
when :within, :in
raise ArgumentError, ":#{option} must be a Range" unless option_value.is_a?(Range)
- too_short = options[:too_short] % option_value.begin
- too_long = options[:too_long] % option_value.end
-
validates_each(attrs, options) do |record, attr, value|
value = value.split(//) if value.kind_of?(String)
if value.nil? or value.size < option_value.begin
- record.errors.add(attr, too_short)
+ message = record.errors.generate_message(attr, :too_short, :default => options[:too_short], :count => option_value.begin)
+ record.errors.add(attr, message)
elsif value.size > option_value.end
- record.errors.add(attr, too_long)
+ message = record.errors.generate_message(attr, :too_long, :default => options[:too_long], :count => option_value.end)
+ record.errors.add(attr, message)
end
end
when :is, :minimum, :maximum
@@ -549,11 +560,14 @@ module ActiveRecord
validity_checks = { :is => "==", :minimum => ">=", :maximum => "<=" }
message_options = { :is => :wrong_length, :minimum => :too_short, :maximum => :too_long }
- message = (options[:message] || options[message_options[option]]) % option_value
-
validates_each(attrs, options) do |record, attr, value|
value = value.split(//) if value.kind_of?(String)
- record.errors.add(attr, message) unless !value.nil? and value.size.method(validity_checks[option])[option_value]
+ unless !value.nil? and value.size.method(validity_checks[option])[option_value]
+ key = message_options[option]
+ custom_message = options[:message] || options[key]
+ message = record.errors.generate_message(attr, key, :default => custom_message, :count => option_value)
+ record.errors.add(attr, message)
+ end
end
end
end
@@ -595,7 +609,7 @@ module ActiveRecord
# not occur (e.g. :unless => :skip_validation , or :unless => Proc.new { |user| user.signup_step <= 2 } ). The
# method, proc or string should return or evaluate to a true or false value.
def validates_uniqueness_of(*attr_names)
- configuration = { :message => ActiveRecord::Errors.default_error_messages[:taken], :case_sensitive => true }
+ configuration = { :case_sensitive => true }
configuration.update(attr_names.extract_options!)
validates_each(attr_names,configuration) do |record, attr_name, value|
@@ -654,8 +668,11 @@ module ActiveRecord
if configuration[:case_sensitive] && finder_class.columns_hash[attr_name.to_s].text?
found = results.any? { |a| a[attr_name.to_s] == value }
end
-
- record.errors.add(attr_name, configuration[:message]) if found
+
+ if found
+ message = record.errors.generate_message(attr_name, :taken, :default => configuration[:message])
+ record.errors.add(attr_name, message)
+ end
end
end
end
@@ -685,13 +702,16 @@ module ActiveRecord
# not occur (e.g. :unless => :skip_validation , or :unless => Proc.new { |user| user.signup_step <= 2 } ). The
# method, proc or string should return or evaluate to a true or false value.
def validates_format_of(*attr_names)
- configuration = { :message => ActiveRecord::Errors.default_error_messages[:invalid], :on => :save, :with => nil }
+ configuration = { :on => :save, :with => nil }
configuration.update(attr_names.extract_options!)
raise(ArgumentError, "A regular expression must be supplied as the :with option of the configuration hash") unless configuration[:with].is_a?(Regexp)
validates_each(attr_names, configuration) do |record, attr_name, value|
- record.errors.add(attr_name, configuration[:message] % value) unless value.to_s =~ configuration[:with]
+ unless value.to_s =~ configuration[:with]
+ message = record.errors.generate_message(attr_name, :invalid, :default => configuration[:message], :value => value)
+ record.errors.add(attr_name, message)
+ end
end
end
@@ -715,7 +735,7 @@ module ActiveRecord
# not occur (e.g. :unless => :skip_validation , or :unless => Proc.new { |user| user.signup_step <= 2 } ). The
# method, proc or string should return or evaluate to a true or false value.
def validates_inclusion_of(*attr_names)
- configuration = { :message => ActiveRecord::Errors.default_error_messages[:inclusion], :on => :save }
+ configuration = { :on => :save, :with => nil }
configuration.update(attr_names.extract_options!)
enum = configuration[:in] || configuration[:within]
@@ -723,7 +743,10 @@ module ActiveRecord
raise(ArgumentError, "An object with the method include? is required must be supplied as the :in option of the configuration hash") unless enum.respond_to?("include?")
validates_each(attr_names, configuration) do |record, attr_name, value|
- record.errors.add(attr_name, configuration[:message] % value) unless enum.include?(value)
+ unless enum.include?(value)
+ message = record.errors.generate_message(attr_name, :inclusion, :default => configuration[:message], :value => value)
+ record.errors.add(attr_name, message)
+ end
end
end
@@ -747,7 +770,7 @@ module ActiveRecord
# not occur (e.g. :unless => :skip_validation , or :unless => Proc.new { |user| user.signup_step <= 2 } ). The
# method, proc or string should return or evaluate to a true or false value.
def validates_exclusion_of(*attr_names)
- configuration = { :message => ActiveRecord::Errors.default_error_messages[:exclusion], :on => :save }
+ configuration = { :on => :save, :with => nil }
configuration.update(attr_names.extract_options!)
enum = configuration[:in] || configuration[:within]
@@ -755,7 +778,10 @@ module ActiveRecord
raise(ArgumentError, "An object with the method include? is required must be supplied as the :in option of the configuration hash") unless enum.respond_to?("include?")
validates_each(attr_names, configuration) do |record, attr_name, value|
- record.errors.add(attr_name, configuration[:message] % value) if enum.include?(value)
+ if enum.include?(value)
+ message = record.errors.generate_message(attr_name, :exclusion, :default => configuration[:message], :value => value)
+ record.errors.add(attr_name, message)
+ end
end
end
@@ -791,12 +817,14 @@ module ActiveRecord
# not occur (e.g. :unless => :skip_validation , or :unless => Proc.new { |user| user.signup_step <= 2 } ). The
# method, proc or string should return or evaluate to a true or false value.
def validates_associated(*attr_names)
- configuration = { :message => ActiveRecord::Errors.default_error_messages[:invalid], :on => :save }
+ configuration = { :on => :save }
configuration.update(attr_names.extract_options!)
validates_each(attr_names, configuration) do |record, attr_name, value|
- record.errors.add(attr_name, configuration[:message]) unless
- (value.is_a?(Array) ? value : [value]).inject(true) { |v, r| (r.nil? || r.valid?) && v }
+ unless (value.is_a?(Array) ? value : [value]).inject(true) { |v, r| (r.nil? || r.valid?) && v }
+ message = record.errors.generate_message(attr_name, :invalid, :default => configuration[:message], :value => value)
+ record.errors.add(attr_name, message)
+ end
end
end
@@ -844,7 +872,8 @@ module ActiveRecord
if configuration[:only_integer]
unless raw_value.to_s =~ /\A[+-]?\d+\Z/
- record.errors.add(attr_name, configuration[:message] || ActiveRecord::Errors.default_error_messages[:not_a_number])
+ message = record.errors.generate_message(attr_name, :not_a_number, :value => raw_value, :default => configuration[:message])
+ record.errors.add(attr_name, message)
next
end
raw_value = raw_value.to_i
@@ -852,7 +881,8 @@ module ActiveRecord
begin
raw_value = Kernel.Float(raw_value.to_s)
rescue ArgumentError, TypeError
- record.errors.add(attr_name, configuration[:message] || ActiveRecord::Errors.default_error_messages[:not_a_number])
+ message = record.errors.generate_message(attr_name, :not_a_number, :value => raw_value, :default => configuration[:message])
+ record.errors.add(attr_name, message)
next
end
end
@@ -860,10 +890,12 @@ module ActiveRecord
numericality_options.each do |option|
case option
when :odd, :even
- record.errors.add(attr_name, configuration[:message] || ActiveRecord::Errors.default_error_messages[option]) unless raw_value.to_i.method(ALL_NUMERICALITY_CHECKS[option])[]
+ unless raw_value.to_i.method(ALL_NUMERICALITY_CHECKS[option])[]
+ message = record.errors.generate_message(attr_name, option, :value => raw_value, :default => configuration[:message])
+ record.errors.add(attr_name, message)
+ end
else
- message = configuration[:message] || ActiveRecord::Errors.default_error_messages[option]
- message = message % configuration[option] if configuration[option]
+ message = record.errors.generate_message(attr_name, option, :default => configuration[:message], :value => raw_value, :count => configuration[option])
record.errors.add(attr_name, message) unless raw_value.method(ALL_NUMERICALITY_CHECKS[option])[configuration[option]]
end
end
diff --git a/activerecord/test/cases/validations_i18n_test.rb b/activerecord/test/cases/validations_i18n_test.rb
new file mode 100644
index 0000000000..eb454fca20
--- /dev/null
+++ b/activerecord/test/cases/validations_i18n_test.rb
@@ -0,0 +1,539 @@
+require "cases/helper"
+require 'models/topic'
+require 'models/reply'
+
+class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
+ def setup
+ reset_callbacks Topic
+ @topic = Topic.new
+ I18n.backend.add_translations('en-US', :active_record => {:error_messages => {:custom => nil}})
+ end
+
+ def teardown
+ reset_callbacks Topic
+ load 'active_record/lang/en-US.rb'
+ end
+
+ def unique_topic
+ @unique ||= Topic.create :title => 'unique!'
+ end
+
+ def replied_topic
+ @replied_topic ||= begin
+ topic = Topic.create(:title => "topic")
+ topic.replies << Reply.new
+ topic
+ end
+ end
+
+ def reset_callbacks(*models)
+ models.each do |model|
+ model.instance_variable_set("@validate_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
+ model.instance_variable_set("@validate_on_create_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
+ model.instance_variable_set("@validate_on_update_callbacks", ActiveSupport::Callbacks::CallbackChain.new)
+ end
+ end
+
+ # ActiveRecord::Errors
+
+ def test_errors_generate_message_translates_custom_model_attribute_key
+ global_scope = [:active_record, :error_messages]
+ custom_scope = global_scope + [:custom, 'topic', :title]
+
+ I18n.expects(:translate).with(:invalid, :scope => custom_scope).returns 'translation'
+ I18n.expects(:translate).with(:invalid, :scope => global_scope).never
+
+ @topic.errors.generate_message :title, :invalid
+ end
+
+ def test_errors_generate_message_given_a_custom_message_translates_custom_model_attribute_key_with_custom_message_as_default
+ custom_scope = [:active_record, :error_messages, :custom, 'topic', :title]
+
+ I18n.expects(:translate).with(:invalid, :scope => custom_scope, :default => 'default from class def').returns 'translation'
+ @topic.errors.generate_message :title, :invalid, :default => 'default from class def'
+ end
+
+ def test_errors_generate_message_given_no_custom_message_falls_back_to_global_default_key_translation
+ global_scope = [:active_record, :error_messages]
+ custom_scope = global_scope + [:custom, 'topic', :title]
+
+ I18n.stubs(:translate).with(:invalid, :scope => custom_scope).returns nil
+ I18n.expects(:translate).with(:invalid, :scope => global_scope)
+ @topic.errors.generate_message :title, :invalid
+ end
+
+ def test_errors_add_given_no_message_it_translates_invalid
+ I18n.expects(:translate).with(:"active_record.error_messages.invalid")
+ @topic.errors.add :title
+ end
+
+ def test_errors_add_on_empty_generates_message
+ @topic.errors.expects(:generate_message).with(:title, :empty, {:default => nil})
+ @topic.errors.add_on_empty :title
+ end
+
+ def test_errors_add_on_empty_generates_message_with_custom_default_message
+ @topic.errors.expects(:generate_message).with(:title, :empty, {:default => 'custom'})
+ @topic.errors.add_on_empty :title, 'custom'
+ end
+
+ def test_errors_add_on_blank_generates_message
+ @topic.errors.expects(:generate_message).with(:title, :blank, {:default => nil})
+ @topic.errors.add_on_blank :title
+ end
+
+ def test_errors_add_on_blank_generates_message_with_custom_default_message
+ @topic.errors.expects(:generate_message).with(:title, :blank, {:default => 'custom'})
+ @topic.errors.add_on_blank :title, 'custom'
+ end
+
+ def test_errors_full_messages_translates_human_attribute_name_for_model_attributes
+ @topic.errors.instance_variable_set :@errors, { 'title' => 'empty' }
+ I18n.expects(:translate).with(:"active_record.human_attribute_names.topic.title", 'en-US').returns('Title')
+ @topic.errors.full_messages :locale => 'en-US'
+ end
+
+
+ # ActiveRecord::Validations
+
+ # validates_confirmation_of
+
+ def test_validates_confirmation_of_generates_message
+ Topic.validates_confirmation_of :title
+ @topic.title_confirmation = 'foo'
+ @topic.errors.expects(:generate_message).with(:title, :confirmation, {:default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_confirmation_of_generates_message_with_custom_default_message
+ Topic.validates_confirmation_of :title, :message => 'custom'
+ @topic.title_confirmation = 'foo'
+ @topic.errors.expects(:generate_message).with(:title, :confirmation, {:default => 'custom'})
+ @topic.valid?
+ end
+
+ def test_validates_confirmation_of_finds_custom_model_key_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:confirmation => 'custom message'}}}}}
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:confirmation => 'global message'}}
+
+ Topic.validates_confirmation_of :title
+ @topic.title_confirmation = 'foo'
+ @topic.valid?
+ assert_equal 'custom message', @topic.errors.on(:title)
+ end
+
+ def test_validates_confirmation_of_finds_global_default_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:confirmation => 'global message'}}
+
+ Topic.validates_confirmation_of :title
+ @topic.title_confirmation = 'foo'
+ @topic.valid?
+ assert_equal 'global message', @topic.errors.on(:title)
+ end
+
+
+ # validates_acceptance_of
+
+ def test_validates_acceptance_of_generates_message
+ Topic.validates_acceptance_of :title, :allow_nil => false
+ @topic.errors.expects(:generate_message).with(:title, :accepted, {:default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_acceptance_of_generates_message_with_custom_default_message
+ Topic.validates_acceptance_of :title, :message => 'custom', :allow_nil => false
+ @topic.errors.expects(:generate_message).with(:title, :accepted, {:default => 'custom'})
+ @topic.valid?
+ end
+
+ def test_validates_acceptance_of_finds_custom_model_key_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:accepted => 'custom message'}}}}}
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:accepted => 'global message'}}
+
+ Topic.validates_acceptance_of :title, :allow_nil => false
+ @topic.valid?
+ assert_equal 'custom message', @topic.errors.on(:title)
+ end
+
+ def test_validates_acceptance_of_finds_global_default_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:accepted => 'global message'}}
+
+ Topic.validates_acceptance_of :title, :allow_nil => false
+ @topic.valid?
+ assert_equal 'global message', @topic.errors.on(:title)
+ end
+
+
+ # validates_presence_of
+
+ def test_validates_presence_of_generates_message
+ Topic.validates_presence_of :title
+ @topic.errors.expects(:generate_message).with(:title, :blank, {:default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_presence_of_generates_message_with_custom_default_message
+ Topic.validates_presence_of :title, :message => 'custom'
+ @topic.errors.expects(:generate_message).with(:title, :blank, {:default => 'custom'})
+ @topic.valid?
+ end
+
+ def test_validates_presence_of_finds_custom_model_key_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:blank => 'custom message'}}}}}
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:blank => 'global message'}}
+
+ Topic.validates_presence_of :title
+ @topic.valid?
+ assert_equal 'custom message', @topic.errors.on(:title)
+ end
+
+ def test_validates_presence_of_finds_global_default_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:blank => 'global message'}}
+
+ Topic.validates_presence_of :title
+ @topic.valid?
+ assert_equal 'global message', @topic.errors.on(:title)
+ end
+
+
+ # validates_length_of :within
+
+ def test_validates_length_of_within_generates_message
+ Topic.validates_length_of :title, :within => 3..5
+ @topic.errors.expects(:generate_message).with(:title, :too_short, {:count => 3, :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_length_of_within_generates_message_with_custom_default_message
+ Topic.validates_length_of :title, :within => 3..5, :too_short => 'custom'
+ @topic.errors.expects(:generate_message).with(:title, :too_short, {:count => 3, :default => 'custom'})
+ @topic.valid?
+ end
+
+ def test_validates_length_of_within_finds_custom_model_key_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:too_short => 'custom message'}}}}}
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:too_short => 'global message'}}
+
+ Topic.validates_length_of :title, :within => 3..5
+ @topic.valid?
+ assert_equal 'custom message', @topic.errors.on(:title)
+ end
+
+ def test_validates_length_of_within_finds_global_default_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:too_short => 'global message'}}
+
+ Topic.validates_length_of :title, :within => 3..5
+ @topic.valid?
+ assert_equal 'global message', @topic.errors.on(:title)
+ end
+
+
+ # validates_length_of :is
+
+ def test_validates_length_of_is_generates_message
+ Topic.validates_length_of :title, :is => 5
+ @topic.errors.expects(:generate_message).with(:title, :wrong_length, {:count => 5, :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_length_of_is_generates_message_with_custom_default_message
+ Topic.validates_length_of :title, :is => 5, :message => 'custom'
+ @topic.errors.expects(:generate_message).with(:title, :wrong_length, {:count => 5, :default => 'custom'})
+ @topic.valid?
+ end
+
+ def test_validates_length_of_within_finds_custom_model_key_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:wrong_length => 'custom message'}}}}}
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
+
+ Topic.validates_length_of :title, :is => 5
+ @topic.valid?
+ assert_equal 'custom message', @topic.errors.on(:title)
+ end
+
+ def test_validates_length_of_within_finds_global_default_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
+
+ Topic.validates_length_of :title, :is => 5
+ @topic.valid?
+ assert_equal 'global message', @topic.errors.on(:title)
+ end
+
+
+ # validates_uniqueness_of
+
+ def test_validates_uniqueness_of_generates_message
+ Topic.validates_uniqueness_of :title
+ @topic.title = unique_topic.title
+ @topic.errors.expects(:generate_message).with(:title, :taken, {:default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_uniqueness_of_generates_message_with_custom_default_message
+ Topic.validates_uniqueness_of :title, :message => 'custom'
+ @topic.title = unique_topic.title
+ @topic.errors.expects(:generate_message).with(:title, :taken, {:default => 'custom'})
+ @topic.valid?
+ end
+
+ def test_validates_length_of_within_finds_custom_model_key_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:wrong_length => 'custom message'}}}}}
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
+
+ Topic.validates_length_of :title, :is => 5
+ @topic.valid?
+ assert_equal 'custom message', @topic.errors.on(:title)
+ end
+
+ def test_validates_length_of_within_finds_global_default_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
+
+ Topic.validates_length_of :title, :is => 5
+ @topic.valid?
+ assert_equal 'global message', @topic.errors.on(:title)
+ end
+
+
+ # validates_format_of
+
+ def test_validates_format_of_generates_message
+ Topic.validates_format_of :title, :with => /^[1-9][0-9]*$/
+ @topic.title = '72x'
+ @topic.errors.expects(:generate_message).with(:title, :invalid, {:value => '72x', :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_format_of_generates_message_with_custom_default_message
+ Topic.validates_format_of :title, :with => /^[1-9][0-9]*$/, :message => 'custom'
+ @topic.title = '72x'
+ @topic.errors.expects(:generate_message).with(:title, :invalid, {:value => '72x', :default => 'custom'})
+ @topic.valid?
+ end
+
+ def test_validates_format_of_finds_custom_model_key_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:invalid => 'custom message'}}}}}
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
+
+ Topic.validates_format_of :title, :with => /^[1-9][0-9]*$/
+ @topic.valid?
+ assert_equal 'custom message', @topic.errors.on(:title)
+ end
+
+ def test_validates_format_of_finds_global_default_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
+
+ Topic.validates_format_of :title, :with => /^[1-9][0-9]*$/
+ @topic.valid?
+ assert_equal 'global message', @topic.errors.on(:title)
+ end
+
+
+ # validates_inclusion_of
+
+ def test_validates_inclusion_of_generates_message
+ Topic.validates_inclusion_of :title, :in => %w(a b c)
+ @topic.title = 'z'
+ @topic.errors.expects(:generate_message).with(:title, :inclusion, {:value => 'z', :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_inclusion_of_generates_message_with_custom_default_message
+ Topic.validates_inclusion_of :title, :in => %w(a b c), :message => 'custom'
+ @topic.title = 'z'
+ @topic.errors.expects(:generate_message).with(:title, :inclusion, {:value => 'z', :default => 'custom'})
+ @topic.valid?
+ end
+
+ def test_validates_inclusion_of_finds_custom_model_key_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:inclusion => 'custom message'}}}}}
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:inclusion => 'global message'}}
+
+ Topic.validates_inclusion_of :title, :in => %w(a b c)
+ @topic.valid?
+ assert_equal 'custom message', @topic.errors.on(:title)
+ end
+
+ def test_validates_inclusion_of_finds_global_default_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:inclusion => 'global message'}}
+
+ Topic.validates_inclusion_of :title, :in => %w(a b c)
+ @topic.valid?
+ assert_equal 'global message', @topic.errors.on(:title)
+ end
+
+
+ # validates_exclusion_of
+
+ def test_validates_exclusion_of_generates_message
+ Topic.validates_exclusion_of :title, :in => %w(a b c)
+ @topic.title = 'a'
+ @topic.errors.expects(:generate_message).with(:title, :exclusion, {:value => 'a', :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_exclusion_of_generates_message_with_custom_default_message
+ Topic.validates_exclusion_of :title, :in => %w(a b c), :message => 'custom'
+ @topic.title = 'a'
+ @topic.errors.expects(:generate_message).with(:title, :exclusion, {:value => 'a', :default => 'custom'})
+ @topic.valid?
+ end
+
+ def test_validates_exclusion_of_finds_custom_model_key_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:exclusion => 'custom message'}}}}}
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:exclusion => 'global message'}}
+
+ Topic.validates_exclusion_of :title, :in => %w(a b c)
+ @topic.title = 'a'
+ @topic.valid?
+ assert_equal 'custom message', @topic.errors.on(:title)
+ end
+
+ def test_validates_exclusion_of_finds_global_default_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:exclusion => 'global message'}}
+
+ Topic.validates_exclusion_of :title, :in => %w(a b c)
+ @topic.title = 'a'
+ @topic.valid?
+ assert_equal 'global message', @topic.errors.on(:title)
+ end
+
+
+ # validates_numericality_of :only_integer
+
+ def test_validates_numericality_of_only_integer_generates_message
+ Topic.validates_numericality_of :title, :only_integer => true
+ @topic.title = 'a'
+ @topic.errors.expects(:generate_message).with(:title, :not_a_number, {:value => 'a', :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_numericality_of_only_integer_generates_message_with_custom_default_message
+ Topic.validates_numericality_of :title, :only_integer => true, :message => 'custom'
+ @topic.title = 'a'
+ @topic.errors.expects(:generate_message).with(:title, :not_a_number, {:value => 'a', :default => 'custom'})
+ @topic.valid?
+ end
+
+ def test_validates_numericality_of_only_integer_finds_custom_model_key_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:not_a_number => 'custom message'}}}}}
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:not_a_number => 'global message'}}
+
+ Topic.validates_numericality_of :title, :only_integer => true
+ @topic.title = 'a'
+ @topic.valid?
+ assert_equal 'custom message', @topic.errors.on(:title)
+ end
+
+ def test_validates_numericality_of_only_integer_finds_global_default_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:not_a_number => 'global message'}}
+
+ Topic.validates_numericality_of :title, :only_integer => true
+ @topic.title = 'a'
+ @topic.valid?
+ assert_equal 'global message', @topic.errors.on(:title)
+ end
+
+
+ # validates_numericality_of :odd
+
+ def test_validates_numericality_of_odd_generates_message
+ Topic.validates_numericality_of :title, :only_integer => true, :odd => true
+ @topic.title = 0
+ @topic.errors.expects(:generate_message).with(:title, :odd, {:value => 0, :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_numericality_of_odd_generates_message_with_custom_default_message
+ Topic.validates_numericality_of :title, :only_integer => true, :odd => true, :message => 'custom'
+ @topic.title = 0
+ @topic.errors.expects(:generate_message).with(:title, :odd, {:value => 0, :default => 'custom'})
+ @topic.valid?
+ end
+
+ def test_validates_numericality_of_odd_finds_custom_model_key_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:odd => 'custom message'}}}}}
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:odd => 'global message'}}
+
+ Topic.validates_numericality_of :title, :only_integer => true, :odd => true
+ @topic.title = 0
+ @topic.valid?
+ assert_equal 'custom message', @topic.errors.on(:title)
+ end
+
+ def test_validates_numericality_of_odd_finds_global_default_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:odd => 'global message'}}
+
+ Topic.validates_numericality_of :title, :only_integer => true, :odd => true
+ @topic.title = 0
+ @topic.valid?
+ assert_equal 'global message', @topic.errors.on(:title)
+ end
+
+
+ # validates_numericality_of :less_than
+
+ def test_validates_numericality_of_less_than_generates_message
+ Topic.validates_numericality_of :title, :only_integer => true, :less_than => 0
+ @topic.title = 1
+ @topic.errors.expects(:generate_message).with(:title, :less_than, {:value => 1, :count => 0, :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_numericality_of_odd_generates_message_with_custom_default_message
+ Topic.validates_numericality_of :title, :only_integer => true, :less_than => 0, :message => 'custom'
+ @topic.title = 1
+ @topic.errors.expects(:generate_message).with(:title, :less_than, {:value => 1, :count => 0, :default => 'custom'})
+ @topic.valid?
+ end
+
+ def test_validates_numericality_of_less_than_finds_custom_model_key_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:less_than => 'custom message'}}}}}
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:less_than => 'global message'}}
+
+ Topic.validates_numericality_of :title, :only_integer => true, :less_than => 0
+ @topic.title = 1
+ @topic.valid?
+ assert_equal 'custom message', @topic.errors.on(:title)
+ end
+
+ def test_validates_numericality_of_less_than_finds_global_default_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:less_than => 'global message'}}
+
+ Topic.validates_numericality_of :title, :only_integer => true, :less_than => 0
+ @topic.title = 1
+ @topic.valid?
+ assert_equal 'global message', @topic.errors.on(:title)
+ end
+
+
+ # validates_associated
+
+ def test_validates_associated_generates_message
+ Topic.validates_associated :replies
+ replied_topic.errors.expects(:generate_message).with(:replies, :invalid, {:value => replied_topic.replies, :default => nil})
+ replied_topic.valid?
+ end
+
+ def test_validates_associated_generates_message_with_custom_default_message
+ Topic.validates_associated :replies
+ replied_topic.errors.expects(:generate_message).with(:replies, :invalid, {:value => replied_topic.replies, :default => nil})
+ replied_topic.valid?
+ end
+
+ def test_validates_associated_finds_custom_model_key_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:replies => {:invalid => 'custom message'}}}}}
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
+
+ Topic.validates_associated :replies
+ replied_topic.valid?
+ assert_equal 'custom message', replied_topic.errors.on(:replies)
+ end
+
+ def test_validates_associated_finds_global_default_translation
+ I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
+
+ Topic.validates_associated :replies
+ replied_topic.valid?
+ assert_equal 'global message', replied_topic.errors.on(:replies)
+ end
+end
\ No newline at end of file
diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb
index a9882828ca..08e608d346 100644
--- a/activesupport/lib/active_support/core_ext/array/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/array/conversions.rb
@@ -6,10 +6,15 @@ module ActiveSupport #:nodoc:
module Conversions
# Converts the array to a comma-separated sentence where the last element is joined by the connector word. Options:
# * :connector - The word used to join the last element in arrays with two or more elements (default: "and")
- # * :skip_last_comma - Set to true to return "a, b and c" instead of "a, b, and c".
- def to_sentence(options = {})
- options.assert_valid_keys(:connector, :skip_last_comma)
- options.reverse_merge! :connector => 'and', :skip_last_comma => false
+ # * :skip_last_comma - Set to true to return "a, b and c" instead of "a, b, and c".
+ def to_sentence(options = {})
+ options.assert_valid_keys(:connector, :skip_last_comma, :locale)
+
+ locale = options[:locale]
+ locale ||= request.locale if respond_to?(:request)
+
+ default = :'support.array.sentence_connector'.t(locale)
+ options.reverse_merge! :connector => default, :skip_last_comma => false
options[:connector] = "#{options[:connector]} " unless options[:connector].nil? || options[:connector].strip == ''
case length
@@ -23,6 +28,7 @@ module ActiveSupport #:nodoc:
"#{self[0...-1].join(', ')}#{options[:skip_last_comma] ? '' : ','} #{options[:connector]}#{self[-1]}"
end
end
+
# Calls to_param on all its elements and joins the result with
# slashes. This is used by url_for in Action Pack.
diff --git a/activesupport/lib/active_support/vendor.rb b/activesupport/lib/active_support/vendor.rb
index a02e42f791..bca2664fa4 100644
--- a/activesupport/lib/active_support/vendor.rb
+++ b/activesupport/lib/active_support/vendor.rb
@@ -23,4 +23,11 @@ begin
gem 'tzinfo', '~> 0.3.9'
rescue Gem::LoadError
$:.unshift "#{File.dirname(__FILE__)}/vendor/tzinfo-0.3.9"
+end
+
+begin
+ gem 'i18n', '~> 0.3.9'
+rescue Gem::LoadError
+ $:.unshift "#{File.dirname(__FILE__)}/vendor/i18n-0.0.1/lib" # TODO
+ require 'i18n'
end
\ No newline at end of file
diff --git a/activesupport/lib/active_support/vendor/i18n-0.0.1 b/activesupport/lib/active_support/vendor/i18n-0.0.1
new file mode 160000
index 0000000000..70ab0f3cc5
--- /dev/null
+++ b/activesupport/lib/active_support/vendor/i18n-0.0.1
@@ -0,0 +1 @@
+Subproject commit 70ab0f3cc5921cc67e09741939a08b2582d707cb
--
cgit v1.2.3
From 4a8486a1b1aa28d4cab5571b55301917221870e9 Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Thu, 19 Jun 2008 16:43:30 +0200
Subject: add lang file for active_support
---
activesupport/lib/active_support.rb | 1 +
activesupport/lib/active_support/lang/en-US.rb | 7 +++++++
2 files changed, 8 insertions(+)
create mode 100644 activesupport/lib/active_support/lang/en-US.rb
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index 1a8603e892..acdb3056d2 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -55,6 +55,7 @@ require 'active_support/multibyte'
require 'active_support/base64'
require 'active_support/time_with_zone'
+require 'active_support/lang/en-US.rb'
Inflector = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Inflector', 'ActiveSupport::Inflector')
Dependencies = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Dependencies', 'ActiveSupport::Dependencies')
diff --git a/activesupport/lib/active_support/lang/en-US.rb b/activesupport/lib/active_support/lang/en-US.rb
new file mode 100644
index 0000000000..8732927f48
--- /dev/null
+++ b/activesupport/lib/active_support/lang/en-US.rb
@@ -0,0 +1,7 @@
+I18n.backend.add_translations :'en-US', {
+ :support => {
+ :array => {
+ :sentence_connector => 'and'
+ }
+ }
+}
\ No newline at end of file
--
cgit v1.2.3
From fdb5f810dc41f54f8cdb9c51154ff8987362c13a Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Thu, 19 Jun 2008 16:55:47 +0200
Subject: I18n has not been released as a gem, yet
---
activesupport/lib/active_support/vendor.rb | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/activesupport/lib/active_support/vendor.rb b/activesupport/lib/active_support/vendor.rb
index bca2664fa4..381471b833 100644
--- a/activesupport/lib/active_support/vendor.rb
+++ b/activesupport/lib/active_support/vendor.rb
@@ -25,9 +25,10 @@ rescue Gem::LoadError
$:.unshift "#{File.dirname(__FILE__)}/vendor/tzinfo-0.3.9"
end
-begin
- gem 'i18n', '~> 0.3.9'
-rescue Gem::LoadError
- $:.unshift "#{File.dirname(__FILE__)}/vendor/i18n-0.0.1/lib" # TODO
+# TODO I18n gem has not been released yet
+# begin
+# gem 'i18n', '~> 0.0.1'
+# rescue Gem::LoadError
+ $:.unshift "#{File.dirname(__FILE__)}/vendor/i18n-0.0.1/lib"
require 'i18n'
-end
\ No newline at end of file
+# end
\ No newline at end of file
--
cgit v1.2.3
From 2fe4d350e98d7f825cf3d1f9233075a5a79e32a1 Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Thu, 19 Jun 2008 18:31:11 +0200
Subject: make ActiveRecord::Errors.default_error_messages look up translated
error messages
---
activerecord/lib/active_record/validations.rb | 33 ++++++---------------------
1 file changed, 7 insertions(+), 26 deletions(-)
diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb
index f54fb80137..0ca68989d2 100755
--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -18,37 +18,18 @@ module ActiveRecord
# determine whether the object is in a valid state to be saved. See usage example in Validations.
class Errors
include Enumerable
+
+ class << self
+ def default_error_messages
+ # TODO deprecate this?
+ :'active_record.error_messages'.t
+ end
+ end
def initialize(base) # :nodoc:
@base, @errors = base, {}
end
- # @@default_error_messages = {
- # :inclusion => "is not included in the list",
- # :exclusion => "is reserved",
- # :invalid => "is invalid",
- # :confirmation => "doesn't match confirmation",
- # :accepted => "must be accepted",
- # :empty => "can't be empty",
- # :blank => "can't be blank",
- # :too_long => "is too long (maximum is %d characters)",
- # :too_short => "is too short (minimum is %d characters)",
- # :wrong_length => "is the wrong length (should be %d characters)",
- # :taken => "has already been taken",
- # :not_a_number => "is not a number",
- # :greater_than => "must be greater than %d",
- # :greater_than_or_equal_to => "must be greater than or equal to %d",
- # :equal_to => "must be equal to %d",
- # :less_than => "must be less than %d",
- # :less_than_or_equal_to => "must be less than or equal to %d",
- # :odd => "must be odd",
- # :even => "must be even"
- # }
- #
- # # Holds a hash with all the default error messages that can be replaced by your own copy or localizations.
- # cattr_accessor :default_error_messages
-
-
# Adds an error to the base object instead of any particular attribute. This is used
# to report errors that don't tie to any specific attribute, but rather to the object
# as a whole. These error messages don't get prepended with any field name when iterating
--
cgit v1.2.3
From b09c6e7444cf05f986e601bcc22cf17ede7b63bd Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Thu, 19 Jun 2008 19:08:14 +0200
Subject: add a generic tranlate view helper
---
actionpack/lib/action_view/helpers/i18n_helper.rb | 19 +++++++++++++
actionpack/test/template/i18n_helper_test.rb | 33 +++++++++++++++++++++++
2 files changed, 52 insertions(+)
create mode 100644 actionpack/lib/action_view/helpers/i18n_helper.rb
create mode 100644 actionpack/test/template/i18n_helper_test.rb
diff --git a/actionpack/lib/action_view/helpers/i18n_helper.rb b/actionpack/lib/action_view/helpers/i18n_helper.rb
new file mode 100644
index 0000000000..1b1d1f301d
--- /dev/null
+++ b/actionpack/lib/action_view/helpers/i18n_helper.rb
@@ -0,0 +1,19 @@
+module ActionView
+ module Helpers
+ module I18nHelper
+ def translate(*args)
+ # inserts the locale or current request locale to the argument list if no locale
+ # has been passed or the locale has been passed as part of the options hash
+ options = args.extract_options!
+ if args.size != 2
+ locale = options.delete :locale
+ locale ||= request.locale if respond_to? :request
+ args << locale if locale
+ end
+ args << options unless options.empty?
+ I18n.translate *args
+ end
+ alias :t :translate
+ end
+ end
+end
\ No newline at end of file
diff --git a/actionpack/test/template/i18n_helper_test.rb b/actionpack/test/template/i18n_helper_test.rb
new file mode 100644
index 0000000000..598731568c
--- /dev/null
+++ b/actionpack/test/template/i18n_helper_test.rb
@@ -0,0 +1,33 @@
+require 'abstract_unit'
+require 'action_view/helpers/i18n_helper'
+
+class I18nHelperTests < Test::Unit::TestCase
+ include ActionView::Helpers::I18nHelper
+
+ attr_reader :request
+ def setup
+ @request = stub :locale => 'en-US'
+ I18n.stubs(:translate).with(:'foo.bar', 'en-US').returns 'Foo Bar'
+ end
+
+ def test_translate_given_a_locale_argument_it_does_not_check_request_for_locale
+ request.expects(:locale).never
+ assert_equal 'Foo Bar', translate(:'foo.bar', :locale => 'en-US')
+ end
+
+ def test_translate_given_a_locale_option_it_does_not_check_request_for_locale
+ request.expects(:locale).never
+ I18n.expects(:translate).with(:'foo.bar', 'en-US').returns 'Foo Bar'
+ assert_equal 'Foo Bar', translate(:'foo.bar', :locale => 'en-US')
+ end
+
+ def test_translate_given_no_locale_it_checks_request_for_locale
+ request.expects(:locale).returns 'en-US'
+ assert_equal 'Foo Bar', translate(:'foo.bar')
+ end
+
+ def test_translate_delegates_to_i18n_translate
+ I18n.expects(:translate).with(:'foo.bar', 'en-US').returns 'Foo Bar'
+ assert_equal 'Foo Bar', translate(:'foo.bar')
+ end
+end
\ No newline at end of file
--
cgit v1.2.3
From 585c8c17c303fc46fcf014a644a541eae6cb5ffd Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Fri, 20 Jun 2008 09:13:20 +0200
Subject: rename Backend::Simple#add_translations to set_translations because
it overwrites existing translations
---
.../lib/action_view/helpers/form_options_helper.rb | 2 +-
actionpack/lib/action_view/lang/en-US.rb | 2 +-
.../test/template/number_helper_i18n_test.rb | 2 +-
activerecord/lib/active_record/lang/en-US.rb | 2 +-
activerecord/lib/active_record/validations.rb | 2 +-
activerecord/test/cases/validations_i18n_test.rb | 80 +++++++++++-----------
activesupport/lib/active_support/lang/en-US.rb | 2 +-
activesupport/lib/active_support/vendor/i18n-0.0.1 | 2 +-
8 files changed, 47 insertions(+), 47 deletions(-)
diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb
index c782c0a816..a6b9e65a77 100644
--- a/actionpack/lib/action_view/helpers/form_options_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -349,7 +349,7 @@ module ActionView
end
# All the countries included in the country_options output.
- # only included for backwards compatibility, please use the I18n interface
+ # deprecated. please use :'countries.names'.t directly
COUNTRIES = :'countries.names'.t 'en-US' unless const_defined?("COUNTRIES")
end
diff --git a/actionpack/lib/action_view/lang/en-US.rb b/actionpack/lib/action_view/lang/en-US.rb
index 659f96a5f3..70eb1b79de 100644
--- a/actionpack/lib/action_view/lang/en-US.rb
+++ b/actionpack/lib/action_view/lang/en-US.rb
@@ -1,4 +1,4 @@
-I18n.backend.add_translations :'en-US', {
+I18n.backend.set_translations :'en-US', {
:date => {
:formats => {
:default => "%Y-%m-%d",
diff --git a/actionpack/test/template/number_helper_i18n_test.rb b/actionpack/test/template/number_helper_i18n_test.rb
index 47cb035f56..d002ad4a2f 100644
--- a/actionpack/test/template/number_helper_i18n_test.rb
+++ b/actionpack/test/template/number_helper_i18n_test.rb
@@ -7,7 +7,7 @@ class NumberHelperI18nTests < Test::Unit::TestCase
def setup
@request = mock
@defaults = {:separator => ".", :unit => "$", :format => "%u%n", :delimiter => ",", :precision => 2}
- I18n.backend.add_translations 'en-US', :currency => {:format => @defaults}
+ I18n.backend.set_translations 'en-US', :currency => {:format => @defaults}
end
def test_number_to_currency_given_a_locale_it_does_not_check_request_for_locale
diff --git a/activerecord/lib/active_record/lang/en-US.rb b/activerecord/lib/active_record/lang/en-US.rb
index 7c3bcfd85e..f307f40f1a 100644
--- a/activerecord/lib/active_record/lang/en-US.rb
+++ b/activerecord/lib/active_record/lang/en-US.rb
@@ -1,4 +1,4 @@
-I18n.backend.add_translations :'en-US', {
+I18n.backend.set_translations :'en-US', {
:active_record => {
:error_messages => {
:inclusion => "is not included in the list",
diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb
index 0ca68989d2..bcb204f1ba 100755
--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -21,7 +21,7 @@ module ActiveRecord
class << self
def default_error_messages
- # TODO deprecate this?
+ # ActiveSupport::Deprecation.warn("ActiveRecord::Errors.default_error_messages has been deprecated. Please use :'active_record.error_messages'.t.")
:'active_record.error_messages'.t
end
end
diff --git a/activerecord/test/cases/validations_i18n_test.rb b/activerecord/test/cases/validations_i18n_test.rb
index eb454fca20..8f8574c242 100644
--- a/activerecord/test/cases/validations_i18n_test.rb
+++ b/activerecord/test/cases/validations_i18n_test.rb
@@ -6,7 +6,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def setup
reset_callbacks Topic
@topic = Topic.new
- I18n.backend.add_translations('en-US', :active_record => {:error_messages => {:custom => nil}})
+ I18n.backend.set_translations('en-US', :active_record => {:error_messages => {:custom => nil}})
end
def teardown
@@ -113,8 +113,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_confirmation_of_finds_custom_model_key_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:confirmation => 'custom message'}}}}}
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:confirmation => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:confirmation => 'custom message'}}}}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:confirmation => 'global message'}}
Topic.validates_confirmation_of :title
@topic.title_confirmation = 'foo'
@@ -123,7 +123,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_confirmation_of_finds_global_default_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:confirmation => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:confirmation => 'global message'}}
Topic.validates_confirmation_of :title
@topic.title_confirmation = 'foo'
@@ -147,8 +147,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_acceptance_of_finds_custom_model_key_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:accepted => 'custom message'}}}}}
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:accepted => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:accepted => 'custom message'}}}}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:accepted => 'global message'}}
Topic.validates_acceptance_of :title, :allow_nil => false
@topic.valid?
@@ -156,7 +156,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_acceptance_of_finds_global_default_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:accepted => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:accepted => 'global message'}}
Topic.validates_acceptance_of :title, :allow_nil => false
@topic.valid?
@@ -179,8 +179,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_presence_of_finds_custom_model_key_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:blank => 'custom message'}}}}}
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:blank => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:blank => 'custom message'}}}}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:blank => 'global message'}}
Topic.validates_presence_of :title
@topic.valid?
@@ -188,7 +188,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_presence_of_finds_global_default_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:blank => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:blank => 'global message'}}
Topic.validates_presence_of :title
@topic.valid?
@@ -211,8 +211,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_length_of_within_finds_custom_model_key_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:too_short => 'custom message'}}}}}
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:too_short => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:too_short => 'custom message'}}}}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:too_short => 'global message'}}
Topic.validates_length_of :title, :within => 3..5
@topic.valid?
@@ -220,7 +220,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_length_of_within_finds_global_default_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:too_short => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:too_short => 'global message'}}
Topic.validates_length_of :title, :within => 3..5
@topic.valid?
@@ -243,8 +243,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_length_of_within_finds_custom_model_key_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:wrong_length => 'custom message'}}}}}
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:wrong_length => 'custom message'}}}}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
Topic.validates_length_of :title, :is => 5
@topic.valid?
@@ -252,7 +252,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_length_of_within_finds_global_default_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
Topic.validates_length_of :title, :is => 5
@topic.valid?
@@ -277,8 +277,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_length_of_within_finds_custom_model_key_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:wrong_length => 'custom message'}}}}}
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:wrong_length => 'custom message'}}}}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
Topic.validates_length_of :title, :is => 5
@topic.valid?
@@ -286,7 +286,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_length_of_within_finds_global_default_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
Topic.validates_length_of :title, :is => 5
@topic.valid?
@@ -311,8 +311,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_format_of_finds_custom_model_key_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:invalid => 'custom message'}}}}}
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:invalid => 'custom message'}}}}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
Topic.validates_format_of :title, :with => /^[1-9][0-9]*$/
@topic.valid?
@@ -320,7 +320,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_format_of_finds_global_default_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
Topic.validates_format_of :title, :with => /^[1-9][0-9]*$/
@topic.valid?
@@ -345,8 +345,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_inclusion_of_finds_custom_model_key_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:inclusion => 'custom message'}}}}}
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:inclusion => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:inclusion => 'custom message'}}}}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:inclusion => 'global message'}}
Topic.validates_inclusion_of :title, :in => %w(a b c)
@topic.valid?
@@ -354,7 +354,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_inclusion_of_finds_global_default_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:inclusion => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:inclusion => 'global message'}}
Topic.validates_inclusion_of :title, :in => %w(a b c)
@topic.valid?
@@ -379,8 +379,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_exclusion_of_finds_custom_model_key_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:exclusion => 'custom message'}}}}}
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:exclusion => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:exclusion => 'custom message'}}}}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:exclusion => 'global message'}}
Topic.validates_exclusion_of :title, :in => %w(a b c)
@topic.title = 'a'
@@ -389,7 +389,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_exclusion_of_finds_global_default_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:exclusion => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:exclusion => 'global message'}}
Topic.validates_exclusion_of :title, :in => %w(a b c)
@topic.title = 'a'
@@ -415,8 +415,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_numericality_of_only_integer_finds_custom_model_key_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:not_a_number => 'custom message'}}}}}
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:not_a_number => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:not_a_number => 'custom message'}}}}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:not_a_number => 'global message'}}
Topic.validates_numericality_of :title, :only_integer => true
@topic.title = 'a'
@@ -425,7 +425,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_numericality_of_only_integer_finds_global_default_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:not_a_number => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:not_a_number => 'global message'}}
Topic.validates_numericality_of :title, :only_integer => true
@topic.title = 'a'
@@ -451,8 +451,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_numericality_of_odd_finds_custom_model_key_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:odd => 'custom message'}}}}}
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:odd => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:odd => 'custom message'}}}}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:odd => 'global message'}}
Topic.validates_numericality_of :title, :only_integer => true, :odd => true
@topic.title = 0
@@ -461,7 +461,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_numericality_of_odd_finds_global_default_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:odd => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:odd => 'global message'}}
Topic.validates_numericality_of :title, :only_integer => true, :odd => true
@topic.title = 0
@@ -487,8 +487,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_numericality_of_less_than_finds_custom_model_key_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:less_than => 'custom message'}}}}}
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:less_than => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:less_than => 'custom message'}}}}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:less_than => 'global message'}}
Topic.validates_numericality_of :title, :only_integer => true, :less_than => 0
@topic.title = 1
@@ -497,7 +497,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_numericality_of_less_than_finds_global_default_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:less_than => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:less_than => 'global message'}}
Topic.validates_numericality_of :title, :only_integer => true, :less_than => 0
@topic.title = 1
@@ -521,8 +521,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_associated_finds_custom_model_key_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:replies => {:invalid => 'custom message'}}}}}
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:replies => {:invalid => 'custom message'}}}}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
Topic.validates_associated :replies
replied_topic.valid?
@@ -530,7 +530,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_associated_finds_global_default_translation
- I18n.backend.add_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
+ I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
Topic.validates_associated :replies
replied_topic.valid?
diff --git a/activesupport/lib/active_support/lang/en-US.rb b/activesupport/lib/active_support/lang/en-US.rb
index 8732927f48..5b8e04363e 100644
--- a/activesupport/lib/active_support/lang/en-US.rb
+++ b/activesupport/lib/active_support/lang/en-US.rb
@@ -1,4 +1,4 @@
-I18n.backend.add_translations :'en-US', {
+I18n.backend.set_translations :'en-US', {
:support => {
:array => {
:sentence_connector => 'and'
diff --git a/activesupport/lib/active_support/vendor/i18n-0.0.1 b/activesupport/lib/active_support/vendor/i18n-0.0.1
index 70ab0f3cc5..1af3435539 160000
--- a/activesupport/lib/active_support/vendor/i18n-0.0.1
+++ b/activesupport/lib/active_support/vendor/i18n-0.0.1
@@ -1 +1 @@
-Subproject commit 70ab0f3cc5921cc67e09741939a08b2582d707cb
+Subproject commit 1af3435539b4a0729c13d21c5df037a635fe98c1
--
cgit v1.2.3
From c1e2506494107892a0962b8491cd234f77949c08 Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Sat, 21 Jun 2008 11:27:19 +0200
Subject: Changed process of storing translations from the client libraries to
the backend: clients now can pass a block to backend#populate which can
contain code to load and register translations.
This makes sense for backends that persist their translations (e.g. to db)
so the repeated loading and passing of translations throughout the server
startup would be wasted resources.
---
actionpack/lib/action_view.rb | 4 +-
actionpack/lib/action_view/lang/en-US.rb | 2 +-
.../test/template/number_helper_i18n_test.rb | 2 +-
activerecord/lib/active_record.rb | 5 +-
activerecord/lib/active_record/lang/en-US.rb | 2 +-
activerecord/test/cases/validations_i18n_test.rb | 80 +++++++++++-----------
activesupport/lib/active_support.rb | 5 +-
activesupport/lib/active_support/lang/en-US.rb | 2 +-
activesupport/lib/active_support/vendor/i18n-0.0.1 | 2 +-
9 files changed, 56 insertions(+), 48 deletions(-)
diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb
index 33d50a61c4..dff487377f 100644
--- a/actionpack/lib/action_view.rb
+++ b/actionpack/lib/action_view.rb
@@ -32,7 +32,9 @@ require 'action_view/base'
require 'action_view/partials'
require 'action_view/template_error'
-require 'action_view/lang/en-US.rb'
+I18n.backend.populate do
+ require 'action_view/lang/en-US.rb'
+end
ActionView::Base.class_eval do
include ActionView::Partials
diff --git a/actionpack/lib/action_view/lang/en-US.rb b/actionpack/lib/action_view/lang/en-US.rb
index 70eb1b79de..6b5345ed90 100644
--- a/actionpack/lib/action_view/lang/en-US.rb
+++ b/actionpack/lib/action_view/lang/en-US.rb
@@ -1,4 +1,4 @@
-I18n.backend.set_translations :'en-US', {
+I18n.backend.store_translations :'en-US', {
:date => {
:formats => {
:default => "%Y-%m-%d",
diff --git a/actionpack/test/template/number_helper_i18n_test.rb b/actionpack/test/template/number_helper_i18n_test.rb
index d002ad4a2f..b75af03378 100644
--- a/actionpack/test/template/number_helper_i18n_test.rb
+++ b/actionpack/test/template/number_helper_i18n_test.rb
@@ -7,7 +7,7 @@ class NumberHelperI18nTests < Test::Unit::TestCase
def setup
@request = mock
@defaults = {:separator => ".", :unit => "$", :format => "%u%n", :delimiter => ",", :precision => 2}
- I18n.backend.set_translations 'en-US', :currency => {:format => @defaults}
+ I18n.backend.store_translations 'en-US', :currency => {:format => @defaults}
end
def test_number_to_currency_given_a_locale_it_does_not_check_request_for_locale
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index b379bd26f8..71882833d4 100755
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -81,4 +81,7 @@ require 'active_record/connection_adapters/abstract_adapter'
require 'active_record/schema_dumper'
-require 'active_record/lang/en-US.rb'
+I18n.backend.populate do
+ require 'active_record/lang/en-US.rb'
+end
+
diff --git a/activerecord/lib/active_record/lang/en-US.rb b/activerecord/lib/active_record/lang/en-US.rb
index f307f40f1a..b31e13ed3a 100644
--- a/activerecord/lib/active_record/lang/en-US.rb
+++ b/activerecord/lib/active_record/lang/en-US.rb
@@ -1,4 +1,4 @@
-I18n.backend.set_translations :'en-US', {
+I18n.backend.store_translations :'en-US', {
:active_record => {
:error_messages => {
:inclusion => "is not included in the list",
diff --git a/activerecord/test/cases/validations_i18n_test.rb b/activerecord/test/cases/validations_i18n_test.rb
index 8f8574c242..de844bf5a6 100644
--- a/activerecord/test/cases/validations_i18n_test.rb
+++ b/activerecord/test/cases/validations_i18n_test.rb
@@ -6,7 +6,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def setup
reset_callbacks Topic
@topic = Topic.new
- I18n.backend.set_translations('en-US', :active_record => {:error_messages => {:custom => nil}})
+ I18n.backend.store_translations('en-US', :active_record => {:error_messages => {:custom => nil}})
end
def teardown
@@ -113,8 +113,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_confirmation_of_finds_custom_model_key_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:confirmation => 'custom message'}}}}}
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:confirmation => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:confirmation => 'custom message'}}}}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:confirmation => 'global message'}}
Topic.validates_confirmation_of :title
@topic.title_confirmation = 'foo'
@@ -123,7 +123,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_confirmation_of_finds_global_default_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:confirmation => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:confirmation => 'global message'}}
Topic.validates_confirmation_of :title
@topic.title_confirmation = 'foo'
@@ -147,8 +147,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_acceptance_of_finds_custom_model_key_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:accepted => 'custom message'}}}}}
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:accepted => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:accepted => 'custom message'}}}}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:accepted => 'global message'}}
Topic.validates_acceptance_of :title, :allow_nil => false
@topic.valid?
@@ -156,7 +156,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_acceptance_of_finds_global_default_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:accepted => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:accepted => 'global message'}}
Topic.validates_acceptance_of :title, :allow_nil => false
@topic.valid?
@@ -179,8 +179,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_presence_of_finds_custom_model_key_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:blank => 'custom message'}}}}}
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:blank => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:blank => 'custom message'}}}}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:blank => 'global message'}}
Topic.validates_presence_of :title
@topic.valid?
@@ -188,7 +188,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_presence_of_finds_global_default_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:blank => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:blank => 'global message'}}
Topic.validates_presence_of :title
@topic.valid?
@@ -211,8 +211,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_length_of_within_finds_custom_model_key_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:too_short => 'custom message'}}}}}
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:too_short => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:too_short => 'custom message'}}}}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:too_short => 'global message'}}
Topic.validates_length_of :title, :within => 3..5
@topic.valid?
@@ -220,7 +220,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_length_of_within_finds_global_default_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:too_short => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:too_short => 'global message'}}
Topic.validates_length_of :title, :within => 3..5
@topic.valid?
@@ -243,8 +243,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_length_of_within_finds_custom_model_key_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:wrong_length => 'custom message'}}}}}
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:wrong_length => 'custom message'}}}}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
Topic.validates_length_of :title, :is => 5
@topic.valid?
@@ -252,7 +252,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_length_of_within_finds_global_default_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
Topic.validates_length_of :title, :is => 5
@topic.valid?
@@ -277,8 +277,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_length_of_within_finds_custom_model_key_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:wrong_length => 'custom message'}}}}}
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:wrong_length => 'custom message'}}}}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
Topic.validates_length_of :title, :is => 5
@topic.valid?
@@ -286,7 +286,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_length_of_within_finds_global_default_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
Topic.validates_length_of :title, :is => 5
@topic.valid?
@@ -311,8 +311,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_format_of_finds_custom_model_key_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:invalid => 'custom message'}}}}}
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:invalid => 'custom message'}}}}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
Topic.validates_format_of :title, :with => /^[1-9][0-9]*$/
@topic.valid?
@@ -320,7 +320,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_format_of_finds_global_default_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
Topic.validates_format_of :title, :with => /^[1-9][0-9]*$/
@topic.valid?
@@ -345,8 +345,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_inclusion_of_finds_custom_model_key_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:inclusion => 'custom message'}}}}}
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:inclusion => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:inclusion => 'custom message'}}}}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:inclusion => 'global message'}}
Topic.validates_inclusion_of :title, :in => %w(a b c)
@topic.valid?
@@ -354,7 +354,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_inclusion_of_finds_global_default_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:inclusion => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:inclusion => 'global message'}}
Topic.validates_inclusion_of :title, :in => %w(a b c)
@topic.valid?
@@ -379,8 +379,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_exclusion_of_finds_custom_model_key_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:exclusion => 'custom message'}}}}}
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:exclusion => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:exclusion => 'custom message'}}}}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:exclusion => 'global message'}}
Topic.validates_exclusion_of :title, :in => %w(a b c)
@topic.title = 'a'
@@ -389,7 +389,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_exclusion_of_finds_global_default_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:exclusion => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:exclusion => 'global message'}}
Topic.validates_exclusion_of :title, :in => %w(a b c)
@topic.title = 'a'
@@ -415,8 +415,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_numericality_of_only_integer_finds_custom_model_key_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:not_a_number => 'custom message'}}}}}
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:not_a_number => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:not_a_number => 'custom message'}}}}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:not_a_number => 'global message'}}
Topic.validates_numericality_of :title, :only_integer => true
@topic.title = 'a'
@@ -425,7 +425,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_numericality_of_only_integer_finds_global_default_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:not_a_number => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:not_a_number => 'global message'}}
Topic.validates_numericality_of :title, :only_integer => true
@topic.title = 'a'
@@ -451,8 +451,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_numericality_of_odd_finds_custom_model_key_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:odd => 'custom message'}}}}}
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:odd => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:odd => 'custom message'}}}}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:odd => 'global message'}}
Topic.validates_numericality_of :title, :only_integer => true, :odd => true
@topic.title = 0
@@ -461,7 +461,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_numericality_of_odd_finds_global_default_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:odd => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:odd => 'global message'}}
Topic.validates_numericality_of :title, :only_integer => true, :odd => true
@topic.title = 0
@@ -487,8 +487,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_numericality_of_less_than_finds_custom_model_key_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:less_than => 'custom message'}}}}}
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:less_than => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:less_than => 'custom message'}}}}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:less_than => 'global message'}}
Topic.validates_numericality_of :title, :only_integer => true, :less_than => 0
@topic.title = 1
@@ -497,7 +497,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_numericality_of_less_than_finds_global_default_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:less_than => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:less_than => 'global message'}}
Topic.validates_numericality_of :title, :only_integer => true, :less_than => 0
@topic.title = 1
@@ -521,8 +521,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_associated_finds_custom_model_key_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:replies => {:invalid => 'custom message'}}}}}
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:replies => {:invalid => 'custom message'}}}}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
Topic.validates_associated :replies
replied_topic.valid?
@@ -530,7 +530,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
def test_validates_associated_finds_global_default_translation
- I18n.backend.set_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
Topic.validates_associated :replies
replied_topic.valid?
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index acdb3056d2..0de948dda9 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -55,7 +55,10 @@ require 'active_support/multibyte'
require 'active_support/base64'
require 'active_support/time_with_zone'
-require 'active_support/lang/en-US.rb'
+
+I18n.backend.populate do
+ require 'active_support/lang/en-US.rb'
+end
Inflector = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Inflector', 'ActiveSupport::Inflector')
Dependencies = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Dependencies', 'ActiveSupport::Dependencies')
diff --git a/activesupport/lib/active_support/lang/en-US.rb b/activesupport/lib/active_support/lang/en-US.rb
index 5b8e04363e..aa06fe14bd 100644
--- a/activesupport/lib/active_support/lang/en-US.rb
+++ b/activesupport/lib/active_support/lang/en-US.rb
@@ -1,4 +1,4 @@
-I18n.backend.set_translations :'en-US', {
+I18n.backend.store_translations :'en-US', {
:support => {
:array => {
:sentence_connector => 'and'
diff --git a/activesupport/lib/active_support/vendor/i18n-0.0.1 b/activesupport/lib/active_support/vendor/i18n-0.0.1
index 1af3435539..8e43afa38a 160000
--- a/activesupport/lib/active_support/vendor/i18n-0.0.1
+++ b/activesupport/lib/active_support/vendor/i18n-0.0.1
@@ -1 +1 @@
-Subproject commit 1af3435539b4a0729c13d21c5df037a635fe98c1
+Subproject commit 8e43afa38aa007d1de6d6acf44d43143c403d13f
--
cgit v1.2.3
From 428aa24d24032d382dc3d9ccf131e0c874043dbd Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Sat, 21 Jun 2008 11:35:02 +0200
Subject: Renamed lang/ to locale/ because that's what we seem to standarize
on. Also, in future this place can be used for data/code that's not literally
translations but conceptually belongs to the locale (like custom
pluralization algorithms etc.).
---
actionpack/lib/action_view.rb | 2 +-
actionpack/lib/action_view/lang/en-US.rb | 93 ------------------------
actionpack/lib/action_view/locale/en-US.rb | 93 ++++++++++++++++++++++++
activerecord/lib/active_record.rb | 2 +-
activerecord/lib/active_record/lang/en-US.rb | 25 -------
activerecord/lib/active_record/locale/en-US.rb | 25 +++++++
activerecord/test/cases/validations_i18n_test.rb | 2 +-
activesupport/lib/active_support.rb | 2 +-
activesupport/lib/active_support/lang/en-US.rb | 7 --
activesupport/lib/active_support/locale/en-US.rb | 7 ++
10 files changed, 129 insertions(+), 129 deletions(-)
delete mode 100644 actionpack/lib/action_view/lang/en-US.rb
create mode 100644 actionpack/lib/action_view/locale/en-US.rb
delete mode 100644 activerecord/lib/active_record/lang/en-US.rb
create mode 100644 activerecord/lib/active_record/locale/en-US.rb
delete mode 100644 activesupport/lib/active_support/lang/en-US.rb
create mode 100644 activesupport/lib/active_support/locale/en-US.rb
diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb
index dff487377f..067a871f79 100644
--- a/actionpack/lib/action_view.rb
+++ b/actionpack/lib/action_view.rb
@@ -33,7 +33,7 @@ require 'action_view/partials'
require 'action_view/template_error'
I18n.backend.populate do
- require 'action_view/lang/en-US.rb'
+ require 'action_view/locale/en-US.rb'
end
ActionView::Base.class_eval do
diff --git a/actionpack/lib/action_view/lang/en-US.rb b/actionpack/lib/action_view/lang/en-US.rb
deleted file mode 100644
index 6b5345ed90..0000000000
--- a/actionpack/lib/action_view/lang/en-US.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-I18n.backend.store_translations :'en-US', {
- :date => {
- :formats => {
- :default => "%Y-%m-%d",
- :short => "%b %d",
- :long => "%B %d, %Y",
- },
- :day_names => Date::DAYNAMES,
- :abbr_day_names => Date::ABBR_DAYNAMES,
- :month_names => Date::MONTHNAMES,
- :abbr_month_names => Date::ABBR_MONTHNAMES,
- :order => [:year, :month, :day]
- },
- :time => {
- :formats => {
- :default => "%a, %d %b %Y %H:%M:%S %z",
- :short => "%d %b %H:%M",
- :long => "%B %d, %Y %H:%M",
- },
- :am => 'am',
- :pm => 'pm'
- },
- :datetime => {
- :distance_in_words => {
- :half_a_minute => 'half a minute',
- :less_than_x_seconds => ['less than 1 second', 'less than {{count}} seconds'],
- :x_seconds => ['1 second', '{{count}} seconds'],
- :less_than_x_minutes => ['less than a minute', 'less than {{count}} minutes'],
- :x_minutes => ['1 minute', '{{count}} minutes'],
- :about_x_hours => ['about 1 hour', 'about {{count}} hours'],
- :x_days => ['1 day', '{{count}} days'],
- :about_x_months => ['about 1 month', 'about {{count}} months'],
- :x_months => ['1 month', '{{count}} months'],
- :about_x_years => ['about 1 year', 'about {{count}} year'],
- :over_x_years => ['over 1 year', 'over {{count}} years']
- }
- },
- :currency => {
- :format => {
- :unit => '$',
- :precision => 2,
- :separator => '.',
- :delimiter => ',',
- :format => '%u%n',
- }
- },
- :countries => {
- :names => ["Afghanistan", "Aland Islands", "Albania", "Algeria", "American Samoa", "Andorra", "Angola",
- "Anguilla", "Antarctica", "Antigua And Barbuda", "Argentina", "Armenia", "Aruba", "Australia", "Austria",
- "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin",
- "Bermuda", "Bhutan", "Bolivia", "Bosnia and Herzegowina", "Botswana", "Bouvet Island", "Brazil",
- "British Indian Ocean Territory", "Brunei Darussalam", "Bulgaria", "Burkina Faso", "Burundi", "Cambodia",
- "Cameroon", "Canada", "Cape Verde", "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
- "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
- "Congo, the Democratic Republic of the", "Cook Islands", "Costa Rica", "Cote d'Ivoire", "Croatia", "Cuba",
- "Cyprus", "Czech Republic", "Denmark", "Djibouti", "Dominica", "Dominican Republic", "Ecuador", "Egypt",
- "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Falkland Islands (Malvinas)",
- "Faroe Islands", "Fiji", "Finland", "France", "French Guiana", "French Polynesia",
- "French Southern Territories", "Gabon", "Gambia", "Georgia", "Germany", "Ghana", "Gibraltar", "Greece",
- "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guernsey", "Guinea",
- "Guinea-Bissau", "Guyana", "Haiti", "Heard and McDonald Islands", "Holy See (Vatican City State)",
- "Honduras", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Iran, Islamic Republic of", "Iraq",
- "Ireland", "Isle of Man", "Israel", "Italy", "Jamaica", "Japan", "Jersey", "Jordan", "Kazakhstan", "Kenya",
- "Kiribati", "Korea, Democratic People's Republic of", "Korea, Republic of", "Kuwait", "Kyrgyzstan",
- "Lao People's Democratic Republic", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libyan Arab Jamahiriya",
- "Liechtenstein", "Lithuania", "Luxembourg", "Macao", "Macedonia, The Former Yugoslav Republic Of",
- "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Martinique",
- "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia, Federated States of", "Moldova, Republic of",
- "Monaco", "Mongolia", "Montenegro", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia", "Nauru",
- "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand", "Nicaragua", "Niger",
- "Nigeria", "Niue", "Norfolk Island", "Northern Mariana Islands", "Norway", "Oman", "Pakistan", "Palau",
- "Palestinian Territory, Occupied", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines",
- "Pitcairn", "Poland", "Portugal", "Puerto Rico", "Qatar", "Reunion", "Romania", "Russian Federation",
- "Rwanda", "Saint Barthelemy", "Saint Helena", "Saint Kitts and Nevis", "Saint Lucia",
- "Saint Pierre and Miquelon", "Saint Vincent and the Grenadines", "Samoa", "San Marino",
- "Sao Tome and Principe", "Saudi Arabia", "Senegal", "Serbia", "Seychelles", "Sierra Leone", "Singapore",
- "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa",
- "South Georgia and the South Sandwich Islands", "Spain", "Sri Lanka", "Sudan", "Suriname",
- "Svalbard and Jan Mayen", "Swaziland", "Sweden", "Switzerland", "Syrian Arab Republic",
- "Taiwan, Province of China", "Tajikistan", "Tanzania, United Republic of", "Thailand", "Timor-Leste",
- "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan",
- "Turks and Caicos Islands", "Tuvalu", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom",
- "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan", "Vanuatu", "Venezuela",
- "Viet Nam", "Virgin Islands, British", "Virgin Islands, U.S.", "Wallis and Futuna", "Western Sahara",
- "Yemen", "Zambia", "Zimbabwe"]
- },
- :active_record => {
- :error => {
- :header_message => ["1 error prohibited this {{object_name}} from being saved", "{{count}} errors prohibited this {{object_name}} from being saved"],
- :message => "There were problems with the following fields:"
- }
- }
-}
diff --git a/actionpack/lib/action_view/locale/en-US.rb b/actionpack/lib/action_view/locale/en-US.rb
new file mode 100644
index 0000000000..6b5345ed90
--- /dev/null
+++ b/actionpack/lib/action_view/locale/en-US.rb
@@ -0,0 +1,93 @@
+I18n.backend.store_translations :'en-US', {
+ :date => {
+ :formats => {
+ :default => "%Y-%m-%d",
+ :short => "%b %d",
+ :long => "%B %d, %Y",
+ },
+ :day_names => Date::DAYNAMES,
+ :abbr_day_names => Date::ABBR_DAYNAMES,
+ :month_names => Date::MONTHNAMES,
+ :abbr_month_names => Date::ABBR_MONTHNAMES,
+ :order => [:year, :month, :day]
+ },
+ :time => {
+ :formats => {
+ :default => "%a, %d %b %Y %H:%M:%S %z",
+ :short => "%d %b %H:%M",
+ :long => "%B %d, %Y %H:%M",
+ },
+ :am => 'am',
+ :pm => 'pm'
+ },
+ :datetime => {
+ :distance_in_words => {
+ :half_a_minute => 'half a minute',
+ :less_than_x_seconds => ['less than 1 second', 'less than {{count}} seconds'],
+ :x_seconds => ['1 second', '{{count}} seconds'],
+ :less_than_x_minutes => ['less than a minute', 'less than {{count}} minutes'],
+ :x_minutes => ['1 minute', '{{count}} minutes'],
+ :about_x_hours => ['about 1 hour', 'about {{count}} hours'],
+ :x_days => ['1 day', '{{count}} days'],
+ :about_x_months => ['about 1 month', 'about {{count}} months'],
+ :x_months => ['1 month', '{{count}} months'],
+ :about_x_years => ['about 1 year', 'about {{count}} year'],
+ :over_x_years => ['over 1 year', 'over {{count}} years']
+ }
+ },
+ :currency => {
+ :format => {
+ :unit => '$',
+ :precision => 2,
+ :separator => '.',
+ :delimiter => ',',
+ :format => '%u%n',
+ }
+ },
+ :countries => {
+ :names => ["Afghanistan", "Aland Islands", "Albania", "Algeria", "American Samoa", "Andorra", "Angola",
+ "Anguilla", "Antarctica", "Antigua And Barbuda", "Argentina", "Armenia", "Aruba", "Australia", "Austria",
+ "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin",
+ "Bermuda", "Bhutan", "Bolivia", "Bosnia and Herzegowina", "Botswana", "Bouvet Island", "Brazil",
+ "British Indian Ocean Territory", "Brunei Darussalam", "Bulgaria", "Burkina Faso", "Burundi", "Cambodia",
+ "Cameroon", "Canada", "Cape Verde", "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
+ "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
+ "Congo, the Democratic Republic of the", "Cook Islands", "Costa Rica", "Cote d'Ivoire", "Croatia", "Cuba",
+ "Cyprus", "Czech Republic", "Denmark", "Djibouti", "Dominica", "Dominican Republic", "Ecuador", "Egypt",
+ "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Falkland Islands (Malvinas)",
+ "Faroe Islands", "Fiji", "Finland", "France", "French Guiana", "French Polynesia",
+ "French Southern Territories", "Gabon", "Gambia", "Georgia", "Germany", "Ghana", "Gibraltar", "Greece",
+ "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guernsey", "Guinea",
+ "Guinea-Bissau", "Guyana", "Haiti", "Heard and McDonald Islands", "Holy See (Vatican City State)",
+ "Honduras", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Iran, Islamic Republic of", "Iraq",
+ "Ireland", "Isle of Man", "Israel", "Italy", "Jamaica", "Japan", "Jersey", "Jordan", "Kazakhstan", "Kenya",
+ "Kiribati", "Korea, Democratic People's Republic of", "Korea, Republic of", "Kuwait", "Kyrgyzstan",
+ "Lao People's Democratic Republic", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libyan Arab Jamahiriya",
+ "Liechtenstein", "Lithuania", "Luxembourg", "Macao", "Macedonia, The Former Yugoslav Republic Of",
+ "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Martinique",
+ "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia, Federated States of", "Moldova, Republic of",
+ "Monaco", "Mongolia", "Montenegro", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia", "Nauru",
+ "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand", "Nicaragua", "Niger",
+ "Nigeria", "Niue", "Norfolk Island", "Northern Mariana Islands", "Norway", "Oman", "Pakistan", "Palau",
+ "Palestinian Territory, Occupied", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines",
+ "Pitcairn", "Poland", "Portugal", "Puerto Rico", "Qatar", "Reunion", "Romania", "Russian Federation",
+ "Rwanda", "Saint Barthelemy", "Saint Helena", "Saint Kitts and Nevis", "Saint Lucia",
+ "Saint Pierre and Miquelon", "Saint Vincent and the Grenadines", "Samoa", "San Marino",
+ "Sao Tome and Principe", "Saudi Arabia", "Senegal", "Serbia", "Seychelles", "Sierra Leone", "Singapore",
+ "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa",
+ "South Georgia and the South Sandwich Islands", "Spain", "Sri Lanka", "Sudan", "Suriname",
+ "Svalbard and Jan Mayen", "Swaziland", "Sweden", "Switzerland", "Syrian Arab Republic",
+ "Taiwan, Province of China", "Tajikistan", "Tanzania, United Republic of", "Thailand", "Timor-Leste",
+ "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan",
+ "Turks and Caicos Islands", "Tuvalu", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom",
+ "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan", "Vanuatu", "Venezuela",
+ "Viet Nam", "Virgin Islands, British", "Virgin Islands, U.S.", "Wallis and Futuna", "Western Sahara",
+ "Yemen", "Zambia", "Zimbabwe"]
+ },
+ :active_record => {
+ :error => {
+ :header_message => ["1 error prohibited this {{object_name}} from being saved", "{{count}} errors prohibited this {{object_name}} from being saved"],
+ :message => "There were problems with the following fields:"
+ }
+ }
+}
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index 71882833d4..17a7949959 100755
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -82,6 +82,6 @@ require 'active_record/connection_adapters/abstract_adapter'
require 'active_record/schema_dumper'
I18n.backend.populate do
- require 'active_record/lang/en-US.rb'
+ require 'active_record/locale/en-US.rb'
end
diff --git a/activerecord/lib/active_record/lang/en-US.rb b/activerecord/lib/active_record/lang/en-US.rb
deleted file mode 100644
index b31e13ed3a..0000000000
--- a/activerecord/lib/active_record/lang/en-US.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-I18n.backend.store_translations :'en-US', {
- :active_record => {
- :error_messages => {
- :inclusion => "is not included in the list",
- :exclusion => "is reserved",
- :invalid => "is invalid",
- :confirmation => "doesn't match confirmation",
- :accepted => "must be accepted",
- :empty => "can't be empty",
- :blank => "can't be blank",
- :too_long => "is too long (maximum is {{count}} characters)",
- :too_short => "is too short (minimum is {{count}} characters)",
- :wrong_length => "is the wrong length (should be {{count}} characters)",
- :taken => "has already been taken",
- :not_a_number => "is not a number",
- :greater_than => "must be greater than {{count}}",
- :greater_than_or_equal_to => "must be greater than or equal to {{count}}",
- :equal_to => "must be equal to {{count}}",
- :less_than => "must be less than {{count}}",
- :less_than_or_equal_to => "must be less than or equal to {{count}}",
- :odd => "must be odd",
- :even => "must be even"
- }
- }
-}
\ No newline at end of file
diff --git a/activerecord/lib/active_record/locale/en-US.rb b/activerecord/lib/active_record/locale/en-US.rb
new file mode 100644
index 0000000000..b31e13ed3a
--- /dev/null
+++ b/activerecord/lib/active_record/locale/en-US.rb
@@ -0,0 +1,25 @@
+I18n.backend.store_translations :'en-US', {
+ :active_record => {
+ :error_messages => {
+ :inclusion => "is not included in the list",
+ :exclusion => "is reserved",
+ :invalid => "is invalid",
+ :confirmation => "doesn't match confirmation",
+ :accepted => "must be accepted",
+ :empty => "can't be empty",
+ :blank => "can't be blank",
+ :too_long => "is too long (maximum is {{count}} characters)",
+ :too_short => "is too short (minimum is {{count}} characters)",
+ :wrong_length => "is the wrong length (should be {{count}} characters)",
+ :taken => "has already been taken",
+ :not_a_number => "is not a number",
+ :greater_than => "must be greater than {{count}}",
+ :greater_than_or_equal_to => "must be greater than or equal to {{count}}",
+ :equal_to => "must be equal to {{count}}",
+ :less_than => "must be less than {{count}}",
+ :less_than_or_equal_to => "must be less than or equal to {{count}}",
+ :odd => "must be odd",
+ :even => "must be even"
+ }
+ }
+}
\ No newline at end of file
diff --git a/activerecord/test/cases/validations_i18n_test.rb b/activerecord/test/cases/validations_i18n_test.rb
index de844bf5a6..10e36b1512 100644
--- a/activerecord/test/cases/validations_i18n_test.rb
+++ b/activerecord/test/cases/validations_i18n_test.rb
@@ -11,7 +11,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def teardown
reset_callbacks Topic
- load 'active_record/lang/en-US.rb'
+ load 'active_record/locale/en-US.rb'
end
def unique_topic
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index 0de948dda9..de50aafe16 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -57,7 +57,7 @@ require 'active_support/base64'
require 'active_support/time_with_zone'
I18n.backend.populate do
- require 'active_support/lang/en-US.rb'
+ require 'active_support/locale/en-US.rb'
end
Inflector = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Inflector', 'ActiveSupport::Inflector')
diff --git a/activesupport/lib/active_support/lang/en-US.rb b/activesupport/lib/active_support/lang/en-US.rb
deleted file mode 100644
index aa06fe14bd..0000000000
--- a/activesupport/lib/active_support/lang/en-US.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-I18n.backend.store_translations :'en-US', {
- :support => {
- :array => {
- :sentence_connector => 'and'
- }
- }
-}
\ No newline at end of file
diff --git a/activesupport/lib/active_support/locale/en-US.rb b/activesupport/lib/active_support/locale/en-US.rb
new file mode 100644
index 0000000000..aa06fe14bd
--- /dev/null
+++ b/activesupport/lib/active_support/locale/en-US.rb
@@ -0,0 +1,7 @@
+I18n.backend.store_translations :'en-US', {
+ :support => {
+ :array => {
+ :sentence_connector => 'and'
+ }
+ }
+}
\ No newline at end of file
--
cgit v1.2.3
From 8bfdabbd8b5137f91d8bcddc8c3d18961c8e316b Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Sat, 21 Jun 2008 17:50:37 +0200
Subject: incorporate #translate usage with several default keys (use first
default key that resolves to a translation). this might, depending on the
backend implementation save some expensive lookups (like db lookups)
---
activerecord/lib/active_record/validations.rb | 19 ++++-
activerecord/test/cases/validations_i18n_test.rb | 86 +++++++++-------------
activesupport/lib/active_support/vendor/i18n-0.0.1 | 2 +-
3 files changed, 52 insertions(+), 55 deletions(-)
diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb
index bcb204f1ba..49d3c59ca7 100755
--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -66,9 +66,11 @@ module ActiveRecord
end
def generate_message(attr, key, options = {})
- scope = [:active_record, :error_messages]
- key.t(options.merge(:scope => scope + [:custom, @base.class.name.downcase, attr])) ||
- key.t(options.merge(:scope => scope))
+ msgs = base_classes(@base.class).map{|klass| :"custom.#{klass.name.underscore}.#{attr}.#{key}"}
+ msgs << options[:default] if options[:default]
+ msgs << key
+
+ I18n.t options.merge(:default => msgs, :scope => [:active_record, :error_messages])
end
# Returns true if the specified +attribute+ has errors associated with it.
@@ -217,6 +219,17 @@ module ActiveRecord
full_messages.each { |msg| e.error(msg) }
end
end
+
+ protected
+
+ # TODO maybe this should be on ActiveRecord::Base, maybe #self_and_descendents_from_active_record
+ def base_classes(klass)
+ classes = [klass]
+ while klass != klass.base_class
+ classes << klass = klass.superclass
+ end
+ classes
+ end
end
diff --git a/activerecord/test/cases/validations_i18n_test.rb b/activerecord/test/cases/validations_i18n_test.rb
index 10e36b1512..37a7c1ce49 100644
--- a/activerecord/test/cases/validations_i18n_test.rb
+++ b/activerecord/test/cases/validations_i18n_test.rb
@@ -40,31 +40,15 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
global_scope = [:active_record, :error_messages]
custom_scope = global_scope + [:custom, 'topic', :title]
- I18n.expects(:translate).with(:invalid, :scope => custom_scope).returns 'translation'
- I18n.expects(:translate).with(:invalid, :scope => global_scope).never
-
- @topic.errors.generate_message :title, :invalid
+ I18n.expects(:t).with :scope => [:active_record, :error_messages], :default => [:"custom.topic.title.invalid", 'default from class def', :invalid]
+ @topic.errors.generate_message :title, :invalid, :default => 'default from class def'
end
- def test_errors_generate_message_given_a_custom_message_translates_custom_model_attribute_key_with_custom_message_as_default
+ def test_errors_generate_message_translates_custom_model_attribute_keys_with_sti
custom_scope = [:active_record, :error_messages, :custom, 'topic', :title]
- I18n.expects(:translate).with(:invalid, :scope => custom_scope, :default => 'default from class def').returns 'translation'
- @topic.errors.generate_message :title, :invalid, :default => 'default from class def'
- end
-
- def test_errors_generate_message_given_no_custom_message_falls_back_to_global_default_key_translation
- global_scope = [:active_record, :error_messages]
- custom_scope = global_scope + [:custom, 'topic', :title]
-
- I18n.stubs(:translate).with(:invalid, :scope => custom_scope).returns nil
- I18n.expects(:translate).with(:invalid, :scope => global_scope)
- @topic.errors.generate_message :title, :invalid
- end
-
- def test_errors_add_given_no_message_it_translates_invalid
- I18n.expects(:translate).with(:"active_record.error_messages.invalid")
- @topic.errors.add :title
+ I18n.expects(:t).with :scope => [:active_record, :error_messages], :default => [:"custom.reply.title.invalid", :"custom.topic.title.invalid", 'default from class def', :invalid]
+ Reply.new.errors.generate_message :title, :invalid, :default => 'default from class def'
end
def test_errors_add_on_empty_generates_message
@@ -115,7 +99,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_confirmation_of_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:confirmation => 'custom message'}}}}}
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:confirmation => 'global message'}}
-
+
Topic.validates_confirmation_of :title
@topic.title_confirmation = 'foo'
@topic.valid?
@@ -124,7 +108,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_confirmation_of_finds_global_default_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:confirmation => 'global message'}}
-
+
Topic.validates_confirmation_of :title
@topic.title_confirmation = 'foo'
@topic.valid?
@@ -133,13 +117,13 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
# validates_acceptance_of
-
+
def test_validates_acceptance_of_generates_message
Topic.validates_acceptance_of :title, :allow_nil => false
@topic.errors.expects(:generate_message).with(:title, :accepted, {:default => nil})
@topic.valid?
end
-
+
def test_validates_acceptance_of_generates_message_with_custom_default_message
Topic.validates_acceptance_of :title, :message => 'custom', :allow_nil => false
@topic.errors.expects(:generate_message).with(:title, :accepted, {:default => 'custom'})
@@ -149,7 +133,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_acceptance_of_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:accepted => 'custom message'}}}}}
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:accepted => 'global message'}}
-
+
Topic.validates_acceptance_of :title, :allow_nil => false
@topic.valid?
assert_equal 'custom message', @topic.errors.on(:title)
@@ -157,7 +141,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_acceptance_of_finds_global_default_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:accepted => 'global message'}}
-
+
Topic.validates_acceptance_of :title, :allow_nil => false
@topic.valid?
assert_equal 'global message', @topic.errors.on(:title)
@@ -165,7 +149,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
# validates_presence_of
-
+
def test_validates_presence_of_generates_message
Topic.validates_presence_of :title
@topic.errors.expects(:generate_message).with(:title, :blank, {:default => nil})
@@ -181,7 +165,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_presence_of_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:blank => 'custom message'}}}}}
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:blank => 'global message'}}
-
+
Topic.validates_presence_of :title
@topic.valid?
assert_equal 'custom message', @topic.errors.on(:title)
@@ -189,7 +173,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_presence_of_finds_global_default_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:blank => 'global message'}}
-
+
Topic.validates_presence_of :title
@topic.valid?
assert_equal 'global message', @topic.errors.on(:title)
@@ -197,7 +181,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
# validates_length_of :within
-
+
def test_validates_length_of_within_generates_message
Topic.validates_length_of :title, :within => 3..5
@topic.errors.expects(:generate_message).with(:title, :too_short, {:count => 3, :default => nil})
@@ -213,7 +197,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_length_of_within_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:too_short => 'custom message'}}}}}
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:too_short => 'global message'}}
-
+
Topic.validates_length_of :title, :within => 3..5
@topic.valid?
assert_equal 'custom message', @topic.errors.on(:title)
@@ -221,7 +205,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_length_of_within_finds_global_default_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:too_short => 'global message'}}
-
+
Topic.validates_length_of :title, :within => 3..5
@topic.valid?
assert_equal 'global message', @topic.errors.on(:title)
@@ -245,7 +229,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_length_of_within_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:wrong_length => 'custom message'}}}}}
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
-
+
Topic.validates_length_of :title, :is => 5
@topic.valid?
assert_equal 'custom message', @topic.errors.on(:title)
@@ -253,7 +237,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_length_of_within_finds_global_default_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
-
+
Topic.validates_length_of :title, :is => 5
@topic.valid?
assert_equal 'global message', @topic.errors.on(:title)
@@ -279,7 +263,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_length_of_within_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:wrong_length => 'custom message'}}}}}
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
-
+
Topic.validates_length_of :title, :is => 5
@topic.valid?
assert_equal 'custom message', @topic.errors.on(:title)
@@ -287,7 +271,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_length_of_within_finds_global_default_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:wrong_length => 'global message'}}
-
+
Topic.validates_length_of :title, :is => 5
@topic.valid?
assert_equal 'global message', @topic.errors.on(:title)
@@ -313,7 +297,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_format_of_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:invalid => 'custom message'}}}}}
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
-
+
Topic.validates_format_of :title, :with => /^[1-9][0-9]*$/
@topic.valid?
assert_equal 'custom message', @topic.errors.on(:title)
@@ -321,7 +305,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_format_of_finds_global_default_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
-
+
Topic.validates_format_of :title, :with => /^[1-9][0-9]*$/
@topic.valid?
assert_equal 'global message', @topic.errors.on(:title)
@@ -347,7 +331,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_inclusion_of_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:inclusion => 'custom message'}}}}}
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:inclusion => 'global message'}}
-
+
Topic.validates_inclusion_of :title, :in => %w(a b c)
@topic.valid?
assert_equal 'custom message', @topic.errors.on(:title)
@@ -355,7 +339,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_inclusion_of_finds_global_default_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:inclusion => 'global message'}}
-
+
Topic.validates_inclusion_of :title, :in => %w(a b c)
@topic.valid?
assert_equal 'global message', @topic.errors.on(:title)
@@ -381,7 +365,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_exclusion_of_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:exclusion => 'custom message'}}}}}
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:exclusion => 'global message'}}
-
+
Topic.validates_exclusion_of :title, :in => %w(a b c)
@topic.title = 'a'
@topic.valid?
@@ -390,7 +374,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_exclusion_of_finds_global_default_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:exclusion => 'global message'}}
-
+
Topic.validates_exclusion_of :title, :in => %w(a b c)
@topic.title = 'a'
@topic.valid?
@@ -417,7 +401,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_numericality_of_only_integer_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:not_a_number => 'custom message'}}}}}
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:not_a_number => 'global message'}}
-
+
Topic.validates_numericality_of :title, :only_integer => true
@topic.title = 'a'
@topic.valid?
@@ -426,7 +410,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_numericality_of_only_integer_finds_global_default_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:not_a_number => 'global message'}}
-
+
Topic.validates_numericality_of :title, :only_integer => true
@topic.title = 'a'
@topic.valid?
@@ -453,7 +437,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_numericality_of_odd_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:odd => 'custom message'}}}}}
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:odd => 'global message'}}
-
+
Topic.validates_numericality_of :title, :only_integer => true, :odd => true
@topic.title = 0
@topic.valid?
@@ -462,7 +446,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_numericality_of_odd_finds_global_default_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:odd => 'global message'}}
-
+
Topic.validates_numericality_of :title, :only_integer => true, :odd => true
@topic.title = 0
@topic.valid?
@@ -489,7 +473,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_numericality_of_less_than_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:less_than => 'custom message'}}}}}
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:less_than => 'global message'}}
-
+
Topic.validates_numericality_of :title, :only_integer => true, :less_than => 0
@topic.title = 1
@topic.valid?
@@ -498,7 +482,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_numericality_of_less_than_finds_global_default_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:less_than => 'global message'}}
-
+
Topic.validates_numericality_of :title, :only_integer => true, :less_than => 0
@topic.title = 1
@topic.valid?
@@ -523,7 +507,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_associated_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:replies => {:invalid => 'custom message'}}}}}
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
-
+
Topic.validates_associated :replies
replied_topic.valid?
assert_equal 'custom message', replied_topic.errors.on(:replies)
@@ -531,7 +515,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_validates_associated_finds_global_default_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:invalid => 'global message'}}
-
+
Topic.validates_associated :replies
replied_topic.valid?
assert_equal 'global message', replied_topic.errors.on(:replies)
diff --git a/activesupport/lib/active_support/vendor/i18n-0.0.1 b/activesupport/lib/active_support/vendor/i18n-0.0.1
index 8e43afa38a..20c331666b 160000
--- a/activesupport/lib/active_support/vendor/i18n-0.0.1
+++ b/activesupport/lib/active_support/vendor/i18n-0.0.1
@@ -1 +1 @@
-Subproject commit 8e43afa38aa007d1de6d6acf44d43143c403d13f
+Subproject commit 20c331666b3b6a21791d4cded53c3d8654fba714
--
cgit v1.2.3
From 55e2e2e8b4efbe6fdb0a921c19cd8be5650eab0a Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Sat, 21 Jun 2008 18:12:59 +0200
Subject: experimental DeprecatedConstantToMethodProxy
---
activesupport/lib/active_support/deprecation.rb | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/activesupport/lib/active_support/deprecation.rb b/activesupport/lib/active_support/deprecation.rb
index ebdaf86146..36933b007d 100644
--- a/activesupport/lib/active_support/deprecation.rb
+++ b/activesupport/lib/active_support/deprecation.rb
@@ -194,6 +194,23 @@ module ActiveSupport
ActiveSupport::Deprecation.warn("#{@old_const} is deprecated! Use #{@new_const} instead.", callstack)
end
end
+
+ class DeprecatedConstantToMethodProxy < DeprecationProxy #:nodoc:
+ def initialize(old_const, new_target, new_method)
+ @old_const = old_const
+ @new_target = new_target
+ @new_method = new_method
+ end
+
+ private
+ def target
+ @new_target.__send__(@new_method)
+ end
+
+ def warn(callstack, called, args)
+ ActiveSupport::Deprecation.warn("#{@old_const} is deprecated! Use #{@new_target.inspect}.#{@new_method} instead.", callstack)
+ end
+ end
end
end
--
cgit v1.2.3
From d897acfbb11aaa2d7f3138e1f9772546ecb6f981 Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Sun, 22 Jun 2008 11:39:10 +0200
Subject: remove DeprecatedConstantToMethodProxy again
---
activesupport/lib/active_support/deprecation.rb | 17 -----------------
1 file changed, 17 deletions(-)
diff --git a/activesupport/lib/active_support/deprecation.rb b/activesupport/lib/active_support/deprecation.rb
index 36933b007d..ebdaf86146 100644
--- a/activesupport/lib/active_support/deprecation.rb
+++ b/activesupport/lib/active_support/deprecation.rb
@@ -194,23 +194,6 @@ module ActiveSupport
ActiveSupport::Deprecation.warn("#{@old_const} is deprecated! Use #{@new_const} instead.", callstack)
end
end
-
- class DeprecatedConstantToMethodProxy < DeprecationProxy #:nodoc:
- def initialize(old_const, new_target, new_method)
- @old_const = old_const
- @new_target = new_target
- @new_method = new_method
- end
-
- private
- def target
- @new_target.__send__(@new_method)
- end
-
- def warn(callstack, called, args)
- ActiveSupport::Deprecation.warn("#{@old_const} is deprecated! Use #{@new_target.inspect}.#{@new_method} instead.", callstack)
- end
- end
end
end
--
cgit v1.2.3
From 20d6630c1bb70f09e1f6a135bd3f9d690ad28250 Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Sun, 22 Jun 2008 11:41:51 +0200
Subject: Replaced country_options_for_select with old, untranslated version
and moved country-related helpers to a new FormCountryHelper helper module so
that they can easily be moved to a plugin. Updated tests accordingly.
---
.../lib/action_view/helpers/form_country_helper.rb | 86 +++
.../lib/action_view/helpers/form_options_helper.rb | 32 +-
actionpack/lib/action_view/locale/en-US.rb | 40 --
.../test/template/form_country_helper_test.rb | 772 +++++++++++++++++++++
.../test/template/form_options_helper_i18n_test.rb | 26 -
.../test/template/form_options_helper_test.rb | 766 +-------------------
6 files changed, 862 insertions(+), 860 deletions(-)
create mode 100644 actionpack/lib/action_view/helpers/form_country_helper.rb
create mode 100644 actionpack/test/template/form_country_helper_test.rb
delete mode 100644 actionpack/test/template/form_options_helper_i18n_test.rb
diff --git a/actionpack/lib/action_view/helpers/form_country_helper.rb b/actionpack/lib/action_view/helpers/form_country_helper.rb
new file mode 100644
index 0000000000..b2d2b7741f
--- /dev/null
+++ b/actionpack/lib/action_view/helpers/form_country_helper.rb
@@ -0,0 +1,86 @@
+require 'action_view/helpers/form_options_helper'
+
+module ActionView
+ module Helpers
+ module FormCountryHelper
+ # Return select and option tags for the given object and method, using country_options_for_select to generate the list of option tags.
+ def country_select(object, method, priority_countries = nil, options = {}, html_options = {})
+ InstanceTag.new(object, method, self, nil, options.delete(:object)).to_country_select_tag(priority_countries, options, html_options)
+ end
+
+ # Returns a string of option tags for pretty much any country in the world. Supply a country name as +selected+ to
+ # have it marked as the selected option tag. You can also supply an array of countries as +priority_countries+, so
+ # that they will be listed above the rest of the (long) list.
+ #
+ # NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag.
+ def country_options_for_select(selected = nil, priority_countries = nil)
+ country_options = ""
+
+ if priority_countries
+ country_options += options_for_select(priority_countries, selected)
+ country_options += "------------- \n"
+ end
+
+ return country_options + options_for_select(COUNTRIES, selected)
+ end
+
+ private
+
+ # All the countries included in the country_options output.
+ COUNTRIES = ["Afghanistan", "Aland Islands", "Albania", "Algeria", "American Samoa", "Andorra", "Angola",
+ "Anguilla", "Antarctica", "Antigua And Barbuda", "Argentina", "Armenia", "Aruba", "Australia", "Austria",
+ "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin",
+ "Bermuda", "Bhutan", "Bolivia", "Bosnia and Herzegowina", "Botswana", "Bouvet Island", "Brazil",
+ "British Indian Ocean Territory", "Brunei Darussalam", "Bulgaria", "Burkina Faso", "Burundi", "Cambodia",
+ "Cameroon", "Canada", "Cape Verde", "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
+ "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
+ "Congo, the Democratic Republic of the", "Cook Islands", "Costa Rica", "Cote d'Ivoire", "Croatia", "Cuba",
+ "Cyprus", "Czech Republic", "Denmark", "Djibouti", "Dominica", "Dominican Republic", "Ecuador", "Egypt",
+ "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Falkland Islands (Malvinas)",
+ "Faroe Islands", "Fiji", "Finland", "France", "French Guiana", "French Polynesia",
+ "French Southern Territories", "Gabon", "Gambia", "Georgia", "Germany", "Ghana", "Gibraltar", "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guernsey", "Guinea",
+ "Guinea-Bissau", "Guyana", "Haiti", "Heard and McDonald Islands", "Holy See (Vatican City State)",
+ "Honduras", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Iran, Islamic Republic of", "Iraq",
+ "Ireland", "Isle of Man", "Israel", "Italy", "Jamaica", "Japan", "Jersey", "Jordan", "Kazakhstan", "Kenya",
+ "Kiribati", "Korea, Democratic People's Republic of", "Korea, Republic of", "Kuwait", "Kyrgyzstan",
+ "Lao People's Democratic Republic", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libyan Arab Jamahiriya",
+ "Liechtenstein", "Lithuania", "Luxembourg", "Macao", "Macedonia, The Former Yugoslav Republic Of",
+ "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Martinique",
+ "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia, Federated States of", "Moldova, Republic of",
+ "Monaco", "Mongolia", "Montenegro", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia", "Nauru",
+ "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand", "Nicaragua", "Niger",
+ "Nigeria", "Niue", "Norfolk Island", "Northern Mariana Islands", "Norway", "Oman", "Pakistan", "Palau",
+ "Palestinian Territory, Occupied", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines",
+ "Pitcairn", "Poland", "Portugal", "Puerto Rico", "Qatar", "Reunion", "Romania", "Russian Federation",
+ "Rwanda", "Saint Barthelemy", "Saint Helena", "Saint Kitts and Nevis", "Saint Lucia",
+ "Saint Pierre and Miquelon", "Saint Vincent and the Grenadines", "Samoa", "San Marino",
+ "Sao Tome and Principe", "Saudi Arabia", "Senegal", "Serbia", "Seychelles", "Sierra Leone", "Singapore",
+ "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa",
+ "South Georgia and the South Sandwich Islands", "Spain", "Sri Lanka", "Sudan", "Suriname",
+ "Svalbard and Jan Mayen", "Swaziland", "Sweden", "Switzerland", "Syrian Arab Republic",
+ "Taiwan, Province of China", "Tajikistan", "Tanzania, United Republic of", "Thailand", "Timor-Leste",
+ "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan",
+ "Turks and Caicos Islands", "Tuvalu", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom",
+ "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan", "Vanuatu", "Venezuela",
+ "Viet Nam", "Virgin Islands, British", "Virgin Islands, U.S.", "Wallis and Futuna", "Western Sahara",
+ "Yemen", "Zambia", "Zimbabwe"] unless const_defined?("COUNTRIES")
+
+ end
+
+ class InstanceTag #:nodoc:
+ include FormCountryHelper
+
+ def to_country_select_tag(priority_countries, options, html_options)
+ html_options = html_options.stringify_keys
+ add_default_name_and_id(html_options)
+ value = value(object)
+ content_tag("select",
+ add_options(
+ country_options_for_select(value, priority_countries),
+ options, value
+ ), html_options
+ )
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb
index a6b9e65a77..8ce092b015 100644
--- a/actionpack/lib/action_view/helpers/form_options_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -133,11 +133,6 @@ module ActionView
InstanceTag.new(object, method, self, nil, options.delete(:object)).to_collection_select_tag(collection, value_method, text_method, options, html_options)
end
- # Return select and option tags for the given object and method, using country_options_for_select to generate the list of option tags.
- def country_select(object, method, priority_countries = nil, options = {}, html_options = {})
- InstanceTag.new(object, method, self, nil, options.delete(:object)).to_country_select_tag(priority_countries, options, html_options)
- end
-
# Return select and option tags for the given object and method, using
# #time_zone_options_for_select to generate the list of option tags.
#
@@ -270,30 +265,6 @@ module ActionView
options_for_select += ''
end
end
-
- # Returns a string of option tags for pretty much any country in the world. Supply a country name as +selected+ to
- # have it marked as the selected option tag. You can also supply an array of countries as +priority_countries+, so
- # that they will be listed above the rest of the (long) list.
- #
- # NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag.
- def country_options_for_select(*args)
- options = args.extract_options!
-
- locale = options[:locale]
- locale ||= request.locale if respond_to?(:request)
-
- selected, priority_countries = *args
- countries = :'countries.names'.t options[:locale]
- country_options = ""
-
- if priority_countries
- # TODO priority_countries need to be translated?
- country_options += options_for_select(priority_countries, selected)
- country_options += "------------- \n"
- end
-
- return country_options + options_for_select(countries, selected)
- end
# Returns a string of option tags for pretty much any time zone in the
@@ -349,8 +320,7 @@ module ActionView
end
# All the countries included in the country_options output.
- # deprecated. please use :'countries.names'.t directly
- COUNTRIES = :'countries.names'.t 'en-US' unless const_defined?("COUNTRIES")
+ COUNTRIES = ActiveSupport::Deprecation::DeprecatedConstantProxy.new 'COUNTRIES', 'ActionView::Helpers::FormCountryHelper::COUNTRIES'
end
class InstanceTag #:nodoc:
diff --git a/actionpack/lib/action_view/locale/en-US.rb b/actionpack/lib/action_view/locale/en-US.rb
index 6b5345ed90..20d668a9e1 100644
--- a/actionpack/lib/action_view/locale/en-US.rb
+++ b/actionpack/lib/action_view/locale/en-US.rb
@@ -44,46 +44,6 @@ I18n.backend.store_translations :'en-US', {
:format => '%u%n',
}
},
- :countries => {
- :names => ["Afghanistan", "Aland Islands", "Albania", "Algeria", "American Samoa", "Andorra", "Angola",
- "Anguilla", "Antarctica", "Antigua And Barbuda", "Argentina", "Armenia", "Aruba", "Australia", "Austria",
- "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin",
- "Bermuda", "Bhutan", "Bolivia", "Bosnia and Herzegowina", "Botswana", "Bouvet Island", "Brazil",
- "British Indian Ocean Territory", "Brunei Darussalam", "Bulgaria", "Burkina Faso", "Burundi", "Cambodia",
- "Cameroon", "Canada", "Cape Verde", "Cayman Islands", "Central African Republic", "Chad", "Chile", "China",
- "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo",
- "Congo, the Democratic Republic of the", "Cook Islands", "Costa Rica", "Cote d'Ivoire", "Croatia", "Cuba",
- "Cyprus", "Czech Republic", "Denmark", "Djibouti", "Dominica", "Dominican Republic", "Ecuador", "Egypt",
- "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Falkland Islands (Malvinas)",
- "Faroe Islands", "Fiji", "Finland", "France", "French Guiana", "French Polynesia",
- "French Southern Territories", "Gabon", "Gambia", "Georgia", "Germany", "Ghana", "Gibraltar", "Greece",
- "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guernsey", "Guinea",
- "Guinea-Bissau", "Guyana", "Haiti", "Heard and McDonald Islands", "Holy See (Vatican City State)",
- "Honduras", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Iran, Islamic Republic of", "Iraq",
- "Ireland", "Isle of Man", "Israel", "Italy", "Jamaica", "Japan", "Jersey", "Jordan", "Kazakhstan", "Kenya",
- "Kiribati", "Korea, Democratic People's Republic of", "Korea, Republic of", "Kuwait", "Kyrgyzstan",
- "Lao People's Democratic Republic", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libyan Arab Jamahiriya",
- "Liechtenstein", "Lithuania", "Luxembourg", "Macao", "Macedonia, The Former Yugoslav Republic Of",
- "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Martinique",
- "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia, Federated States of", "Moldova, Republic of",
- "Monaco", "Mongolia", "Montenegro", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia", "Nauru",
- "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand", "Nicaragua", "Niger",
- "Nigeria", "Niue", "Norfolk Island", "Northern Mariana Islands", "Norway", "Oman", "Pakistan", "Palau",
- "Palestinian Territory, Occupied", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines",
- "Pitcairn", "Poland", "Portugal", "Puerto Rico", "Qatar", "Reunion", "Romania", "Russian Federation",
- "Rwanda", "Saint Barthelemy", "Saint Helena", "Saint Kitts and Nevis", "Saint Lucia",
- "Saint Pierre and Miquelon", "Saint Vincent and the Grenadines", "Samoa", "San Marino",
- "Sao Tome and Principe", "Saudi Arabia", "Senegal", "Serbia", "Seychelles", "Sierra Leone", "Singapore",
- "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa",
- "South Georgia and the South Sandwich Islands", "Spain", "Sri Lanka", "Sudan", "Suriname",
- "Svalbard and Jan Mayen", "Swaziland", "Sweden", "Switzerland", "Syrian Arab Republic",
- "Taiwan, Province of China", "Tajikistan", "Tanzania, United Republic of", "Thailand", "Timor-Leste",
- "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan",
- "Turks and Caicos Islands", "Tuvalu", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom",
- "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan", "Vanuatu", "Venezuela",
- "Viet Nam", "Virgin Islands, British", "Virgin Islands, U.S.", "Wallis and Futuna", "Western Sahara",
- "Yemen", "Zambia", "Zimbabwe"]
- },
:active_record => {
:error => {
:header_message => ["1 error prohibited this {{object_name}} from being saved", "{{count}} errors prohibited this {{object_name}} from being saved"],
diff --git a/actionpack/test/template/form_country_helper_test.rb b/actionpack/test/template/form_country_helper_test.rb
new file mode 100644
index 0000000000..224b2e21c2
--- /dev/null
+++ b/actionpack/test/template/form_country_helper_test.rb
@@ -0,0 +1,772 @@
+require 'abstract_unit'
+
+class FormCountryHelperTest < ActionView::TestCase
+ tests ActionView::Helpers::FormCountryHelper
+
+ silence_warnings do
+ Post = Struct.new('Post', :title, :author_name, :body, :secret, :written_on, :category, :origin)
+ end
+
+ def test_country_select
+ @post = Post.new
+ @post.origin = "Denmark"
+ expected_select = <<-COUNTRIES
+Afghanistan
+Aland Islands
+Albania
+Algeria
+American Samoa
+Andorra
+Angola
+Anguilla
+Antarctica
+Antigua And Barbuda
+Argentina
+Armenia
+Aruba
+Australia
+Austria
+Azerbaijan
+Bahamas
+Bahrain
+Bangladesh
+Barbados
+Belarus
+Belgium
+Belize
+Benin
+Bermuda
+Bhutan
+Bolivia
+Bosnia and Herzegowina
+Botswana
+Bouvet Island
+Brazil
+British Indian Ocean Territory
+Brunei Darussalam
+Bulgaria
+Burkina Faso
+Burundi
+Cambodia
+Cameroon
+Canada
+Cape Verde
+Cayman Islands
+Central African Republic
+Chad
+Chile
+China
+Christmas Island
+Cocos (Keeling) Islands
+Colombia
+Comoros
+Congo
+Congo, the Democratic Republic of the
+Cook Islands
+Costa Rica
+Cote d'Ivoire
+Croatia
+Cuba
+Cyprus
+Czech Republic
+Denmark
+Djibouti
+Dominica
+Dominican Republic
+Ecuador
+Egypt
+El Salvador
+Equatorial Guinea
+Eritrea
+Estonia
+Ethiopia
+Falkland Islands (Malvinas)
+Faroe Islands
+Fiji
+Finland
+France
+French Guiana
+French Polynesia
+French Southern Territories
+Gabon
+Gambia
+Georgia
+Germany
+Ghana
+Gibraltar
+Greece
+Greenland
+Grenada
+Guadeloupe
+Guam
+Guatemala
+Guernsey
+Guinea
+Guinea-Bissau
+Guyana
+Haiti
+Heard and McDonald Islands
+Holy See (Vatican City State)
+Honduras
+Hong Kong
+Hungary
+Iceland
+India
+Indonesia
+Iran, Islamic Republic of
+Iraq
+Ireland
+Isle of Man
+Israel
+Italy
+Jamaica
+Japan
+Jersey
+Jordan
+Kazakhstan
+Kenya
+Kiribati
+Korea, Democratic People's Republic of
+Korea, Republic of
+Kuwait
+Kyrgyzstan
+Lao People's Democratic Republic
+Latvia
+Lebanon
+Lesotho
+Liberia
+Libyan Arab Jamahiriya
+Liechtenstein
+Lithuania
+Luxembourg
+Macao
+Macedonia, The Former Yugoslav Republic Of
+Madagascar
+Malawi
+Malaysia
+Maldives
+Mali
+Malta
+Marshall Islands
+Martinique
+Mauritania
+Mauritius
+Mayotte
+Mexico
+Micronesia, Federated States of
+Moldova, Republic of
+Monaco
+Mongolia
+Montenegro
+Montserrat
+Morocco
+Mozambique
+Myanmar
+Namibia
+Nauru
+Nepal
+Netherlands
+Netherlands Antilles
+New Caledonia
+New Zealand
+Nicaragua
+Niger
+Nigeria
+Niue
+Norfolk Island
+Northern Mariana Islands
+Norway
+Oman
+Pakistan
+Palau
+Palestinian Territory, Occupied
+Panama
+Papua New Guinea
+Paraguay
+Peru
+Philippines
+Pitcairn
+Poland
+Portugal
+Puerto Rico
+Qatar
+Reunion
+Romania
+Russian Federation
+Rwanda
+Saint Barthelemy
+Saint Helena
+Saint Kitts and Nevis
+Saint Lucia
+Saint Pierre and Miquelon
+Saint Vincent and the Grenadines
+Samoa
+San Marino
+Sao Tome and Principe
+Saudi Arabia
+Senegal
+Serbia
+Seychelles
+Sierra Leone
+Singapore
+Slovakia
+Slovenia
+Solomon Islands
+Somalia
+South Africa
+South Georgia and the South Sandwich Islands
+Spain
+Sri Lanka
+Sudan
+Suriname
+Svalbard and Jan Mayen
+Swaziland
+Sweden
+Switzerland
+Syrian Arab Republic
+Taiwan, Province of China
+Tajikistan
+Tanzania, United Republic of
+Thailand
+Timor-Leste
+Togo
+Tokelau
+Tonga
+Trinidad and Tobago
+Tunisia
+Turkey
+Turkmenistan
+Turks and Caicos Islands
+Tuvalu
+Uganda
+Ukraine
+United Arab Emirates
+United Kingdom
+United States
+United States Minor Outlying Islands
+Uruguay
+Uzbekistan
+Vanuatu
+Venezuela
+Viet Nam
+Virgin Islands, British
+Virgin Islands, U.S.
+Wallis and Futuna
+Western Sahara
+Yemen
+Zambia
+Zimbabwe
+COUNTRIES
+ assert_dom_equal(expected_select[0..-2], country_select("post", "origin"))
+ end
+
+ def test_country_select_with_priority_countries
+ @post = Post.new
+ @post.origin = "Denmark"
+ expected_select = <<-COUNTRIES
+New Zealand
+Nicaragua -------------
+Afghanistan
+Aland Islands
+Albania
+Algeria
+American Samoa
+Andorra
+Angola
+Anguilla
+Antarctica
+Antigua And Barbuda
+Argentina
+Armenia
+Aruba
+Australia
+Austria
+Azerbaijan
+Bahamas
+Bahrain
+Bangladesh
+Barbados
+Belarus
+Belgium
+Belize
+Benin
+Bermuda
+Bhutan
+Bolivia
+Bosnia and Herzegowina
+Botswana
+Bouvet Island
+Brazil
+British Indian Ocean Territory
+Brunei Darussalam
+Bulgaria
+Burkina Faso
+Burundi
+Cambodia
+Cameroon
+Canada
+Cape Verde
+Cayman Islands
+Central African Republic
+Chad
+Chile
+China
+Christmas Island
+Cocos (Keeling) Islands
+Colombia
+Comoros
+Congo
+Congo, the Democratic Republic of the
+Cook Islands
+Costa Rica
+Cote d'Ivoire
+Croatia
+Cuba
+Cyprus
+Czech Republic
+Denmark
+Djibouti
+Dominica
+Dominican Republic
+Ecuador
+Egypt
+El Salvador
+Equatorial Guinea
+Eritrea
+Estonia
+Ethiopia
+Falkland Islands (Malvinas)
+Faroe Islands
+Fiji
+Finland
+France
+French Guiana
+French Polynesia
+French Southern Territories
+Gabon
+Gambia
+Georgia
+Germany
+Ghana
+Gibraltar
+Greece
+Greenland
+Grenada
+Guadeloupe
+Guam
+Guatemala
+Guernsey
+Guinea
+Guinea-Bissau
+Guyana
+Haiti
+Heard and McDonald Islands
+Holy See (Vatican City State)
+Honduras
+Hong Kong
+Hungary
+Iceland
+India
+Indonesia
+Iran, Islamic Republic of
+Iraq
+Ireland
+Isle of Man
+Israel
+Italy
+Jamaica
+Japan
+Jersey
+Jordan
+Kazakhstan
+Kenya
+Kiribati
+Korea, Democratic People's Republic of
+Korea, Republic of
+Kuwait
+Kyrgyzstan
+Lao People's Democratic Republic
+Latvia
+Lebanon
+Lesotho
+Liberia
+Libyan Arab Jamahiriya
+Liechtenstein
+Lithuania
+Luxembourg
+Macao
+Macedonia, The Former Yugoslav Republic Of
+Madagascar
+Malawi
+Malaysia
+Maldives
+Mali
+Malta
+Marshall Islands
+Martinique
+Mauritania
+Mauritius
+Mayotte
+Mexico
+Micronesia, Federated States of
+Moldova, Republic of
+Monaco
+Mongolia
+Montenegro
+Montserrat
+Morocco
+Mozambique
+Myanmar
+Namibia
+Nauru
+Nepal
+Netherlands
+Netherlands Antilles
+New Caledonia
+New Zealand
+Nicaragua
+Niger
+Nigeria
+Niue
+Norfolk Island
+Northern Mariana Islands
+Norway
+Oman
+Pakistan
+Palau
+Palestinian Territory, Occupied
+Panama
+Papua New Guinea
+Paraguay
+Peru
+Philippines
+Pitcairn
+Poland
+Portugal
+Puerto Rico
+Qatar
+Reunion
+Romania
+Russian Federation
+Rwanda
+Saint Barthelemy
+Saint Helena
+Saint Kitts and Nevis
+Saint Lucia
+Saint Pierre and Miquelon
+Saint Vincent and the Grenadines
+Samoa
+San Marino
+Sao Tome and Principe
+Saudi Arabia
+Senegal
+Serbia
+Seychelles
+Sierra Leone
+Singapore
+Slovakia
+Slovenia
+Solomon Islands
+Somalia
+South Africa
+South Georgia and the South Sandwich Islands
+Spain
+Sri Lanka
+Sudan
+Suriname
+Svalbard and Jan Mayen
+Swaziland
+Sweden
+Switzerland
+Syrian Arab Republic
+Taiwan, Province of China
+Tajikistan
+Tanzania, United Republic of
+Thailand
+Timor-Leste
+Togo
+Tokelau
+Tonga
+Trinidad and Tobago
+Tunisia
+Turkey
+Turkmenistan
+Turks and Caicos Islands
+Tuvalu
+Uganda
+Ukraine
+United Arab Emirates
+United Kingdom
+United States
+United States Minor Outlying Islands
+Uruguay
+Uzbekistan
+Vanuatu
+Venezuela
+Viet Nam
+Virgin Islands, British
+Virgin Islands, U.S.
+Wallis and Futuna
+Western Sahara
+Yemen
+Zambia
+Zimbabwe
+COUNTRIES
+ assert_dom_equal(expected_select[0..-2], country_select("post", "origin", ["New Zealand", "Nicaragua"]))
+ end
+
+ def test_country_select_with_selected_priority_country
+ @post = Post.new
+ @post.origin = "New Zealand"
+ expected_select = <<-COUNTRIES
+New Zealand
+Nicaragua -------------
+Afghanistan
+Aland Islands
+Albania
+Algeria
+American Samoa
+Andorra
+Angola
+Anguilla
+Antarctica
+Antigua And Barbuda
+Argentina
+Armenia
+Aruba
+Australia
+Austria
+Azerbaijan
+Bahamas
+Bahrain
+Bangladesh
+Barbados
+Belarus
+Belgium
+Belize
+Benin
+Bermuda
+Bhutan
+Bolivia
+Bosnia and Herzegowina
+Botswana
+Bouvet Island
+Brazil
+British Indian Ocean Territory
+Brunei Darussalam
+Bulgaria
+Burkina Faso
+Burundi
+Cambodia
+Cameroon
+Canada
+Cape Verde
+Cayman Islands
+Central African Republic
+Chad
+Chile
+China
+Christmas Island
+Cocos (Keeling) Islands
+Colombia
+Comoros
+Congo
+Congo, the Democratic Republic of the
+Cook Islands
+Costa Rica
+Cote d'Ivoire
+Croatia
+Cuba
+Cyprus
+Czech Republic
+Denmark
+Djibouti
+Dominica
+Dominican Republic
+Ecuador
+Egypt
+El Salvador
+Equatorial Guinea
+Eritrea
+Estonia
+Ethiopia
+Falkland Islands (Malvinas)
+Faroe Islands
+Fiji
+Finland
+France
+French Guiana
+French Polynesia
+French Southern Territories
+Gabon
+Gambia
+Georgia
+Germany
+Ghana
+Gibraltar
+Greece
+Greenland
+Grenada
+Guadeloupe
+Guam
+Guatemala
+Guernsey
+Guinea
+Guinea-Bissau
+Guyana
+Haiti
+Heard and McDonald Islands
+Holy See (Vatican City State)
+Honduras
+Hong Kong
+Hungary
+Iceland
+India
+Indonesia
+Iran, Islamic Republic of
+Iraq
+Ireland
+Isle of Man
+Israel
+Italy
+Jamaica
+Japan
+Jersey
+Jordan
+Kazakhstan
+Kenya
+Kiribati
+Korea, Democratic People's Republic of
+Korea, Republic of
+Kuwait
+Kyrgyzstan
+Lao People's Democratic Republic
+Latvia
+Lebanon
+Lesotho
+Liberia
+Libyan Arab Jamahiriya
+Liechtenstein
+Lithuania
+Luxembourg
+Macao
+Macedonia, The Former Yugoslav Republic Of
+Madagascar
+Malawi
+Malaysia
+Maldives
+Mali
+Malta
+Marshall Islands
+Martinique
+Mauritania
+Mauritius
+Mayotte
+Mexico
+Micronesia, Federated States of
+Moldova, Republic of
+Monaco
+Mongolia
+Montenegro
+Montserrat
+Morocco
+Mozambique
+Myanmar
+Namibia
+Nauru
+Nepal
+Netherlands
+Netherlands Antilles
+New Caledonia
+New Zealand
+Nicaragua
+Niger
+Nigeria
+Niue
+Norfolk Island
+Northern Mariana Islands
+Norway
+Oman
+Pakistan
+Palau
+Palestinian Territory, Occupied
+Panama
+Papua New Guinea
+Paraguay
+Peru
+Philippines
+Pitcairn
+Poland
+Portugal
+Puerto Rico
+Qatar
+Reunion
+Romania
+Russian Federation
+Rwanda
+Saint Barthelemy
+Saint Helena
+Saint Kitts and Nevis
+Saint Lucia
+Saint Pierre and Miquelon
+Saint Vincent and the Grenadines
+Samoa
+San Marino
+Sao Tome and Principe
+Saudi Arabia
+Senegal
+Serbia
+Seychelles
+Sierra Leone
+Singapore
+Slovakia
+Slovenia
+Solomon Islands
+Somalia
+South Africa
+South Georgia and the South Sandwich Islands
+Spain
+Sri Lanka
+Sudan
+Suriname
+Svalbard and Jan Mayen
+Swaziland
+Sweden
+Switzerland
+Syrian Arab Republic
+Taiwan, Province of China
+Tajikistan
+Tanzania, United Republic of
+Thailand
+Timor-Leste
+Togo
+Tokelau
+Tonga
+Trinidad and Tobago
+Tunisia
+Turkey
+Turkmenistan
+Turks and Caicos Islands
+Tuvalu
+Uganda
+Ukraine
+United Arab Emirates
+United Kingdom
+United States
+United States Minor Outlying Islands
+Uruguay
+Uzbekistan
+Vanuatu
+Venezuela
+Viet Nam
+Virgin Islands, British
+Virgin Islands, U.S.
+Wallis and Futuna
+Western Sahara
+Yemen
+Zambia
+Zimbabwe
+COUNTRIES
+ assert_dom_equal(expected_select[0..-2], country_select("post", "origin", ["New Zealand", "Nicaragua"]))
+ end
+end
\ No newline at end of file
diff --git a/actionpack/test/template/form_options_helper_i18n_test.rb b/actionpack/test/template/form_options_helper_i18n_test.rb
deleted file mode 100644
index c9fc0768bb..0000000000
--- a/actionpack/test/template/form_options_helper_i18n_test.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-require 'abstract_unit'
-
-class FormOptionsHelperI18nTests < Test::Unit::TestCase
- include ActionView::Helpers::FormOptionsHelper
- attr_reader :request
-
- def setup
- @request = mock
- end
-
- def test_country_options_for_select_given_a_locale_it_does_not_check_request_for_locale
- request.expects(:locale).never
- country_options_for_select :locale => 'en-US'
- end
-
- def test_country_options_for_select_given_no_locale_it_checks_request_for_locale
- request.expects(:locale).returns 'en-US'
- country_options_for_select
- end
-
- def test_country_options_for_select_translates_country_names
- countries = ActionView::Helpers::FormOptionsHelper::COUNTRIES
- I18n.expects(:translate).with(:'countries.names', 'en-US').returns countries
- country_options_for_select :locale => 'en-US'
- end
-end
\ No newline at end of file
diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb
index 3f89a5e426..5ba81aac02 100644
--- a/actionpack/test/template/form_options_helper_test.rb
+++ b/actionpack/test/template/form_options_helper_test.rb
@@ -412,769 +412,6 @@ class FormOptionsHelperTest < ActionView::TestCase
assert_dom_equal expected, collection_select("post", "author_name", @posts, "author_name", "author_name", { :include_blank => true, :name => 'post[author_name][]' }, :multiple => true)
end
- def test_country_select
- @post = Post.new
- @post.origin = "Denmark"
- expected_select = <<-COUNTRIES
-Afghanistan
-Aland Islands
-Albania
-Algeria
-American Samoa
-Andorra
-Angola
-Anguilla
-Antarctica
-Antigua And Barbuda
-Argentina
-Armenia
-Aruba
-Australia
-Austria
-Azerbaijan
-Bahamas
-Bahrain
-Bangladesh
-Barbados
-Belarus
-Belgium
-Belize
-Benin
-Bermuda
-Bhutan
-Bolivia
-Bosnia and Herzegowina
-Botswana
-Bouvet Island
-Brazil
-British Indian Ocean Territory
-Brunei Darussalam
-Bulgaria
-Burkina Faso
-Burundi
-Cambodia
-Cameroon
-Canada
-Cape Verde
-Cayman Islands
-Central African Republic
-Chad
-Chile
-China
-Christmas Island
-Cocos (Keeling) Islands
-Colombia
-Comoros
-Congo
-Congo, the Democratic Republic of the
-Cook Islands
-Costa Rica
-Cote d'Ivoire
-Croatia
-Cuba
-Cyprus
-Czech Republic
-Denmark
-Djibouti
-Dominica
-Dominican Republic
-Ecuador
-Egypt
-El Salvador
-Equatorial Guinea
-Eritrea
-Estonia
-Ethiopia
-Falkland Islands (Malvinas)
-Faroe Islands
-Fiji
-Finland
-France
-French Guiana
-French Polynesia
-French Southern Territories
-Gabon
-Gambia
-Georgia
-Germany
-Ghana
-Gibraltar
-Greece
-Greenland
-Grenada
-Guadeloupe
-Guam
-Guatemala
-Guernsey
-Guinea
-Guinea-Bissau
-Guyana
-Haiti
-Heard and McDonald Islands
-Holy See (Vatican City State)
-Honduras
-Hong Kong
-Hungary
-Iceland
-India
-Indonesia
-Iran, Islamic Republic of
-Iraq
-Ireland
-Isle of Man
-Israel
-Italy
-Jamaica
-Japan
-Jersey
-Jordan
-Kazakhstan
-Kenya
-Kiribati
-Korea, Democratic People's Republic of
-Korea, Republic of
-Kuwait
-Kyrgyzstan
-Lao People's Democratic Republic
-Latvia
-Lebanon
-Lesotho
-Liberia
-Libyan Arab Jamahiriya
-Liechtenstein
-Lithuania
-Luxembourg
-Macao
-Macedonia, The Former Yugoslav Republic Of
-Madagascar
-Malawi
-Malaysia
-Maldives
-Mali
-Malta
-Marshall Islands
-Martinique
-Mauritania
-Mauritius
-Mayotte
-Mexico
-Micronesia, Federated States of
-Moldova, Republic of
-Monaco
-Mongolia
-Montenegro
-Montserrat
-Morocco
-Mozambique
-Myanmar
-Namibia
-Nauru
-Nepal
-Netherlands
-Netherlands Antilles
-New Caledonia
-New Zealand
-Nicaragua
-Niger
-Nigeria
-Niue
-Norfolk Island
-Northern Mariana Islands
-Norway
-Oman
-Pakistan
-Palau
-Palestinian Territory, Occupied
-Panama
-Papua New Guinea
-Paraguay
-Peru
-Philippines
-Pitcairn
-Poland
-Portugal
-Puerto Rico
-Qatar
-Reunion
-Romania
-Russian Federation
-Rwanda
-Saint Barthelemy
-Saint Helena
-Saint Kitts and Nevis
-Saint Lucia
-Saint Pierre and Miquelon
-Saint Vincent and the Grenadines
-Samoa
-San Marino
-Sao Tome and Principe
-Saudi Arabia
-Senegal
-Serbia
-Seychelles
-Sierra Leone
-Singapore
-Slovakia
-Slovenia
-Solomon Islands
-Somalia
-South Africa
-South Georgia and the South Sandwich Islands
-Spain
-Sri Lanka
-Sudan
-Suriname
-Svalbard and Jan Mayen
-Swaziland
-Sweden
-Switzerland
-Syrian Arab Republic
-Taiwan, Province of China
-Tajikistan
-Tanzania, United Republic of
-Thailand
-Timor-Leste
-Togo
-Tokelau
-Tonga
-Trinidad and Tobago
-Tunisia
-Turkey
-Turkmenistan
-Turks and Caicos Islands
-Tuvalu
-Uganda
-Ukraine
-United Arab Emirates
-United Kingdom
-United States
-United States Minor Outlying Islands
-Uruguay
-Uzbekistan
-Vanuatu
-Venezuela
-Viet Nam
-Virgin Islands, British
-Virgin Islands, U.S.
-Wallis and Futuna
-Western Sahara
-Yemen
-Zambia
-Zimbabwe
-COUNTRIES
- assert_dom_equal(expected_select[0..-2], country_select("post", "origin"))
- end
-
- def test_country_select_with_priority_countries
- @post = Post.new
- @post.origin = "Denmark"
- expected_select = <<-COUNTRIES
-New Zealand
-Nicaragua -------------
-Afghanistan
-Aland Islands
-Albania
-Algeria
-American Samoa
-Andorra
-Angola
-Anguilla
-Antarctica
-Antigua And Barbuda
-Argentina
-Armenia
-Aruba
-Australia
-Austria
-Azerbaijan
-Bahamas
-Bahrain
-Bangladesh
-Barbados
-Belarus
-Belgium
-Belize
-Benin
-Bermuda
-Bhutan
-Bolivia
-Bosnia and Herzegowina
-Botswana
-Bouvet Island
-Brazil
-British Indian Ocean Territory
-Brunei Darussalam
-Bulgaria
-Burkina Faso
-Burundi
-Cambodia
-Cameroon
-Canada
-Cape Verde
-Cayman Islands
-Central African Republic
-Chad
-Chile
-China
-Christmas Island
-Cocos (Keeling) Islands
-Colombia
-Comoros
-Congo
-Congo, the Democratic Republic of the
-Cook Islands
-Costa Rica
-Cote d'Ivoire
-Croatia
-Cuba
-Cyprus
-Czech Republic
-Denmark
-Djibouti
-Dominica
-Dominican Republic
-Ecuador
-Egypt
-El Salvador
-Equatorial Guinea
-Eritrea
-Estonia
-Ethiopia
-Falkland Islands (Malvinas)
-Faroe Islands
-Fiji
-Finland
-France
-French Guiana
-French Polynesia
-French Southern Territories
-Gabon
-Gambia
-Georgia
-Germany
-Ghana
-Gibraltar
-Greece
-Greenland
-Grenada
-Guadeloupe
-Guam
-Guatemala
-Guernsey
-Guinea
-Guinea-Bissau
-Guyana
-Haiti
-Heard and McDonald Islands
-Holy See (Vatican City State)
-Honduras
-Hong Kong
-Hungary
-Iceland
-India
-Indonesia
-Iran, Islamic Republic of
-Iraq
-Ireland
-Isle of Man
-Israel
-Italy
-Jamaica
-Japan
-Jersey
-Jordan
-Kazakhstan
-Kenya
-Kiribati
-Korea, Democratic People's Republic of
-Korea, Republic of
-Kuwait
-Kyrgyzstan
-Lao People's Democratic Republic
-Latvia
-Lebanon
-Lesotho
-Liberia
-Libyan Arab Jamahiriya
-Liechtenstein
-Lithuania
-Luxembourg
-Macao
-Macedonia, The Former Yugoslav Republic Of
-Madagascar
-Malawi
-Malaysia
-Maldives
-Mali
-Malta
-Marshall Islands
-Martinique
-Mauritania
-Mauritius
-Mayotte
-Mexico
-Micronesia, Federated States of
-Moldova, Republic of
-Monaco
-Mongolia
-Montenegro
-Montserrat
-Morocco
-Mozambique
-Myanmar
-Namibia
-Nauru
-Nepal
-Netherlands
-Netherlands Antilles
-New Caledonia
-New Zealand
-Nicaragua
-Niger
-Nigeria
-Niue
-Norfolk Island
-Northern Mariana Islands
-Norway
-Oman
-Pakistan
-Palau
-Palestinian Territory, Occupied
-Panama
-Papua New Guinea
-Paraguay
-Peru
-Philippines
-Pitcairn
-Poland
-Portugal
-Puerto Rico
-Qatar
-Reunion
-Romania
-Russian Federation
-Rwanda
-Saint Barthelemy
-Saint Helena
-Saint Kitts and Nevis
-Saint Lucia
-Saint Pierre and Miquelon
-Saint Vincent and the Grenadines
-Samoa
-San Marino
-Sao Tome and Principe
-Saudi Arabia
-Senegal
-Serbia
-Seychelles
-Sierra Leone
-Singapore
-Slovakia
-Slovenia
-Solomon Islands
-Somalia
-South Africa
-South Georgia and the South Sandwich Islands
-Spain
-Sri Lanka
-Sudan
-Suriname
-Svalbard and Jan Mayen
-Swaziland
-Sweden
-Switzerland
-Syrian Arab Republic
-Taiwan, Province of China
-Tajikistan
-Tanzania, United Republic of
-Thailand
-Timor-Leste
-Togo
-Tokelau
-Tonga
-Trinidad and Tobago
-Tunisia
-Turkey
-Turkmenistan
-Turks and Caicos Islands
-Tuvalu
-Uganda
-Ukraine
-United Arab Emirates
-United Kingdom
-United States
-United States Minor Outlying Islands
-Uruguay
-Uzbekistan
-Vanuatu
-Venezuela
-Viet Nam
-Virgin Islands, British
-Virgin Islands, U.S.
-Wallis and Futuna
-Western Sahara
-Yemen
-Zambia
-Zimbabwe
-COUNTRIES
- assert_dom_equal(expected_select[0..-2], country_select("post", "origin", ["New Zealand", "Nicaragua"]))
- end
-
- def test_country_select_with_selected_priority_country
- @post = Post.new
- @post.origin = "New Zealand"
- expected_select = <<-COUNTRIES
-New Zealand
-Nicaragua -------------
-Afghanistan
-Aland Islands
-Albania
-Algeria
-American Samoa
-Andorra
-Angola
-Anguilla
-Antarctica
-Antigua And Barbuda
-Argentina
-Armenia
-Aruba
-Australia
-Austria
-Azerbaijan
-Bahamas
-Bahrain
-Bangladesh
-Barbados
-Belarus
-Belgium
-Belize
-Benin
-Bermuda
-Bhutan
-Bolivia
-Bosnia and Herzegowina
-Botswana
-Bouvet Island
-Brazil
-British Indian Ocean Territory
-Brunei Darussalam
-Bulgaria
-Burkina Faso
-Burundi
-Cambodia
-Cameroon
-Canada
-Cape Verde
-Cayman Islands
-Central African Republic
-Chad
-Chile
-China
-Christmas Island
-Cocos (Keeling) Islands
-Colombia
-Comoros
-Congo
-Congo, the Democratic Republic of the
-Cook Islands
-Costa Rica
-Cote d'Ivoire
-Croatia
-Cuba
-Cyprus
-Czech Republic
-Denmark
-Djibouti
-Dominica
-Dominican Republic
-Ecuador
-Egypt
-El Salvador
-Equatorial Guinea
-Eritrea
-Estonia
-Ethiopia
-Falkland Islands (Malvinas)
-Faroe Islands
-Fiji
-Finland
-France
-French Guiana
-French Polynesia
-French Southern Territories
-Gabon
-Gambia
-Georgia
-Germany
-Ghana
-Gibraltar
-Greece
-Greenland
-Grenada
-Guadeloupe
-Guam
-Guatemala
-Guernsey
-Guinea
-Guinea-Bissau
-Guyana
-Haiti
-Heard and McDonald Islands
-Holy See (Vatican City State)
-Honduras
-Hong Kong
-Hungary
-Iceland
-India
-Indonesia
-Iran, Islamic Republic of
-Iraq
-Ireland
-Isle of Man
-Israel
-Italy
-Jamaica
-Japan
-Jersey
-Jordan
-Kazakhstan
-Kenya
-Kiribati
-Korea, Democratic People's Republic of
-Korea, Republic of
-Kuwait
-Kyrgyzstan
-Lao People's Democratic Republic
-Latvia
-Lebanon
-Lesotho
-Liberia
-Libyan Arab Jamahiriya
-Liechtenstein
-Lithuania
-Luxembourg
-Macao
-Macedonia, The Former Yugoslav Republic Of
-Madagascar
-Malawi
-Malaysia
-Maldives
-Mali
-Malta
-Marshall Islands
-Martinique
-Mauritania
-Mauritius
-Mayotte
-Mexico
-Micronesia, Federated States of
-Moldova, Republic of
-Monaco
-Mongolia
-Montenegro
-Montserrat
-Morocco
-Mozambique
-Myanmar
-Namibia
-Nauru
-Nepal
-Netherlands
-Netherlands Antilles
-New Caledonia
-New Zealand
-Nicaragua
-Niger
-Nigeria
-Niue
-Norfolk Island
-Northern Mariana Islands
-Norway
-Oman
-Pakistan
-Palau
-Palestinian Territory, Occupied
-Panama
-Papua New Guinea
-Paraguay
-Peru
-Philippines
-Pitcairn
-Poland
-Portugal
-Puerto Rico
-Qatar
-Reunion
-Romania
-Russian Federation
-Rwanda
-Saint Barthelemy
-Saint Helena
-Saint Kitts and Nevis
-Saint Lucia
-Saint Pierre and Miquelon
-Saint Vincent and the Grenadines
-Samoa
-San Marino
-Sao Tome and Principe
-Saudi Arabia
-Senegal
-Serbia
-Seychelles
-Sierra Leone
-Singapore
-Slovakia
-Slovenia
-Solomon Islands
-Somalia
-South Africa
-South Georgia and the South Sandwich Islands
-Spain
-Sri Lanka
-Sudan
-Suriname
-Svalbard and Jan Mayen
-Swaziland
-Sweden
-Switzerland
-Syrian Arab Republic
-Taiwan, Province of China
-Tajikistan
-Tanzania, United Republic of
-Thailand
-Timor-Leste
-Togo
-Tokelau
-Tonga
-Trinidad and Tobago
-Tunisia
-Turkey
-Turkmenistan
-Turks and Caicos Islands
-Tuvalu
-Uganda
-Ukraine
-United Arab Emirates
-United Kingdom
-United States
-United States Minor Outlying Islands
-Uruguay
-Uzbekistan
-Vanuatu
-Venezuela
-Viet Nam
-Virgin Islands, British
-Virgin Islands, U.S.
-Wallis and Futuna
-Western Sahara
-Yemen
-Zambia
-Zimbabwe
-COUNTRIES
- assert_dom_equal(expected_select[0..-2], country_select("post", "origin", ["New Zealand", "Nicaragua"]))
- end
-
def test_time_zone_select
@firm = Firm.new("D")
html = time_zone_select( "firm", "time_zone" )
@@ -1327,4 +564,7 @@ COUNTRIES
html
end
+ def test_countries_is_deprectated
+ assert_deprecated(/COUNTRIES/) { ActionView::Helpers::FormOptionsHelper::COUNTRIES.size }
+ end
end
--
cgit v1.2.3
From 67fce4671e8bcfe2aa670a89195b20837546183a Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Sun, 22 Jun 2008 13:49:08 +0200
Subject: crap, an array never has a request, stupid.
---
activesupport/lib/active_support/core_ext/array/conversions.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb
index 08e608d346..80d91a6cbd 100644
--- a/activesupport/lib/active_support/core_ext/array/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/array/conversions.rb
@@ -11,7 +11,7 @@ module ActiveSupport #:nodoc:
options.assert_valid_keys(:connector, :skip_last_comma, :locale)
locale = options[:locale]
- locale ||= request.locale if respond_to?(:request)
+ locale ||= self.locale if respond_to?(:locale)
default = :'support.array.sentence_connector'.t(locale)
options.reverse_merge! :connector => default, :skip_last_comma => false
--
cgit v1.2.3
From 3533dc68120ed40a4ec44ed9900c9035108cfcf1 Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Sun, 22 Jun 2008 13:49:38 +0200
Subject: check self.locale instead of request.locale in helpers
---
actionpack/lib/action_view/helpers/active_record_helper.rb | 2 +-
actionpack/lib/action_view/helpers/date_helper.rb | 4 ++--
actionpack/lib/action_view/helpers/number_helper.rb | 2 +-
actionpack/test/template/active_record_helper_i18n_test.rb | 6 +++---
actionpack/test/template/date_helper_i18n_test.rb | 8 ++++----
actionpack/test/template/number_helper_i18n_test.rb | 6 +++---
6 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/actionpack/lib/action_view/helpers/active_record_helper.rb b/actionpack/lib/action_view/helpers/active_record_helper.rb
index 5ad9d5f76d..716e303a5d 100644
--- a/actionpack/lib/action_view/helpers/active_record_helper.rb
+++ b/actionpack/lib/action_view/helpers/active_record_helper.rb
@@ -160,7 +160,7 @@ module ActionView
count = objects.inject(0) {|sum, object| sum + object.errors.count }
locale = options[:locale]
- locale ||= request.locale if respond_to?(:request)
+ locale ||= self.locale if respond_to?(:locale)
unless count.zero?
html = {}
diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb
index 0337be0744..dbb5d458bf 100755
--- a/actionpack/lib/action_view/helpers/date_helper.rb
+++ b/actionpack/lib/action_view/helpers/date_helper.rb
@@ -60,7 +60,7 @@ module ActionView
#
def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false, options = {})
locale = options[:locale]
- locale ||= request.locale if respond_to?(:request)
+ locale ||= self.locale if respond_to?(:locale)
from_time = from_time.to_time if from_time.respond_to?(:to_time)
to_time = to_time.to_time if to_time.respond_to?(:to_time)
@@ -507,7 +507,7 @@ module ActionView
#
def select_month(date, options = {}, html_options = {})
locale = options[:locale]
- locale ||= request.locale if respond_to?(:request)
+ locale ||= self.locale if respond_to?(:locale)
val = date ? (date.kind_of?(Fixnum) ? date : date.month) : ''
if options[:use_hidden]
diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb
index 9d98036f2d..dc56817c12 100644
--- a/actionpack/lib/action_view/helpers/number_helper.rb
+++ b/actionpack/lib/action_view/helpers/number_helper.rb
@@ -72,7 +72,7 @@ module ActionView
options = options.symbolize_keys
locale = options[:locale]
- locale ||= request.locale if respond_to?(:request)
+ locale ||= self.locale if respond_to?(:locale)
defaults = :'currency.format'.t(locale) || {}
precision = options[:precision] || defaults[:precision]
diff --git a/actionpack/test/template/active_record_helper_i18n_test.rb b/actionpack/test/template/active_record_helper_i18n_test.rb
index 057fb9bd1a..3a2197ac93 100644
--- a/actionpack/test/template/active_record_helper_i18n_test.rb
+++ b/actionpack/test/template/active_record_helper_i18n_test.rb
@@ -5,22 +5,22 @@ class ActiveRecordHelperI18nTest < Test::Unit::TestCase
attr_reader :request
def setup
- @request = mock
@object = stub :errors => stub(:count => 1, :full_messages => ['full_messages'])
stubs(:content_tag).returns 'content_tag'
+ stubs(:locale)
I18n.stubs(:t).with(:'header_message', :locale => 'en-US', :scope => [:active_record, :error], :count => 1, :object_name => '').returns "1 error prohibited this from being saved"
I18n.stubs(:t).with(:'message', :locale => 'en-US', :scope => [:active_record, :error]).returns 'There were problems with the following fields:'
end
def test_error_messages_for_given_a_locale_it_does_not_check_request_for_locale
- request.expects(:locale).never
+ expects(:locale).never
@object.errors.stubs(:count).returns 0
error_messages_for(:object => @object, :locale => 'en-US')
end
def test_error_messages_for_given_no_locale_it_checks_request_for_locale
- request.expects(:locale).returns 'en-US'
+ expects(:locale).returns 'en-US'
@object.errors.stubs(:count).returns 0
error_messages_for(:object => @object)
end
diff --git a/actionpack/test/template/date_helper_i18n_test.rb b/actionpack/test/template/date_helper_i18n_test.rb
index 9b7c03a400..f245ca1fc8 100644
--- a/actionpack/test/template/date_helper_i18n_test.rb
+++ b/actionpack/test/template/date_helper_i18n_test.rb
@@ -5,19 +5,19 @@ class DateHelperDistanceOfTimeInWordsI18nTests < Test::Unit::TestCase
attr_reader :request
def setup
- @request = mock
+ stubs(:locale)
@from = Time.mktime(2004, 6, 6, 21, 45, 0)
end
# distance_of_time_in_words
def test_distance_of_time_in_words_given_a_locale_it_does_not_check_request_for_locale
- request.expects(:locale).never
+ expects(:locale).never
distance_of_time_in_words @from, @from + 1.second, false, :locale => 'en-US'
end
def test_distance_of_time_in_words_given_no_locale_it_checks_request_for_locale
- request.expects(:locale).returns 'en-US'
+ expects(:locale).returns 'en-US'
distance_of_time_in_words @from, @from + 1.second
end
@@ -64,7 +64,7 @@ class DateHelperSelectTagsI18nTests < Test::Unit::TestCase
attr_reader :request
def setup
- @request = mock
+ # stubs(:locale)
I18n.stubs(:translate).with(:'date.month_names', 'en-US').returns Date::MONTHNAMES
end
diff --git a/actionpack/test/template/number_helper_i18n_test.rb b/actionpack/test/template/number_helper_i18n_test.rb
index b75af03378..5db60ece04 100644
--- a/actionpack/test/template/number_helper_i18n_test.rb
+++ b/actionpack/test/template/number_helper_i18n_test.rb
@@ -5,18 +5,18 @@ class NumberHelperI18nTests < Test::Unit::TestCase
attr_reader :request
def setup
- @request = mock
+ stubs(:locale)
@defaults = {:separator => ".", :unit => "$", :format => "%u%n", :delimiter => ",", :precision => 2}
I18n.backend.store_translations 'en-US', :currency => {:format => @defaults}
end
def test_number_to_currency_given_a_locale_it_does_not_check_request_for_locale
- request.expects(:locale).never
+ expects(:locale).never
number_to_currency(1, :locale => 'en-US')
end
def test_number_to_currency_given_no_locale_it_checks_request_for_locale
- request.expects(:locale).returns 'en-US'
+ expects(:locale).returns 'en-US'
number_to_currency(1)
end
--
cgit v1.2.3
From 0dddba41fcfcd28de2ce1a88a23514fbde53afcf Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Mon, 23 Jun 2008 14:33:29 +0200
Subject: rather cosmetic improvements of test coverage
---
.../lib/action_view/helpers/number_helper.rb | 2 +-
activerecord/lib/active_record/validations.rb | 8 +--
activerecord/test/cases/validations_i18n_test.rb | 62 ++++++++++++++++++++--
3 files changed, 64 insertions(+), 8 deletions(-)
diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb
index dc56817c12..4373d063bb 100644
--- a/actionpack/lib/action_view/helpers/number_helper.rb
+++ b/actionpack/lib/action_view/helpers/number_helper.rb
@@ -70,7 +70,7 @@ module ActionView
# # => 1234567890,50 £
def number_to_currency(number, options = {})
options = options.symbolize_keys
-
+
locale = options[:locale]
locale ||= self.locale if respond_to?(:locale)
diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb
index 49d3c59ca7..5bbd10394c 100755
--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -21,8 +21,8 @@ module ActiveRecord
class << self
def default_error_messages
- # ActiveSupport::Deprecation.warn("ActiveRecord::Errors.default_error_messages has been deprecated. Please use :'active_record.error_messages'.t.")
- :'active_record.error_messages'.t
+ ActiveSupport::Deprecation.warn("ActiveRecord::Errors.default_error_messages has been deprecated. Please use 'active_record.error_messages'.t.")
+ 'active_record.error_messages'.t
end
end
@@ -163,7 +163,7 @@ module ActiveRecord
@errors.each_key do |attr|
@errors[attr].each do |message|
next unless message
-
+
if attr == "base"
full_messages << message
else
@@ -872,7 +872,7 @@ module ActiveRecord
end
raw_value = raw_value.to_i
else
- begin
+ begin
raw_value = Kernel.Float(raw_value.to_s)
rescue ArgumentError, TypeError
message = record.errors.generate_message(attr_name, :not_a_number, :value => raw_value, :default => configuration[:message])
diff --git a/activerecord/test/cases/validations_i18n_test.rb b/activerecord/test/cases/validations_i18n_test.rb
index 37a7c1ce49..158ff69e57 100644
--- a/activerecord/test/cases/validations_i18n_test.rb
+++ b/activerecord/test/cases/validations_i18n_test.rb
@@ -34,6 +34,12 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
end
+ def test_default_error_messages_is_deprecated
+ assert_deprecated('ActiveRecord::Errors.default_error_messages') do
+ ActiveRecord::Errors.default_error_messages
+ end
+ end
+
# ActiveRecord::Errors
def test_errors_generate_message_translates_custom_model_attribute_key
@@ -182,18 +188,32 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
# validates_length_of :within
- def test_validates_length_of_within_generates_message
+ def test_validates_length_of_within_generates_message_with_title_too_short
Topic.validates_length_of :title, :within => 3..5
@topic.errors.expects(:generate_message).with(:title, :too_short, {:count => 3, :default => nil})
@topic.valid?
end
- def test_validates_length_of_within_generates_message_with_custom_default_message
+ def test_validates_length_of_within_generates_message_with_title_too_short_and_custom_default_message
Topic.validates_length_of :title, :within => 3..5, :too_short => 'custom'
@topic.errors.expects(:generate_message).with(:title, :too_short, {:count => 3, :default => 'custom'})
@topic.valid?
end
+ def test_validates_length_of_within_generates_message_with_title_too_long
+ Topic.validates_length_of :title, :within => 3..5
+ @topic.title = 'this title is too long'
+ @topic.errors.expects(:generate_message).with(:title, :too_long, {:count => 5, :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_length_of_within_generates_message_with_title_too_long_and_custom_default_message
+ Topic.validates_length_of :title, :within => 3..5, :too_long => 'custom'
+ @topic.title = 'this title is too long'
+ @topic.errors.expects(:generate_message).with(:title, :too_long, {:count => 5, :default => 'custom'})
+ @topic.valid?
+ end
+
def test_validates_length_of_within_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:too_short => 'custom message'}}}}}
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:too_short => 'global message'}}
@@ -382,7 +402,43 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
- # validates_numericality_of :only_integer
+ # validates_numericality_of without :only_integer
+
+ def test_validates_numericality_of_generates_message
+ Topic.validates_numericality_of :title
+ @topic.title = 'a'
+ @topic.errors.expects(:generate_message).with(:title, :not_a_number, {:value => 'a', :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_numericality_of_generates_message_with_custom_default_message
+ Topic.validates_numericality_of :title, :message => 'custom'
+ @topic.title = 'a'
+ @topic.errors.expects(:generate_message).with(:title, :not_a_number, {:value => 'a', :default => 'custom'})
+ @topic.valid?
+ end
+
+ def test_validates_numericality_of_finds_custom_model_key_translation
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:not_a_number => 'custom message'}}}}}
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:not_a_number => 'global message'}}
+
+ Topic.validates_numericality_of :title
+ @topic.title = 'a'
+ @topic.valid?
+ assert_equal 'custom message', @topic.errors.on(:title)
+ end
+
+ def test_validates_numericality_of_finds_global_default_translation
+ I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:not_a_number => 'global message'}}
+
+ Topic.validates_numericality_of :title, :only_integer => true
+ @topic.title = 'a'
+ @topic.valid?
+ assert_equal 'global message', @topic.errors.on(:title)
+ end
+
+
+ # validates_numericality_of with :only_integer
def test_validates_numericality_of_only_integer_generates_message
Topic.validates_numericality_of :title, :only_integer => true
--
cgit v1.2.3
From 2ee9f2a0303cba95b2d8073fc7e22ec75229a8ee Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Mon, 23 Jun 2008 14:34:01 +0200
Subject: remove generic translate helpers
---
actionpack/lib/action_view/helpers/i18n_helper.rb | 19 -------------
actionpack/test/template/i18n_helper_test.rb | 33 -----------------------
2 files changed, 52 deletions(-)
delete mode 100644 actionpack/lib/action_view/helpers/i18n_helper.rb
delete mode 100644 actionpack/test/template/i18n_helper_test.rb
diff --git a/actionpack/lib/action_view/helpers/i18n_helper.rb b/actionpack/lib/action_view/helpers/i18n_helper.rb
deleted file mode 100644
index 1b1d1f301d..0000000000
--- a/actionpack/lib/action_view/helpers/i18n_helper.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-module ActionView
- module Helpers
- module I18nHelper
- def translate(*args)
- # inserts the locale or current request locale to the argument list if no locale
- # has been passed or the locale has been passed as part of the options hash
- options = args.extract_options!
- if args.size != 2
- locale = options.delete :locale
- locale ||= request.locale if respond_to? :request
- args << locale if locale
- end
- args << options unless options.empty?
- I18n.translate *args
- end
- alias :t :translate
- end
- end
-end
\ No newline at end of file
diff --git a/actionpack/test/template/i18n_helper_test.rb b/actionpack/test/template/i18n_helper_test.rb
deleted file mode 100644
index 598731568c..0000000000
--- a/actionpack/test/template/i18n_helper_test.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-require 'abstract_unit'
-require 'action_view/helpers/i18n_helper'
-
-class I18nHelperTests < Test::Unit::TestCase
- include ActionView::Helpers::I18nHelper
-
- attr_reader :request
- def setup
- @request = stub :locale => 'en-US'
- I18n.stubs(:translate).with(:'foo.bar', 'en-US').returns 'Foo Bar'
- end
-
- def test_translate_given_a_locale_argument_it_does_not_check_request_for_locale
- request.expects(:locale).never
- assert_equal 'Foo Bar', translate(:'foo.bar', :locale => 'en-US')
- end
-
- def test_translate_given_a_locale_option_it_does_not_check_request_for_locale
- request.expects(:locale).never
- I18n.expects(:translate).with(:'foo.bar', 'en-US').returns 'Foo Bar'
- assert_equal 'Foo Bar', translate(:'foo.bar', :locale => 'en-US')
- end
-
- def test_translate_given_no_locale_it_checks_request_for_locale
- request.expects(:locale).returns 'en-US'
- assert_equal 'Foo Bar', translate(:'foo.bar')
- end
-
- def test_translate_delegates_to_i18n_translate
- I18n.expects(:translate).with(:'foo.bar', 'en-US').returns 'Foo Bar'
- assert_equal 'Foo Bar', translate(:'foo.bar')
- end
-end
\ No newline at end of file
--
cgit v1.2.3
From c178a87b4326edd491922136c0a55bf4b889473d Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Mon, 23 Jun 2008 14:37:50 +0200
Subject: remove call to self.locale from helpers
---
actionpack/lib/action_view/helpers/active_record_helper.rb | 5 +----
actionpack/lib/action_view/helpers/date_helper.rb | 5 +----
actionpack/lib/action_view/helpers/number_helper.rb | 9 +++------
3 files changed, 5 insertions(+), 14 deletions(-)
diff --git a/actionpack/lib/action_view/helpers/active_record_helper.rb b/actionpack/lib/action_view/helpers/active_record_helper.rb
index 716e303a5d..4ff16cd70c 100644
--- a/actionpack/lib/action_view/helpers/active_record_helper.rb
+++ b/actionpack/lib/action_view/helpers/active_record_helper.rb
@@ -159,9 +159,6 @@ module ActionView
end
count = objects.inject(0) {|sum, object| sum + object.errors.count }
- locale = options[:locale]
- locale ||= self.locale if respond_to?(:locale)
-
unless count.zero?
html = {}
[:id, :class].each do |key|
@@ -174,7 +171,7 @@ module ActionView
end
options[:object_name] ||= params.first
- I18n.with_options :locale => locale, :scope => [:active_record, :error] do |locale|
+ I18n.with_options :locale => options[:locale], :scope => [:active_record, :error] do |locale|
header_message = if options.include?(:header_message)
options[:header_message]
else
diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb
index dbb5d458bf..6ac4171fd5 100755
--- a/actionpack/lib/action_view/helpers/date_helper.rb
+++ b/actionpack/lib/action_view/helpers/date_helper.rb
@@ -59,15 +59,12 @@ module ActionView
# distance_of_time_in_words(Time.now, Time.now) # => less than a minute
#
def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false, options = {})
- locale = options[:locale]
- locale ||= self.locale if respond_to?(:locale)
-
from_time = from_time.to_time if from_time.respond_to?(:to_time)
to_time = to_time.to_time if to_time.respond_to?(:to_time)
distance_in_minutes = (((to_time - from_time).abs)/60).round
distance_in_seconds = ((to_time - from_time).abs).round
- I18n.with_options :locale => locale, :scope => :'datetime.distance_in_words' do |locale|
+ I18n.with_options :locale => options[:locale], :scope => :'datetime.distance_in_words' do |locale|
case distance_in_minutes
when 0..1
return distance_in_minutes == 0 ?
diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb
index 4373d063bb..3e0d5b1db4 100644
--- a/actionpack/lib/action_view/helpers/number_helper.rb
+++ b/actionpack/lib/action_view/helpers/number_helper.rb
@@ -69,12 +69,9 @@ module ActionView
# number_to_currency(1234567890.50, :unit => "£", :separator => ",", :delimiter => "", :format => "%n %u")
# # => 1234567890,50 £
def number_to_currency(number, options = {})
- options = options.symbolize_keys
-
- locale = options[:locale]
- locale ||= self.locale if respond_to?(:locale)
-
- defaults = :'currency.format'.t(locale) || {}
+ options = options.symbolize_keys
+ defaults = :'currency.format'.t(options[:locale]) || {}
+
precision = options[:precision] || defaults[:precision]
unit = options[:unit] || defaults[:unit]
separator = options[:separator] || defaults[:separator]
--
cgit v1.2.3
From ac66865ea3d0eb0de8e19fef49293feb9e61281b Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Mon, 23 Jun 2008 14:49:02 +0200
Subject: update tests according to removal of self.locale from helpers
---
actionpack/test/template/active_record_helper_i18n_test.rb | 13 -------------
actionpack/test/template/date_helper_i18n_test.rb | 12 ------------
actionpack/test/template/number_helper_i18n_test.rb | 11 -----------
3 files changed, 36 deletions(-)
diff --git a/actionpack/test/template/active_record_helper_i18n_test.rb b/actionpack/test/template/active_record_helper_i18n_test.rb
index 3a2197ac93..d1b92c7e4d 100644
--- a/actionpack/test/template/active_record_helper_i18n_test.rb
+++ b/actionpack/test/template/active_record_helper_i18n_test.rb
@@ -7,24 +7,11 @@ class ActiveRecordHelperI18nTest < Test::Unit::TestCase
def setup
@object = stub :errors => stub(:count => 1, :full_messages => ['full_messages'])
stubs(:content_tag).returns 'content_tag'
- stubs(:locale)
I18n.stubs(:t).with(:'header_message', :locale => 'en-US', :scope => [:active_record, :error], :count => 1, :object_name => '').returns "1 error prohibited this from being saved"
I18n.stubs(:t).with(:'message', :locale => 'en-US', :scope => [:active_record, :error]).returns 'There were problems with the following fields:'
end
- def test_error_messages_for_given_a_locale_it_does_not_check_request_for_locale
- expects(:locale).never
- @object.errors.stubs(:count).returns 0
- error_messages_for(:object => @object, :locale => 'en-US')
- end
-
- def test_error_messages_for_given_no_locale_it_checks_request_for_locale
- expects(:locale).returns 'en-US'
- @object.errors.stubs(:count).returns 0
- error_messages_for(:object => @object)
- end
-
def test_error_messages_for_given_a_header_message_option_it_does_not_translate_header_message
I18n.expects(:translate).with(:'header_message', :locale => 'en-US', :scope => [:active_record, :error], :count => 1, :object_name => '').never
error_messages_for(:object => @object, :header_message => 'header message', :locale => 'en-US')
diff --git a/actionpack/test/template/date_helper_i18n_test.rb b/actionpack/test/template/date_helper_i18n_test.rb
index f245ca1fc8..3e1eed61fd 100644
--- a/actionpack/test/template/date_helper_i18n_test.rb
+++ b/actionpack/test/template/date_helper_i18n_test.rb
@@ -5,22 +5,11 @@ class DateHelperDistanceOfTimeInWordsI18nTests < Test::Unit::TestCase
attr_reader :request
def setup
- stubs(:locale)
@from = Time.mktime(2004, 6, 6, 21, 45, 0)
end
# distance_of_time_in_words
- def test_distance_of_time_in_words_given_a_locale_it_does_not_check_request_for_locale
- expects(:locale).never
- distance_of_time_in_words @from, @from + 1.second, false, :locale => 'en-US'
- end
-
- def test_distance_of_time_in_words_given_no_locale_it_checks_request_for_locale
- expects(:locale).returns 'en-US'
- distance_of_time_in_words @from, @from + 1.second
- end
-
def test_distance_of_time_in_words_calls_i18n
{ # with include_seconds
[2.seconds, true] => [:'less_than_x_seconds', 5],
@@ -64,7 +53,6 @@ class DateHelperSelectTagsI18nTests < Test::Unit::TestCase
attr_reader :request
def setup
- # stubs(:locale)
I18n.stubs(:translate).with(:'date.month_names', 'en-US').returns Date::MONTHNAMES
end
diff --git a/actionpack/test/template/number_helper_i18n_test.rb b/actionpack/test/template/number_helper_i18n_test.rb
index 5db60ece04..bee9ceaa71 100644
--- a/actionpack/test/template/number_helper_i18n_test.rb
+++ b/actionpack/test/template/number_helper_i18n_test.rb
@@ -5,21 +5,10 @@ class NumberHelperI18nTests < Test::Unit::TestCase
attr_reader :request
def setup
- stubs(:locale)
@defaults = {:separator => ".", :unit => "$", :format => "%u%n", :delimiter => ",", :precision => 2}
I18n.backend.store_translations 'en-US', :currency => {:format => @defaults}
end
- def test_number_to_currency_given_a_locale_it_does_not_check_request_for_locale
- expects(:locale).never
- number_to_currency(1, :locale => 'en-US')
- end
-
- def test_number_to_currency_given_no_locale_it_checks_request_for_locale
- expects(:locale).returns 'en-US'
- number_to_currency(1)
- end
-
def test_number_to_currency_translates_currency_formats
I18n.expects(:translate).with(:'currency.format', 'en-US').returns @defaults
number_to_currency(1, :locale => 'en-US')
--
cgit v1.2.3
From 77177441d1bd8f62c5b6a990ddee155061df661c Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Mon, 23 Jun 2008 14:49:47 +0200
Subject: including rcov shell scripts for reference
---
actionpack/test/i18n_coverage | 9 +++++++++
activerecord/test/i18n_coverage | 6 ++++++
2 files changed, 15 insertions(+)
create mode 100755 actionpack/test/i18n_coverage
create mode 100755 activerecord/test/i18n_coverage
diff --git a/actionpack/test/i18n_coverage b/actionpack/test/i18n_coverage
new file mode 100755
index 0000000000..57b54e9d47
--- /dev/null
+++ b/actionpack/test/i18n_coverage
@@ -0,0 +1,9 @@
+rcov -x abstract_unit.rb \
+-i action_view/helpers/number_helper.rb,action_view/helpers/date_helper.rb,action_view/helpers/active_record_helper.rb \
+template/number_helper_i18n_test.rb \
+template/date_helper_i18n_test.rb \
+template/active_record_helper_i18n_test.rb \
+
+# template/number_helper_test.rb \
+# template/date_helper_test.rb \
+# template/active_record_helper_test.rb
\ No newline at end of file
diff --git a/activerecord/test/i18n_coverage b/activerecord/test/i18n_coverage
new file mode 100755
index 0000000000..1589a6c06f
--- /dev/null
+++ b/activerecord/test/i18n_coverage
@@ -0,0 +1,6 @@
+rcov -I connections/native_mysql \
+-x cases/helper,config,connection,models \
+-i active_record/validations.rb \
+cases/validations_i18n_test.rb \
+
+# cases/validations_test.rb
\ No newline at end of file
--
cgit v1.2.3
From 8461526f346b8d8387ba3b74221fbeefef3aefeb Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Mon, 23 Jun 2008 14:55:07 +0200
Subject: silence deprecation warning during validations test
---
activerecord/test/cases/validations_test.rb | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/activerecord/test/cases/validations_test.rb b/activerecord/test/cases/validations_test.rb
index 7b71647d25..ad27ac951c 100755
--- a/activerecord/test/cases/validations_test.rb
+++ b/activerecord/test/cases/validations_test.rb
@@ -853,7 +853,9 @@ class ValidationsTest < ActiveRecord::TestCase
end
def test_validates_length_with_globally_modified_error_message
- ActiveRecord::Errors.default_error_messages[:too_short] = 'tu est trops petit hombre %d'
+ ActiveSupport::Deprecation.silence do
+ ActiveRecord::Errors.default_error_messages[:too_short] = 'tu est trops petit hombre %d'
+ end
Topic.validates_length_of :title, :minimum => 10
t = Topic.create(:title => 'too short')
assert !t.valid?
--
cgit v1.2.3
From 66c2508ebbca06e551255a76cc47a1608f091992 Mon Sep 17 00:00:00 2001
From: Luca Guidi
Date: Fri, 27 Jun 2008 15:00:55 +0200
Subject: Make sure mocha is available
---
.../template/active_record_helper_i18n_test.rb | 48 +-
actionpack/test/template/date_helper_i18n_test.rb | 134 ++---
.../test/template/number_helper_i18n_test.rb | 16 +-
activerecord/test/cases/validations_i18n_test.rb | 576 +++++++++++----------
4 files changed, 413 insertions(+), 361 deletions(-)
diff --git a/actionpack/test/template/active_record_helper_i18n_test.rb b/actionpack/test/template/active_record_helper_i18n_test.rb
index d1b92c7e4d..d78b0e4c0c 100644
--- a/actionpack/test/template/active_record_helper_i18n_test.rb
+++ b/actionpack/test/template/active_record_helper_i18n_test.rb
@@ -4,31 +4,33 @@ class ActiveRecordHelperI18nTest < Test::Unit::TestCase
include ActionView::Helpers::ActiveRecordHelper
attr_reader :request
- def setup
- @object = stub :errors => stub(:count => 1, :full_messages => ['full_messages'])
- stubs(:content_tag).returns 'content_tag'
-
- I18n.stubs(:t).with(:'header_message', :locale => 'en-US', :scope => [:active_record, :error], :count => 1, :object_name => '').returns "1 error prohibited this from being saved"
- I18n.stubs(:t).with(:'message', :locale => 'en-US', :scope => [:active_record, :error]).returns 'There were problems with the following fields:'
- end
+ uses_mocha 'active_record_helper_i18n_test' do
+ def setup
+ @object = stub :errors => stub(:count => 1, :full_messages => ['full_messages'])
+ stubs(:content_tag).returns 'content_tag'
- def test_error_messages_for_given_a_header_message_option_it_does_not_translate_header_message
- I18n.expects(:translate).with(:'header_message', :locale => 'en-US', :scope => [:active_record, :error], :count => 1, :object_name => '').never
- error_messages_for(:object => @object, :header_message => 'header message', :locale => 'en-US')
- end
+ I18n.stubs(:t).with(:'header_message', :locale => 'en-US', :scope => [:active_record, :error], :count => 1, :object_name => '').returns "1 error prohibited this from being saved"
+ I18n.stubs(:t).with(:'message', :locale => 'en-US', :scope => [:active_record, :error]).returns 'There were problems with the following fields:'
+ end
- def test_error_messages_for_given_no_header_message_option_it_translates_header_message
- I18n.expects(:t).with(:'header_message', :locale => 'en-US', :scope => [:active_record, :error], :count => 1, :object_name => '').returns 'header message'
- error_messages_for(:object => @object, :locale => 'en-US')
- end
-
- def test_error_messages_for_given_a_message_option_it_does_not_translate_message
- I18n.expects(:t).with(:'message', :locale => 'en-US', :scope => [:active_record, :error]).never
- error_messages_for(:object => @object, :message => 'message', :locale => 'en-US')
- end
+ def test_error_messages_for_given_a_header_message_option_it_does_not_translate_header_message
+ I18n.expects(:translate).with(:'header_message', :locale => 'en-US', :scope => [:active_record, :error], :count => 1, :object_name => '').never
+ error_messages_for(:object => @object, :header_message => 'header message', :locale => 'en-US')
+ end
+
+ def test_error_messages_for_given_no_header_message_option_it_translates_header_message
+ I18n.expects(:t).with(:'header_message', :locale => 'en-US', :scope => [:active_record, :error], :count => 1, :object_name => '').returns 'header message'
+ error_messages_for(:object => @object, :locale => 'en-US')
+ end
+
+ def test_error_messages_for_given_a_message_option_it_does_not_translate_message
+ I18n.expects(:t).with(:'message', :locale => 'en-US', :scope => [:active_record, :error]).never
+ error_messages_for(:object => @object, :message => 'message', :locale => 'en-US')
+ end
- def test_error_messages_for_given_no_message_option_it_translates_message
- I18n.expects(:t).with(:'message', :locale => 'en-US', :scope => [:active_record, :error]).returns 'There were problems with the following fields:'
- error_messages_for(:object => @object, :locale => 'en-US')
+ def test_error_messages_for_given_no_message_option_it_translates_message
+ I18n.expects(:t).with(:'message', :locale => 'en-US', :scope => [:active_record, :error]).returns 'There were problems with the following fields:'
+ error_messages_for(:object => @object, :locale => 'en-US')
+ end
end
end
\ No newline at end of file
diff --git a/actionpack/test/template/date_helper_i18n_test.rb b/actionpack/test/template/date_helper_i18n_test.rb
index 3e1eed61fd..aeb06c55ea 100644
--- a/actionpack/test/template/date_helper_i18n_test.rb
+++ b/actionpack/test/template/date_helper_i18n_test.rb
@@ -8,43 +8,45 @@ class DateHelperDistanceOfTimeInWordsI18nTests < Test::Unit::TestCase
@from = Time.mktime(2004, 6, 6, 21, 45, 0)
end
- # distance_of_time_in_words
+ uses_mocha 'date_helper_distance_of_time_in_words_i18n_test' do
+ # distance_of_time_in_words
- def test_distance_of_time_in_words_calls_i18n
- { # with include_seconds
- [2.seconds, true] => [:'less_than_x_seconds', 5],
- [9.seconds, true] => [:'less_than_x_seconds', 10],
- [19.seconds, true] => [:'less_than_x_seconds', 20],
- [30.seconds, true] => [:'half_a_minute', nil],
- [59.seconds, true] => [:'less_than_x_minutes', 1],
- [60.seconds, true] => [:'x_minutes', 1],
-
- # without include_seconds
- [29.seconds, false] => [:'less_than_x_minutes', 1],
- [60.seconds, false] => [:'x_minutes', 1],
- [44.minutes, false] => [:'x_minutes', 44],
- [61.minutes, false] => [:'about_x_hours', 1],
- [24.hours, false] => [:'x_days', 1],
- [30.days, false] => [:'about_x_months', 1],
- [60.days, false] => [:'x_months', 2],
- [1.year, false] => [:'about_x_years', 1],
- [3.years, false] => [:'over_x_years', 3]
-
- }.each do |passed, expected|
- assert_distance_of_time_in_words_translates_key passed, expected
+ def test_distance_of_time_in_words_calls_i18n
+ { # with include_seconds
+ [2.seconds, true] => [:'less_than_x_seconds', 5],
+ [9.seconds, true] => [:'less_than_x_seconds', 10],
+ [19.seconds, true] => [:'less_than_x_seconds', 20],
+ [30.seconds, true] => [:'half_a_minute', nil],
+ [59.seconds, true] => [:'less_than_x_minutes', 1],
+ [60.seconds, true] => [:'x_minutes', 1],
+
+ # without include_seconds
+ [29.seconds, false] => [:'less_than_x_minutes', 1],
+ [60.seconds, false] => [:'x_minutes', 1],
+ [44.minutes, false] => [:'x_minutes', 44],
+ [61.minutes, false] => [:'about_x_hours', 1],
+ [24.hours, false] => [:'x_days', 1],
+ [30.days, false] => [:'about_x_months', 1],
+ [60.days, false] => [:'x_months', 2],
+ [1.year, false] => [:'about_x_years', 1],
+ [3.years, false] => [:'over_x_years', 3]
+
+ }.each do |passed, expected|
+ assert_distance_of_time_in_words_translates_key passed, expected
+ end
end
- end
-
- def assert_distance_of_time_in_words_translates_key(passed, expected)
- diff, include_seconds = *passed
- key, count = *expected
- to = @from + diff
- options = {:locale => 'en-US', :scope => :'datetime.distance_in_words'}
- options[:count] = count if count
-
- I18n.expects(:t).with(key, options)
- distance_of_time_in_words(@from, to, include_seconds, :locale => 'en-US')
+ def assert_distance_of_time_in_words_translates_key(passed, expected)
+ diff, include_seconds = *passed
+ key, count = *expected
+ to = @from + diff
+
+ options = {:locale => 'en-US', :scope => :'datetime.distance_in_words'}
+ options[:count] = count if count
+
+ I18n.expects(:t).with(key, options)
+ distance_of_time_in_words(@from, to, include_seconds, :locale => 'en-US')
+ end
end
end
@@ -52,36 +54,38 @@ class DateHelperSelectTagsI18nTests < Test::Unit::TestCase
include ActionView::Helpers::DateHelper
attr_reader :request
- def setup
- I18n.stubs(:translate).with(:'date.month_names', 'en-US').returns Date::MONTHNAMES
- end
-
- # select_month
-
- def test_select_month_given_use_month_names_option_does_not_translate_monthnames
- I18n.expects(:translate).never
- select_month(8, :locale => 'en-US', :use_month_names => Date::MONTHNAMES)
- end
-
- def test_select_month_translates_monthnames
- I18n.expects(:translate).with(:'date.month_names', 'en-US').returns Date::MONTHNAMES
- select_month(8, :locale => 'en-US')
- end
-
- def test_select_month_given_use_short_month_option_translates_abbr_monthnames
- I18n.expects(:translate).with(:'date.abbr_month_names', 'en-US').returns Date::ABBR_MONTHNAMES
- select_month(8, :locale => 'en-US', :use_short_month => true)
- end
-
- # date_or_time_select
-
- def test_date_or_time_select_given_an_order_options_does_not_translate_order
- I18n.expects(:translate).never
- datetime_select('post', 'updated_at', :order => [:year, :month, :day], :locale => 'en-US')
- end
-
- def test_date_or_time_select_given_no_order_options_translates_order
- I18n.expects(:translate).with(:'date.order', 'en-US').returns [:year, :month, :day]
- datetime_select('post', 'updated_at', :locale => 'en-US')
+ uses_mocha 'date_helper_select_tags_i18n_tests' do
+ def setup
+ I18n.stubs(:translate).with(:'date.month_names', 'en-US').returns Date::MONTHNAMES
+ end
+
+ # select_month
+
+ def test_select_month_given_use_month_names_option_does_not_translate_monthnames
+ I18n.expects(:translate).never
+ select_month(8, :locale => 'en-US', :use_month_names => Date::MONTHNAMES)
+ end
+
+ def test_select_month_translates_monthnames
+ I18n.expects(:translate).with(:'date.month_names', 'en-US').returns Date::MONTHNAMES
+ select_month(8, :locale => 'en-US')
+ end
+
+ def test_select_month_given_use_short_month_option_translates_abbr_monthnames
+ I18n.expects(:translate).with(:'date.abbr_month_names', 'en-US').returns Date::ABBR_MONTHNAMES
+ select_month(8, :locale => 'en-US', :use_short_month => true)
+ end
+
+ # date_or_time_select
+
+ def test_date_or_time_select_given_an_order_options_does_not_translate_order
+ I18n.expects(:translate).never
+ datetime_select('post', 'updated_at', :order => [:year, :month, :day], :locale => 'en-US')
+ end
+
+ def test_date_or_time_select_given_no_order_options_translates_order
+ I18n.expects(:translate).with(:'date.order', 'en-US').returns [:year, :month, :day]
+ datetime_select('post', 'updated_at', :locale => 'en-US')
+ end
end
end
\ No newline at end of file
diff --git a/actionpack/test/template/number_helper_i18n_test.rb b/actionpack/test/template/number_helper_i18n_test.rb
index bee9ceaa71..be40ddbc88 100644
--- a/actionpack/test/template/number_helper_i18n_test.rb
+++ b/actionpack/test/template/number_helper_i18n_test.rb
@@ -4,13 +4,15 @@ class NumberHelperI18nTests < Test::Unit::TestCase
include ActionView::Helpers::NumberHelper
attr_reader :request
- def setup
- @defaults = {:separator => ".", :unit => "$", :format => "%u%n", :delimiter => ",", :precision => 2}
- I18n.backend.store_translations 'en-US', :currency => {:format => @defaults}
- end
+ uses_mocha 'number_helper_i18n_tests' do
+ def setup
+ @defaults = {:separator => ".", :unit => "$", :format => "%u%n", :delimiter => ",", :precision => 2}
+ I18n.backend.store_translations 'en-US', :currency => {:format => @defaults}
+ end
- def test_number_to_currency_translates_currency_formats
- I18n.expects(:translate).with(:'currency.format', 'en-US').returns @defaults
- number_to_currency(1, :locale => 'en-US')
+ def test_number_to_currency_translates_currency_formats
+ I18n.expects(:translate).with(:'currency.format', 'en-US').returns @defaults
+ number_to_currency(1, :locale => 'en-US')
+ end
end
end
\ No newline at end of file
diff --git a/activerecord/test/cases/validations_i18n_test.rb b/activerecord/test/cases/validations_i18n_test.rb
index 158ff69e57..53e90f4d53 100644
--- a/activerecord/test/cases/validations_i18n_test.rb
+++ b/activerecord/test/cases/validations_i18n_test.rb
@@ -41,66 +41,307 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
# ActiveRecord::Errors
+ uses_mocha 'ActiveRecord::Errors' do
+ def test_errors_generate_message_translates_custom_model_attribute_key
+ global_scope = [:active_record, :error_messages]
+ custom_scope = global_scope + [:custom, 'topic', :title]
+
+ I18n.expects(:t).with :scope => [:active_record, :error_messages], :default => [:"custom.topic.title.invalid", 'default from class def', :invalid]
+ @topic.errors.generate_message :title, :invalid, :default => 'default from class def'
+ end
+
+ def test_errors_generate_message_translates_custom_model_attribute_keys_with_sti
+ custom_scope = [:active_record, :error_messages, :custom, 'topic', :title]
+
+ I18n.expects(:t).with :scope => [:active_record, :error_messages], :default => [:"custom.reply.title.invalid", :"custom.topic.title.invalid", 'default from class def', :invalid]
+ Reply.new.errors.generate_message :title, :invalid, :default => 'default from class def'
+ end
+
+ def test_errors_add_on_empty_generates_message
+ @topic.errors.expects(:generate_message).with(:title, :empty, {:default => nil})
+ @topic.errors.add_on_empty :title
+ end
+
+ def test_errors_add_on_empty_generates_message_with_custom_default_message
+ @topic.errors.expects(:generate_message).with(:title, :empty, {:default => 'custom'})
+ @topic.errors.add_on_empty :title, 'custom'
+ end
+
+ def test_errors_add_on_blank_generates_message
+ @topic.errors.expects(:generate_message).with(:title, :blank, {:default => nil})
+ @topic.errors.add_on_blank :title
+ end
+
+ def test_errors_add_on_blank_generates_message_with_custom_default_message
+ @topic.errors.expects(:generate_message).with(:title, :blank, {:default => 'custom'})
+ @topic.errors.add_on_blank :title, 'custom'
+ end
+
+ def test_errors_full_messages_translates_human_attribute_name_for_model_attributes
+ @topic.errors.instance_variable_set :@errors, { 'title' => 'empty' }
+ I18n.expects(:translate).with(:"active_record.human_attribute_names.topic.title", 'en-US').returns('Title')
+ @topic.errors.full_messages :locale => 'en-US'
+ end
+ end
- def test_errors_generate_message_translates_custom_model_attribute_key
- global_scope = [:active_record, :error_messages]
- custom_scope = global_scope + [:custom, 'topic', :title]
+ # ActiveRecord::Validations
+ uses_mocha 'ActiveRecord::Validations' do
+ # validates_confirmation_of w/ mocha
+
+ def test_validates_confirmation_of_generates_message
+ Topic.validates_confirmation_of :title
+ @topic.title_confirmation = 'foo'
+ @topic.errors.expects(:generate_message).with(:title, :confirmation, {:default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_confirmation_of_generates_message_with_custom_default_message
+ Topic.validates_confirmation_of :title, :message => 'custom'
+ @topic.title_confirmation = 'foo'
+ @topic.errors.expects(:generate_message).with(:title, :confirmation, {:default => 'custom'})
+ @topic.valid?
+ end
- I18n.expects(:t).with :scope => [:active_record, :error_messages], :default => [:"custom.topic.title.invalid", 'default from class def', :invalid]
- @topic.errors.generate_message :title, :invalid, :default => 'default from class def'
- end
-
- def test_errors_generate_message_translates_custom_model_attribute_keys_with_sti
- custom_scope = [:active_record, :error_messages, :custom, 'topic', :title]
+ # validates_acceptance_of w/ mocha
+
+ def test_validates_acceptance_of_generates_message
+ Topic.validates_acceptance_of :title, :allow_nil => false
+ @topic.errors.expects(:generate_message).with(:title, :accepted, {:default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_acceptance_of_generates_message_with_custom_default_message
+ Topic.validates_acceptance_of :title, :message => 'custom', :allow_nil => false
+ @topic.errors.expects(:generate_message).with(:title, :accepted, {:default => 'custom'})
+ @topic.valid?
+ end
- I18n.expects(:t).with :scope => [:active_record, :error_messages], :default => [:"custom.reply.title.invalid", :"custom.topic.title.invalid", 'default from class def', :invalid]
- Reply.new.errors.generate_message :title, :invalid, :default => 'default from class def'
- end
-
- def test_errors_add_on_empty_generates_message
- @topic.errors.expects(:generate_message).with(:title, :empty, {:default => nil})
- @topic.errors.add_on_empty :title
- end
-
- def test_errors_add_on_empty_generates_message_with_custom_default_message
- @topic.errors.expects(:generate_message).with(:title, :empty, {:default => 'custom'})
- @topic.errors.add_on_empty :title, 'custom'
- end
-
- def test_errors_add_on_blank_generates_message
- @topic.errors.expects(:generate_message).with(:title, :blank, {:default => nil})
- @topic.errors.add_on_blank :title
- end
-
- def test_errors_add_on_blank_generates_message_with_custom_default_message
- @topic.errors.expects(:generate_message).with(:title, :blank, {:default => 'custom'})
- @topic.errors.add_on_blank :title, 'custom'
- end
-
- def test_errors_full_messages_translates_human_attribute_name_for_model_attributes
- @topic.errors.instance_variable_set :@errors, { 'title' => 'empty' }
- I18n.expects(:translate).with(:"active_record.human_attribute_names.topic.title", 'en-US').returns('Title')
- @topic.errors.full_messages :locale => 'en-US'
- end
-
-
- # ActiveRecord::Validations
-
- # validates_confirmation_of
-
- def test_validates_confirmation_of_generates_message
- Topic.validates_confirmation_of :title
- @topic.title_confirmation = 'foo'
- @topic.errors.expects(:generate_message).with(:title, :confirmation, {:default => nil})
- @topic.valid?
+ # validates_presence_of w/ mocha
+
+ def test_validates_presence_of_generates_message
+ Topic.validates_presence_of :title
+ @topic.errors.expects(:generate_message).with(:title, :blank, {:default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_presence_of_generates_message_with_custom_default_message
+ Topic.validates_presence_of :title, :message => 'custom'
+ @topic.errors.expects(:generate_message).with(:title, :blank, {:default => 'custom'})
+ @topic.valid?
+ end
+
+ def test_validates_length_of_within_generates_message_with_title_too_short
+ Topic.validates_length_of :title, :within => 3..5
+ @topic.errors.expects(:generate_message).with(:title, :too_short, {:count => 3, :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_length_of_within_generates_message_with_title_too_short_and_custom_default_message
+ Topic.validates_length_of :title, :within => 3..5, :too_short => 'custom'
+ @topic.errors.expects(:generate_message).with(:title, :too_short, {:count => 3, :default => 'custom'})
+ @topic.valid?
+ end
+
+ def test_validates_length_of_within_generates_message_with_title_too_long
+ Topic.validates_length_of :title, :within => 3..5
+ @topic.title = 'this title is too long'
+ @topic.errors.expects(:generate_message).with(:title, :too_long, {:count => 5, :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_length_of_within_generates_message_with_title_too_long_and_custom_default_message
+ Topic.validates_length_of :title, :within => 3..5, :too_long => 'custom'
+ @topic.title = 'this title is too long'
+ @topic.errors.expects(:generate_message).with(:title, :too_long, {:count => 5, :default => 'custom'})
+ @topic.valid?
+ end
+
+ # validates_length_of :within w/ mocha
+
+ def test_validates_length_of_within_generates_message_with_title_too_short
+ Topic.validates_length_of :title, :within => 3..5
+ @topic.errors.expects(:generate_message).with(:title, :too_short, {:count => 3, :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_length_of_within_generates_message_with_title_too_short_and_custom_default_message
+ Topic.validates_length_of :title, :within => 3..5, :too_short => 'custom'
+ @topic.errors.expects(:generate_message).with(:title, :too_short, {:count => 3, :default => 'custom'})
+ @topic.valid?
+ end
+
+ def test_validates_length_of_within_generates_message_with_title_too_long
+ Topic.validates_length_of :title, :within => 3..5
+ @topic.title = 'this title is too long'
+ @topic.errors.expects(:generate_message).with(:title, :too_long, {:count => 5, :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_length_of_within_generates_message_with_title_too_long_and_custom_default_message
+ Topic.validates_length_of :title, :within => 3..5, :too_long => 'custom'
+ @topic.title = 'this title is too long'
+ @topic.errors.expects(:generate_message).with(:title, :too_long, {:count => 5, :default => 'custom'})
+ @topic.valid?
+ end
+
+ # validates_length_of :is w/ mocha
+
+ def test_validates_length_of_is_generates_message
+ Topic.validates_length_of :title, :is => 5
+ @topic.errors.expects(:generate_message).with(:title, :wrong_length, {:count => 5, :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_length_of_is_generates_message_with_custom_default_message
+ Topic.validates_length_of :title, :is => 5, :message => 'custom'
+ @topic.errors.expects(:generate_message).with(:title, :wrong_length, {:count => 5, :default => 'custom'})
+ @topic.valid?
+ end
+
+ # validates_uniqueness_of w/ mocha
+
+ def test_validates_uniqueness_of_generates_message
+ Topic.validates_uniqueness_of :title
+ @topic.title = unique_topic.title
+ @topic.errors.expects(:generate_message).with(:title, :taken, {:default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_uniqueness_of_generates_message_with_custom_default_message
+ Topic.validates_uniqueness_of :title, :message => 'custom'
+ @topic.title = unique_topic.title
+ @topic.errors.expects(:generate_message).with(:title, :taken, {:default => 'custom'})
+ @topic.valid?
+ end
+
+ # validates_format_of w/ mocha
+
+ def test_validates_format_of_generates_message
+ Topic.validates_format_of :title, :with => /^[1-9][0-9]*$/
+ @topic.title = '72x'
+ @topic.errors.expects(:generate_message).with(:title, :invalid, {:value => '72x', :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_format_of_generates_message_with_custom_default_message
+ Topic.validates_format_of :title, :with => /^[1-9][0-9]*$/, :message => 'custom'
+ @topic.title = '72x'
+ @topic.errors.expects(:generate_message).with(:title, :invalid, {:value => '72x', :default => 'custom'})
+ @topic.valid?
+ end
+
+ # validates_inclusion_of w/ mocha
+
+ def test_validates_inclusion_of_generates_message
+ Topic.validates_inclusion_of :title, :in => %w(a b c)
+ @topic.title = 'z'
+ @topic.errors.expects(:generate_message).with(:title, :inclusion, {:value => 'z', :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_inclusion_of_generates_message_with_custom_default_message
+ Topic.validates_inclusion_of :title, :in => %w(a b c), :message => 'custom'
+ @topic.title = 'z'
+ @topic.errors.expects(:generate_message).with(:title, :inclusion, {:value => 'z', :default => 'custom'})
+ @topic.valid?
+ end
+
+ # validates_exclusion_of w/ mocha
+
+ def test_validates_exclusion_of_generates_message
+ Topic.validates_exclusion_of :title, :in => %w(a b c)
+ @topic.title = 'a'
+ @topic.errors.expects(:generate_message).with(:title, :exclusion, {:value => 'a', :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_exclusion_of_generates_message_with_custom_default_message
+ Topic.validates_exclusion_of :title, :in => %w(a b c), :message => 'custom'
+ @topic.title = 'a'
+ @topic.errors.expects(:generate_message).with(:title, :exclusion, {:value => 'a', :default => 'custom'})
+ @topic.valid?
+ end
+
+ # validates_numericality_of without :only_integer w/ mocha
+
+ def test_validates_numericality_of_generates_message
+ Topic.validates_numericality_of :title
+ @topic.title = 'a'
+ @topic.errors.expects(:generate_message).with(:title, :not_a_number, {:value => 'a', :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_numericality_of_generates_message_with_custom_default_message
+ Topic.validates_numericality_of :title, :message => 'custom'
+ @topic.title = 'a'
+ @topic.errors.expects(:generate_message).with(:title, :not_a_number, {:value => 'a', :default => 'custom'})
+ @topic.valid?
+ end
+
+ # validates_numericality_of with :only_integer w/ mocha
+
+ def test_validates_numericality_of_only_integer_generates_message
+ Topic.validates_numericality_of :title, :only_integer => true
+ @topic.title = 'a'
+ @topic.errors.expects(:generate_message).with(:title, :not_a_number, {:value => 'a', :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_numericality_of_only_integer_generates_message_with_custom_default_message
+ Topic.validates_numericality_of :title, :only_integer => true, :message => 'custom'
+ @topic.title = 'a'
+ @topic.errors.expects(:generate_message).with(:title, :not_a_number, {:value => 'a', :default => 'custom'})
+ @topic.valid?
+ end
+
+ # validates_numericality_of :odd w/ mocha
+
+ def test_validates_numericality_of_odd_generates_message
+ Topic.validates_numericality_of :title, :only_integer => true, :odd => true
+ @topic.title = 0
+ @topic.errors.expects(:generate_message).with(:title, :odd, {:value => 0, :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_numericality_of_odd_generates_message_with_custom_default_message
+ Topic.validates_numericality_of :title, :only_integer => true, :odd => true, :message => 'custom'
+ @topic.title = 0
+ @topic.errors.expects(:generate_message).with(:title, :odd, {:value => 0, :default => 'custom'})
+ @topic.valid?
+ end
+
+ # validates_numericality_of :less_than w/ mocha
+
+ def test_validates_numericality_of_less_than_generates_message
+ Topic.validates_numericality_of :title, :only_integer => true, :less_than => 0
+ @topic.title = 1
+ @topic.errors.expects(:generate_message).with(:title, :less_than, {:value => 1, :count => 0, :default => nil})
+ @topic.valid?
+ end
+
+ def test_validates_numericality_of_odd_generates_message_with_custom_default_message
+ Topic.validates_numericality_of :title, :only_integer => true, :less_than => 0, :message => 'custom'
+ @topic.title = 1
+ @topic.errors.expects(:generate_message).with(:title, :less_than, {:value => 1, :count => 0, :default => 'custom'})
+ @topic.valid?
+ end
+
+ # validates_associated w/ mocha
+
+ def test_validates_associated_generates_message
+ Topic.validates_associated :replies
+ replied_topic.errors.expects(:generate_message).with(:replies, :invalid, {:value => replied_topic.replies, :default => nil})
+ replied_topic.valid?
+ end
+
+ def test_validates_associated_generates_message_with_custom_default_message
+ Topic.validates_associated :replies
+ replied_topic.errors.expects(:generate_message).with(:replies, :invalid, {:value => replied_topic.replies, :default => nil})
+ replied_topic.valid?
+ end
end
- def test_validates_confirmation_of_generates_message_with_custom_default_message
- Topic.validates_confirmation_of :title, :message => 'custom'
- @topic.title_confirmation = 'foo'
- @topic.errors.expects(:generate_message).with(:title, :confirmation, {:default => 'custom'})
- @topic.valid?
- end
+ # validates_confirmation_of w/o mocha
def test_validates_confirmation_of_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:confirmation => 'custom message'}}}}}
@@ -121,20 +362,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
assert_equal 'global message', @topic.errors.on(:title)
end
-
- # validates_acceptance_of
-
- def test_validates_acceptance_of_generates_message
- Topic.validates_acceptance_of :title, :allow_nil => false
- @topic.errors.expects(:generate_message).with(:title, :accepted, {:default => nil})
- @topic.valid?
- end
-
- def test_validates_acceptance_of_generates_message_with_custom_default_message
- Topic.validates_acceptance_of :title, :message => 'custom', :allow_nil => false
- @topic.errors.expects(:generate_message).with(:title, :accepted, {:default => 'custom'})
- @topic.valid?
- end
+ # validates_acceptance_of w/o mocha
def test_validates_acceptance_of_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:accepted => 'custom message'}}}}}
@@ -153,21 +381,8 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
assert_equal 'global message', @topic.errors.on(:title)
end
-
- # validates_presence_of
-
- def test_validates_presence_of_generates_message
- Topic.validates_presence_of :title
- @topic.errors.expects(:generate_message).with(:title, :blank, {:default => nil})
- @topic.valid?
- end
-
- def test_validates_presence_of_generates_message_with_custom_default_message
- Topic.validates_presence_of :title, :message => 'custom'
- @topic.errors.expects(:generate_message).with(:title, :blank, {:default => 'custom'})
- @topic.valid?
- end
-
+ # validates_presence_of w/o mocha
+
def test_validates_presence_of_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:blank => 'custom message'}}}}}
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:blank => 'global message'}}
@@ -185,34 +400,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
assert_equal 'global message', @topic.errors.on(:title)
end
-
- # validates_length_of :within
-
- def test_validates_length_of_within_generates_message_with_title_too_short
- Topic.validates_length_of :title, :within => 3..5
- @topic.errors.expects(:generate_message).with(:title, :too_short, {:count => 3, :default => nil})
- @topic.valid?
- end
-
- def test_validates_length_of_within_generates_message_with_title_too_short_and_custom_default_message
- Topic.validates_length_of :title, :within => 3..5, :too_short => 'custom'
- @topic.errors.expects(:generate_message).with(:title, :too_short, {:count => 3, :default => 'custom'})
- @topic.valid?
- end
-
- def test_validates_length_of_within_generates_message_with_title_too_long
- Topic.validates_length_of :title, :within => 3..5
- @topic.title = 'this title is too long'
- @topic.errors.expects(:generate_message).with(:title, :too_long, {:count => 5, :default => nil})
- @topic.valid?
- end
-
- def test_validates_length_of_within_generates_message_with_title_too_long_and_custom_default_message
- Topic.validates_length_of :title, :within => 3..5, :too_long => 'custom'
- @topic.title = 'this title is too long'
- @topic.errors.expects(:generate_message).with(:title, :too_long, {:count => 5, :default => 'custom'})
- @topic.valid?
- end
+ # validates_length_of :within w/o mocha
def test_validates_length_of_within_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:too_short => 'custom message'}}}}}
@@ -231,20 +419,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
assert_equal 'global message', @topic.errors.on(:title)
end
-
- # validates_length_of :is
-
- def test_validates_length_of_is_generates_message
- Topic.validates_length_of :title, :is => 5
- @topic.errors.expects(:generate_message).with(:title, :wrong_length, {:count => 5, :default => nil})
- @topic.valid?
- end
-
- def test_validates_length_of_is_generates_message_with_custom_default_message
- Topic.validates_length_of :title, :is => 5, :message => 'custom'
- @topic.errors.expects(:generate_message).with(:title, :wrong_length, {:count => 5, :default => 'custom'})
- @topic.valid?
- end
+ # validates_length_of :is w/o mocha
def test_validates_length_of_within_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:wrong_length => 'custom message'}}}}}
@@ -263,22 +438,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
assert_equal 'global message', @topic.errors.on(:title)
end
-
- # validates_uniqueness_of
-
- def test_validates_uniqueness_of_generates_message
- Topic.validates_uniqueness_of :title
- @topic.title = unique_topic.title
- @topic.errors.expects(:generate_message).with(:title, :taken, {:default => nil})
- @topic.valid?
- end
-
- def test_validates_uniqueness_of_generates_message_with_custom_default_message
- Topic.validates_uniqueness_of :title, :message => 'custom'
- @topic.title = unique_topic.title
- @topic.errors.expects(:generate_message).with(:title, :taken, {:default => 'custom'})
- @topic.valid?
- end
+ # validates_uniqueness_of w/o mocha
def test_validates_length_of_within_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:wrong_length => 'custom message'}}}}}
@@ -298,21 +458,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
- # validates_format_of
-
- def test_validates_format_of_generates_message
- Topic.validates_format_of :title, :with => /^[1-9][0-9]*$/
- @topic.title = '72x'
- @topic.errors.expects(:generate_message).with(:title, :invalid, {:value => '72x', :default => nil})
- @topic.valid?
- end
-
- def test_validates_format_of_generates_message_with_custom_default_message
- Topic.validates_format_of :title, :with => /^[1-9][0-9]*$/, :message => 'custom'
- @topic.title = '72x'
- @topic.errors.expects(:generate_message).with(:title, :invalid, {:value => '72x', :default => 'custom'})
- @topic.valid?
- end
+ # validates_format_of w/o mocha
def test_validates_format_of_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:invalid => 'custom message'}}}}}
@@ -331,22 +477,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
assert_equal 'global message', @topic.errors.on(:title)
end
-
- # validates_inclusion_of
-
- def test_validates_inclusion_of_generates_message
- Topic.validates_inclusion_of :title, :in => %w(a b c)
- @topic.title = 'z'
- @topic.errors.expects(:generate_message).with(:title, :inclusion, {:value => 'z', :default => nil})
- @topic.valid?
- end
-
- def test_validates_inclusion_of_generates_message_with_custom_default_message
- Topic.validates_inclusion_of :title, :in => %w(a b c), :message => 'custom'
- @topic.title = 'z'
- @topic.errors.expects(:generate_message).with(:title, :inclusion, {:value => 'z', :default => 'custom'})
- @topic.valid?
- end
+ # validates_inclusion_of w/o mocha
def test_validates_inclusion_of_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:inclusion => 'custom message'}}}}}
@@ -365,22 +496,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
assert_equal 'global message', @topic.errors.on(:title)
end
-
- # validates_exclusion_of
-
- def test_validates_exclusion_of_generates_message
- Topic.validates_exclusion_of :title, :in => %w(a b c)
- @topic.title = 'a'
- @topic.errors.expects(:generate_message).with(:title, :exclusion, {:value => 'a', :default => nil})
- @topic.valid?
- end
-
- def test_validates_exclusion_of_generates_message_with_custom_default_message
- Topic.validates_exclusion_of :title, :in => %w(a b c), :message => 'custom'
- @topic.title = 'a'
- @topic.errors.expects(:generate_message).with(:title, :exclusion, {:value => 'a', :default => 'custom'})
- @topic.valid?
- end
+ # validates_exclusion_of w/o mocha
def test_validates_exclusion_of_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:exclusion => 'custom message'}}}}}
@@ -401,22 +517,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
assert_equal 'global message', @topic.errors.on(:title)
end
-
- # validates_numericality_of without :only_integer
-
- def test_validates_numericality_of_generates_message
- Topic.validates_numericality_of :title
- @topic.title = 'a'
- @topic.errors.expects(:generate_message).with(:title, :not_a_number, {:value => 'a', :default => nil})
- @topic.valid?
- end
-
- def test_validates_numericality_of_generates_message_with_custom_default_message
- Topic.validates_numericality_of :title, :message => 'custom'
- @topic.title = 'a'
- @topic.errors.expects(:generate_message).with(:title, :not_a_number, {:value => 'a', :default => 'custom'})
- @topic.valid?
- end
+ # validates_numericality_of without :only_integer w/o mocha
def test_validates_numericality_of_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:not_a_number => 'custom message'}}}}}
@@ -437,22 +538,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
assert_equal 'global message', @topic.errors.on(:title)
end
-
- # validates_numericality_of with :only_integer
-
- def test_validates_numericality_of_only_integer_generates_message
- Topic.validates_numericality_of :title, :only_integer => true
- @topic.title = 'a'
- @topic.errors.expects(:generate_message).with(:title, :not_a_number, {:value => 'a', :default => nil})
- @topic.valid?
- end
-
- def test_validates_numericality_of_only_integer_generates_message_with_custom_default_message
- Topic.validates_numericality_of :title, :only_integer => true, :message => 'custom'
- @topic.title = 'a'
- @topic.errors.expects(:generate_message).with(:title, :not_a_number, {:value => 'a', :default => 'custom'})
- @topic.valid?
- end
+ # validates_numericality_of with :only_integer w/o mocha
def test_validates_numericality_of_only_integer_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:not_a_number => 'custom message'}}}}}
@@ -473,22 +559,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
assert_equal 'global message', @topic.errors.on(:title)
end
-
- # validates_numericality_of :odd
-
- def test_validates_numericality_of_odd_generates_message
- Topic.validates_numericality_of :title, :only_integer => true, :odd => true
- @topic.title = 0
- @topic.errors.expects(:generate_message).with(:title, :odd, {:value => 0, :default => nil})
- @topic.valid?
- end
-
- def test_validates_numericality_of_odd_generates_message_with_custom_default_message
- Topic.validates_numericality_of :title, :only_integer => true, :odd => true, :message => 'custom'
- @topic.title = 0
- @topic.errors.expects(:generate_message).with(:title, :odd, {:value => 0, :default => 'custom'})
- @topic.valid?
- end
+ # validates_numericality_of :odd w/o mocha
def test_validates_numericality_of_odd_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:odd => 'custom message'}}}}}
@@ -509,22 +580,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
assert_equal 'global message', @topic.errors.on(:title)
end
-
- # validates_numericality_of :less_than
-
- def test_validates_numericality_of_less_than_generates_message
- Topic.validates_numericality_of :title, :only_integer => true, :less_than => 0
- @topic.title = 1
- @topic.errors.expects(:generate_message).with(:title, :less_than, {:value => 1, :count => 0, :default => nil})
- @topic.valid?
- end
-
- def test_validates_numericality_of_odd_generates_message_with_custom_default_message
- Topic.validates_numericality_of :title, :only_integer => true, :less_than => 0, :message => 'custom'
- @topic.title = 1
- @topic.errors.expects(:generate_message).with(:title, :less_than, {:value => 1, :count => 0, :default => 'custom'})
- @topic.valid?
- end
+ # validates_numericality_of :less_than w/o mocha
def test_validates_numericality_of_less_than_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:title => {:less_than => 'custom message'}}}}}
@@ -546,19 +602,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
end
- # validates_associated
-
- def test_validates_associated_generates_message
- Topic.validates_associated :replies
- replied_topic.errors.expects(:generate_message).with(:replies, :invalid, {:value => replied_topic.replies, :default => nil})
- replied_topic.valid?
- end
-
- def test_validates_associated_generates_message_with_custom_default_message
- Topic.validates_associated :replies
- replied_topic.errors.expects(:generate_message).with(:replies, :invalid, {:value => replied_topic.replies, :default => nil})
- replied_topic.valid?
- end
+ # validates_associated w/o mocha
def test_validates_associated_finds_custom_model_key_translation
I18n.backend.store_translations 'en-US', :active_record => {:error_messages => {:custom => {:topic => {:replies => {:invalid => 'custom message'}}}}}
--
cgit v1.2.3
From 6982acb0793fb6e59f52cab4062344a88e3691ce Mon Sep 17 00:00:00 2001
From: Luca Guidi
Date: Tue, 1 Jul 2008 16:52:48 +0200
Subject: Experimental I18n charset support for ActionMailer
---
actionmailer/lib/action_mailer.rb | 4 +
actionmailer/lib/action_mailer/base.rb | 14 ++-
actionmailer/lib/action_mailer/locale/en-US.rb | 3 +
actionmailer/test/i18n_test.rb | 133 +++++++++++++++++++++++++
4 files changed, 149 insertions(+), 5 deletions(-)
create mode 100644 actionmailer/lib/action_mailer/locale/en-US.rb
create mode 100644 actionmailer/test/i18n_test.rb
diff --git a/actionmailer/lib/action_mailer.rb b/actionmailer/lib/action_mailer.rb
index 2e324d4637..806edf1f9e 100755
--- a/actionmailer/lib/action_mailer.rb
+++ b/actionmailer/lib/action_mailer.rb
@@ -49,4 +49,8 @@ ActionMailer::Base.class_eval do
helper MailHelper
end
+I18n.backend.populate do
+ require 'action_mailer/locale/en-US.rb'
+end
+
silence_warnings { TMail::Encoder.const_set("MAX_LINE_LEN", 200) }
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index 1518e23dfe..e787c1b8da 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -307,10 +307,6 @@ module ActionMailer #:nodoc:
# Specify the CC addresses for the message.
adv_attr_accessor :cc
- # Specify the charset to use for the message. This defaults to the
- # +default_charset+ specified for ActionMailer::Base.
- adv_attr_accessor :charset
-
# Specify the content type for the message. This defaults to text/plain
# in most cases, but can be automatically set in some situations.
adv_attr_accessor :content_type
@@ -348,6 +344,15 @@ module ActionMailer #:nodoc:
# have multiple mailer methods share the same template.
adv_attr_accessor :template
+ # Specify the charset to use for the message.
+ # It performs a lookup, on the specified charset, then on the charset from
+ # the current locale, and, finally, on the +default_charset+ specified
+ # for ActionMailer::Base.
+ def charset(charset = nil)
+ @charset ||= charset || :'charset'.t || @@default_charset
+ end
+ attr_writer :charset
+
# Override the mailer name, which defaults to an inflected version of the
# mailer's class name. If you want to use a template in a non-standard
# location, you can use this to specify that location.
@@ -517,7 +522,6 @@ module ActionMailer #:nodoc:
# mailer. Subclasses may override this method to provide different
# defaults.
def initialize_defaults(method_name)
- @charset ||= @@default_charset.dup
@content_type ||= @@default_content_type.dup
@implicit_parts_order ||= @@default_implicit_parts_order.dup
@template ||= method_name
diff --git a/actionmailer/lib/action_mailer/locale/en-US.rb b/actionmailer/lib/action_mailer/locale/en-US.rb
new file mode 100644
index 0000000000..369f2d1a1c
--- /dev/null
+++ b/actionmailer/lib/action_mailer/locale/en-US.rb
@@ -0,0 +1,3 @@
+I18n.backend.store_translations :'en-US', {
+ :charset => 'utf-8'
+}
\ No newline at end of file
diff --git a/actionmailer/test/i18n_test.rb b/actionmailer/test/i18n_test.rb
new file mode 100644
index 0000000000..92b128bce6
--- /dev/null
+++ b/actionmailer/test/i18n_test.rb
@@ -0,0 +1,133 @@
+require 'abstract_unit'
+
+class I18nMailer < ActionMailer::Base
+ def use_locale_charset(recipient)
+ recipients recipient
+ subject "using locale charset"
+ from "tester@example.com"
+ body "x"
+ end
+
+ def use_explicit_charset(recipient)
+ recipients recipient
+ subject "using explicit charset"
+ from "tester@example.com"
+ body "x"
+ charset "iso-8859-2"
+ end
+
+ def multiparted(recipient)
+ recipients recipient
+ subject "Multiparted"
+ from "tester@example.com"
+ body "x"
+
+ part "text/html" do |p|
+ p.body = "multiparted iso-8859-1 html "
+ end
+
+ part :content_type => "text/plain",
+ :body => "multiparted utf-8 text",
+ :charset => 'utf-8'
+ end
+
+ def rxml_template(recipient)
+ recipients recipient
+ subject "rendering rxml template"
+ from "tester@example.com"
+ end
+
+ def initialize_defaults(method_name)
+ super
+ mailer_name "test_mailer"
+ end
+end
+
+I18n.backend.store_translations :'en-GB', { }
+I18n.backend.store_translations :'de-DE', {
+ :charset => 'iso-8859-1'
+}
+
+class I18nTest < Test::Unit::TestCase
+ def setup
+ @charset = 'utf-8'
+ @recipient = 'test@localhost'
+ end
+
+ def test_should_use_locale_charset
+ assert_equal @charset, mail.charset
+ end
+
+ def test_should_use_default_charset_if_no_current_locale
+ uses_locale nil do
+ assert_equal @charset, mail.charset
+ end
+ end
+
+ def test_mail_headers_should_contains_current_charset
+ uses_locale 'de-DE' do
+ assert_match /iso-8859-1/, mail.header['content-type'].body
+ end
+ end
+
+ def test_should_use_charset_from_current_locale
+ uses_locale 'de-DE' do
+ assert_equal 'iso-8859-1', mail.charset
+ end
+ end
+
+ def test_should_raise_exception_if_current_locale_doesnt_specify_a_charset
+ assert_raise I18n::MissingTranslationData do
+ uses_locale 'en-GB' do
+ mail
+ end
+ end
+ end
+
+ def test_should_use_explicit_charset
+ assert_equal 'iso-8859-2', mail('use_explicit_charset').charset
+ end
+
+ def test_mail_parts_charsets
+ uses_locale 'de-DE' do
+ charsets = mail('multiparted').parts.map(&:charset)
+ assert_equal 'iso-8859-1', charsets[0]
+ assert_equal 'iso-8859-1', charsets[1]
+ assert_equal 'utf-8', charsets[2]
+ end
+ end
+
+ def test_mail_parts_headers
+ uses_locale 'de-DE' do
+ content_types = mail('multiparted').parts.map(&:header).map do |header|
+ header['content-type'].body
+ end
+ assert_match /iso-8859-1/, content_types[0]
+ assert_match /iso-8859-1/, content_types[1]
+ assert_match /utf-8/, content_types[2]
+ end
+ end
+
+ # TODO: this case depends on XML Builder,
+ # should we pass Builder::XmlMarkup.new :encoding => charset_from_i18n ?
+ def _ignore_test_rxml_template_should_use_current_charset
+ uses_locale 'de-DE' do
+ assert_equal "\n ",
+ mail('rxml_template').body.strip
+ end
+ end
+
+ private
+ def mail(method = 'use_locale_charset')
+ I18nMailer.__send__('create_' + method, @recipient)
+ end
+
+ def uses_locale(locale, &block)
+ begin
+ I18n.locale = locale
+ yield
+ ensure
+ I18n.locale = I18n.default_locale
+ end
+ end
+end
--
cgit v1.2.3
From 7403c825a05af320e20f1b7e20b0c565081ede89 Mon Sep 17 00:00:00 2001
From: Luca Guidi
Date: Wed, 2 Jul 2008 17:51:34 +0200
Subject: Fixed Date and Time localization for ActiveSupport
---
actionpack/lib/action_view/locale/en-US.rb | 21 -------
activesupport/lib/active_support/locale/en-US.rb | 21 +++++++
activesupport/test/core_ext/i18n_test.rb | 75 ++++++++++++++++++++++++
3 files changed, 96 insertions(+), 21 deletions(-)
create mode 100644 activesupport/test/core_ext/i18n_test.rb
diff --git a/actionpack/lib/action_view/locale/en-US.rb b/actionpack/lib/action_view/locale/en-US.rb
index 20d668a9e1..3adb199681 100644
--- a/actionpack/lib/action_view/locale/en-US.rb
+++ b/actionpack/lib/action_view/locale/en-US.rb
@@ -1,25 +1,4 @@
I18n.backend.store_translations :'en-US', {
- :date => {
- :formats => {
- :default => "%Y-%m-%d",
- :short => "%b %d",
- :long => "%B %d, %Y",
- },
- :day_names => Date::DAYNAMES,
- :abbr_day_names => Date::ABBR_DAYNAMES,
- :month_names => Date::MONTHNAMES,
- :abbr_month_names => Date::ABBR_MONTHNAMES,
- :order => [:year, :month, :day]
- },
- :time => {
- :formats => {
- :default => "%a, %d %b %Y %H:%M:%S %z",
- :short => "%d %b %H:%M",
- :long => "%B %d, %Y %H:%M",
- },
- :am => 'am',
- :pm => 'pm'
- },
:datetime => {
:distance_in_words => {
:half_a_minute => 'half a minute',
diff --git a/activesupport/lib/active_support/locale/en-US.rb b/activesupport/lib/active_support/locale/en-US.rb
index aa06fe14bd..51324a90bf 100644
--- a/activesupport/lib/active_support/locale/en-US.rb
+++ b/activesupport/lib/active_support/locale/en-US.rb
@@ -3,5 +3,26 @@ I18n.backend.store_translations :'en-US', {
:array => {
:sentence_connector => 'and'
}
+ },
+ :date => {
+ :formats => {
+ :default => "%Y-%m-%d",
+ :short => "%b %d",
+ :long => "%B %d, %Y",
+ },
+ :day_names => Date::DAYNAMES,
+ :abbr_day_names => Date::ABBR_DAYNAMES,
+ :month_names => Date::MONTHNAMES,
+ :abbr_month_names => Date::ABBR_MONTHNAMES,
+ :order => [:year, :month, :day]
+ },
+ :time => {
+ :formats => {
+ :default => "%a, %d %b %Y %H:%M:%S %z",
+ :short => "%d %b %H:%M",
+ :long => "%B %d, %Y %H:%M",
+ },
+ :am => 'am',
+ :pm => 'pm'
}
}
\ No newline at end of file
diff --git a/activesupport/test/core_ext/i18n_test.rb b/activesupport/test/core_ext/i18n_test.rb
new file mode 100644
index 0000000000..a67b6a5d8c
--- /dev/null
+++ b/activesupport/test/core_ext/i18n_test.rb
@@ -0,0 +1,75 @@
+require 'abstract_unit'
+
+class I18nTest < Test::Unit::TestCase
+ def setup
+ @date = Date.parse("2008-7-2")
+ @time = Time.utc(2008, 7, 2, 16, 47, 1)
+ end
+
+ uses_mocha 'I18nTimeZoneTest' do
+ def test_time_zone_localization_with_default_format
+ Time.zone.stubs(:now).returns Time.local(2000)
+ assert_equal "Sat, 01 Jan 2000 00:00:00 +0100", Time.zone.now.l
+ end
+ end
+
+ def test_date_localization_should_use_default_format
+ assert_equal "2008-07-02", @date.l
+ end
+
+ def test_date_localization_with_default_format
+ assert_equal "2008-07-02", @date.l(nil, :default)
+ end
+
+ def test_date_localization_with_short_format
+ assert_equal "Jul 02", @date.l(nil, :short)
+ end
+
+ def test_date_localization_with_long_format
+ assert_equal "July 02, 2008", @date.l(nil, :long)
+ end
+
+ def test_time_localization_should_use_default_format
+ assert_equal "Wed, 02 Jul 2008 16:47:01 +0100", @time.l
+ end
+
+ def test_time_localization_with_default_format
+ assert_equal "Wed, 02 Jul 2008 16:47:01 +0100", @time.l(nil, :default)
+ end
+
+ def test_time_localization_with_short_format
+ assert_equal "02 Jul 16:47", @time.l(nil, :short)
+ end
+
+ def test_time_localization_with_long_format
+ assert_equal "July 02, 2008 16:47", @time.l(nil, :long)
+ end
+
+ def test_day_names
+ assert_equal Date::DAYNAMES, :'date.day_names'.t
+ end
+
+ def test_abbr_day_names
+ assert_equal Date::ABBR_DAYNAMES, :'date.abbr_day_names'.t
+ end
+
+ def test_month_names
+ assert_equal Date::MONTHNAMES, :'date.month_names'.t
+ end
+
+ def test_abbr_month_names
+ assert_equal Date::ABBR_MONTHNAMES, :'date.abbr_month_names'.t
+ end
+
+ def test_date_order
+ assert_equal [:year, :month, :day], :'date.order'.t
+ end
+
+ def test_time_am
+ assert_equal 'am', :'time.am'.t
+ end
+
+ def test_time_pm
+ assert_equal 'pm', :'time.pm'.t
+ end
+end
--
cgit v1.2.3
From 8f74ba96c47e77e18ce363c8e7cd2fc9196faf7a Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Wed, 2 Jul 2008 19:21:07 +0200
Subject: remove core extensions in favor of I18n#translate and I18n#localize
---
actionmailer/lib/action_mailer/base.rb | 2 +-
actionpack/lib/action_view/helpers/date_helper.rb | 5 +-
.../lib/action_view/helpers/number_helper.rb | 2 +-
activerecord/lib/active_record/validations.rb | 6 +-
activerecord/test/cases/validations_i18n_test.rb | 2 +-
.../active_support/core_ext/array/conversions.rb | 2 +-
activesupport/lib/active_support/vendor/i18n-0.0.1 | 2 +-
activesupport/test/core_ext/i18n_test.rb | 75 ----------------------
activesupport/test/i18n_test.rb | 75 ++++++++++++++++++++++
9 files changed, 86 insertions(+), 85 deletions(-)
delete mode 100644 activesupport/test/core_ext/i18n_test.rb
create mode 100644 activesupport/test/i18n_test.rb
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index e787c1b8da..f7da90d10f 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -349,7 +349,7 @@ module ActionMailer #:nodoc:
# the current locale, and, finally, on the +default_charset+ specified
# for ActionMailer::Base.
def charset(charset = nil)
- @charset ||= charset || :'charset'.t || @@default_charset
+ @charset ||= charset || I18n.translate(:charset) || @@default_charset
end
attr_writer :charset
diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb
index 6ac4171fd5..d306c7a742 100755
--- a/actionpack/lib/action_view/helpers/date_helper.rb
+++ b/actionpack/lib/action_view/helpers/date_helper.rb
@@ -512,7 +512,8 @@ module ActionView
else
month_options = []
month_names = options[:use_month_names] || begin
- (options[:use_short_month] ? :'date.abbr_month_names' : :'date.month_names').t locale
+ key = options[:use_short_month] ? :'date.abbr_month_names' : :'date.month_names'
+ I18n.translate key, locale
end
month_names.unshift(nil) if month_names.size < 13
@@ -632,7 +633,7 @@ module ActionView
position = { :year => 1, :month => 2, :day => 3, :hour => 4, :minute => 5, :second => 6 }
- order = options[:order] ||= :'date.order'.t(locale)
+ order = options[:order] ||= I18n.translate(:'date.order', locale)
# Discard explicit and implicit by not being included in the :order
discard = {}
diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb
index 3e0d5b1db4..981589437d 100644
--- a/actionpack/lib/action_view/helpers/number_helper.rb
+++ b/actionpack/lib/action_view/helpers/number_helper.rb
@@ -70,7 +70,7 @@ module ActionView
# # => 1234567890,50 £
def number_to_currency(number, options = {})
options = options.symbolize_keys
- defaults = :'currency.format'.t(options[:locale]) || {}
+ defaults = I18n.translate(:'currency.format', options[:locale]) || {}
precision = options[:precision] || defaults[:precision]
unit = options[:unit] || defaults[:unit]
diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb
index 5bbd10394c..5245f65869 100755
--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -22,7 +22,7 @@ module ActiveRecord
class << self
def default_error_messages
ActiveSupport::Deprecation.warn("ActiveRecord::Errors.default_error_messages has been deprecated. Please use 'active_record.error_messages'.t.")
- 'active_record.error_messages'.t
+ I18n.translate 'active_record.error_messages'
end
end
@@ -43,7 +43,7 @@ module ActiveRecord
# error can be added to the same +attribute+ in which case an array will be returned on a call to on(attribute) .
# If no +msg+ is supplied, "invalid" is assumed.
def add(attribute, message = nil)
- message ||= :"active_record.error_messages.invalid".t
+ message ||= I18n.translate :"active_record.error_messages.invalid"
@errors[attribute.to_s] ||= []
@errors[attribute.to_s] << message
end
@@ -168,7 +168,7 @@ module ActiveRecord
full_messages << message
else
key = :"active_record.human_attribute_names.#{@base.class.name.underscore.to_sym}.#{attr}"
- attr_name = key.t(locale) || @base.class.human_attribute_name(attr)
+ attr_name = I18n.translate(key, locale, :raise => true) rescue @base.class.human_attribute_name(attr)
full_messages << attr_name + " " + message
end
end
diff --git a/activerecord/test/cases/validations_i18n_test.rb b/activerecord/test/cases/validations_i18n_test.rb
index 53e90f4d53..840fcd81d0 100644
--- a/activerecord/test/cases/validations_i18n_test.rb
+++ b/activerecord/test/cases/validations_i18n_test.rb
@@ -79,7 +79,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_errors_full_messages_translates_human_attribute_name_for_model_attributes
@topic.errors.instance_variable_set :@errors, { 'title' => 'empty' }
- I18n.expects(:translate).with(:"active_record.human_attribute_names.topic.title", 'en-US').returns('Title')
+ I18n.expects(:translate).with(:"active_record.human_attribute_names.topic.title", 'en-US', :raise => true).returns('Title')
@topic.errors.full_messages :locale => 'en-US'
end
end
diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb
index 80d91a6cbd..80bf1404de 100644
--- a/activesupport/lib/active_support/core_ext/array/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/array/conversions.rb
@@ -13,7 +13,7 @@ module ActiveSupport #:nodoc:
locale = options[:locale]
locale ||= self.locale if respond_to?(:locale)
- default = :'support.array.sentence_connector'.t(locale)
+ default = I18n.translate(:'support.array.sentence_connector', locale)
options.reverse_merge! :connector => default, :skip_last_comma => false
options[:connector] = "#{options[:connector]} " unless options[:connector].nil? || options[:connector].strip == ''
diff --git a/activesupport/lib/active_support/vendor/i18n-0.0.1 b/activesupport/lib/active_support/vendor/i18n-0.0.1
index 20c331666b..970bc7ab5f 160000
--- a/activesupport/lib/active_support/vendor/i18n-0.0.1
+++ b/activesupport/lib/active_support/vendor/i18n-0.0.1
@@ -1 +1 @@
-Subproject commit 20c331666b3b6a21791d4cded53c3d8654fba714
+Subproject commit 970bc7ab5faa94e41ee4a56bc8913c144c1cdd19
diff --git a/activesupport/test/core_ext/i18n_test.rb b/activesupport/test/core_ext/i18n_test.rb
deleted file mode 100644
index a67b6a5d8c..0000000000
--- a/activesupport/test/core_ext/i18n_test.rb
+++ /dev/null
@@ -1,75 +0,0 @@
-require 'abstract_unit'
-
-class I18nTest < Test::Unit::TestCase
- def setup
- @date = Date.parse("2008-7-2")
- @time = Time.utc(2008, 7, 2, 16, 47, 1)
- end
-
- uses_mocha 'I18nTimeZoneTest' do
- def test_time_zone_localization_with_default_format
- Time.zone.stubs(:now).returns Time.local(2000)
- assert_equal "Sat, 01 Jan 2000 00:00:00 +0100", Time.zone.now.l
- end
- end
-
- def test_date_localization_should_use_default_format
- assert_equal "2008-07-02", @date.l
- end
-
- def test_date_localization_with_default_format
- assert_equal "2008-07-02", @date.l(nil, :default)
- end
-
- def test_date_localization_with_short_format
- assert_equal "Jul 02", @date.l(nil, :short)
- end
-
- def test_date_localization_with_long_format
- assert_equal "July 02, 2008", @date.l(nil, :long)
- end
-
- def test_time_localization_should_use_default_format
- assert_equal "Wed, 02 Jul 2008 16:47:01 +0100", @time.l
- end
-
- def test_time_localization_with_default_format
- assert_equal "Wed, 02 Jul 2008 16:47:01 +0100", @time.l(nil, :default)
- end
-
- def test_time_localization_with_short_format
- assert_equal "02 Jul 16:47", @time.l(nil, :short)
- end
-
- def test_time_localization_with_long_format
- assert_equal "July 02, 2008 16:47", @time.l(nil, :long)
- end
-
- def test_day_names
- assert_equal Date::DAYNAMES, :'date.day_names'.t
- end
-
- def test_abbr_day_names
- assert_equal Date::ABBR_DAYNAMES, :'date.abbr_day_names'.t
- end
-
- def test_month_names
- assert_equal Date::MONTHNAMES, :'date.month_names'.t
- end
-
- def test_abbr_month_names
- assert_equal Date::ABBR_MONTHNAMES, :'date.abbr_month_names'.t
- end
-
- def test_date_order
- assert_equal [:year, :month, :day], :'date.order'.t
- end
-
- def test_time_am
- assert_equal 'am', :'time.am'.t
- end
-
- def test_time_pm
- assert_equal 'pm', :'time.pm'.t
- end
-end
diff --git a/activesupport/test/i18n_test.rb b/activesupport/test/i18n_test.rb
new file mode 100644
index 0000000000..e6d90f09c1
--- /dev/null
+++ b/activesupport/test/i18n_test.rb
@@ -0,0 +1,75 @@
+require 'abstract_unit'
+
+class I18nTest < Test::Unit::TestCase
+ def setup
+ @date = Date.parse("2008-7-2")
+ @time = Time.utc(2008, 7, 2, 16, 47, 1)
+ end
+
+ uses_mocha 'I18nTimeZoneTest' do
+ def test_time_zone_localization_with_default_format
+ Time.zone.stubs(:now).returns Time.local(2000)
+ assert_equal "Sat, 01 Jan 2000 00:00:00 +0100", I18n.localize(Time.zone.now)
+ end
+ end
+
+ def test_date_localization_should_use_default_format
+ assert_equal "2008-07-02", I18n.localize(@date)
+ end
+
+ def test_date_localization_with_default_format
+ assert_equal "2008-07-02", I18n.localize(@date, nil, :default)
+ end
+
+ def test_date_localization_with_short_format
+ assert_equal "Jul 02", I18n.localize(@date, nil, :short)
+ end
+
+ def test_date_localization_with_long_format
+ assert_equal "July 02, 2008", I18n.localize(@date, nil, :long)
+ end
+
+ def test_time_localization_should_use_default_format
+ assert_equal "Wed, 02 Jul 2008 16:47:01 +0100", I18n.localize(@time)
+ end
+
+ def test_time_localization_with_default_format
+ assert_equal "Wed, 02 Jul 2008 16:47:01 +0100", I18n.localize(@time, nil, :default)
+ end
+
+ def test_time_localization_with_short_format
+ assert_equal "02 Jul 16:47", I18n.localize(@time, nil, :short)
+ end
+
+ def test_time_localization_with_long_format
+ assert_equal "July 02, 2008 16:47", I18n.localize(@time, nil, :long)
+ end
+
+ def test_day_names
+ assert_equal Date::DAYNAMES, I18n.translate(:'date.day_names')
+ end
+
+ def test_abbr_day_names
+ assert_equal Date::ABBR_DAYNAMES, I18n.translate(:'date.abbr_day_names')
+ end
+
+ def test_month_names
+ assert_equal Date::MONTHNAMES, I18n.translate(:'date.month_names')
+ end
+
+ def test_abbr_month_names
+ assert_equal Date::ABBR_MONTHNAMES, I18n.translate(:'date.abbr_month_names')
+ end
+
+ def test_date_order
+ assert_equal [:year, :month, :day], I18n.translate(:'date.order')
+ end
+
+ def test_time_am
+ assert_equal 'am', I18n.translate(:'time.am')
+ end
+
+ def test_time_pm
+ assert_equal 'pm', I18n.translate(:'time.pm')
+ end
+end
--
cgit v1.2.3
From d41e4c1c3d6e6259f1cfc0cdbd4fc30fee0f866a Mon Sep 17 00:00:00 2001
From: Luca Guidi
Date: Thu, 3 Jul 2008 11:50:18 +0200
Subject: Make sure ActionMailer use default charset if no defined by current
locale
---
actionmailer/lib/action_mailer/base.rb | 4 ++--
actionmailer/test/i18n_test.rb | 26 ++++++++++++--------------
2 files changed, 14 insertions(+), 16 deletions(-)
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index f7da90d10f..a1a7f55d2b 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -346,10 +346,10 @@ module ActionMailer #:nodoc:
# Specify the charset to use for the message.
# It performs a lookup, on the specified charset, then on the charset from
- # the current locale, and, finally, on the +default_charset+ specified
+ # the current locale, and, in the end, on the +default_charset+ specified
# for ActionMailer::Base.
def charset(charset = nil)
- @charset ||= charset || I18n.translate(:charset) || @@default_charset
+ @charset ||= charset || I18n.translate(:charset, :default => @@default_charset)
end
attr_writer :charset
diff --git a/actionmailer/test/i18n_test.rb b/actionmailer/test/i18n_test.rb
index 92b128bce6..a775128519 100644
--- a/actionmailer/test/i18n_test.rb
+++ b/actionmailer/test/i18n_test.rb
@@ -59,37 +59,35 @@ class I18nTest < Test::Unit::TestCase
end
def test_should_use_default_charset_if_no_current_locale
- uses_locale nil do
+ with_locale nil do
assert_equal @charset, mail.charset
end
end
def test_mail_headers_should_contains_current_charset
- uses_locale 'de-DE' do
+ with_locale 'de-DE' do
assert_match /iso-8859-1/, mail.header['content-type'].body
end
end
def test_should_use_charset_from_current_locale
- uses_locale 'de-DE' do
+ with_locale 'de-DE' do
assert_equal 'iso-8859-1', mail.charset
end
end
-
- def test_should_raise_exception_if_current_locale_doesnt_specify_a_charset
- assert_raise I18n::MissingTranslationData do
- uses_locale 'en-GB' do
- mail
- end
+
+ def test_should_use_default_charset_if_missing_for_current_locale
+ with_locale 'en-GB' do
+ assert_equal @charset, mail.charset
end
end
-
+
def test_should_use_explicit_charset
assert_equal 'iso-8859-2', mail('use_explicit_charset').charset
end
def test_mail_parts_charsets
- uses_locale 'de-DE' do
+ with_locale 'de-DE' do
charsets = mail('multiparted').parts.map(&:charset)
assert_equal 'iso-8859-1', charsets[0]
assert_equal 'iso-8859-1', charsets[1]
@@ -98,7 +96,7 @@ class I18nTest < Test::Unit::TestCase
end
def test_mail_parts_headers
- uses_locale 'de-DE' do
+ with_locale 'de-DE' do
content_types = mail('multiparted').parts.map(&:header).map do |header|
header['content-type'].body
end
@@ -111,7 +109,7 @@ class I18nTest < Test::Unit::TestCase
# TODO: this case depends on XML Builder,
# should we pass Builder::XmlMarkup.new :encoding => charset_from_i18n ?
def _ignore_test_rxml_template_should_use_current_charset
- uses_locale 'de-DE' do
+ with_locale 'de-DE' do
assert_equal "\n ",
mail('rxml_template').body.strip
end
@@ -122,7 +120,7 @@ class I18nTest < Test::Unit::TestCase
I18nMailer.__send__('create_' + method, @recipient)
end
- def uses_locale(locale, &block)
+ def with_locale(locale, &block)
begin
I18n.locale = locale
yield
--
cgit v1.2.3
From e1a7f83fca862fd7472ef6b80f8b6a8d33849a8e Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Fri, 4 Jul 2008 22:22:20 +0200
Subject: use :default for human_attribute_name
---
activerecord/lib/active_record/validations.rb | 2 +-
activerecord/test/cases/validations_i18n_test.rb | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb
index 5245f65869..8ba09b3992 100755
--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -168,7 +168,7 @@ module ActiveRecord
full_messages << message
else
key = :"active_record.human_attribute_names.#{@base.class.name.underscore.to_sym}.#{attr}"
- attr_name = I18n.translate(key, locale, :raise => true) rescue @base.class.human_attribute_name(attr)
+ attr_name = I18n.translate(key, locale, :default => @base.class.human_attribute_name(attr))
full_messages << attr_name + " " + message
end
end
diff --git a/activerecord/test/cases/validations_i18n_test.rb b/activerecord/test/cases/validations_i18n_test.rb
index 840fcd81d0..5be518c547 100644
--- a/activerecord/test/cases/validations_i18n_test.rb
+++ b/activerecord/test/cases/validations_i18n_test.rb
@@ -79,7 +79,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_errors_full_messages_translates_human_attribute_name_for_model_attributes
@topic.errors.instance_variable_set :@errors, { 'title' => 'empty' }
- I18n.expects(:translate).with(:"active_record.human_attribute_names.topic.title", 'en-US', :raise => true).returns('Title')
+ I18n.expects(:translate).with(:"active_record.human_attribute_names.topic.title", 'en-US', :default => 'Title').returns('Title')
@topic.errors.full_messages :locale => 'en-US'
end
end
--
cgit v1.2.3
From 8305d6759abe2b8511ccee35fd0998e6fb0dffd0 Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Fri, 4 Jul 2008 22:26:53 +0200
Subject: Reverting changes to ActionMailer Revert "Make sure ActionMailer use
default charset if no defined by current locale" This reverts commit
d41e4c1c3d6e6259f1cfc0cdbd4fc30fee0f866a.
---
actionmailer/lib/action_mailer/base.rb | 4 ++--
actionmailer/test/i18n_test.rb | 26 ++++++++++++++------------
2 files changed, 16 insertions(+), 14 deletions(-)
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index a1a7f55d2b..f7da90d10f 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -346,10 +346,10 @@ module ActionMailer #:nodoc:
# Specify the charset to use for the message.
# It performs a lookup, on the specified charset, then on the charset from
- # the current locale, and, in the end, on the +default_charset+ specified
+ # the current locale, and, finally, on the +default_charset+ specified
# for ActionMailer::Base.
def charset(charset = nil)
- @charset ||= charset || I18n.translate(:charset, :default => @@default_charset)
+ @charset ||= charset || I18n.translate(:charset) || @@default_charset
end
attr_writer :charset
diff --git a/actionmailer/test/i18n_test.rb b/actionmailer/test/i18n_test.rb
index a775128519..92b128bce6 100644
--- a/actionmailer/test/i18n_test.rb
+++ b/actionmailer/test/i18n_test.rb
@@ -59,35 +59,37 @@ class I18nTest < Test::Unit::TestCase
end
def test_should_use_default_charset_if_no_current_locale
- with_locale nil do
+ uses_locale nil do
assert_equal @charset, mail.charset
end
end
def test_mail_headers_should_contains_current_charset
- with_locale 'de-DE' do
+ uses_locale 'de-DE' do
assert_match /iso-8859-1/, mail.header['content-type'].body
end
end
def test_should_use_charset_from_current_locale
- with_locale 'de-DE' do
+ uses_locale 'de-DE' do
assert_equal 'iso-8859-1', mail.charset
end
end
-
- def test_should_use_default_charset_if_missing_for_current_locale
- with_locale 'en-GB' do
- assert_equal @charset, mail.charset
+
+ def test_should_raise_exception_if_current_locale_doesnt_specify_a_charset
+ assert_raise I18n::MissingTranslationData do
+ uses_locale 'en-GB' do
+ mail
+ end
end
end
-
+
def test_should_use_explicit_charset
assert_equal 'iso-8859-2', mail('use_explicit_charset').charset
end
def test_mail_parts_charsets
- with_locale 'de-DE' do
+ uses_locale 'de-DE' do
charsets = mail('multiparted').parts.map(&:charset)
assert_equal 'iso-8859-1', charsets[0]
assert_equal 'iso-8859-1', charsets[1]
@@ -96,7 +98,7 @@ class I18nTest < Test::Unit::TestCase
end
def test_mail_parts_headers
- with_locale 'de-DE' do
+ uses_locale 'de-DE' do
content_types = mail('multiparted').parts.map(&:header).map do |header|
header['content-type'].body
end
@@ -109,7 +111,7 @@ class I18nTest < Test::Unit::TestCase
# TODO: this case depends on XML Builder,
# should we pass Builder::XmlMarkup.new :encoding => charset_from_i18n ?
def _ignore_test_rxml_template_should_use_current_charset
- with_locale 'de-DE' do
+ uses_locale 'de-DE' do
assert_equal "\n ",
mail('rxml_template').body.strip
end
@@ -120,7 +122,7 @@ class I18nTest < Test::Unit::TestCase
I18nMailer.__send__('create_' + method, @recipient)
end
- def with_locale(locale, &block)
+ def uses_locale(locale, &block)
begin
I18n.locale = locale
yield
--
cgit v1.2.3
From 34bd1e95c7a08c9266fc99281417dad4a19cdf73 Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Fri, 4 Jul 2008 22:34:32 +0200
Subject: Reverting changes to ActionMailer Revert "Experimental I18n charset
support for ActionMailer" This reverts commit
6982acb0793fb6e59f52cab4062344a88e3691ce.
Conflicts:
actionmailer/lib/action_mailer/base.rb
---
actionmailer/lib/action_mailer.rb | 4 -
actionmailer/lib/action_mailer/base.rb | 9 --
actionmailer/lib/action_mailer/locale/en-US.rb | 3 -
actionmailer/test/i18n_test.rb | 133 -------------------------
4 files changed, 149 deletions(-)
delete mode 100644 actionmailer/lib/action_mailer/locale/en-US.rb
delete mode 100644 actionmailer/test/i18n_test.rb
diff --git a/actionmailer/lib/action_mailer.rb b/actionmailer/lib/action_mailer.rb
index 806edf1f9e..2e324d4637 100755
--- a/actionmailer/lib/action_mailer.rb
+++ b/actionmailer/lib/action_mailer.rb
@@ -49,8 +49,4 @@ ActionMailer::Base.class_eval do
helper MailHelper
end
-I18n.backend.populate do
- require 'action_mailer/locale/en-US.rb'
-end
-
silence_warnings { TMail::Encoder.const_set("MAX_LINE_LEN", 200) }
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index f7da90d10f..b1f23583a6 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -344,15 +344,6 @@ module ActionMailer #:nodoc:
# have multiple mailer methods share the same template.
adv_attr_accessor :template
- # Specify the charset to use for the message.
- # It performs a lookup, on the specified charset, then on the charset from
- # the current locale, and, finally, on the +default_charset+ specified
- # for ActionMailer::Base.
- def charset(charset = nil)
- @charset ||= charset || I18n.translate(:charset) || @@default_charset
- end
- attr_writer :charset
-
# Override the mailer name, which defaults to an inflected version of the
# mailer's class name. If you want to use a template in a non-standard
# location, you can use this to specify that location.
diff --git a/actionmailer/lib/action_mailer/locale/en-US.rb b/actionmailer/lib/action_mailer/locale/en-US.rb
deleted file mode 100644
index 369f2d1a1c..0000000000
--- a/actionmailer/lib/action_mailer/locale/en-US.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-I18n.backend.store_translations :'en-US', {
- :charset => 'utf-8'
-}
\ No newline at end of file
diff --git a/actionmailer/test/i18n_test.rb b/actionmailer/test/i18n_test.rb
deleted file mode 100644
index 92b128bce6..0000000000
--- a/actionmailer/test/i18n_test.rb
+++ /dev/null
@@ -1,133 +0,0 @@
-require 'abstract_unit'
-
-class I18nMailer < ActionMailer::Base
- def use_locale_charset(recipient)
- recipients recipient
- subject "using locale charset"
- from "tester@example.com"
- body "x"
- end
-
- def use_explicit_charset(recipient)
- recipients recipient
- subject "using explicit charset"
- from "tester@example.com"
- body "x"
- charset "iso-8859-2"
- end
-
- def multiparted(recipient)
- recipients recipient
- subject "Multiparted"
- from "tester@example.com"
- body "x"
-
- part "text/html" do |p|
- p.body = "multiparted iso-8859-1 html "
- end
-
- part :content_type => "text/plain",
- :body => "multiparted utf-8 text",
- :charset => 'utf-8'
- end
-
- def rxml_template(recipient)
- recipients recipient
- subject "rendering rxml template"
- from "tester@example.com"
- end
-
- def initialize_defaults(method_name)
- super
- mailer_name "test_mailer"
- end
-end
-
-I18n.backend.store_translations :'en-GB', { }
-I18n.backend.store_translations :'de-DE', {
- :charset => 'iso-8859-1'
-}
-
-class I18nTest < Test::Unit::TestCase
- def setup
- @charset = 'utf-8'
- @recipient = 'test@localhost'
- end
-
- def test_should_use_locale_charset
- assert_equal @charset, mail.charset
- end
-
- def test_should_use_default_charset_if_no_current_locale
- uses_locale nil do
- assert_equal @charset, mail.charset
- end
- end
-
- def test_mail_headers_should_contains_current_charset
- uses_locale 'de-DE' do
- assert_match /iso-8859-1/, mail.header['content-type'].body
- end
- end
-
- def test_should_use_charset_from_current_locale
- uses_locale 'de-DE' do
- assert_equal 'iso-8859-1', mail.charset
- end
- end
-
- def test_should_raise_exception_if_current_locale_doesnt_specify_a_charset
- assert_raise I18n::MissingTranslationData do
- uses_locale 'en-GB' do
- mail
- end
- end
- end
-
- def test_should_use_explicit_charset
- assert_equal 'iso-8859-2', mail('use_explicit_charset').charset
- end
-
- def test_mail_parts_charsets
- uses_locale 'de-DE' do
- charsets = mail('multiparted').parts.map(&:charset)
- assert_equal 'iso-8859-1', charsets[0]
- assert_equal 'iso-8859-1', charsets[1]
- assert_equal 'utf-8', charsets[2]
- end
- end
-
- def test_mail_parts_headers
- uses_locale 'de-DE' do
- content_types = mail('multiparted').parts.map(&:header).map do |header|
- header['content-type'].body
- end
- assert_match /iso-8859-1/, content_types[0]
- assert_match /iso-8859-1/, content_types[1]
- assert_match /utf-8/, content_types[2]
- end
- end
-
- # TODO: this case depends on XML Builder,
- # should we pass Builder::XmlMarkup.new :encoding => charset_from_i18n ?
- def _ignore_test_rxml_template_should_use_current_charset
- uses_locale 'de-DE' do
- assert_equal "\n ",
- mail('rxml_template').body.strip
- end
- end
-
- private
- def mail(method = 'use_locale_charset')
- I18nMailer.__send__('create_' + method, @recipient)
- end
-
- def uses_locale(locale, &block)
- begin
- I18n.locale = locale
- yield
- ensure
- I18n.locale = I18n.default_locale
- end
- end
-end
--
cgit v1.2.3
From a865d19516a716762b46ca29212bac668dd7c4a0 Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Fri, 4 Jul 2008 22:45:53 +0200
Subject: reverting changes to ActionMailer
---
actionmailer/lib/action_mailer/base.rb | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index b1f23583a6..1518e23dfe 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -307,6 +307,10 @@ module ActionMailer #:nodoc:
# Specify the CC addresses for the message.
adv_attr_accessor :cc
+ # Specify the charset to use for the message. This defaults to the
+ # +default_charset+ specified for ActionMailer::Base.
+ adv_attr_accessor :charset
+
# Specify the content type for the message. This defaults to text/plain
# in most cases, but can be automatically set in some situations.
adv_attr_accessor :content_type
@@ -513,6 +517,7 @@ module ActionMailer #:nodoc:
# mailer. Subclasses may override this method to provide different
# defaults.
def initialize_defaults(method_name)
+ @charset ||= @@default_charset.dup
@content_type ||= @@default_content_type.dup
@implicit_parts_order ||= @@default_implicit_parts_order.dup
@template ||= method_name
--
cgit v1.2.3
From c9ed2c9bd24b9f4cdfcb692151f87ba900469e71 Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Sun, 6 Jul 2008 19:00:55 +0200
Subject: add a translation helper
---
.../lib/action_view/helpers/translation_helper.rb | 16 +++++++++
.../test/template/translation_helper_test.rb | 42 ++++++++++++++++++++++
2 files changed, 58 insertions(+)
create mode 100644 actionpack/lib/action_view/helpers/translation_helper.rb
create mode 100644 actionpack/test/template/translation_helper_test.rb
diff --git a/actionpack/lib/action_view/helpers/translation_helper.rb b/actionpack/lib/action_view/helpers/translation_helper.rb
new file mode 100644
index 0000000000..0bfe6bf771
--- /dev/null
+++ b/actionpack/lib/action_view/helpers/translation_helper.rb
@@ -0,0 +1,16 @@
+require 'action_view/helpers/tag_helper'
+
+module ActionView
+ module Helpers
+ module TranslationHelper
+ def translate(*args)
+ key, locale, options = I18n.send :process_translate_arguments, *args
+ I18n.translate key, locale, options.merge(:raise => true)
+
+ rescue I18n::MissingTranslationData => e
+ keys = I18n.send :normalize_translation_keys, locale, key, options[:scope]
+ content_tag('span', keys.join(', '), :class => 'translation_missing')
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/actionpack/test/template/translation_helper_test.rb b/actionpack/test/template/translation_helper_test.rb
new file mode 100644
index 0000000000..e97bcdb731
--- /dev/null
+++ b/actionpack/test/template/translation_helper_test.rb
@@ -0,0 +1,42 @@
+require 'abstract_unit'
+
+class TranslationHelperTest < Test::Unit::TestCase
+ include ActionView::Helpers::TagHelper
+ include ActionView::Helpers::TranslationHelper
+
+ attr_reader :request
+ uses_mocha 'translation_helper_test' do
+ def setup
+ end
+
+ def test_delegates_to_i18n_setting_the_raise_option
+ I18n.expects(:translate).with(:foo, 'en-US', :raise => true)
+ translate :foo, 'en-US'
+ end
+
+ def test_returns_missing_translation_message_wrapped_into_span
+ expected = 'en-US, foo '
+ assert_equal expected, translate(:foo)
+ end
+
+ # def test_error_messages_for_given_a_header_message_option_it_does_not_translate_header_message
+ # I18n.expects(:translate).with(:'header_message', :locale => 'en-US', :scope => [:active_record, :error], :count => 1, :object_name => '').never
+ # error_messages_for(:object => @object, :header_message => 'header message', :locale => 'en-US')
+ # end
+ #
+ # def test_error_messages_for_given_no_header_message_option_it_translates_header_message
+ # I18n.expects(:t).with(:'header_message', :locale => 'en-US', :scope => [:active_record, :error], :count => 1, :object_name => '').returns 'header message'
+ # error_messages_for(:object => @object, :locale => 'en-US')
+ # end
+ #
+ # def test_error_messages_for_given_a_message_option_it_does_not_translate_message
+ # I18n.expects(:t).with(:'message', :locale => 'en-US', :scope => [:active_record, :error]).never
+ # error_messages_for(:object => @object, :message => 'message', :locale => 'en-US')
+ # end
+ #
+ # def test_error_messages_for_given_no_message_option_it_translates_message
+ # I18n.expects(:t).with(:'message', :locale => 'en-US', :scope => [:active_record, :error]).returns 'There were problems with the following fields:'
+ # error_messages_for(:object => @object, :locale => 'en-US')
+ # end
+ end
+end
\ No newline at end of file
--
cgit v1.2.3
From 84816ae981a8598e5e401eb1b9b805de840fefc9 Mon Sep 17 00:00:00 2001
From: Sven Fuchs
Date: Sun, 6 Jul 2008 21:20:02 +0200
Subject: align with changes in i18n
---
actionpack/lib/action_view/helpers/date_helper.rb | 5 ++---
actionpack/lib/action_view/helpers/number_helper.rb | 2 +-
actionpack/lib/action_view/helpers/translation_helper.rb | 6 +++---
actionpack/test/template/date_helper_i18n_test.rb | 8 ++++----
actionpack/test/template/number_helper_i18n_test.rb | 2 +-
activerecord/lib/active_record/validations.rb | 5 ++---
activerecord/test/cases/validations_i18n_test.rb | 6 +++---
.../lib/active_support/core_ext/array/conversions.rb | 5 +----
activesupport/lib/active_support/vendor/i18n-0.0.1 | 2 +-
activesupport/test/i18n_test.rb | 12 ++++++------
10 files changed, 24 insertions(+), 29 deletions(-)
diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb
index d306c7a742..61fff42d5a 100755
--- a/actionpack/lib/action_view/helpers/date_helper.rb
+++ b/actionpack/lib/action_view/helpers/date_helper.rb
@@ -504,7 +504,6 @@ module ActionView
#
def select_month(date, options = {}, html_options = {})
locale = options[:locale]
- locale ||= self.locale if respond_to?(:locale)
val = date ? (date.kind_of?(Fixnum) ? date : date.month) : ''
if options[:use_hidden]
@@ -513,7 +512,7 @@ module ActionView
month_options = []
month_names = options[:use_month_names] || begin
key = options[:use_short_month] ? :'date.abbr_month_names' : :'date.month_names'
- I18n.translate key, locale
+ I18n.translate key, :locale => locale
end
month_names.unshift(nil) if month_names.size < 13
@@ -633,7 +632,7 @@ module ActionView
position = { :year => 1, :month => 2, :day => 3, :hour => 4, :minute => 5, :second => 6 }
- order = options[:order] ||= I18n.translate(:'date.order', locale)
+ order = options[:order] ||= I18n.translate(:'date.order', :locale => locale)
# Discard explicit and implicit by not being included in the :order
discard = {}
diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb
index 981589437d..6bb8263794 100644
--- a/actionpack/lib/action_view/helpers/number_helper.rb
+++ b/actionpack/lib/action_view/helpers/number_helper.rb
@@ -70,7 +70,7 @@ module ActionView
# # => 1234567890,50 £
def number_to_currency(number, options = {})
options = options.symbolize_keys
- defaults = I18n.translate(:'currency.format', options[:locale]) || {}
+ defaults = I18n.translate(:'currency.format', :locale => options[:locale]) || {}
precision = options[:precision] || defaults[:precision]
unit = options[:unit] || defaults[:unit]
diff --git a/actionpack/lib/action_view/helpers/translation_helper.rb b/actionpack/lib/action_view/helpers/translation_helper.rb
index 0bfe6bf771..c13c2dfc04 100644
--- a/actionpack/lib/action_view/helpers/translation_helper.rb
+++ b/actionpack/lib/action_view/helpers/translation_helper.rb
@@ -4,11 +4,11 @@ module ActionView
module Helpers
module TranslationHelper
def translate(*args)
- key, locale, options = I18n.send :process_translate_arguments, *args
- I18n.translate key, locale, options.merge(:raise => true)
+ args << args.extract_options!.merge(:raise => true)
+ I18n.translate *args
rescue I18n::MissingTranslationData => e
- keys = I18n.send :normalize_translation_keys, locale, key, options[:scope]
+ keys = I18n.send :normalize_translation_keys, e.locale, e.key, e.options[:scope]
content_tag('span', keys.join(', '), :class => 'translation_missing')
end
end
diff --git a/actionpack/test/template/date_helper_i18n_test.rb b/actionpack/test/template/date_helper_i18n_test.rb
index aeb06c55ea..aca3593921 100644
--- a/actionpack/test/template/date_helper_i18n_test.rb
+++ b/actionpack/test/template/date_helper_i18n_test.rb
@@ -56,7 +56,7 @@ class DateHelperSelectTagsI18nTests < Test::Unit::TestCase
uses_mocha 'date_helper_select_tags_i18n_tests' do
def setup
- I18n.stubs(:translate).with(:'date.month_names', 'en-US').returns Date::MONTHNAMES
+ I18n.stubs(:translate).with(:'date.month_names', :locale => 'en-US').returns Date::MONTHNAMES
end
# select_month
@@ -67,12 +67,12 @@ class DateHelperSelectTagsI18nTests < Test::Unit::TestCase
end
def test_select_month_translates_monthnames
- I18n.expects(:translate).with(:'date.month_names', 'en-US').returns Date::MONTHNAMES
+ I18n.expects(:translate).with(:'date.month_names', :locale => 'en-US').returns Date::MONTHNAMES
select_month(8, :locale => 'en-US')
end
def test_select_month_given_use_short_month_option_translates_abbr_monthnames
- I18n.expects(:translate).with(:'date.abbr_month_names', 'en-US').returns Date::ABBR_MONTHNAMES
+ I18n.expects(:translate).with(:'date.abbr_month_names', :locale => 'en-US').returns Date::ABBR_MONTHNAMES
select_month(8, :locale => 'en-US', :use_short_month => true)
end
@@ -84,7 +84,7 @@ class DateHelperSelectTagsI18nTests < Test::Unit::TestCase
end
def test_date_or_time_select_given_no_order_options_translates_order
- I18n.expects(:translate).with(:'date.order', 'en-US').returns [:year, :month, :day]
+ I18n.expects(:translate).with(:'date.order', :locale => 'en-US').returns [:year, :month, :day]
datetime_select('post', 'updated_at', :locale => 'en-US')
end
end
diff --git a/actionpack/test/template/number_helper_i18n_test.rb b/actionpack/test/template/number_helper_i18n_test.rb
index be40ddbc88..50c20c3627 100644
--- a/actionpack/test/template/number_helper_i18n_test.rb
+++ b/actionpack/test/template/number_helper_i18n_test.rb
@@ -11,7 +11,7 @@ class NumberHelperI18nTests < Test::Unit::TestCase
end
def test_number_to_currency_translates_currency_formats
- I18n.expects(:translate).with(:'currency.format', 'en-US').returns @defaults
+ I18n.expects(:translate).with(:'currency.format', :locale => 'en-US').returns @defaults
number_to_currency(1, :locale => 'en-US')
end
end
diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb
index 8ba09b3992..a328c4d927 100755
--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -70,7 +70,7 @@ module ActiveRecord
msgs << options[:default] if options[:default]
msgs << key
- I18n.t options.merge(:default => msgs, :scope => [:active_record, :error_messages])
+ I18n.t nil, options.merge(:default => msgs, :scope => [:active_record, :error_messages])
end
# Returns true if the specified +attribute+ has errors associated with it.
@@ -158,7 +158,6 @@ module ActiveRecord
# ["Name is too short (minimum is 5 characters)", "Name can't be blank", "Address can't be blank"]
def full_messages(options = {})
full_messages = []
- locale = options[:locale]
@errors.each_key do |attr|
@errors[attr].each do |message|
@@ -168,7 +167,7 @@ module ActiveRecord
full_messages << message
else
key = :"active_record.human_attribute_names.#{@base.class.name.underscore.to_sym}.#{attr}"
- attr_name = I18n.translate(key, locale, :default => @base.class.human_attribute_name(attr))
+ attr_name = I18n.translate(key, :locale => options[:locale], :default => @base.class.human_attribute_name(attr))
full_messages << attr_name + " " + message
end
end
diff --git a/activerecord/test/cases/validations_i18n_test.rb b/activerecord/test/cases/validations_i18n_test.rb
index 5be518c547..86834fe920 100644
--- a/activerecord/test/cases/validations_i18n_test.rb
+++ b/activerecord/test/cases/validations_i18n_test.rb
@@ -46,14 +46,14 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
global_scope = [:active_record, :error_messages]
custom_scope = global_scope + [:custom, 'topic', :title]
- I18n.expects(:t).with :scope => [:active_record, :error_messages], :default => [:"custom.topic.title.invalid", 'default from class def', :invalid]
+ I18n.expects(:t).with nil, :scope => [:active_record, :error_messages], :default => [:"custom.topic.title.invalid", 'default from class def', :invalid]
@topic.errors.generate_message :title, :invalid, :default => 'default from class def'
end
def test_errors_generate_message_translates_custom_model_attribute_keys_with_sti
custom_scope = [:active_record, :error_messages, :custom, 'topic', :title]
- I18n.expects(:t).with :scope => [:active_record, :error_messages], :default => [:"custom.reply.title.invalid", :"custom.topic.title.invalid", 'default from class def', :invalid]
+ I18n.expects(:t).with nil, :scope => [:active_record, :error_messages], :default => [:"custom.reply.title.invalid", :"custom.topic.title.invalid", 'default from class def', :invalid]
Reply.new.errors.generate_message :title, :invalid, :default => 'default from class def'
end
@@ -79,7 +79,7 @@ class ActiveRecordValidationsI18nTests < Test::Unit::TestCase
def test_errors_full_messages_translates_human_attribute_name_for_model_attributes
@topic.errors.instance_variable_set :@errors, { 'title' => 'empty' }
- I18n.expects(:translate).with(:"active_record.human_attribute_names.topic.title", 'en-US', :default => 'Title').returns('Title')
+ I18n.expects(:translate).with(:"active_record.human_attribute_names.topic.title", :locale => 'en-US', :default => 'Title').returns('Title')
@topic.errors.full_messages :locale => 'en-US'
end
end
diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb
index 80bf1404de..59dc96754f 100644
--- a/activesupport/lib/active_support/core_ext/array/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/array/conversions.rb
@@ -10,10 +10,7 @@ module ActiveSupport #:nodoc:
def to_sentence(options = {})
options.assert_valid_keys(:connector, :skip_last_comma, :locale)
- locale = options[:locale]
- locale ||= self.locale if respond_to?(:locale)
-
- default = I18n.translate(:'support.array.sentence_connector', locale)
+ default = I18n.translate(:'support.array.sentence_connector', :locale => options[:locale])
options.reverse_merge! :connector => default, :skip_last_comma => false
options[:connector] = "#{options[:connector]} " unless options[:connector].nil? || options[:connector].strip == ''
diff --git a/activesupport/lib/active_support/vendor/i18n-0.0.1 b/activesupport/lib/active_support/vendor/i18n-0.0.1
index 970bc7ab5f..46aad28993 160000
--- a/activesupport/lib/active_support/vendor/i18n-0.0.1
+++ b/activesupport/lib/active_support/vendor/i18n-0.0.1
@@ -1 +1 @@
-Subproject commit 970bc7ab5faa94e41ee4a56bc8913c144c1cdd19
+Subproject commit 46aad289935eaf059c429acb5f3bfa0946f2d99f
diff --git a/activesupport/test/i18n_test.rb b/activesupport/test/i18n_test.rb
index e6d90f09c1..17074b6cc6 100644
--- a/activesupport/test/i18n_test.rb
+++ b/activesupport/test/i18n_test.rb
@@ -18,15 +18,15 @@ class I18nTest < Test::Unit::TestCase
end
def test_date_localization_with_default_format
- assert_equal "2008-07-02", I18n.localize(@date, nil, :default)
+ assert_equal "2008-07-02", I18n.localize(@date, :format => :default)
end
def test_date_localization_with_short_format
- assert_equal "Jul 02", I18n.localize(@date, nil, :short)
+ assert_equal "Jul 02", I18n.localize(@date, :format => :short)
end
def test_date_localization_with_long_format
- assert_equal "July 02, 2008", I18n.localize(@date, nil, :long)
+ assert_equal "July 02, 2008", I18n.localize(@date, :format => :long)
end
def test_time_localization_should_use_default_format
@@ -34,15 +34,15 @@ class I18nTest < Test::Unit::TestCase
end
def test_time_localization_with_default_format
- assert_equal "Wed, 02 Jul 2008 16:47:01 +0100", I18n.localize(@time, nil, :default)
+ assert_equal "Wed, 02 Jul 2008 16:47:01 +0100", I18n.localize(@time, :format => :default)
end
def test_time_localization_with_short_format
- assert_equal "02 Jul 16:47", I18n.localize(@time, nil, :short)
+ assert_equal "02 Jul 16:47", I18n.localize(@time, :format => :short)
end
def test_time_localization_with_long_format
- assert_equal "July 02, 2008 16:47", I18n.localize(@time, nil, :long)
+ assert_equal "July 02, 2008 16:47", I18n.localize(@time, :format => :long)
end
def test_day_names
--
cgit v1.2.3
From 826c3db42105518b3a88cf56e348b48c1660f850 Mon Sep 17 00:00:00 2001
From: Luca Guidi
Date: Mon, 7 Jul 2008 22:46:16 +0200
Subject: Updated ActiveRecord::Errors#default_error_messages deprecation
warning according to i18n changes
---
activerecord/lib/active_record/validations.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb
index a328c4d927..83d55f23ea 100755
--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -21,7 +21,7 @@ module ActiveRecord
class << self
def default_error_messages
- ActiveSupport::Deprecation.warn("ActiveRecord::Errors.default_error_messages has been deprecated. Please use 'active_record.error_messages'.t.")
+ ActiveSupport::Deprecation.warn("ActiveRecord::Errors.default_error_messages has been deprecated. Please use I18n.translate('active_record.error_messages').")
I18n.translate 'active_record.error_messages'
end
end
--
cgit v1.2.3
From 2949918b4cea26435d1f0a076fe884c8113b40fa Mon Sep 17 00:00:00 2001
From: Luca Guidi
Date: Tue, 8 Jul 2008 11:53:19 +0200
Subject: Make sure object name is translated in #error_messages_for
---
actionpack/lib/action_view/helpers/active_record_helper.rb | 1 +
actionpack/test/template/active_record_helper_i18n_test.rb | 10 ++++++++++
2 files changed, 11 insertions(+)
diff --git a/actionpack/lib/action_view/helpers/active_record_helper.rb b/actionpack/lib/action_view/helpers/active_record_helper.rb
index 4ff16cd70c..a2fee53fb6 100644
--- a/actionpack/lib/action_view/helpers/active_record_helper.rb
+++ b/actionpack/lib/action_view/helpers/active_record_helper.rb
@@ -176,6 +176,7 @@ module ActionView
options[:header_message]
else
object_name = options[:object_name].to_s.gsub('_', ' ')
+ object_name = I18n.t(object_name, :default => object_name) || ''
locale.t :header_message, :count => count, :object_name => object_name
end
message = options.include?(:message) ? options[:message] : locale.t(:message)
diff --git a/actionpack/test/template/active_record_helper_i18n_test.rb b/actionpack/test/template/active_record_helper_i18n_test.rb
index d78b0e4c0c..d35e79b94a 100644
--- a/actionpack/test/template/active_record_helper_i18n_test.rb
+++ b/actionpack/test/template/active_record_helper_i18n_test.rb
@@ -7,6 +7,7 @@ class ActiveRecordHelperI18nTest < Test::Unit::TestCase
uses_mocha 'active_record_helper_i18n_test' do
def setup
@object = stub :errors => stub(:count => 1, :full_messages => ['full_messages'])
+ @object_name = 'book'
stubs(:content_tag).returns 'content_tag'
I18n.stubs(:t).with(:'header_message', :locale => 'en-US', :scope => [:active_record, :error], :count => 1, :object_name => '').returns "1 error prohibited this from being saved"
@@ -20,17 +21,26 @@ class ActiveRecordHelperI18nTest < Test::Unit::TestCase
def test_error_messages_for_given_no_header_message_option_it_translates_header_message
I18n.expects(:t).with(:'header_message', :locale => 'en-US', :scope => [:active_record, :error], :count => 1, :object_name => '').returns 'header message'
+ I18n.expects(:t).with('', :default => '').once
error_messages_for(:object => @object, :locale => 'en-US')
end
def test_error_messages_for_given_a_message_option_it_does_not_translate_message
I18n.expects(:t).with(:'message', :locale => 'en-US', :scope => [:active_record, :error]).never
+ I18n.expects(:t).with('', :default => '').once
error_messages_for(:object => @object, :message => 'message', :locale => 'en-US')
end
def test_error_messages_for_given_no_message_option_it_translates_message
I18n.expects(:t).with(:'message', :locale => 'en-US', :scope => [:active_record, :error]).returns 'There were problems with the following fields:'
+ I18n.expects(:t).with('', :default => '').once
error_messages_for(:object => @object, :locale => 'en-US')
end
+
+ def test_error_messages_for_given_object_name_it_translates_object_name
+ I18n.expects(:t).with(:header_message, :locale => 'en-US', :scope => [:active_record, :error], :count => 1, :object_name => @object_name).returns "1 error prohibited this #{@object_name} from being saved"
+ I18n.expects(:t).with(@object_name, :default => @object_name).once.returns @object_name
+ error_messages_for(:object => @object, :locale => 'en-US', :object_name => @object_name)
+ end
end
end
\ No newline at end of file
--
cgit v1.2.3
From cf5d6ab9a849d19ac683180cc7b603ca94b13ed7 Mon Sep 17 00:00:00 2001
From: Luca Guidi
Date: Tue, 8 Jul 2008 12:37:49 +0200
Subject: Added localize helper method
---
actionpack/lib/action_view/helpers/translation_helper.rb | 4 ++++
actionpack/test/template/translation_helper_test.rb | 6 ++++++
2 files changed, 10 insertions(+)
diff --git a/actionpack/lib/action_view/helpers/translation_helper.rb b/actionpack/lib/action_view/helpers/translation_helper.rb
index c13c2dfc04..e1010ccf5f 100644
--- a/actionpack/lib/action_view/helpers/translation_helper.rb
+++ b/actionpack/lib/action_view/helpers/translation_helper.rb
@@ -11,6 +11,10 @@ module ActionView
keys = I18n.send :normalize_translation_keys, e.locale, e.key, e.options[:scope]
content_tag('span', keys.join(', '), :class => 'translation_missing')
end
+
+ def localize(*args)
+ I18n.l *args
+ end
end
end
end
\ No newline at end of file
diff --git a/actionpack/test/template/translation_helper_test.rb b/actionpack/test/template/translation_helper_test.rb
index e97bcdb731..2263d48a65 100644
--- a/actionpack/test/template/translation_helper_test.rb
+++ b/actionpack/test/template/translation_helper_test.rb
@@ -39,4 +39,10 @@ class TranslationHelperTest < Test::Unit::TestCase
# error_messages_for(:object => @object, :locale => 'en-US')
# end
end
+
+ def test_delegates_localize_to_i18n
+ @time = Time.utc(2008, 7, 8, 12, 18, 38)
+ assert_equal "Tue, 08 Jul 2008 12:18:38 +0100", localize(@time)
+ assert_equal "08 Jul 12:18", localize(@time, :format => :short)
+ end
end
\ No newline at end of file
--
cgit v1.2.3
From dc77359c16abc0f693e3847e677c0cad62d0df50 Mon Sep 17 00:00:00 2001
From: Luca Guidi
Date: Tue, 8 Jul 2008 17:41:18 +0200
Subject: Removed unnecessary or condition in #error_messages_for
---
actionpack/lib/action_view/helpers/active_record_helper.rb | 2 +-
actionpack/test/template/active_record_helper_i18n_test.rb | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/actionpack/lib/action_view/helpers/active_record_helper.rb b/actionpack/lib/action_view/helpers/active_record_helper.rb
index a2fee53fb6..aa978a33bd 100644
--- a/actionpack/lib/action_view/helpers/active_record_helper.rb
+++ b/actionpack/lib/action_view/helpers/active_record_helper.rb
@@ -176,7 +176,7 @@ module ActionView
options[:header_message]
else
object_name = options[:object_name].to_s.gsub('_', ' ')
- object_name = I18n.t(object_name, :default => object_name) || ''
+ object_name = I18n.t(object_name, :default => object_name)
locale.t :header_message, :count => count, :object_name => object_name
end
message = options.include?(:message) ? options[:message] : locale.t(:message)
diff --git a/actionpack/test/template/active_record_helper_i18n_test.rb b/actionpack/test/template/active_record_helper_i18n_test.rb
index d35e79b94a..feec64aa30 100644
--- a/actionpack/test/template/active_record_helper_i18n_test.rb
+++ b/actionpack/test/template/active_record_helper_i18n_test.rb
@@ -21,19 +21,19 @@ class ActiveRecordHelperI18nTest < Test::Unit::TestCase
def test_error_messages_for_given_no_header_message_option_it_translates_header_message
I18n.expects(:t).with(:'header_message', :locale => 'en-US', :scope => [:active_record, :error], :count => 1, :object_name => '').returns 'header message'
- I18n.expects(:t).with('', :default => '').once
+ I18n.expects(:t).with('', :default => '').once.returns ''
error_messages_for(:object => @object, :locale => 'en-US')
end
def test_error_messages_for_given_a_message_option_it_does_not_translate_message
I18n.expects(:t).with(:'message', :locale => 'en-US', :scope => [:active_record, :error]).never
- I18n.expects(:t).with('', :default => '').once
+ I18n.expects(:t).with('', :default => '').once.returns ''
error_messages_for(:object => @object, :message => 'message', :locale => 'en-US')
end
def test_error_messages_for_given_no_message_option_it_translates_message
I18n.expects(:t).with(:'message', :locale => 'en-US', :scope => [:active_record, :error]).returns 'There were problems with the following fields:'
- I18n.expects(:t).with('', :default => '').once
+ I18n.expects(:t).with('', :default => '').once.returns ''
error_messages_for(:object => @object, :locale => 'en-US')
end
--
cgit v1.2.3
From e0fef66149092dd3d2988fff64f0ce8765735687 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sun, 13 Jul 2008 13:26:48 -0500
Subject: Made ActionView::Base#first_render a little more private. And added
_last_render to track the most recent render. Will fix #609 as a side effect.
[#609 state:resolved]
---
.../action_controller/assertions/response_assertions.rb | 4 ++--
actionpack/lib/action_controller/test_process.rb | 15 ++++-----------
actionpack/lib/action_view/base.rb | 6 +++---
actionpack/lib/action_view/helpers/cache_helper.rb | 3 +--
actionpack/lib/action_view/renderable.rb | 4 ++--
actionpack/test/controller/action_pack_assertions_test.rb | 6 +++---
actionpack/test/controller/caching_test.rb | 8 ++++++++
.../functional_caching/inline_fragment_cached.html.erb | 2 ++
8 files changed, 25 insertions(+), 23 deletions(-)
create mode 100644 actionpack/test/fixtures/functional_caching/inline_fragment_cached.html.erb
diff --git a/actionpack/lib/action_controller/assertions/response_assertions.rb b/actionpack/lib/action_controller/assertions/response_assertions.rb
index cb36405700..a98c70d66f 100644
--- a/actionpack/lib/action_controller/assertions/response_assertions.rb
+++ b/actionpack/lib/action_controller/assertions/response_assertions.rb
@@ -87,11 +87,11 @@ module ActionController
#
def assert_template(expected = nil, message=nil)
clean_backtrace do
- rendered = expected ? @response.rendered_file(!expected.include?('/')) : @response.rendered_file
+ rendered = @response.rendered_template.to_s
msg = build_message(message, "expecting > but rendering with >", expected, rendered)
assert_block(msg) do
if expected.nil?
- !@response.rendered_with_file?
+ @response.rendered_template ? true : false
else
rendered.match(expected)
end
diff --git a/actionpack/lib/action_controller/test_process.rb b/actionpack/lib/action_controller/test_process.rb
index 52884a93f4..a6e0c98936 100644
--- a/actionpack/lib/action_controller/test_process.rb
+++ b/actionpack/lib/action_controller/test_process.rb
@@ -205,17 +205,10 @@ module ActionController #:nodoc:
p.match(redirect_url) != nil
end
- # Returns the template path of the file which was used to
- # render this response (or nil)
- def rendered_file(with_controller = false)
- if template.first_render
- template.first_render.to_s
- end
- end
-
- # Was this template rendered by a file?
- def rendered_with_file?
- !rendered_file.nil?
+ # Returns the template of the file which was used to
+ # render this response (or nil)
+ def rendered_template
+ template._first_render
end
# A shortcut to the flash. Returns an empyt hash if no session flash exists.
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index 989e92a890..9f244d7250 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -159,11 +159,11 @@ module ActionView #:nodoc:
class Base
include ERB::Util
- attr_accessor :base_path, :assigns, :template_extension, :first_render
+ attr_accessor :base_path, :assigns, :template_extension
attr_accessor :controller
+ attr_accessor :_first_render, :_last_render
attr_writer :template_format
- attr_accessor :current_render_extension
attr_accessor :output_buffer
@@ -313,7 +313,7 @@ module ActionView #:nodoc:
template
elsif template = self.view_paths[template_file_name]
template
- elsif first_render && template = self.view_paths["#{template_file_name}.#{first_render.extension}"]
+ elsif _first_render && template = self.view_paths["#{template_file_name}.#{_first_render.extension}"]
template
elsif template_format == :js && template = self.view_paths["#{template_file_name}.html"]
@template_format = :html
diff --git a/actionpack/lib/action_view/helpers/cache_helper.rb b/actionpack/lib/action_view/helpers/cache_helper.rb
index 930c397785..2cdbae6e40 100644
--- a/actionpack/lib/action_view/helpers/cache_helper.rb
+++ b/actionpack/lib/action_view/helpers/cache_helper.rb
@@ -32,8 +32,7 @@ module ActionView
# Topics listed alphabetically
# <% end %>
def cache(name = {}, options = nil, &block)
- handler = Template.handler_class_for_extension(current_render_extension.to_sym)
- handler.new(@controller).cache_fragment(block, name, options)
+ _last_render.handler.new(@controller).cache_fragment(block, name, options)
end
end
end
diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb
index 2c4302146f..ebb0f1b674 100644
--- a/actionpack/lib/action_view/renderable.rb
+++ b/actionpack/lib/action_view/renderable.rb
@@ -18,9 +18,9 @@ module ActionView
end
def render(view, local_assigns = {})
- view.first_render ||= self
+ view._first_render ||= self
+ view._last_render = self
view.send(:evaluate_assigns)
- view.current_render_extension = extension
compile(local_assigns) if handler.compilable?
handler.new(view).render(self, local_assigns)
end
diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb
index 610e196362..56ba36cee5 100644
--- a/actionpack/test/controller/action_pack_assertions_test.rb
+++ b/actionpack/test/controller/action_pack_assertions_test.rb
@@ -328,11 +328,11 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase
# check if we were rendered by a file-based template?
def test_rendered_action
process :nothing
- assert !@response.rendered_with_file?
+ assert_nil @response.rendered_template
process :hello_world
- assert @response.rendered_with_file?
- assert 'hello_world', @response.rendered_file
+ assert @response.rendered_template
+ assert 'hello_world', @response.rendered_template.to_s
end
# check the redirection location
diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb
index 2e98837a35..c30f7be700 100644
--- a/actionpack/test/controller/caching_test.rb
+++ b/actionpack/test/controller/caching_test.rb
@@ -664,6 +664,14 @@ CACHED
assert_match "Fragment caching in a partial", @store.read('views/test.host/functional_caching/html_fragment_cached_with_partial')
end
+ def test_render_inline_before_fragment_caching
+ get :inline_fragment_cached
+ assert_response :success
+ assert_match /Some inline content/, @response.body
+ assert_match /Some cached content/, @response.body
+ assert_match "Some cached content", @store.read('views/test.host/functional_caching/inline_fragment_cached')
+ end
+
def test_fragment_caching_in_rjs_partials
xhr :get, :js_fragment_cached_with_partial
assert_response :success
diff --git a/actionpack/test/fixtures/functional_caching/inline_fragment_cached.html.erb b/actionpack/test/fixtures/functional_caching/inline_fragment_cached.html.erb
new file mode 100644
index 0000000000..87309b8ccb
--- /dev/null
+++ b/actionpack/test/fixtures/functional_caching/inline_fragment_cached.html.erb
@@ -0,0 +1,2 @@
+<%= render :inline => 'Some inline content' %>
+<% cache do %>Some cached content<% end %>
--
cgit v1.2.3
From 26bc867151a8f302b4c6122e6375c3ea2088a037 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sun, 13 Jul 2008 14:00:40 -0500
Subject: Small tweak to e0fef66
---
actionpack/lib/action_controller/assertions/response_assertions.rb | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/actionpack/lib/action_controller/assertions/response_assertions.rb b/actionpack/lib/action_controller/assertions/response_assertions.rb
index a98c70d66f..765225ae24 100644
--- a/actionpack/lib/action_controller/assertions/response_assertions.rb
+++ b/actionpack/lib/action_controller/assertions/response_assertions.rb
@@ -87,13 +87,13 @@ module ActionController
#
def assert_template(expected = nil, message=nil)
clean_backtrace do
- rendered = @response.rendered_template.to_s
+ rendered = @response.rendered_template
msg = build_message(message, "expecting > but rendering with >", expected, rendered)
assert_block(msg) do
if expected.nil?
- @response.rendered_template ? true : false
+ @response.rendered_template.nil?
else
- rendered.match(expected)
+ rendered.to_s.match(expected)
end
end
end
--
cgit v1.2.3
From 68fe898189a27e4e3c4c2fe005c99975d40e1dd7 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sun, 13 Jul 2008 14:05:21 -0500
Subject: Check first render format and extension. Fixes failing ActionMailer
test.
---
actionpack/lib/action_view/base.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index 9f244d7250..04e8d3a358 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -313,7 +313,7 @@ module ActionView #:nodoc:
template
elsif template = self.view_paths[template_file_name]
template
- elsif _first_render && template = self.view_paths["#{template_file_name}.#{_first_render.extension}"]
+ elsif _first_render && template = self.view_paths["#{template_file_name}.#{_first_render.format_and_extension}"]
template
elsif template_format == :js && template = self.view_paths["#{template_file_name}.html"]
@template_format = :html
--
cgit v1.2.3
From 0d241f4434bafa2107cd6c3f3ab77c05f5d5ec71 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tapaj=C3=B3s?=
Date: Sun, 13 Jul 2008 14:19:03 -0500
Subject: Use full path in database tasks so commands will work outside of
Rails root [#612 state:resolved]
Signed-off-by: Joshua Peek
---
railties/lib/tasks/databases.rake | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/railties/lib/tasks/databases.rake b/railties/lib/tasks/databases.rake
index 75fba8b45a..22b8459ce4 100644
--- a/railties/lib/tasks/databases.rake
+++ b/railties/lib/tasks/databases.rake
@@ -215,14 +215,14 @@ namespace :db do
desc "Create a db/schema.rb file that can be portably used against any DB supported by AR"
task :dump => :environment do
require 'active_record/schema_dumper'
- File.open(ENV['SCHEMA'] || "db/schema.rb", "w") do |file|
+ File.open(ENV['SCHEMA'] || "#{RAILS_ROOT}/db/schema.rb", "w") do |file|
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
end
end
desc "Load a schema.rb file into the database"
task :load => :environment do
- file = ENV['SCHEMA'] || "db/schema.rb"
+ file = ENV['SCHEMA'] || "#{RAILS_ROOT}/db/schema.rb"
load(file)
end
end
@@ -234,7 +234,7 @@ namespace :db do
case abcs[RAILS_ENV]["adapter"]
when "mysql", "oci", "oracle"
ActiveRecord::Base.establish_connection(abcs[RAILS_ENV])
- File.open("db/#{RAILS_ENV}_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump }
+ File.open("#{RAILS_ROOT}/db/#{RAILS_ENV}_structure.sql", "w+") { |f| f << ActiveRecord::Base.connection.structure_dump }
when "postgresql"
ENV['PGHOST'] = abcs[RAILS_ENV]["host"] if abcs[RAILS_ENV]["host"]
ENV['PGPORT'] = abcs[RAILS_ENV]["port"].to_s if abcs[RAILS_ENV]["port"]
@@ -252,13 +252,13 @@ namespace :db do
when "firebird"
set_firebird_env(abcs[RAILS_ENV])
db_string = firebird_db_string(abcs[RAILS_ENV])
- sh "isql -a #{db_string} > db/#{RAILS_ENV}_structure.sql"
+ sh "isql -a #{db_string} > #{RAILS_ROOT}/db/#{RAILS_ENV}_structure.sql"
else
raise "Task not supported by '#{abcs["test"]["adapter"]}'"
end
if ActiveRecord::Base.connection.supports_migrations?
- File.open("db/#{RAILS_ENV}_structure.sql", "a") { |f| f << ActiveRecord::Base.connection.dump_schema_information }
+ File.open("#{RAILS_ROOT}/db/#{RAILS_ENV}_structure.sql", "a") { |f| f << ActiveRecord::Base.connection.dump_schema_information }
end
end
end
@@ -281,28 +281,28 @@ namespace :db do
when "mysql"
ActiveRecord::Base.establish_connection(:test)
ActiveRecord::Base.connection.execute('SET foreign_key_checks = 0')
- IO.readlines("db/#{RAILS_ENV}_structure.sql").join.split("\n\n").each do |table|
+ IO.readlines("#{RAILS_ROOT}/db/#{RAILS_ENV}_structure.sql").join.split("\n\n").each do |table|
ActiveRecord::Base.connection.execute(table)
end
when "postgresql"
ENV['PGHOST'] = abcs["test"]["host"] if abcs["test"]["host"]
ENV['PGPORT'] = abcs["test"]["port"].to_s if abcs["test"]["port"]
ENV['PGPASSWORD'] = abcs["test"]["password"].to_s if abcs["test"]["password"]
- `psql -U "#{abcs["test"]["username"]}" -f db/#{RAILS_ENV}_structure.sql #{abcs["test"]["database"]}`
+ `psql -U "#{abcs["test"]["username"]}" -f #{RAILS_ROOT}/db/#{RAILS_ENV}_structure.sql #{abcs["test"]["database"]}`
when "sqlite", "sqlite3"
dbfile = abcs["test"]["database"] || abcs["test"]["dbfile"]
- `#{abcs["test"]["adapter"]} #{dbfile} < db/#{RAILS_ENV}_structure.sql`
+ `#{abcs["test"]["adapter"]} #{dbfile} < #{RAILS_ROOT}/db/#{RAILS_ENV}_structure.sql`
when "sqlserver"
`osql -E -S #{abcs["test"]["host"]} -d #{abcs["test"]["database"]} -i db\\#{RAILS_ENV}_structure.sql`
when "oci", "oracle"
ActiveRecord::Base.establish_connection(:test)
- IO.readlines("db/#{RAILS_ENV}_structure.sql").join.split(";\n\n").each do |ddl|
+ IO.readlines("#{RAILS_ROOT}/db/#{RAILS_ENV}_structure.sql").join.split(";\n\n").each do |ddl|
ActiveRecord::Base.connection.execute(ddl)
end
when "firebird"
set_firebird_env(abcs["test"])
db_string = firebird_db_string(abcs["test"])
- sh "isql -i db/#{RAILS_ENV}_structure.sql #{db_string}"
+ sh "isql -i #{RAILS_ROOT}/db/#{RAILS_ENV}_structure.sql #{db_string}"
else
raise "Task not supported by '#{abcs["test"]["adapter"]}'"
end
--
cgit v1.2.3
From 95812d5eafc3b63ce5eeb0748a5d0132f5108b64 Mon Sep 17 00:00:00 2001
From: rsl
Date: Mon, 14 Jul 2008 00:55:57 +0100
Subject: Ensure :index works with fields_for select methods. [#518
state:resolved]
Signed-off-by: Pratik Naik
---
.../lib/action_view/helpers/form_options_helper.rb | 8 +-
.../test/template/form_options_helper_test.rb | 929 ++++++++++++++++++++-
2 files changed, 911 insertions(+), 26 deletions(-)
diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb
index ab9e174621..87d49397c6 100644
--- a/actionpack/lib/action_view/helpers/form_options_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -445,19 +445,19 @@ module ActionView
class FormBuilder
def select(method, choices, options = {}, html_options = {})
- @template.select(@object_name, method, choices, options.merge(:object => @object), html_options)
+ @template.select(@object_name, method, choices, objectify_options(options), @default_options.merge(html_options))
end
def collection_select(method, collection, value_method, text_method, options = {}, html_options = {})
- @template.collection_select(@object_name, method, collection, value_method, text_method, options.merge(:object => @object), html_options)
+ @template.collection_select(@object_name, method, collection, value_method, text_method, objectify_options(options), @default_options.merge(html_options))
end
def country_select(method, priority_countries = nil, options = {}, html_options = {})
- @template.country_select(@object_name, method, priority_countries, options.merge(:object => @object), html_options)
+ @template.country_select(@object_name, method, priority_countries, objectify_options(options), @default_options.merge(html_options))
end
def time_zone_select(method, priority_zones = nil, options = {}, html_options = {})
- @template.time_zone_select(@object_name, method, priority_zones, options.merge(:object => @object), html_options)
+ @template.time_zone_select(@object_name, method, priority_zones, objectify_options(options), @default_options.merge(html_options))
end
end
end
diff --git a/actionpack/test/template/form_options_helper_test.rb b/actionpack/test/template/form_options_helper_test.rb
index 2496931f4b..9dd43d7b4f 100644
--- a/actionpack/test/template/form_options_helper_test.rb
+++ b/actionpack/test/template/form_options_helper_test.rb
@@ -231,6 +231,35 @@ uses_mocha "FormOptionsHelperTest" do
)
end
+ def test_select_under_fields_for_with_index
+ @post = Post.new
+ @post.category = ""
+
+ fields_for :post, @post, :index => 108 do |f|
+ concat f.select(:category, %w( abe hest))
+ end
+
+ assert_dom_equal(
+ "abe \n<mus> \nhest ",
+ output_buffer
+ )
+ end
+
+ def test_select_under_fields_for_with_auto_index
+ @post = Post.new
+ @post.category = ""
+ def @post.to_param; 108; end
+
+ fields_for "post[]", @post do |f|
+ concat f.select(:category, %w( abe hest))
+ end
+
+ assert_dom_equal(
+ "abe \n<mus> \nhest ",
+ output_buffer
+ )
+ end
+
def test_select_with_blank
@post = Post.new
@post.category = ""
@@ -351,6 +380,47 @@ uses_mocha "FormOptionsHelperTest" do
)
end
+ def test_collection_select_under_fields_for_with_index
+ @posts = [
+ Post.new(" went home", "", "To a little house", "shh!"),
+ Post.new("Babe went home", "Babe", "To a little house", "shh!"),
+ Post.new("Cabe went home", "Cabe", "To a little house", "shh!")
+ ]
+
+ @post = Post.new
+ @post.author_name = "Babe"
+
+ fields_for :post, @post, :index => 815 do |f|
+ concat f.collection_select(:author_name, @posts, :author_name, :author_name)
+ end
+
+ assert_dom_equal(
+ "<Abe> \nBabe \nCabe ",
+ output_buffer
+ )
+ end
+
+ def test_collection_select_under_fields_for_with_auto_index
+ @posts = [
+ Post.new(" went home", "", "To a little house", "shh!"),
+ Post.new("Babe went home", "Babe", "To a little house", "shh!"),
+ Post.new("Cabe went home", "Cabe", "To a little house", "shh!")
+ ]
+
+ @post = Post.new
+ @post.author_name = "Babe"
+ def @post.to_param; 815; end
+
+ fields_for "post[]", @post do |f|
+ concat f.collection_select(:author_name, @posts, :author_name, :author_name)
+ end
+
+ assert_dom_equal(
+ "<Abe> \nBabe \nCabe ",
+ output_buffer
+ )
+ end
+
def test_collection_select_with_blank_and_style
@posts = [
Post.new(" went home", "", "To a little house", "shh!"),
@@ -1165,28 +1235,843 @@ uses_mocha "FormOptionsHelperTest" do
assert_dom_equal(expected_select[0..-2], country_select("post", "origin", ["New Zealand", "Nicaragua"]))
end
- def test_time_zone_select
- @firm = Firm.new("D")
- html = time_zone_select( "firm", "time_zone" )
- assert_dom_equal "" +
- "A \n" +
- "B \n" +
- "C \n" +
- "D \n" +
- "E " +
- " ",
- html
- end
-
- def test_time_zone_select_under_fields_for
- @firm = Firm.new("D")
-
- fields_for :firm, @firm do |f|
- concat f.time_zone_select(:time_zone)
- end
-
- assert_dom_equal(
- "" +
+ def test_country_select_under_fields_for
+ @post = Post.new
+ @post.origin = "Australia"
+ expected_select = <<-COUNTRIES
+Afghanistan
+Aland Islands
+Albania
+Algeria
+American Samoa
+Andorra
+Angola
+Anguilla
+Antarctica
+Antigua And Barbuda
+Argentina
+Armenia
+Aruba
+Australia
+Austria
+Azerbaijan
+Bahamas
+Bahrain
+Bangladesh
+Barbados
+Belarus
+Belgium
+Belize
+Benin
+Bermuda
+Bhutan
+Bolivia
+Bosnia and Herzegowina
+Botswana
+Bouvet Island
+Brazil
+British Indian Ocean Territory
+Brunei Darussalam
+Bulgaria
+Burkina Faso
+Burundi
+Cambodia
+Cameroon
+Canada
+Cape Verde
+Cayman Islands
+Central African Republic
+Chad
+Chile
+China
+Christmas Island
+Cocos (Keeling) Islands
+Colombia
+Comoros
+Congo
+Congo, the Democratic Republic of the
+Cook Islands
+Costa Rica
+Cote d'Ivoire
+Croatia
+Cuba
+Cyprus
+Czech Republic
+Denmark
+Djibouti
+Dominica
+Dominican Republic
+Ecuador
+Egypt
+El Salvador
+Equatorial Guinea
+Eritrea
+Estonia
+Ethiopia
+Falkland Islands (Malvinas)
+Faroe Islands
+Fiji
+Finland
+France
+French Guiana
+French Polynesia
+French Southern Territories
+Gabon
+Gambia
+Georgia
+Germany
+Ghana
+Gibraltar
+Greece
+Greenland
+Grenada
+Guadeloupe
+Guam
+Guatemala
+Guernsey
+Guinea
+Guinea-Bissau
+Guyana
+Haiti
+Heard and McDonald Islands
+Holy See (Vatican City State)
+Honduras
+Hong Kong
+Hungary
+Iceland
+India
+Indonesia
+Iran, Islamic Republic of
+Iraq
+Ireland
+Isle of Man
+Israel
+Italy
+Jamaica
+Japan
+Jersey
+Jordan
+Kazakhstan
+Kenya
+Kiribati
+Korea, Democratic People's Republic of
+Korea, Republic of
+Kuwait
+Kyrgyzstan
+Lao People's Democratic Republic
+Latvia
+Lebanon
+Lesotho
+Liberia
+Libyan Arab Jamahiriya
+Liechtenstein
+Lithuania
+Luxembourg
+Macao
+Macedonia, The Former Yugoslav Republic Of
+Madagascar
+Malawi
+Malaysia
+Maldives
+Mali
+Malta
+Marshall Islands
+Martinique
+Mauritania
+Mauritius
+Mayotte
+Mexico
+Micronesia, Federated States of
+Moldova, Republic of
+Monaco
+Mongolia
+Montenegro
+Montserrat
+Morocco
+Mozambique
+Myanmar
+Namibia
+Nauru
+Nepal
+Netherlands
+Netherlands Antilles
+New Caledonia
+New Zealand
+Nicaragua
+Niger
+Nigeria
+Niue
+Norfolk Island
+Northern Mariana Islands
+Norway
+Oman
+Pakistan
+Palau
+Palestinian Territory, Occupied
+Panama
+Papua New Guinea
+Paraguay
+Peru
+Philippines
+Pitcairn
+Poland
+Portugal
+Puerto Rico
+Qatar
+Reunion
+Romania
+Russian Federation
+Rwanda
+Saint Barthelemy
+Saint Helena
+Saint Kitts and Nevis
+Saint Lucia
+Saint Pierre and Miquelon
+Saint Vincent and the Grenadines
+Samoa
+San Marino
+Sao Tome and Principe
+Saudi Arabia
+Senegal
+Serbia
+Seychelles
+Sierra Leone
+Singapore
+Slovakia
+Slovenia
+Solomon Islands
+Somalia
+South Africa
+South Georgia and the South Sandwich Islands
+Spain
+Sri Lanka
+Sudan
+Suriname
+Svalbard and Jan Mayen
+Swaziland
+Sweden
+Switzerland
+Syrian Arab Republic
+Taiwan, Province of China
+Tajikistan
+Tanzania, United Republic of
+Thailand
+Timor-Leste
+Togo
+Tokelau
+Tonga
+Trinidad and Tobago
+Tunisia
+Turkey
+Turkmenistan
+Turks and Caicos Islands
+Tuvalu
+Uganda
+Ukraine
+United Arab Emirates
+United Kingdom
+United States
+United States Minor Outlying Islands
+Uruguay
+Uzbekistan
+Vanuatu
+Venezuela
+Viet Nam
+Virgin Islands, British
+Virgin Islands, U.S.
+Wallis and Futuna
+Western Sahara
+Yemen
+Zambia
+Zimbabwe
+ COUNTRIES
+
+ fields_for :post, @post do |f|
+ concat f.country_select("origin")
+ end
+
+ assert_dom_equal(expected_select[0..-2], output_buffer)
+ end
+
+ def test_country_select_under_fields_for_with_index
+ @post = Post.new
+ @post.origin = "United States"
+ expected_select = <<-COUNTRIES
+Afghanistan
+Aland Islands
+Albania
+Algeria
+American Samoa
+Andorra
+Angola
+Anguilla
+Antarctica
+Antigua And Barbuda
+Argentina
+Armenia
+Aruba
+Australia
+Austria
+Azerbaijan
+Bahamas
+Bahrain
+Bangladesh
+Barbados
+Belarus
+Belgium
+Belize
+Benin
+Bermuda
+Bhutan
+Bolivia
+Bosnia and Herzegowina
+Botswana
+Bouvet Island
+Brazil
+British Indian Ocean Territory
+Brunei Darussalam
+Bulgaria
+Burkina Faso
+Burundi
+Cambodia
+Cameroon
+Canada
+Cape Verde
+Cayman Islands
+Central African Republic
+Chad
+Chile
+China
+Christmas Island
+Cocos (Keeling) Islands
+Colombia
+Comoros
+Congo
+Congo, the Democratic Republic of the
+Cook Islands
+Costa Rica
+Cote d'Ivoire
+Croatia
+Cuba
+Cyprus
+Czech Republic
+Denmark
+Djibouti
+Dominica
+Dominican Republic
+Ecuador
+Egypt
+El Salvador
+Equatorial Guinea
+Eritrea
+Estonia
+Ethiopia
+Falkland Islands (Malvinas)
+Faroe Islands
+Fiji
+Finland
+France
+French Guiana
+French Polynesia
+French Southern Territories
+Gabon
+Gambia
+Georgia
+Germany
+Ghana
+Gibraltar
+Greece
+Greenland
+Grenada
+Guadeloupe
+Guam
+Guatemala
+Guernsey
+Guinea
+Guinea-Bissau
+Guyana
+Haiti
+Heard and McDonald Islands
+Holy See (Vatican City State)
+Honduras
+Hong Kong
+Hungary
+Iceland
+India
+Indonesia
+Iran, Islamic Republic of
+Iraq
+Ireland
+Isle of Man
+Israel
+Italy
+Jamaica
+Japan
+Jersey
+Jordan
+Kazakhstan
+Kenya
+Kiribati
+Korea, Democratic People's Republic of
+Korea, Republic of
+Kuwait
+Kyrgyzstan
+Lao People's Democratic Republic
+Latvia
+Lebanon
+Lesotho
+Liberia
+Libyan Arab Jamahiriya
+Liechtenstein
+Lithuania
+Luxembourg
+Macao
+Macedonia, The Former Yugoslav Republic Of
+Madagascar
+Malawi
+Malaysia
+Maldives
+Mali
+Malta
+Marshall Islands
+Martinique
+Mauritania
+Mauritius
+Mayotte
+Mexico
+Micronesia, Federated States of
+Moldova, Republic of
+Monaco
+Mongolia
+Montenegro
+Montserrat
+Morocco
+Mozambique
+Myanmar
+Namibia
+Nauru
+Nepal
+Netherlands
+Netherlands Antilles
+New Caledonia
+New Zealand
+Nicaragua
+Niger
+Nigeria
+Niue
+Norfolk Island
+Northern Mariana Islands
+Norway
+Oman
+Pakistan
+Palau
+Palestinian Territory, Occupied
+Panama
+Papua New Guinea
+Paraguay
+Peru
+Philippines
+Pitcairn
+Poland
+Portugal
+Puerto Rico
+Qatar
+Reunion
+Romania
+Russian Federation
+Rwanda
+Saint Barthelemy
+Saint Helena
+Saint Kitts and Nevis
+Saint Lucia
+Saint Pierre and Miquelon
+Saint Vincent and the Grenadines
+Samoa
+San Marino
+Sao Tome and Principe
+Saudi Arabia
+Senegal
+Serbia
+Seychelles
+Sierra Leone
+Singapore
+Slovakia
+Slovenia
+Solomon Islands
+Somalia
+South Africa
+South Georgia and the South Sandwich Islands
+Spain
+Sri Lanka
+Sudan
+Suriname
+Svalbard and Jan Mayen
+Swaziland
+Sweden
+Switzerland
+Syrian Arab Republic
+Taiwan, Province of China
+Tajikistan
+Tanzania, United Republic of
+Thailand
+Timor-Leste
+Togo
+Tokelau
+Tonga
+Trinidad and Tobago
+Tunisia
+Turkey
+Turkmenistan
+Turks and Caicos Islands
+Tuvalu
+Uganda
+Ukraine
+United Arab Emirates
+United Kingdom
+United States
+United States Minor Outlying Islands
+Uruguay
+Uzbekistan
+Vanuatu
+Venezuela
+Viet Nam
+Virgin Islands, British
+Virgin Islands, U.S.
+Wallis and Futuna
+Western Sahara
+Yemen
+Zambia
+Zimbabwe
+ COUNTRIES
+
+ fields_for :post, @post, :index => 325 do |f|
+ concat f.country_select("origin")
+ end
+
+ assert_dom_equal(expected_select[0..-2], output_buffer)
+ end
+
+ def test_country_select_under_fields_for_with_auto_index
+ @post = Post.new
+ @post.origin = "Iraq"
+ def @post.to_param; 325; end
+
+ expected_select = <<-COUNTRIES
+Afghanistan
+Aland Islands
+Albania
+Algeria
+American Samoa
+Andorra
+Angola
+Anguilla
+Antarctica
+Antigua And Barbuda
+Argentina
+Armenia
+Aruba
+Australia
+Austria
+Azerbaijan
+Bahamas
+Bahrain
+Bangladesh
+Barbados
+Belarus
+Belgium
+Belize
+Benin
+Bermuda
+Bhutan
+Bolivia
+Bosnia and Herzegowina
+Botswana
+Bouvet Island
+Brazil
+British Indian Ocean Territory
+Brunei Darussalam
+Bulgaria
+Burkina Faso
+Burundi
+Cambodia
+Cameroon
+Canada
+Cape Verde
+Cayman Islands
+Central African Republic
+Chad
+Chile
+China
+Christmas Island
+Cocos (Keeling) Islands
+Colombia
+Comoros
+Congo
+Congo, the Democratic Republic of the
+Cook Islands
+Costa Rica
+Cote d'Ivoire
+Croatia
+Cuba
+Cyprus
+Czech Republic
+Denmark
+Djibouti
+Dominica
+Dominican Republic
+Ecuador
+Egypt
+El Salvador
+Equatorial Guinea
+Eritrea
+Estonia
+Ethiopia
+Falkland Islands (Malvinas)
+Faroe Islands
+Fiji
+Finland
+France
+French Guiana
+French Polynesia
+French Southern Territories
+Gabon
+Gambia
+Georgia
+Germany
+Ghana
+Gibraltar
+Greece
+Greenland
+Grenada
+Guadeloupe
+Guam
+Guatemala
+Guernsey
+Guinea
+Guinea-Bissau
+Guyana
+Haiti
+Heard and McDonald Islands
+Holy See (Vatican City State)
+Honduras
+Hong Kong
+Hungary
+Iceland
+India
+Indonesia
+Iran, Islamic Republic of
+Iraq
+Ireland
+Isle of Man
+Israel
+Italy
+Jamaica
+Japan
+Jersey
+Jordan
+Kazakhstan
+Kenya
+Kiribati
+Korea, Democratic People's Republic of
+Korea, Republic of
+Kuwait
+Kyrgyzstan
+Lao People's Democratic Republic
+Latvia
+Lebanon
+Lesotho
+Liberia
+Libyan Arab Jamahiriya
+Liechtenstein
+Lithuania
+Luxembourg
+Macao
+Macedonia, The Former Yugoslav Republic Of
+Madagascar
+Malawi
+Malaysia
+Maldives
+Mali
+Malta
+Marshall Islands
+Martinique
+Mauritania
+Mauritius
+Mayotte
+Mexico
+Micronesia, Federated States of
+Moldova, Republic of
+Monaco
+Mongolia
+Montenegro
+Montserrat
+Morocco
+Mozambique
+Myanmar
+Namibia
+Nauru
+Nepal
+Netherlands
+Netherlands Antilles
+New Caledonia
+New Zealand
+Nicaragua
+Niger
+Nigeria
+Niue
+Norfolk Island
+Northern Mariana Islands
+Norway
+Oman
+Pakistan
+Palau
+Palestinian Territory, Occupied
+Panama
+Papua New Guinea
+Paraguay
+Peru
+Philippines
+Pitcairn
+Poland
+Portugal
+Puerto Rico
+Qatar
+Reunion
+Romania
+Russian Federation
+Rwanda
+Saint Barthelemy
+Saint Helena
+Saint Kitts and Nevis
+Saint Lucia
+Saint Pierre and Miquelon
+Saint Vincent and the Grenadines
+Samoa
+San Marino
+Sao Tome and Principe
+Saudi Arabia
+Senegal
+Serbia
+Seychelles
+Sierra Leone
+Singapore
+Slovakia
+Slovenia
+Solomon Islands
+Somalia
+South Africa
+South Georgia and the South Sandwich Islands
+Spain
+Sri Lanka
+Sudan
+Suriname
+Svalbard and Jan Mayen
+Swaziland
+Sweden
+Switzerland
+Syrian Arab Republic
+Taiwan, Province of China
+Tajikistan
+Tanzania, United Republic of
+Thailand
+Timor-Leste
+Togo
+Tokelau
+Tonga
+Trinidad and Tobago
+Tunisia
+Turkey
+Turkmenistan
+Turks and Caicos Islands
+Tuvalu
+Uganda
+Ukraine
+United Arab Emirates
+United Kingdom
+United States
+United States Minor Outlying Islands
+Uruguay
+Uzbekistan
+Vanuatu
+Venezuela
+Viet Nam
+Virgin Islands, British
+Virgin Islands, U.S.
+Wallis and Futuna
+Western Sahara
+Yemen
+Zambia
+Zimbabwe
+ COUNTRIES
+
+ fields_for "post[]", @post do |f|
+ concat f.country_select("origin")
+ end
+
+ assert_dom_equal(expected_select[0..-2], output_buffer)
+ end
+
+ def test_time_zone_select
+ @firm = Firm.new("D")
+ html = time_zone_select( "firm", "time_zone" )
+ assert_dom_equal "" +
+ "A \n" +
+ "B \n" +
+ "C \n" +
+ "D \n" +
+ "E " +
+ " ",
+ html
+ end
+
+ def test_time_zone_select_under_fields_for
+ @firm = Firm.new("D")
+
+ fields_for :firm, @firm do |f|
+ concat f.time_zone_select(:time_zone)
+ end
+
+ assert_dom_equal(
+ "" +
+ "A \n" +
+ "B \n" +
+ "C \n" +
+ "D \n" +
+ "E " +
+ " ",
+ output_buffer
+ )
+ end
+
+ def test_time_zone_select_under_fields_for_with_index
+ @firm = Firm.new("D")
+
+ fields_for :firm, @firm, :index => 305 do |f|
+ concat f.time_zone_select(:time_zone)
+ end
+
+ assert_dom_equal(
+ "" +
+ "A \n" +
+ "B \n" +
+ "C \n" +
+ "D \n" +
+ "E " +
+ " ",
+ output_buffer
+ )
+ end
+
+ def test_time_zone_select_under_fields_for_with_auto_index
+ @firm = Firm.new("D")
+ def @firm.to_param; 305; end
+
+ fields_for "firm[]", @firm do |f|
+ concat f.time_zone_select(:time_zone)
+ end
+
+ assert_dom_equal(
+ "" +
"A \n" +
"B \n" +
"C \n" +
--
cgit v1.2.3
From 9783e66cade4d145389cca18fab822f44d03161a Mon Sep 17 00:00:00 2001
From: Pratik Naik
Date: Mon, 14 Jul 2008 01:02:07 +0100
Subject: Slightly faster DateTime#to_json. [#598 state:resolved] [Alex Zepeda]
---
activesupport/lib/active_support/json/encoders/date_time.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/activesupport/lib/active_support/json/encoders/date_time.rb b/activesupport/lib/active_support/json/encoders/date_time.rb
index d41c3e9786..a4a5efbfb1 100644
--- a/activesupport/lib/active_support/json/encoders/date_time.rb
+++ b/activesupport/lib/active_support/json/encoders/date_time.rb
@@ -8,7 +8,7 @@ class DateTime
if ActiveSupport.use_standard_json_time_format
xmlschema.inspect
else
- %("#{strftime("%Y/%m/%d %H:%M:%S %z")}")
+ strftime('"%Y/%m/%d %H:%M:%S %z"')
end
end
end
--
cgit v1.2.3
From 697ee1a50dea7580a7240535d3ad89d2d090721a Mon Sep 17 00:00:00 2001
From: Jacek Becela
Date: Wed, 9 Jul 2008 21:34:04 +0200
Subject: Enable loading fixtures from arbitrary locations. [#586
state:resolved]
Signed-off-by: Pratik Naik
---
railties/lib/tasks/databases.rake | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/railties/lib/tasks/databases.rake b/railties/lib/tasks/databases.rake
index 22b8459ce4..87934c295e 100644
--- a/railties/lib/tasks/databases.rake
+++ b/railties/lib/tasks/databases.rake
@@ -179,12 +179,15 @@ namespace :db do
end
namespace :fixtures do
- desc "Load fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y"
+ desc "Load fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y. Load from subdirectory in test/fixtures using FIXTURES_DIR=z."
task :load => :environment do
require 'active_record/fixtures'
- ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
- (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(RAILS_ROOT, 'test', 'fixtures', '*.{yml,csv}'))).each do |fixture_file|
- Fixtures.create_fixtures('test/fixtures', File.basename(fixture_file, '.*'))
+ ActiveRecord::Base.establish_connection(Rails.env)
+ base_dir = File.join(Rails.root, 'test', 'fixtures')
+ fixtures_dir = ENV['FIXTURES_DIR'] ? File.join(base_dir, ENV['FIXTURES_DIR']) : base_dir
+
+ (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/).map {|f| File.join(fixtures_dir, f) } : Dir.glob(File.join(fixtures_dir, '*.{yml,csv}'))).each do |fixture_file|
+ Fixtures.create_fixtures(File.dirname(fixture_file), File.basename(fixture_file, '.*'))
end
end
--
cgit v1.2.3
From d72c66532f959846cdc2d7fb1dc1ef6ba87bdcb1 Mon Sep 17 00:00:00 2001
From: Rhett Sutphin
Date: Mon, 14 Jul 2008 02:01:52 +0100
Subject: Make fixture accessors work when fixture name is not same as the
table name. [#124 state:resolved]
Signed-off-by: Pratik Naik
---
activerecord/lib/active_record/fixtures.rb | 7 ++++---
activerecord/test/cases/fixtures_test.rb | 29 +++++++++++++++++++++++++++++
2 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index e19614e31f..17fb9355c4 100755
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -541,10 +541,11 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
label.to_s.hash.abs
end
- attr_reader :table_name
+ attr_reader :table_name, :name
def initialize(connection, table_name, class_name, fixture_path, file_filter = DEFAULT_FILTER_RE)
@connection, @table_name, @fixture_path, @file_filter = connection, table_name, fixture_path, file_filter
+ @name = table_name # preserve fixture base name
@class_name = class_name ||
(ActiveRecord::Base.pluralize_table_names ? @table_name.singularize.camelize : @table_name.camelize)
@table_name = "#{ActiveRecord::Base.table_name_prefix}#{@table_name}#{ActiveRecord::Base.table_name_suffix}"
@@ -963,9 +964,9 @@ module Test #:nodoc:
fixtures = Fixtures.create_fixtures(fixture_path, fixture_table_names, fixture_class_names)
unless fixtures.nil?
if fixtures.instance_of?(Fixtures)
- @loaded_fixtures[fixtures.table_name] = fixtures
+ @loaded_fixtures[fixtures.name] = fixtures
else
- fixtures.each { |f| @loaded_fixtures[f.table_name] = f }
+ fixtures.each { |f| @loaded_fixtures[f.name] = f }
end
end
end
diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb
index aca7cfb367..0ea24868f1 100755
--- a/activerecord/test/cases/fixtures_test.rb
+++ b/activerecord/test/cases/fixtures_test.rb
@@ -15,6 +15,7 @@ require 'models/pirate'
require 'models/treasure'
require 'models/matey'
require 'models/ship'
+require 'models/book'
class FixturesTest < ActiveRecord::TestCase
self.use_instantiated_fixtures = true
@@ -373,6 +374,34 @@ class CheckSetTableNameFixturesTest < ActiveRecord::TestCase
end
end
+class FixtureNameIsNotTableNameFixturesTest < ActiveRecord::TestCase
+ set_fixture_class :items => Book
+ fixtures :items
+ # Set to false to blow away fixtures cache and ensure our fixtures are loaded
+ # and thus takes into account our set_fixture_class
+ self.use_transactional_fixtures = false
+
+ def test_named_accessor
+ assert_kind_of Book, items(:dvd)
+ end
+end
+
+class FixtureNameIsNotTableNameMultipleFixturesTest < ActiveRecord::TestCase
+ set_fixture_class :items => Book, :funny_jokes => Joke
+ fixtures :items, :funny_jokes
+ # Set to false to blow away fixtures cache and ensure our fixtures are loaded
+ # and thus takes into account our set_fixture_class
+ self.use_transactional_fixtures = false
+
+ def test_named_accessor_of_differently_named_fixture
+ assert_kind_of Book, items(:dvd)
+ end
+
+ def test_named_accessor_of_same_named_fixture
+ assert_kind_of Joke, funny_jokes(:a_joke)
+ end
+end
+
class CustomConnectionFixturesTest < ActiveRecord::TestCase
set_fixture_class :courses => Course
fixtures :courses
--
cgit v1.2.3
From c6f397c5cecf183680c191dd2128c0a96c5b9399 Mon Sep 17 00:00:00 2001
From: Jason Dew
Date: Fri, 27 Jun 2008 12:25:26 -0400
Subject: Add block syntax to HasManyAssociation#build. [#502 state:resolve]
Signed-off-by: Pratik Naik
---
.../associations/association_collection.rb | 9 ++++---
.../associations/has_many_associations_test.rb | 31 ++++++++++++++++++++++
2 files changed, 37 insertions(+), 3 deletions(-)
diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb
index eb39714909..04be59e89d 100644
--- a/activerecord/lib/active_record/associations/association_collection.rb
+++ b/activerecord/lib/active_record/associations/association_collection.rb
@@ -78,11 +78,14 @@ module ActiveRecord
@loaded = false
end
- def build(attributes = {})
+ def build(attributes = {}, &block)
if attributes.is_a?(Array)
- attributes.collect { |attr| build(attr) }
+ attributes.collect { |attr| build(attr, &block) }
else
- build_record(attributes) { |record| set_belongs_to_association_for(record) }
+ build_record(attributes) do |record|
+ block.call(record) if block_given?
+ set_belongs_to_association_for(record)
+ end
end
end
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index e90edbb213..b9c7ec6377 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -425,6 +425,37 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_equal 2, first_topic.replies.to_ary.size
end
+ def test_build_via_block
+ company = companies(:first_firm)
+ new_client = assert_no_queries { company.clients_of_firm.build {|client| client.name = "Another Client" } }
+ assert !company.clients_of_firm.loaded?
+
+ assert_equal "Another Client", new_client.name
+ assert new_client.new_record?
+ assert_equal new_client, company.clients_of_firm.last
+ company.name += '-changed'
+ assert_queries(2) { assert company.save }
+ assert !new_client.new_record?
+ assert_equal 2, company.clients_of_firm(true).size
+ end
+
+ def test_build_many_via_block
+ company = companies(:first_firm)
+ new_clients = assert_no_queries do
+ company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) do |client|
+ client.name = "changed"
+ end
+ end
+
+ assert_equal 2, new_clients.size
+ assert_equal "changed", new_clients.first.name
+ assert_equal "changed", new_clients.last.name
+
+ company.name += '-changed'
+ assert_queries(3) { assert company.save }
+ assert_equal 3, company.clients_of_firm(true).size
+ end
+
def test_create_without_loading_association
first_firm = companies(:first_firm)
Firm.column_names
--
cgit v1.2.3
From e0750d6a5c7f621e4ca12205137c0b135cab444a Mon Sep 17 00:00:00 2001
From: David Dollar
Date: Sun, 13 Jul 2008 21:13:50 -0400
Subject: Add :accessible option to Associations for allowing mass assignments
using hash. [#474 state:resolved]
Allows nested Hashes (i.e. from nested forms) to hydrate the appropriate
ActiveRecord models.
class Post < ActiveRecord::Base
belongs_to :author, :accessible => true
has_many :comments, :accessible => true
end
post = Post.create({
:title => 'Accessible Attributes',
:author => { :name => 'David Dollar' },
:comments => [
{ :body => 'First Post!' },
{ :body => 'Nested Hashes are great!' }
]
})
post.comments << { :body => 'Another Comment' }
Signed-off-by: Pratik Naik
---
activerecord/CHANGELOG | 18 ++++
activerecord/lib/active_record/associations.rb | 14 ++-
.../associations/association_collection.rb | 6 ++
activerecord/test/cases/associations_test.rb | 108 +++++++++++++++++++++
activerecord/test/models/author.rb | 2 +-
activerecord/test/models/post.rb | 6 ++
6 files changed, 149 insertions(+), 5 deletions(-)
diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG
index d92b89cfe0..56b1781537 100644
--- a/activerecord/CHANGELOG
+++ b/activerecord/CHANGELOG
@@ -1,5 +1,23 @@
*Edge*
+* Add :accessible option to associations for allowing (opt-in) mass assignment. #474. [David Dollar] Example :
+
+ class Post < ActiveRecord::Base
+ belongs_to :author, :accessible => true
+ has_many :comments, :accessible => true
+ end
+
+ post = Post.create({
+ :title => 'Accessible Attributes',
+ :author => { :name => 'David Dollar' },
+ :comments => [
+ { :body => 'First Post!' },
+ { :body => 'Nested Hashes are great!' }
+ ]
+ })
+
+ post.comments << { :body => 'Another Comment' }
+
* Add :tokenizer option to validates_length_of to specify how to split up the attribute string. #507. [David Lowenfels] Example :
# Ensure essay contains at least 100 words.
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 6931744058..d43e07ab4e 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -692,6 +692,7 @@ module ActiveRecord
# * :uniq - If true, duplicates will be omitted from the collection. Useful in conjunction with :through .
# * :readonly - If true, all the associated objects are readonly through the association.
# * :validate - If false, don't validate the associated objects when saving the parent object. true by default.
+ # * :accessible - Mass assignment is allowed for this assocation (similar to ActiveRecord::Base#attr_accessible ).
#
# Option examples:
# has_many :comments, :order => "posted_on"
@@ -774,6 +775,7 @@ module ActiveRecord
# association is a polymorphic +belongs_to+.
# * :readonly - If true, the associated object is readonly through the association.
# * :validate - If false, don't validate the associated object when saving the parent object. +false+ by default.
+ # * :accessible - Mass assignment is allowed for this assocation (similar to ActiveRecord::Base#attr_accessible ).
#
# Option examples:
# has_one :credit_card, :dependent => :destroy # destroys the associated credit card
@@ -863,6 +865,7 @@ module ActiveRecord
# to the +attr_readonly+ list in the associated classes (e.g. class Post; attr_readonly :comments_count; end ).
# * :readonly - If true, the associated object is readonly through the association.
# * :validate - If false, don't validate the associated objects when saving the parent object. +false+ by default.
+ # * :accessible - Mass assignment is allowed for this assocation (similar to ActiveRecord::Base#attr_accessible ).
#
# Option examples:
# belongs_to :firm, :foreign_key => "client_of"
@@ -1034,6 +1037,7 @@ module ActiveRecord
# but not include the joined columns. Do not forget to include the primary and foreign keys, otherwise it will raise an error.
# * :readonly - If true, all the associated objects are readonly through the association.
# * :validate - If false, don't validate the associated objects when saving the parent object. +true+ by default.
+ # * :accessible - Mass assignment is allowed for this assocation (similar to ActiveRecord::Base#attr_accessible ).
#
# Option examples:
# has_and_belongs_to_many :projects
@@ -1109,6 +1113,8 @@ module ActiveRecord
association = association_proxy_class.new(self, reflection)
end
+ new_value = reflection.klass.new(new_value) if reflection.options[:accessible] && new_value.is_a?(Hash)
+
if association_proxy_class == HasOneThroughAssociation
association.create_through_record(new_value)
self.send(reflection.name, new_value)
@@ -1357,7 +1363,7 @@ module ActiveRecord
:finder_sql, :counter_sql,
:before_add, :after_add, :before_remove, :after_remove,
:extend, :readonly,
- :validate
+ :validate, :accessible
)
options[:extend] = create_extension_modules(association_id, extension, options[:extend])
@@ -1367,7 +1373,7 @@ module ActiveRecord
def create_has_one_reflection(association_id, options)
options.assert_valid_keys(
- :class_name, :foreign_key, :remote, :select, :conditions, :order, :include, :dependent, :counter_cache, :extend, :as, :readonly, :validate, :primary_key
+ :class_name, :foreign_key, :remote, :select, :conditions, :order, :include, :dependent, :counter_cache, :extend, :as, :readonly, :validate, :primary_key, :accessible
)
create_reflection(:has_one, association_id, options, self)
@@ -1383,7 +1389,7 @@ module ActiveRecord
def create_belongs_to_reflection(association_id, options)
options.assert_valid_keys(
:class_name, :foreign_key, :foreign_type, :remote, :select, :conditions, :include, :dependent,
- :counter_cache, :extend, :polymorphic, :readonly, :validate
+ :counter_cache, :extend, :polymorphic, :readonly, :validate, :accessible
)
reflection = create_reflection(:belongs_to, association_id, options, self)
@@ -1403,7 +1409,7 @@ module ActiveRecord
:finder_sql, :delete_sql, :insert_sql,
:before_add, :after_add, :before_remove, :after_remove,
:extend, :readonly,
- :validate
+ :validate, :accessible
)
options[:extend] = create_extension_modules(association_id, extension, options[:extend])
diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb
index 04be59e89d..a28be9eed1 100644
--- a/activerecord/lib/active_record/associations/association_collection.rb
+++ b/activerecord/lib/active_record/associations/association_collection.rb
@@ -97,6 +97,8 @@ module ActiveRecord
@owner.transaction do
flatten_deeper(records).each do |record|
+ record = @reflection.klass.new(record) if @reflection.options[:accessible] && record.is_a?(Hash)
+
raise_on_type_mismatch(record)
add_record_to_target_with_callbacks(record) do |r|
result &&= insert_record(record) unless @owner.new_record?
@@ -229,6 +231,10 @@ module ActiveRecord
# Replace this collection with +other_array+
# This will perform a diff and delete/add only records that have changed.
def replace(other_array)
+ other_array.map! do |val|
+ val.is_a?(Hash) ? @reflection.klass.new(val) : val
+ end if @reflection.options[:accessible]
+
other_array.each { |val| raise_on_type_mismatch(val) }
load_target
diff --git a/activerecord/test/cases/associations_test.rb b/activerecord/test/cases/associations_test.rb
index 59349dd7cf..4904feeb7d 100755
--- a/activerecord/test/cases/associations_test.rb
+++ b/activerecord/test/cases/associations_test.rb
@@ -189,6 +189,114 @@ class AssociationProxyTest < ActiveRecord::TestCase
end
end
+ def test_belongs_to_mass_assignment
+ post_attributes = { :title => 'Associations', :body => 'Are They Accessible?' }
+ author_attributes = { :name => 'David Dollar' }
+
+ assert_no_difference 'Author.count' do
+ assert_raise(ActiveRecord::AssociationTypeMismatch) do
+ Post.create(post_attributes.merge({:author => author_attributes}))
+ end
+ end
+
+ assert_difference 'Author.count' do
+ post = Post.create(post_attributes.merge({:creatable_author => author_attributes}))
+ assert_equal post.creatable_author.name, author_attributes[:name]
+ end
+ end
+
+ def test_has_one_mass_assignment
+ post_attributes = { :title => 'Associations', :body => 'Are They Accessible?' }
+ comment_attributes = { :body => 'Setter Takes Hash' }
+
+ assert_no_difference 'Comment.count' do
+ assert_raise(ActiveRecord::AssociationTypeMismatch) do
+ Post.create(post_attributes.merge({:uncreatable_comment => comment_attributes}))
+ end
+ end
+
+ assert_difference 'Comment.count' do
+ post = Post.create(post_attributes.merge({:creatable_comment => comment_attributes}))
+ assert_equal post.creatable_comment.body, comment_attributes[:body]
+ end
+ end
+
+ def test_has_many_mass_assignment
+ post = posts(:welcome)
+ post_attributes = { :title => 'Associations', :body => 'Are They Accessible?' }
+ comment_attributes = { :body => 'Setter Takes Hash' }
+
+ assert_no_difference 'Comment.count' do
+ assert_raise(ActiveRecord::AssociationTypeMismatch) do
+ Post.create(post_attributes.merge({:comments => [comment_attributes]}))
+ end
+ assert_raise(ActiveRecord::AssociationTypeMismatch) do
+ post.comments << comment_attributes
+ end
+ end
+
+ assert_difference 'Comment.count' do
+ post = Post.create(post_attributes.merge({:creatable_comments => [comment_attributes]}))
+ assert_equal post.creatable_comments.last.body, comment_attributes[:body]
+ end
+
+ assert_difference 'Comment.count' do
+ post.creatable_comments << comment_attributes
+ assert_equal post.comments.last.body, comment_attributes[:body]
+ end
+
+ post.creatable_comments = [comment_attributes, comment_attributes]
+ assert_equal post.creatable_comments.count, 2
+ end
+
+ def test_has_and_belongs_to_many_mass_assignment
+ post = posts(:welcome)
+ post_attributes = { :title => 'Associations', :body => 'Are They Accessible?' }
+ category_attributes = { :name => 'Accessible Association', :type => 'Category' }
+
+ assert_no_difference 'Category.count' do
+ assert_raise(ActiveRecord::AssociationTypeMismatch) do
+ Post.create(post_attributes.merge({:categories => [category_attributes]}))
+ end
+ assert_raise(ActiveRecord::AssociationTypeMismatch) do
+ post.categories << category_attributes
+ end
+ end
+
+ assert_difference 'Category.count' do
+ post = Post.create(post_attributes.merge({:creatable_categories => [category_attributes]}))
+ assert_equal post.creatable_categories.last.name, category_attributes[:name]
+ end
+
+ assert_difference 'Category.count' do
+ post.creatable_categories << category_attributes
+ assert_equal post.creatable_categories.last.name, category_attributes[:name]
+ end
+
+ post.creatable_categories = [category_attributes, category_attributes]
+ assert_equal post.creatable_categories.count, 2
+ end
+
+ def test_association_proxy_setter_can_take_hash
+ special_comment_attributes = { :body => 'Setter Takes Hash' }
+
+ post = posts(:welcome)
+ post.creatable_comment = { :body => 'Setter Takes Hash' }
+
+ assert_equal post.creatable_comment.body, special_comment_attributes[:body]
+ end
+
+ def test_association_collection_can_take_hash
+ post_attributes = { :title => 'Setter Takes', :body => 'Hash' }
+ david = authors(:david)
+
+ post = (david.posts << post_attributes).last
+ assert_equal post.title, post_attributes[:title]
+
+ david.posts = [post_attributes, post_attributes]
+ assert_equal david.posts.count, 2
+ end
+
def setup_dangling_association
josh = Author.create(:name => "Josh")
p = Post.create(:title => "New on Edge", :body => "More cool stuff!", :author => josh)
diff --git a/activerecord/test/models/author.rb b/activerecord/test/models/author.rb
index 82e069005a..136dc39cf3 100644
--- a/activerecord/test/models/author.rb
+++ b/activerecord/test/models/author.rb
@@ -1,5 +1,5 @@
class Author < ActiveRecord::Base
- has_many :posts
+ has_many :posts, :accessible => true
has_many :posts_with_comments, :include => :comments, :class_name => "Post"
has_many :posts_with_comments_sorted_by_comment_id, :include => :comments, :class_name => "Post", :order => 'comments.id'
has_many :posts_with_categories, :include => :categories, :class_name => "Post"
diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb
index 3adbc0ce1f..e23818eb33 100644
--- a/activerecord/test/models/post.rb
+++ b/activerecord/test/models/post.rb
@@ -33,6 +33,12 @@ class Post < ActiveRecord::Base
has_and_belongs_to_many :categories
has_and_belongs_to_many :special_categories, :join_table => "categories_posts", :association_foreign_key => 'category_id'
+ belongs_to :creatable_author, :class_name => 'Author', :accessible => true
+ has_one :uncreatable_comment, :class_name => 'Comment', :accessible => false, :order => 'id desc'
+ has_one :creatable_comment, :class_name => 'Comment', :accessible => true, :order => 'id desc'
+ has_many :creatable_comments, :class_name => 'Comment', :accessible => true, :dependent => :destroy
+ has_and_belongs_to_many :creatable_categories, :class_name => 'Category', :accessible => true
+
has_many :taggings, :as => :taggable
has_many :tags, :through => :taggings do
def add_joins_and_select
--
cgit v1.2.3
From 5c086070824bf7dd2bc4c9ce97956d82ac3fa206 Mon Sep 17 00:00:00 2001
From: Tim Pope
Date: Sun, 13 Jul 2008 22:24:16 -0400
Subject: Make script/plugin install -r option work with
git based plugins. [#257 state:resolved]
Signed-off-by: Pratik Naik
---
railties/CHANGELOG | 5 +++++
railties/lib/commands/plugin.rb | 47 ++++++++++++++++++++++++++++-------------
2 files changed, 37 insertions(+), 15 deletions(-)
diff --git a/railties/CHANGELOG b/railties/CHANGELOG
index 1b9bdb57f2..b5c5aba460 100644
--- a/railties/CHANGELOG
+++ b/railties/CHANGELOG
@@ -1,5 +1,10 @@
*Edge*
+* Make script/plugin install -r option work with git based plugins. #257. [Tim Pope Jakub Kuźma]. Example:
+
+ script/plugin install git://github.com/mislav/will_paginate.git -r agnostic # Installs 'agnostic' branch
+ script/plugin install git://github.com/dchelimsky/rspec.git -r 'tag 1.1.4'
+
* Added Rails.initialized? flag [Josh Peek]
* Make rake test:uncommitted work with Git. [Tim Pope]
diff --git a/railties/lib/commands/plugin.rb b/railties/lib/commands/plugin.rb
index ce4b0d051d..0256090d16 100644
--- a/railties/lib/commands/plugin.rb
+++ b/railties/lib/commands/plugin.rb
@@ -43,6 +43,16 @@
# plugin is pulled via `svn checkout` or `svn export` but looks
# exactly the same.
#
+# Specifying revisions:
+#
+# * Subversion revision is a single integer.
+#
+# * Git revision format:
+# - full - 'refs/tags/1.8.0' or 'refs/heads/experimental'
+# - short: 'experimental' (equivalent to 'refs/heads/experimental')
+# 'tag 1.8.0' (equivalent to 'refs/tags/1.8.0')
+#
+#
# This is Free Software, copyright 2005 by Ryan Tomayko (rtomayko@gmail.com)
# and is licensed MIT: (http://www.opensource.org/licenses/mit-license.php)
@@ -175,7 +185,7 @@ class Plugin
method ||= rails_env.best_install_method?
if :http == method
method = :export if svn_url?
- method = :clone if git_url?
+ method = :git if git_url?
end
uninstall if installed? and options[:force]
@@ -255,8 +265,25 @@ class Plugin
end
end
- def install_using_clone(options = {})
- git_command :clone, options
+ def install_using_git(options = {})
+ root = rails_env.root
+ install_path = mkdir_p "#{root}/vendor/plugins/#{name}"
+ Dir.chdir install_path do
+ init_cmd = "git init"
+ init_cmd += " -q" if options[:quiet] and not $verbose
+ puts init_cmd if $verbose
+ system(init_cmd)
+ base_cmd = "git pull --depth 1 #{uri}"
+ base_cmd += " -q" if options[:quiet] and not $verbose
+ base_cmd += " #{options[:revision]}" if options[:revision]
+ puts base_cmd if $verbose
+ if system(base_cmd)
+ puts "removing: .git" if $verbose
+ rm_rf ".git"
+ else
+ rm_rf install_path
+ end
+ end
end
def svn_command(cmd, options = {})
@@ -268,16 +295,6 @@ class Plugin
puts base_cmd if $verbose
system(base_cmd)
end
-
- def git_command(cmd, options = {})
- root = rails_env.root
- mkdir_p "#{root}/vendor/plugins"
- base_cmd = "git #{cmd} --depth 1 #{uri} \"#{root}/vendor/plugins/#{name}\""
- puts base_cmd if $verbose
- puts "removing: #{root}/vendor/plugins/#{name}/.git"
- system(base_cmd)
- rm_rf "#{root}/vendor/plugins/#{name}/.git"
- end
def guess_name(url)
@name = File.basename(url)
@@ -756,8 +773,8 @@ module Commands
"Suppresses the output from installation.",
"Ignored if -v is passed (./script/plugin -v install ...)") { |v| @options[:quiet] = true }
o.on( "-r REVISION", "--revision REVISION",
- "Checks out the given revision from subversion.",
- "Ignored if subversion is not used.") { |v| @options[:revision] = v }
+ "Checks out the given revision from subversion or git.",
+ "Ignored if subversion/git is not used.") { |v| @options[:revision] = v }
o.on( "-f", "--force",
"Reinstalls a plugin if it's already installed.") { |v| @options[:force] = true }
o.separator ""
--
cgit v1.2.3
From 0176e6adb388998414083e99523de318d3b8ca49 Mon Sep 17 00:00:00 2001
From: "Sebastian A. Espindola"
Date: Tue, 8 Jul 2008 01:14:11 -0300
Subject: Added db:charset support to PostgreSQL. [#556 state:resolved]
Signed-off-by: Pratik Naik
---
.../active_record/connection_adapters/postgresql_adapter.rb | 13 +++++++++++++
activerecord/test/cases/adapter_test.rb | 6 ++++++
cleanlogs.sh | 1 -
railties/lib/tasks/databases.rake | 3 +++
4 files changed, 22 insertions(+), 1 deletion(-)
delete mode 100755 cleanlogs.sh
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 2e2d50ccf4..29ecd83ba0 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -623,6 +623,19 @@ module ActiveRecord
end
end
+ # Returns the current database name.
+ def current_database
+ query('select current_database()')[0][0]
+ end
+
+ # Returns the current database encoding format.
+ def encoding
+ query(<<-end_sql)[0][0]
+ SELECT pg_encoding_to_char(pg_database.encoding) FROM pg_database
+ WHERE pg_database.datname LIKE '#{current_database}'
+ end_sql
+ end
+
# Sets the schema search path to a string of comma-separated schema names.
# Names beginning with $ have to be quoted (e.g. $user => '$user').
# See: http://www.postgresql.org/docs/current/static/ddl-schemas.html
diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb
index 11f9870534..04770646b2 100644
--- a/activerecord/test/cases/adapter_test.rb
+++ b/activerecord/test/cases/adapter_test.rb
@@ -65,6 +65,12 @@ class AdapterTest < ActiveRecord::TestCase
end
end
+ if current_adapter?(:PostgreSQLAdapter)
+ def test_encoding
+ assert_not_nil @connection.encoding
+ end
+ end
+
def test_table_alias
def @connection.test_table_alias_length() 10; end
class << @connection
diff --git a/cleanlogs.sh b/cleanlogs.sh
deleted file mode 100755
index a4e6baf0df..0000000000
--- a/cleanlogs.sh
+++ /dev/null
@@ -1 +0,0 @@
-rm activerecord/debug.log activerecord/test/debug.log actionpack/debug.log activeresource/test/debug.log
diff --git a/railties/lib/tasks/databases.rake b/railties/lib/tasks/databases.rake
index 87934c295e..5ec712a02d 100644
--- a/railties/lib/tasks/databases.rake
+++ b/railties/lib/tasks/databases.rake
@@ -141,6 +141,9 @@ namespace :db do
when 'mysql'
ActiveRecord::Base.establish_connection(config)
puts ActiveRecord::Base.connection.charset
+ when 'postgresql'
+ ActiveRecord::Base.establish_connection(config)
+ puts ActiveRecord::Base.connection.encoding
else
puts 'sorry, your database adapter is not supported yet, feel free to submit a patch'
end
--
cgit v1.2.3
From 30370227890dc950f1544b7b1040aa75e505f877 Mon Sep 17 00:00:00 2001
From: David Heinemeier Hansson
Date: Mon, 14 Jul 2008 10:12:54 -0500
Subject: Fixed that create database statements would always include "DEFAULT
NULL" (Nick Sieger) [#334 status:committed]
---
activerecord/CHANGELOG | 2 ++
.../abstract/schema_definitions.rb | 5 ++-
activerecord/test/cases/column_definition_test.rb | 36 ++++++++++++++++++++++
3 files changed, 42 insertions(+), 1 deletion(-)
create mode 100644 activerecord/test/cases/column_definition_test.rb
diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG
index 56b1781537..17430ba0b7 100644
--- a/activerecord/CHANGELOG
+++ b/activerecord/CHANGELOG
@@ -1,5 +1,7 @@
*Edge*
+* Fixed that create database statements would always include "DEFAULT NULL" (Nick Sieger) [#334]
+
* Add :accessible option to associations for allowing (opt-in) mass assignment. #474. [David Dollar] Example :
class Post < ActiveRecord::Base
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
index d4c8a80448..13ccfea0b8 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
@@ -257,7 +257,10 @@ module ActiveRecord
def to_sql
column_sql = "#{base.quote_column_name(name)} #{sql_type}"
- add_column_options!(column_sql, :null => null, :default => default) unless type.to_sym == :primary_key
+ column_options = {}
+ column_options[:null] = null unless null.nil?
+ column_options[:default] = default unless default.nil?
+ add_column_options!(column_sql, column_options) unless type.to_sym == :primary_key
column_sql
end
alias to_s :to_sql
diff --git a/activerecord/test/cases/column_definition_test.rb b/activerecord/test/cases/column_definition_test.rb
new file mode 100644
index 0000000000..540f42f4b6
--- /dev/null
+++ b/activerecord/test/cases/column_definition_test.rb
@@ -0,0 +1,36 @@
+require "cases/helper"
+
+class ColumnDefinitionTest < ActiveRecord::TestCase
+ def setup
+ @adapter = ActiveRecord::ConnectionAdapters::AbstractAdapter.new(nil)
+ def @adapter.native_database_types
+ {:string => "varchar"}
+ end
+ end
+
+ # Avoid column definitions in create table statements like:
+ # `title` varchar(255) DEFAULT NULL NULL
+ def test_should_not_include_default_clause_when_default_is_null
+ column = ActiveRecord::ConnectionAdapters::Column.new("title", nil, "varchar(20)")
+ column_def = ActiveRecord::ConnectionAdapters::ColumnDefinition.new(
+ @adapter, column.name, "string",
+ column.limit, column.precision, column.scale, column.default, column.null)
+ assert_equal "title varchar(20) NULL", column_def.to_sql
+ end
+
+ def test_should_include_default_clause_when_default_is_present
+ column = ActiveRecord::ConnectionAdapters::Column.new("title", "Hello", "varchar(20)")
+ column_def = ActiveRecord::ConnectionAdapters::ColumnDefinition.new(
+ @adapter, column.name, "string",
+ column.limit, column.precision, column.scale, column.default, column.null)
+ assert_equal %Q{title varchar(20) DEFAULT 'Hello' NULL}, column_def.to_sql
+ end
+
+ def test_should_specify_not_null_if_null_option_is_false
+ column = ActiveRecord::ConnectionAdapters::Column.new("title", "Hello", "varchar(20)", false)
+ column_def = ActiveRecord::ConnectionAdapters::ColumnDefinition.new(
+ @adapter, column.name, "string",
+ column.limit, column.precision, column.scale, column.default, column.null)
+ assert_equal %Q{title varchar(20) DEFAULT 'Hello' NOT NULL}, column_def.to_sql
+ end
+end
\ No newline at end of file
--
cgit v1.2.3
From 2167f95d857224b88901c5fb4cda63c2e0756676 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 9 Jul 2008 12:38:59 -0700
Subject: Restore the more readable before_ and after_filters methods since
they aren't called frequently
---
actionpack/lib/action_controller/filters.rb | 12 ++----------
1 file changed, 2 insertions(+), 10 deletions(-)
diff --git a/actionpack/lib/action_controller/filters.rb b/actionpack/lib/action_controller/filters.rb
index fc63890d13..10dc0cc45b 100644
--- a/actionpack/lib/action_controller/filters.rb
+++ b/actionpack/lib/action_controller/filters.rb
@@ -569,21 +569,13 @@ module ActionController #:nodoc:
# Returns all the before filters for this class and all its ancestors.
# This method returns the actual filter that was assigned in the controller to maintain existing functionality.
def before_filters #:nodoc:
- filters = []
- filter_chain.each do |filter|
- filters << filter.method if filter.before?
- end
- filters
+ filter_chain.select(&:before?).map(&:method)
end
# Returns all the after filters for this class and all its ancestors.
# This method returns the actual filter that was assigned in the controller to maintain existing functionality.
def after_filters #:nodoc:
- filters = []
- filter_chain.each do |filter|
- filters << filter.method if filter.after?
- end
- filters
+ filter_chain.select(&:after?).map(&:method)
end
end
--
cgit v1.2.3
From 425de8db6adf13f21242bdd9adcb931bb836ad8b Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 9 Jul 2008 13:30:53 -0700
Subject: Use instance_method(...) to check whether the method exists
---
.../action_view/template_handlers/compilable.rb | 46 +++++++++++++++++++++-
1 file changed, 44 insertions(+), 2 deletions(-)
diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb
index a0ebaefeef..2a19fc7628 100644
--- a/actionpack/lib/action_view/template_handlers/compilable.rb
+++ b/actionpack/lib/action_view/template_handlers/compilable.rb
@@ -12,9 +12,51 @@ module ActionView
end
end
- def render(template, local_assigns = {})
- @view.send(:execute, template, local_assigns)
+ def render(template)
+ @view.send(:execute, template)
end
+
+ # Compile and evaluate the template's code
+ def compile_template(template)
+ return false unless recompile_template?(template)
+
+ @@mutex.synchronize do
+ locals_code = template.locals.keys.map { |key| "#{key} = local_assigns[:#{key}];" }.join
+
+ source = <<-end_src
+ def #{template.method}(local_assigns)
+ old_output_buffer = output_buffer;#{locals_code};#{compile(template)}
+ ensure
+ self.output_buffer = old_output_buffer
+ end
+ end_src
+
+ begin
+ file_name = template.filename || 'compiled-template'
+ ActionView::Base::CompiledTemplates.module_eval(source, file_name, 0)
+ rescue Exception => e # errors from template code
+ if logger = ActionController::Base.logger
+ logger.debug "ERROR: compiling #{template.method} RAISED #{e}"
+ logger.debug "Function body: #{source}"
+ logger.debug "Backtrace: #{e.backtrace.join("\n")}"
+ end
+
+ raise ActionView::TemplateError.new(template, @view.assigns, e)
+ end
+ end
+ end
+
+ private
+ # Method to check whether template compilation is necessary.
+ # The template will be compiled if the inline template or file has not been compiled yet,
+ # if local_assigns has a new key, which isn't supported by the compiled code yet.
+ def recompile_template?(template)
+ # Unless the template has been compiled yet, compile
+ # If template caching is disabled, compile
+ # Always recompile inline templates
+ meth = Base::CompiledTemplates.instance_method(template.method) rescue nil
+ !meth || !Base.cache_template_loading || template.is_a?(InlineTemplate)
+ end
end
end
end
--
cgit v1.2.3
From ae9356ae9eff4072efae7433204578c30c6ddbf7 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 9 Jul 2008 19:41:49 -0700
Subject: Cache template loading for performance tests
---
railties/helpers/performance_test_helper.rb | 1 +
1 file changed, 1 insertion(+)
diff --git a/railties/helpers/performance_test_helper.rb b/railties/helpers/performance_test_helper.rb
index 3c4c7fb740..f1662fa30a 100644
--- a/railties/helpers/performance_test_helper.rb
+++ b/railties/helpers/performance_test_helper.rb
@@ -2,5 +2,6 @@ require 'test_helper'
require 'action_controller/performance_test'
ActionController::Base.perform_caching = true
+ActionView::Base.cache_template_loading = true
ActiveSupport::Dependencies.mechanism = :require
Rails.logger.level = ActiveSupport::BufferedLogger::INFO
--
cgit v1.2.3
From 269c6c6bcfec342cf830e0b20c44bb2c888e8fdf Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 9 Jul 2008 19:43:38 -0700
Subject: Cache Module#parent_name
---
.../core_ext/module/introspection.rb | 23 ++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/activesupport/lib/active_support/core_ext/module/introspection.rb b/activesupport/lib/active_support/core_ext/module/introspection.rb
index bb894ec080..45f3e4bf5c 100644
--- a/activesupport/lib/active_support/core_ext/module/introspection.rb
+++ b/activesupport/lib/active_support/core_ext/module/introspection.rb
@@ -1,4 +1,14 @@
class Module
+ # Returns the name of the module containing this one.
+ #
+ # p M::N.parent_name # => "M"
+ def parent_name
+ unless defined? @parent_name
+ @parent_name = name =~ /::[^:]+\Z/ ? $`.freeze : nil
+ end
+ @parent_name
+ end
+
# Returns the module which contains this one according to its name.
#
# module M
@@ -16,8 +26,7 @@ class Module
# p Module.new.parent # => Object
#
def parent
- parent_name = name.split('::')[0..-2] * '::'
- parent_name.empty? ? Object : parent_name.constantize
+ parent_name ? parent_name.constantize : Object
end
# Returns all the parents of this module according to its name, ordered from
@@ -35,10 +44,12 @@ class Module
#
def parents
parents = []
- parts = name.split('::')[0..-2]
- until parts.empty?
- parents << (parts * '::').constantize
- parts.pop
+ if parent_name
+ parts = parent_name.split('::')
+ until parts.empty?
+ parents << (parts * '::').constantize
+ parts.pop
+ end
end
parents << Object unless parents.include? Object
parents
--
cgit v1.2.3
From cdf0f1aa2ee4ba73bafc9b9217ee35b7f7eb3273 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Sat, 12 Jul 2008 11:42:17 -0700
Subject: Faster and clearer value_to_boolean
---
.../connection_adapters/abstract/schema_definitions.rb | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
index 13ccfea0b8..31d6c7942c 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
@@ -1,4 +1,5 @@
require 'date'
+require 'set'
require 'bigdecimal'
require 'bigdecimal/util'
@@ -6,6 +7,8 @@ module ActiveRecord
module ConnectionAdapters #:nodoc:
# An abstract definition of a column in a table.
class Column
+ TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE'].to_set
+
module Format
ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/
ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/
@@ -135,11 +138,7 @@ module ActiveRecord
# convert something to a boolean
def value_to_boolean(value)
- if value == true || value == false
- value
- else
- !(value.to_s !~ /\A(?:1|t|true)\Z/i)
- end
+ TRUE_VALUES.include?(value)
end
# convert something to a BigDecimal
--
cgit v1.2.3
From 4e323f6ef09fed146a9302d7b7e3f09934de6e37 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Mon, 14 Jul 2008 11:50:07 -0700
Subject: Fix bad merge
---
actionpack/lib/action_view/template_handlers/compilable.rb | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb
index 2a19fc7628..2b96e7f133 100644
--- a/actionpack/lib/action_view/template_handlers/compilable.rb
+++ b/actionpack/lib/action_view/template_handlers/compilable.rb
@@ -12,8 +12,8 @@ module ActionView
end
end
- def render(template)
- @view.send(:execute, template)
+ def render(template, local_assigns = {})
+ @view.send(:execute, template, local_assigns)
end
# Compile and evaluate the template's code
--
cgit v1.2.3
From c760dbfd3117562c6f27170a213f586e3ba2b794 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Mon, 14 Jul 2008 11:59:46 -0700
Subject: PostgreSQL: don't dump :limit => 4 for integers
---
activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb | 1 -
1 file changed, 1 deletion(-)
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 29ecd83ba0..6d16d72dea 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -49,7 +49,6 @@ module ActiveRecord
private
def extract_limit(sql_type)
case sql_type
- when /^integer/i; 4
when /^bigint/i; 8
when /^smallint/i; 2
else super
--
cgit v1.2.3
From 8f72bc92e20b1242272714f253e23b256761ec1a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tarmo=20T=C3=A4nav?=
Date: Mon, 14 Jul 2008 09:40:05 +0300
Subject: Fixed test_rename_nonexistent_column for PostgreSQL
Also fixed ability to run migration_test.rb alone
[#616 state:resolved]
---
activerecord/test/cases/migration_test.rb | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb
index 4482b487dd..f9a2d9c47c 100644
--- a/activerecord/test/cases/migration_test.rb
+++ b/activerecord/test/cases/migration_test.rb
@@ -3,6 +3,7 @@ require 'bigdecimal/util'
require 'models/person'
require 'models/topic'
+require 'models/developer'
require MIGRATIONS_ROOT + "/valid/1_people_have_last_names"
require MIGRATIONS_ROOT + "/valid/2_we_need_reminders"
@@ -511,7 +512,12 @@ if ActiveRecord::Base.connection.supports_migrations?
ActiveRecord::Base.connection.create_table(:hats) do |table|
table.column :hat_name, :string, :default => nil
end
- assert_raises(ActiveRecord::ActiveRecordError) do
+ exception = if current_adapter?(:PostgreSQLAdapter)
+ ActiveRecord::StatementInvalid
+ else
+ ActiveRecord::ActiveRecordError
+ end
+ assert_raises(exception) do
Person.connection.rename_column "hats", "nonexistent", "should_fail"
end
ensure
--
cgit v1.2.3
From 07578ac85585d3c64d4d38d4892fd31582c7c473 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tarmo=20T=C3=A4nav?=
Date: Mon, 14 Jul 2008 09:42:20 +0300
Subject: Fixed mysql change_column_default to not make the column always
nullable.
Also added change_column_null to both mysql and sqlite to keep the api features closer to postgresql.
[#617 state:resolved]
---
activerecord/CHANGELOG | 2 +
.../connection_adapters/mysql_adapter.rb | 33 +++++++++++----
.../connection_adapters/sqlite_adapter.rb | 9 ++++
activerecord/test/cases/migration_test.rb | 49 ++++++++++++++++++++++
4 files changed, 86 insertions(+), 7 deletions(-)
diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG
index 17430ba0b7..95fdd93f65 100644
--- a/activerecord/CHANGELOG
+++ b/activerecord/CHANGELOG
@@ -1,5 +1,7 @@
*Edge*
+* change_column_default preserves the not-null constraint. #617 [Tarmo Tänav]
+
* Fixed that create database statements would always include "DEFAULT NULL" (Nick Sieger) [#334]
* Add :accessible option to associations for allowing (opt-in) mass assignment. #474. [David Dollar] Example :
diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
index 4b13ac8be0..35b9ed4746 100755
--- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
@@ -437,18 +437,29 @@ module ActiveRecord
end
def change_column_default(table_name, column_name, default) #:nodoc:
- current_type = select_one("SHOW COLUMNS FROM #{quote_table_name(table_name)} LIKE '#{column_name}'")["Type"]
+ column = column_for(table_name, column_name)
+ change_column table_name, column_name, column.sql_type, :default => default
+ end
+
+ def change_column_null(table_name, column_name, null, default = nil)
+ column = column_for(table_name, column_name)
+
+ unless null || default.nil?
+ execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
+ end
- execute("ALTER TABLE #{quote_table_name(table_name)} CHANGE #{quote_column_name(column_name)} #{quote_column_name(column_name)} #{current_type} DEFAULT #{quote(default)}")
+ change_column table_name, column_name, column.sql_type, :null => null
end
def change_column(table_name, column_name, type, options = {}) #:nodoc:
+ column = column_for(table_name, column_name)
+
unless options_include_default?(options)
- if column = columns(table_name).find { |c| c.name == column_name.to_s }
- options[:default] = column.default
- else
- raise "No such column: #{table_name}.#{column_name}"
- end
+ options[:default] = column.default
+ end
+
+ unless options.has_key?(:null)
+ options[:null] = column.null
end
change_column_sql = "ALTER TABLE #{quote_table_name(table_name)} CHANGE #{quote_column_name(column_name)} #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
@@ -460,6 +471,7 @@ module ActiveRecord
options = {}
if column = columns(table_name).find { |c| c.name == column_name.to_s }
options[:default] = column.default
+ options[:null] = column.null
else
raise ActiveRecordError, "No such column: #{table_name}.#{column_name}"
end
@@ -536,6 +548,13 @@ module ActiveRecord
def version
@version ||= @connection.server_info.scan(/^(\d+)\.(\d+)\.(\d+)/).flatten.map { |v| v.to_i }
end
+
+ def column_for(table_name, column_name)
+ unless column = columns(table_name).find { |c| c.name == column_name.to_s }
+ raise "No such column: #{table_name}.#{column_name}"
+ end
+ column
+ end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
index 51cfd10e5c..f4d387cfb4 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
@@ -238,6 +238,15 @@ module ActiveRecord
end
end
+ def change_column_null(table_name, column_name, null, default = nil)
+ unless null || default.nil?
+ execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
+ end
+ alter_table(table_name) do |definition|
+ definition[column_name].null = null
+ end
+ end
+
def change_column(table_name, column_name, type, options = {}) #:nodoc:
alter_table(table_name) do |definition|
include_default = options_include_default?(options)
diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb
index f9a2d9c47c..7ecf755ef8 100644
--- a/activerecord/test/cases/migration_test.rb
+++ b/activerecord/test/cases/migration_test.rb
@@ -703,6 +703,55 @@ if ActiveRecord::Base.connection.supports_migrations?
Person.connection.drop_table :testings rescue nil
end
+ def test_keeping_default_and_notnull_constaint_on_change
+ Person.connection.create_table :testings do |t|
+ t.column :title, :string
+ end
+ person_klass = Class.new(Person)
+ person_klass.set_table_name 'testings'
+
+ person_klass.connection.add_column "testings", "wealth", :integer, :null => false, :default => 99
+ person_klass.reset_column_information
+ assert_equal 99, person_klass.columns_hash["wealth"].default
+ assert_equal false, person_klass.columns_hash["wealth"].null
+ assert_nothing_raised {person_klass.connection.execute("insert into testings (title) values ('tester')")}
+
+ # change column default to see that column doesn't lose its not null definition
+ person_klass.connection.change_column_default "testings", "wealth", 100
+ person_klass.reset_column_information
+ assert_equal 100, person_klass.columns_hash["wealth"].default
+ assert_equal false, person_klass.columns_hash["wealth"].null
+
+ # rename column to see that column doesn't lose its not null and/or default definition
+ person_klass.connection.rename_column "testings", "wealth", "money"
+ person_klass.reset_column_information
+ assert_nil person_klass.columns_hash["wealth"]
+ assert_equal 100, person_klass.columns_hash["money"].default
+ assert_equal false, person_klass.columns_hash["money"].null
+
+ # change column
+ person_klass.connection.change_column "testings", "money", :integer, :null => false, :default => 1000
+ person_klass.reset_column_information
+ assert_equal 1000, person_klass.columns_hash["money"].default
+ assert_equal false, person_klass.columns_hash["money"].null
+
+ # change column, make it nullable and clear default
+ person_klass.connection.change_column "testings", "money", :integer, :null => true, :default => nil
+ person_klass.reset_column_information
+ assert_nil person_klass.columns_hash["money"].default
+ assert_equal true, person_klass.columns_hash["money"].null
+
+ # change_column_null, make it not nullable and set null values to a default value
+ person_klass.connection.execute('UPDATE testings SET money = NULL')
+ person_klass.connection.change_column_null "testings", "money", false, 2000
+ person_klass.reset_column_information
+ assert_nil person_klass.columns_hash["money"].default
+ assert_equal false, person_klass.columns_hash["money"].null
+ assert_equal [2000], Person.connection.select_values("SELECT money FROM testings").map { |s| s.to_i }.sort
+ ensure
+ Person.connection.drop_table :testings rescue nil
+ end
+
def test_change_column_default_to_null
Person.connection.change_column_default "people", "first_name", nil
Person.reset_column_information
--
cgit v1.2.3
From 3fbefecc9cdc0d1a903d6ab76170223166cc69ab Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Mon, 14 Jul 2008 13:47:51 -0700
Subject: Remove dead code from merge
---
.../action_view/template_handlers/compilable.rb | 30 ----------------------
1 file changed, 30 deletions(-)
diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb
index 2b96e7f133..7e45761481 100644
--- a/actionpack/lib/action_view/template_handlers/compilable.rb
+++ b/actionpack/lib/action_view/template_handlers/compilable.rb
@@ -16,36 +16,6 @@ module ActionView
@view.send(:execute, template, local_assigns)
end
- # Compile and evaluate the template's code
- def compile_template(template)
- return false unless recompile_template?(template)
-
- @@mutex.synchronize do
- locals_code = template.locals.keys.map { |key| "#{key} = local_assigns[:#{key}];" }.join
-
- source = <<-end_src
- def #{template.method}(local_assigns)
- old_output_buffer = output_buffer;#{locals_code};#{compile(template)}
- ensure
- self.output_buffer = old_output_buffer
- end
- end_src
-
- begin
- file_name = template.filename || 'compiled-template'
- ActionView::Base::CompiledTemplates.module_eval(source, file_name, 0)
- rescue Exception => e # errors from template code
- if logger = ActionController::Base.logger
- logger.debug "ERROR: compiling #{template.method} RAISED #{e}"
- logger.debug "Function body: #{source}"
- logger.debug "Backtrace: #{e.backtrace.join("\n")}"
- end
-
- raise ActionView::TemplateError.new(template, @view.assigns, e)
- end
- end
- end
-
private
# Method to check whether template compilation is necessary.
# The template will be compiled if the inline template or file has not been compiled yet,
--
cgit v1.2.3
From 2d6562d51b96af518c1eb2947d6d34d5dd5bad12 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Mon, 14 Jul 2008 13:51:59 -0700
Subject: Move dead recompile_template? also
---
actionpack/lib/action_view/renderable.rb | 7 ++-----
actionpack/lib/action_view/template_handlers/compilable.rb | 12 ------------
2 files changed, 2 insertions(+), 17 deletions(-)
diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb
index ebb0f1b674..ffcffd1667 100644
--- a/actionpack/lib/action_view/renderable.rb
+++ b/actionpack/lib/action_view/renderable.rb
@@ -69,11 +69,8 @@ module ActionView
# The template will be compiled if the file has not been compiled yet, or
# if local_assigns has a new key, which isn't supported by the compiled code yet.
def recompile?(symbol)
- unless Base::CompiledTemplates.instance_methods.include?(symbol) && Base.cache_template_loading
- true
- else
- false
- end
+ meth = Base::CompiledTemplates.instance_method(template.method) rescue nil
+ !(meth && Base.cache_template_loading)
end
end
end
diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb
index 7e45761481..a0ebaefeef 100644
--- a/actionpack/lib/action_view/template_handlers/compilable.rb
+++ b/actionpack/lib/action_view/template_handlers/compilable.rb
@@ -15,18 +15,6 @@ module ActionView
def render(template, local_assigns = {})
@view.send(:execute, template, local_assigns)
end
-
- private
- # Method to check whether template compilation is necessary.
- # The template will be compiled if the inline template or file has not been compiled yet,
- # if local_assigns has a new key, which isn't supported by the compiled code yet.
- def recompile_template?(template)
- # Unless the template has been compiled yet, compile
- # If template caching is disabled, compile
- # Always recompile inline templates
- meth = Base::CompiledTemplates.instance_method(template.method) rescue nil
- !meth || !Base.cache_template_loading || template.is_a?(InlineTemplate)
- end
end
end
end
--
cgit v1.2.3
From cd9b24286a90111a08002e0da753198c5fb2432a Mon Sep 17 00:00:00 2001
From: Gabe da Silveira
Date: Tue, 3 Jun 2008 17:50:42 -0300
Subject: Add assert_sql helper method to check for specific SQL output in
Active Record test suite. [#325 state:resolved]
Signed-off-by: Pratik Naik
---
activerecord/lib/active_record/test_case.rb | 15 +++++++++++++--
activerecord/test/cases/helper.rb | 10 +++++-----
2 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/activerecord/lib/active_record/test_case.rb b/activerecord/lib/active_record/test_case.rb
index 7dee962c8a..ca5591ae35 100644
--- a/activerecord/lib/active_record/test_case.rb
+++ b/activerecord/lib/active_record/test_case.rb
@@ -22,11 +22,22 @@ module ActiveRecord
end
end
+ def assert_sql(*patterns_to_match)
+ $queries_executed = []
+ yield
+ ensure
+ failed_patterns = []
+ patterns_to_match.each do |pattern|
+ failed_patterns << pattern unless $queries_executed.any?{ |sql| pattern === sql }
+ end
+ assert failed_patterns.empty?, "Query pattern(s) #{failed_patterns.map(&:inspect).join(', ')} not found."
+ end
+
def assert_queries(num = 1)
- $query_count = 0
+ $queries_executed = []
yield
ensure
- assert_equal num, $query_count, "#{$query_count} instead of #{num} queries were executed."
+ assert_equal num, $queries_executed.size, "#{$queries_executed.size} instead of #{num} queries were executed."
end
def assert_no_queries(&block)
diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb
index dc83300efa..0530ba9bd9 100644
--- a/activerecord/test/cases/helper.rb
+++ b/activerecord/test/cases/helper.rb
@@ -32,13 +32,13 @@ end
ActiveRecord::Base.connection.class.class_eval do
IGNORED_SQL = [/^PRAGMA/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/]
- def execute_with_counting(sql, name = nil, &block)
- $query_count ||= 0
- $query_count += 1 unless IGNORED_SQL.any? { |r| sql =~ r }
- execute_without_counting(sql, name, &block)
+ def execute_with_query_record(sql, name = nil, &block)
+ $queries_executed ||= []
+ $queries_executed << sql unless IGNORED_SQL.any? { |r| sql =~ r }
+ execute_without_query_record(sql, name, &block)
end
- alias_method_chain :execute, :counting
+ alias_method_chain :execute, :query_record
end
# Make with_scope public for tests
--
cgit v1.2.3
From 76df9fa0680d62ce41fa6f3b743c605101d101d2 Mon Sep 17 00:00:00 2001
From: Tiago Macedo
Date: Fri, 11 Jul 2008 04:18:41 +0100
Subject: Fix integer quoting issues in association preload. [#602
state:resolved]
Signed-off-by: Pratik Naik
---
activerecord/lib/active_record/association_preload.rb | 15 ++++++++++++---
activerecord/test/cases/inheritance_test.rb | 7 +++++++
2 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/activerecord/lib/active_record/association_preload.rb b/activerecord/lib/active_record/association_preload.rb
index 49f5270396..174ec95de2 100644
--- a/activerecord/lib/active_record/association_preload.rb
+++ b/activerecord/lib/active_record/association_preload.rb
@@ -188,7 +188,6 @@ module ActiveRecord
through_records
end
- # FIXME: quoting
def preload_belongs_to_association(records, reflection, preload_options={})
options = reflection.options
primary_key_name = reflection.primary_key_name
@@ -227,9 +226,19 @@ module ActiveRecord
table_name = klass.quoted_table_name
primary_key = klass.primary_key
- conditions = "#{table_name}.#{primary_key} IN (?)"
+ conditions = "#{table_name}.#{connection.quote_column_name(primary_key)} IN (?)"
conditions << append_conditions(options, preload_options)
- associated_records = klass.find(:all, :conditions => [conditions, id_map.keys.uniq],
+ column_type = klass.columns.detect{|c| c.name == primary_key}.type
+ ids = id_map.keys.uniq.map do |id|
+ if column_type == :integer
+ id.to_i
+ elsif column_type == :float
+ id.to_f
+ else
+ id
+ end
+ end
+ associated_records = klass.find(:all, :conditions => [conditions, ids],
:include => options[:include],
:select => options[:select],
:joins => options[:joins],
diff --git a/activerecord/test/cases/inheritance_test.rb b/activerecord/test/cases/inheritance_test.rb
index 47fb5c608f..4fd38bfbc9 100755
--- a/activerecord/test/cases/inheritance_test.rb
+++ b/activerecord/test/cases/inheritance_test.rb
@@ -191,6 +191,13 @@ class InheritanceTest < ActiveRecord::TestCase
assert_not_nil account.instance_variable_get("@firm"), "nil proves eager load failed"
end
+ def test_eager_load_belongs_to_primary_key_quoting
+ con = Account.connection
+ assert_sql(/\(#{con.quote_table_name('companies')}.#{con.quote_column_name('id')} IN \(1\)\)/) do
+ Account.find(1, :include => :firm)
+ end
+ end
+
def test_alt_eager_loading
switch_to_alt_inheritance_column
test_eager_load_belongs_to_something_inherited
--
cgit v1.2.3
From 9dc258d6147c8dab772d1f041098a38389cd3e73 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Mon, 14 Jul 2008 17:40:03 -0500
Subject: Eager load Partial variable_name and counter_name. Tidy up
render_partial_collection.
---
actionpack/lib/action_view/partials.rb | 33 +++++++-----------------
actionpack/lib/action_view/renderable.rb | 9 +++++--
actionpack/lib/action_view/renderable_partial.rb | 28 +++++++++++++++++---
actionpack/lib/action_view/template.rb | 24 +++++++----------
4 files changed, 49 insertions(+), 45 deletions(-)
diff --git a/actionpack/lib/action_view/partials.rb b/actionpack/lib/action_view/partials.rb
index 116d61e13b..5aa4c83009 100644
--- a/actionpack/lib/action_view/partials.rb
+++ b/actionpack/lib/action_view/partials.rb
@@ -108,8 +108,7 @@ module ActionView
case partial_path
when String, Symbol, NilClass
- variable_name, path = partial_pieces(partial_path)
- pick_template(path).render_partial(self, variable_name, object_assigns, local_assigns)
+ pick_template(find_partial_path(partial_path)).render_partial(self, object_assigns, local_assigns)
when ActionView::Helpers::FormBuilder
builder_partial_path = partial_path.class.to_s.demodulize.underscore.sub(/_builder$/, '')
render_partial(builder_partial_path, object_assigns, (local_assigns || {}).merge(builder_partial_path.to_sym => partial_path))
@@ -130,43 +129,29 @@ module ActionView
local_assigns = local_assigns ? local_assigns.clone : {}
spacer = partial_spacer_template ? render(:partial => partial_spacer_template) : ''
- _partial_pieces = {}
+ _paths = {}
_templates = {}
index = 0
collection.map do |object|
_partial_path ||= partial_path || ActionController::RecordIdentifier.partial_path(object, controller.class.controller_path)
- variable_name, path = _partial_pieces[_partial_path] ||= partial_pieces(_partial_path)
+ path = _paths[_partial_path] ||= find_partial_path(_partial_path)
template = _templates[path] ||= pick_template(path)
-
- local_assigns["#{variable_name}_counter".to_sym] = index
- local_assigns[:object] = local_assigns[variable_name] = object
- local_assigns[as] = object if as
-
- result = template.render_partial(self, variable_name, object, local_assigns)
-
- local_assigns.delete(as)
- local_assigns.delete(variable_name)
- local_assigns.delete(:object)
+ local_assigns[template.counter_name] = index
+ result = template.render_partial(self, object, local_assigns, as)
index += 1
-
result
end.join(spacer)
end
- def partial_pieces(partial_path)
+ def find_partial_path(partial_path)
if partial_path.include?('/')
- variable_name = File.basename(partial_path)
- path = "#{File.dirname(partial_path)}/_#{variable_name}"
+ "#{File.dirname(partial_path)}/_#{File.basename(partial_path)}"
elsif respond_to?(:controller)
- variable_name = partial_path
- path = "#{controller.class.controller_path}/_#{variable_name}"
+ "#{controller.class.controller_path}/_#{partial_path}"
else
- variable_name = partial_path
- path = "_#{variable_name}"
+ "_#{partial_path}"
end
- variable_name = variable_name.sub(/\..*$/, '').to_sym
- return variable_name, path
end
end
end
diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb
index ffcffd1667..4fda408367 100644
--- a/actionpack/lib/action_view/renderable.rb
+++ b/actionpack/lib/action_view/renderable.rb
@@ -7,16 +7,21 @@ module ActionView
@@mutex = Mutex.new
end
- # NOTE: Exception to earlier notice. Ensure this is called before freeze
def handler
@handler ||= Template.handler_class_for_extension(extension)
end
- # NOTE: Exception to earlier notice. Ensure this is called before freeze
def compiled_source
@compiled_source ||= handler.new(nil).compile(self) if handler.compilable?
end
+ def freeze
+ # Eager load and freeze memoized methods
+ handler.freeze
+ compiled_source.freeze
+ super
+ end
+
def render(view, local_assigns = {})
view._first_render ||= self
view._last_render = self
diff --git a/actionpack/lib/action_view/renderable_partial.rb b/actionpack/lib/action_view/renderable_partial.rb
index 6a17b50a14..250b4e1624 100644
--- a/actionpack/lib/action_view/renderable_partial.rb
+++ b/actionpack/lib/action_view/renderable_partial.rb
@@ -3,16 +3,36 @@ module ActionView
# NOTE: The template that this mixin is beening include into is frozen
# So you can not set or modify any instance variables
+ def variable_name
+ @variable_name ||= name.gsub(/^_/, '').to_sym
+ end
+
+ def counter_name
+ @counter_name ||= "#{variable_name}_counter".to_sym
+ end
+
+ def freeze
+ # Eager load and freeze memoized methods
+ variable_name.freeze
+ counter_name.freeze
+ super
+ end
+
def render(view, local_assigns = {})
ActionController::Base.benchmark("Rendered #{path_without_format_and_extension}", Logger::DEBUG, false) do
super
end
end
- def render_partial(view, variable_name, object = nil, local_assigns = {}, as = nil)
- object ||= view.controller.instance_variable_get("@#{variable_name}") if view.respond_to?(:controller)
- local_assigns[:object] ||= local_assigns[variable_name] ||= object
- local_assigns[as] ||= local_assigns[:object] if as
+ def render_partial(view, object = nil, local_assigns = {}, as = nil)
+ object ||= local_assigns[:object] ||
+ local_assigns[variable_name] ||
+ view.controller.instance_variable_get("@#{variable_name}") if view.respond_to?(:controller)
+
+ # Ensure correct object is reassigned to other accessors
+ local_assigns[:object] = local_assigns[variable_name] = object
+ local_assigns[as] = object if as
+
render_template(view, local_assigns)
end
end
diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb
index 03f9234289..42659efbd4 100644
--- a/actionpack/lib/action_view/template.rb
+++ b/actionpack/lib/action_view/template.rb
@@ -17,19 +17,13 @@ module ActionView #:nodoc:
end
def freeze
- # Eager load memoized methods
- format_and_extension
- path
- path_without_extension
- path_without_format_and_extension
- source
- method_segment
-
- # Eager load memoized methods from Renderable
- handler
- compiled_source
-
- instance_variables.each { |ivar| ivar.freeze }
+ # Eager load and freeze memoized methods
+ format_and_extension.freeze
+ path.freeze
+ path_without_extension.freeze
+ path_without_format_and_extension.freeze
+ source.freeze
+ method_segment.freeze
super
end
@@ -51,12 +45,12 @@ module ActionView #:nodoc:
end
def source
- @source ||= File.read(@filename)
+ @source ||= File.read(filename)
end
def method_segment
unless @method_segment
- segment = File.expand_path(@filename)
+ segment = File.expand_path(filename)
segment.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}/, '') if defined?(RAILS_ROOT)
segment.gsub!(/([^a-zA-Z0-9_])/) { $1.ord }
@method_segment = segment
--
cgit v1.2.3
From d27dd860c7f4f9b9e5aebe7d0c6e9b6108d8717c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tarmo=20T=C3=A4nav?=
Date: Mon, 14 Jul 2008 18:02:59 -0500
Subject: Use sub instead of gsub
Signed-off-by: Joshua Peek
---
actionpack/lib/action_view/renderable_partial.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/actionpack/lib/action_view/renderable_partial.rb b/actionpack/lib/action_view/renderable_partial.rb
index 250b4e1624..7b51eccc27 100644
--- a/actionpack/lib/action_view/renderable_partial.rb
+++ b/actionpack/lib/action_view/renderable_partial.rb
@@ -4,7 +4,7 @@ module ActionView
# So you can not set or modify any instance variables
def variable_name
- @variable_name ||= name.gsub(/^_/, '').to_sym
+ @variable_name ||= name.sub(/\A_/, '').to_sym
end
def counter_name
--
cgit v1.2.3
From 8a9934a9d9fc98b56c4566ae2e3fd4d83e505d3e Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Mon, 14 Jul 2008 19:50:32 -0500
Subject: Added Memoizable mixin for caching simple lazy loaded attributes
---
activesupport/CHANGELOG | 2 ++
activesupport/lib/active_support.rb | 1 +
activesupport/lib/active_support/memoizable.rb | 32 ++++++++++++++++++
activesupport/test/memoizable_test.rb | 45 ++++++++++++++++++++++++++
4 files changed, 80 insertions(+)
create mode 100644 activesupport/lib/active_support/memoizable.rb
create mode 100644 activesupport/test/memoizable_test.rb
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index 983e7d0dac..0c308a1cfe 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,5 +1,7 @@
*Edge*
+* Added Memoizable mixin for caching simple lazy loaded attributes [Josh Peek]
+
* Move the test related core_ext stuff out of core_ext so it's only loaded by the test helpers. [Michael Koziarski]
* Add Inflection rules for String#humanize. #535 [dcmanges]
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index 1a8603e892..0526057b15 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -43,6 +43,7 @@ require 'active_support/ordered_hash'
require 'active_support/ordered_options'
require 'active_support/option_merger'
+require 'active_support/memoizable'
require 'active_support/string_inquirer'
require 'active_support/values/time_zone'
diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb
new file mode 100644
index 0000000000..c78fb0a793
--- /dev/null
+++ b/activesupport/lib/active_support/memoizable.rb
@@ -0,0 +1,32 @@
+module ActiveSupport
+ module Memoizable
+ def self.included(base) #:nodoc:
+ base.extend(ClassMethods)
+ end
+
+ module ClassMethods
+ def memorize(symbol)
+ original_method = "_unmemorized_#{symbol}"
+ alias_method original_method, symbol
+ class_eval <<-EOS, __FILE__, __LINE__
+ def #{symbol}
+ if instance_variable_defined?(:@#{symbol})
+ @#{symbol}
+ else
+ @#{symbol} = #{original_method}
+ end
+ end
+ EOS
+ end
+ end
+
+ def freeze
+ methods.each do |method|
+ if m = method.to_s.match(/^_unmemorized_(.*)/)
+ send(m[1]).freeze
+ end
+ end
+ super
+ end
+ end
+end
diff --git a/activesupport/test/memoizable_test.rb b/activesupport/test/memoizable_test.rb
new file mode 100644
index 0000000000..40a02cf253
--- /dev/null
+++ b/activesupport/test/memoizable_test.rb
@@ -0,0 +1,45 @@
+require 'abstract_unit'
+
+uses_mocha 'Memoizable' do
+ class MemoizableTest < Test::Unit::TestCase
+ class Person
+ include ActiveSupport::Memoizable
+
+ def name
+ fetch_name_from_floppy
+ end
+ memorize :name
+
+ def age
+ nil
+ end
+ memorize :age
+
+ private
+ def fetch_name_from_floppy
+ "Josh"
+ end
+ end
+
+ def test_memoization
+ person = Person.new
+ assert_equal "Josh", person.name
+
+ person.expects(:fetch_name_from_floppy).never
+ 2.times { assert_equal "Josh", person.name }
+ end
+
+ def test_memoized_methods_are_frozen
+ person = Person.new
+ person.freeze
+ assert_equal "Josh", person.name
+ assert_equal true, person.name.frozen?
+ end
+
+ def test_memoization_frozen_with_nil_value
+ person = Person.new
+ person.freeze
+ assert_equal nil, person.age
+ end
+ end
+end
--
cgit v1.2.3
From dd41f66af577947ad420fbd2a44184344ad5c983 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Mon, 14 Jul 2008 19:51:43 -0500
Subject: Include Memoizable in ActionView::Template
---
actionpack/lib/action_view/renderable.rb | 15 ++++-----
actionpack/lib/action_view/renderable_partial.rb | 15 ++++-----
actionpack/lib/action_view/template.rb | 40 +++++++++---------------
3 files changed, 27 insertions(+), 43 deletions(-)
diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb
index 4fda408367..9185045adf 100644
--- a/actionpack/lib/action_view/renderable.rb
+++ b/actionpack/lib/action_view/renderable.rb
@@ -7,20 +7,17 @@ module ActionView
@@mutex = Mutex.new
end
+ include ActiveSupport::Memoizable
+
def handler
- @handler ||= Template.handler_class_for_extension(extension)
+ Template.handler_class_for_extension(extension)
end
+ memorize :handler
def compiled_source
- @compiled_source ||= handler.new(nil).compile(self) if handler.compilable?
- end
-
- def freeze
- # Eager load and freeze memoized methods
- handler.freeze
- compiled_source.freeze
- super
+ handler.new(nil).compile(self) if handler.compilable?
end
+ memorize :compiled_source
def render(view, local_assigns = {})
view._first_render ||= self
diff --git a/actionpack/lib/action_view/renderable_partial.rb b/actionpack/lib/action_view/renderable_partial.rb
index 7b51eccc27..d2fe635b9c 100644
--- a/actionpack/lib/action_view/renderable_partial.rb
+++ b/actionpack/lib/action_view/renderable_partial.rb
@@ -3,20 +3,17 @@ module ActionView
# NOTE: The template that this mixin is beening include into is frozen
# So you can not set or modify any instance variables
+ include ActiveSupport::Memoizable
+
def variable_name
- @variable_name ||= name.sub(/\A_/, '').to_sym
+ name.sub(/\A_/, '').to_sym
end
+ memorize :variable_name
def counter_name
- @counter_name ||= "#{variable_name}_counter".to_sym
- end
-
- def freeze
- # Eager load and freeze memoized methods
- variable_name.freeze
- counter_name.freeze
- super
+ "#{variable_name}_counter".to_sym
end
+ memorize :counter_name
def render(view, local_assigns = {})
ActionController::Base.benchmark("Rendered #{path_without_format_and_extension}", Logger::DEBUG, false) do
diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb
index 42659efbd4..b39ba0c48b 100644
--- a/actionpack/lib/action_view/template.rb
+++ b/actionpack/lib/action_view/template.rb
@@ -1,6 +1,7 @@
module ActionView #:nodoc:
class Template
extend TemplateHandlers
+ include ActiveSupport::Memoizable
include Renderable
attr_accessor :filename, :load_path, :base_path, :name, :format, :extension
@@ -16,48 +17,37 @@ module ActionView #:nodoc:
extend RenderablePartial if @name =~ /^_/
end
- def freeze
- # Eager load and freeze memoized methods
- format_and_extension.freeze
- path.freeze
- path_without_extension.freeze
- path_without_format_and_extension.freeze
- source.freeze
- method_segment.freeze
-
- super
- end
-
def format_and_extension
- @format_and_extension ||= (extensions = [format, extension].compact.join(".")).blank? ? nil : extensions
+ (extensions = [format, extension].compact.join(".")).blank? ? nil : extensions
end
+ memorize :format_and_extension
def path
- @path ||= [base_path, [name, format, extension].compact.join('.')].compact.join('/')
+ [base_path, [name, format, extension].compact.join('.')].compact.join('/')
end
+ memorize :path
def path_without_extension
- @path_without_extension ||= [base_path, [name, format].compact.join('.')].compact.join('/')
+ [base_path, [name, format].compact.join('.')].compact.join('/')
end
+ memorize :path_without_extension
def path_without_format_and_extension
- @path_without_format_and_extension ||= [base_path, name].compact.join('/')
+ [base_path, name].compact.join('/')
end
+ memorize :path_without_format_and_extension
def source
- @source ||= File.read(filename)
+ File.read(filename)
end
+ memorize :source
def method_segment
- unless @method_segment
- segment = File.expand_path(filename)
- segment.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}/, '') if defined?(RAILS_ROOT)
- segment.gsub!(/([^a-zA-Z0-9_])/) { $1.ord }
- @method_segment = segment
- end
-
- @method_segment
+ segment = File.expand_path(filename)
+ segment.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}/, '') if defined?(RAILS_ROOT)
+ segment.gsub!(/([^a-zA-Z0-9_])/) { $1.ord }
end
+ memorize :method_segment
def render_template(view, local_assigns = {})
render(view, local_assigns)
--
cgit v1.2.3
From 001c8beb4d0999a858a8b52ad511ee1251cc3517 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Mon, 14 Jul 2008 20:02:59 -0500
Subject: memorize typo
---
actionpack/lib/action_view/renderable.rb | 4 ++--
actionpack/lib/action_view/renderable_partial.rb | 4 ++--
actionpack/lib/action_view/template.rb | 12 ++++++------
activesupport/lib/active_support/memoizable.rb | 6 +++---
activesupport/test/memoizable_test.rb | 4 ++--
5 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb
index 9185045adf..f66356c939 100644
--- a/actionpack/lib/action_view/renderable.rb
+++ b/actionpack/lib/action_view/renderable.rb
@@ -12,12 +12,12 @@ module ActionView
def handler
Template.handler_class_for_extension(extension)
end
- memorize :handler
+ memoize :handler
def compiled_source
handler.new(nil).compile(self) if handler.compilable?
end
- memorize :compiled_source
+ memoize :compiled_source
def render(view, local_assigns = {})
view._first_render ||= self
diff --git a/actionpack/lib/action_view/renderable_partial.rb b/actionpack/lib/action_view/renderable_partial.rb
index d2fe635b9c..fdb1a5e6a7 100644
--- a/actionpack/lib/action_view/renderable_partial.rb
+++ b/actionpack/lib/action_view/renderable_partial.rb
@@ -8,12 +8,12 @@ module ActionView
def variable_name
name.sub(/\A_/, '').to_sym
end
- memorize :variable_name
+ memoize :variable_name
def counter_name
"#{variable_name}_counter".to_sym
end
- memorize :counter_name
+ memoize :counter_name
def render(view, local_assigns = {})
ActionController::Base.benchmark("Rendered #{path_without_format_and_extension}", Logger::DEBUG, false) do
diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb
index b39ba0c48b..304aec3a4c 100644
--- a/actionpack/lib/action_view/template.rb
+++ b/actionpack/lib/action_view/template.rb
@@ -20,34 +20,34 @@ module ActionView #:nodoc:
def format_and_extension
(extensions = [format, extension].compact.join(".")).blank? ? nil : extensions
end
- memorize :format_and_extension
+ memoize :format_and_extension
def path
[base_path, [name, format, extension].compact.join('.')].compact.join('/')
end
- memorize :path
+ memoize :path
def path_without_extension
[base_path, [name, format].compact.join('.')].compact.join('/')
end
- memorize :path_without_extension
+ memoize :path_without_extension
def path_without_format_and_extension
[base_path, name].compact.join('/')
end
- memorize :path_without_format_and_extension
+ memoize :path_without_format_and_extension
def source
File.read(filename)
end
- memorize :source
+ memoize :source
def method_segment
segment = File.expand_path(filename)
segment.sub!(/^#{Regexp.escape(File.expand_path(RAILS_ROOT))}/, '') if defined?(RAILS_ROOT)
segment.gsub!(/([^a-zA-Z0-9_])/) { $1.ord }
end
- memorize :method_segment
+ memoize :method_segment
def render_template(view, local_assigns = {})
render(view, local_assigns)
diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb
index c78fb0a793..65feca363a 100644
--- a/activesupport/lib/active_support/memoizable.rb
+++ b/activesupport/lib/active_support/memoizable.rb
@@ -5,8 +5,8 @@ module ActiveSupport
end
module ClassMethods
- def memorize(symbol)
- original_method = "_unmemorized_#{symbol}"
+ def memoize(symbol)
+ original_method = "_unmemoized_#{symbol}"
alias_method original_method, symbol
class_eval <<-EOS, __FILE__, __LINE__
def #{symbol}
@@ -22,7 +22,7 @@ module ActiveSupport
def freeze
methods.each do |method|
- if m = method.to_s.match(/^_unmemorized_(.*)/)
+ if m = method.to_s.match(/^_unmemoized_(.*)/)
send(m[1]).freeze
end
end
diff --git a/activesupport/test/memoizable_test.rb b/activesupport/test/memoizable_test.rb
index 40a02cf253..1b6cec2b2f 100644
--- a/activesupport/test/memoizable_test.rb
+++ b/activesupport/test/memoizable_test.rb
@@ -8,12 +8,12 @@ uses_mocha 'Memoizable' do
def name
fetch_name_from_floppy
end
- memorize :name
+ memoize :name
def age
nil
end
- memorize :age
+ memoize :age
private
def fetch_name_from_floppy
--
cgit v1.2.3
From 911c2c381347ffb04615896ee6afe45277eeb103 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tarmo=20T=C3=A4nav?=
Date: Mon, 14 Jul 2008 20:23:23 -0500
Subject: Some performance tweaks to ActiveSupport::Memoizable
Signed-off-by: Joshua Peek
---
activesupport/lib/active_support/memoizable.rb | 6 ++++--
activesupport/test/memoizable_test.rb | 4 ++++
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb
index 65feca363a..5af50df023 100644
--- a/activesupport/lib/active_support/memoizable.rb
+++ b/activesupport/lib/active_support/memoizable.rb
@@ -7,10 +7,12 @@ module ActiveSupport
module ClassMethods
def memoize(symbol)
original_method = "_unmemoized_#{symbol}"
+ raise "Already memoized #{symbol}" if instance_methods.map(&:to_s).include?(original_method)
+
alias_method original_method, symbol
class_eval <<-EOS, __FILE__, __LINE__
def #{symbol}
- if instance_variable_defined?(:@#{symbol})
+ if defined? @#{symbol}
@#{symbol}
else
@#{symbol} = #{original_method}
@@ -22,7 +24,7 @@ module ActiveSupport
def freeze
methods.each do |method|
- if m = method.to_s.match(/^_unmemoized_(.*)/)
+ if m = method.to_s.match(/\A_unmemoized_(.*)/)
send(m[1]).freeze
end
end
diff --git a/activesupport/test/memoizable_test.rb b/activesupport/test/memoizable_test.rb
index 1b6cec2b2f..fc24a2942d 100644
--- a/activesupport/test/memoizable_test.rb
+++ b/activesupport/test/memoizable_test.rb
@@ -41,5 +41,9 @@ uses_mocha 'Memoizable' do
person.freeze
assert_equal nil, person.age
end
+
+ def test_double_memoization
+ assert_raise(RuntimeError) { Person.memoize :name }
+ end
end
end
--
cgit v1.2.3
From 7f0346237e30e55d6cd16a8b4a9dfe4193f61804 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Mon, 14 Jul 2008 20:25:09 -0500
Subject: Append a "_" to memoized instance variables
---
activesupport/lib/active_support/memoizable.rb | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb
index 5af50df023..d06250171a 100644
--- a/activesupport/lib/active_support/memoizable.rb
+++ b/activesupport/lib/active_support/memoizable.rb
@@ -7,15 +7,16 @@ module ActiveSupport
module ClassMethods
def memoize(symbol)
original_method = "_unmemoized_#{symbol}"
+ memoized_ivar = "@_memoized_#{symbol}"
raise "Already memoized #{symbol}" if instance_methods.map(&:to_s).include?(original_method)
alias_method original_method, symbol
class_eval <<-EOS, __FILE__, __LINE__
def #{symbol}
- if defined? @#{symbol}
- @#{symbol}
+ if defined? #{memoized_ivar}
+ #{memoized_ivar}
else
- @#{symbol} = #{original_method}
+ #{memoized_ivar} = #{original_method}
end
end
EOS
--
cgit v1.2.3
From 34510456585216004e483b79beeea3ddc3eb4de6 Mon Sep 17 00:00:00 2001
From: gbuesing
Date: Mon, 14 Jul 2008 23:16:39 -0500
Subject: Fix TimeWithZone unmarshaling: coerce unmarshaled Time instances to
utc, because Ruby's marshaling of Time instances doesn't respect the zone
---
activesupport/CHANGELOG | 2 ++
activesupport/lib/active_support/time_with_zone.rb | 2 +-
activesupport/test/core_ext/time_with_zone_test.rb | 6 ++++++
3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index 0c308a1cfe..a7b33c09ad 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,5 +1,7 @@
*Edge*
+* Fix TimeWithZone unmarshaling: coerce unmarshaled Time instances to utc, because Ruby's marshaling of Time instances doesn't respect the zone [Geoff Buesing]
+
* Added Memoizable mixin for caching simple lazy loaded attributes [Josh Peek]
* Move the test related core_ext stuff out of core_ext so it's only loaded by the test helpers. [Michael Koziarski]
diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb
index 88593eb92d..e85bfe9b2e 100644
--- a/activesupport/lib/active_support/time_with_zone.rb
+++ b/activesupport/lib/active_support/time_with_zone.rb
@@ -263,7 +263,7 @@ module ActiveSupport
end
def marshal_load(variables)
- initialize(variables[0], ::Time.send!(:get_zone, variables[1]), variables[2])
+ initialize(variables[0].utc, ::Time.send!(:get_zone, variables[1]), variables[2].utc)
end
# Ensure proxy class responds to all methods that underlying time instance responds to.
diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb
index ac52a1be0b..dfe04485be 100644
--- a/activesupport/test/core_ext/time_with_zone_test.rb
+++ b/activesupport/test/core_ext/time_with_zone_test.rb
@@ -320,8 +320,11 @@ class TimeWithZoneTest < Test::Unit::TestCase
marshal_str = Marshal.dump(@twz)
mtime = Marshal.load(marshal_str)
assert_equal Time.utc(2000, 1, 1, 0), mtime.utc
+ assert mtime.utc.utc?
assert_equal ActiveSupport::TimeZone['Eastern Time (US & Canada)'], mtime.time_zone
assert_equal Time.utc(1999, 12, 31, 19), mtime.time
+ assert mtime.time.utc?
+ assert_equal @twz.inspect, mtime.inspect
end
end
@@ -331,8 +334,11 @@ class TimeWithZoneTest < Test::Unit::TestCase
marshal_str = Marshal.dump(twz)
mtime = Marshal.load(marshal_str)
assert_equal Time.utc(2000, 1, 1, 0), mtime.utc
+ assert mtime.utc.utc?
assert_equal 'America/New_York', mtime.time_zone.name
assert_equal Time.utc(1999, 12, 31, 19), mtime.time
+ assert mtime.time.utc?
+ assert_equal @twz.inspect, mtime.inspect
end
end
--
cgit v1.2.3
From 8c91b767c0f36e9d767eb230ec42b111e57d90da Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tarmo=20T=C3=A4nav?=
Date: Tue, 15 Jul 2008 05:17:06 +0300
Subject: Fixed postgresql limited eager loading for the case where scoped
:order was present
---
activerecord/lib/active_record/associations.rb | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index d43e07ab4e..7ad7802cbc 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1486,10 +1486,15 @@ module ActiveRecord
join_dependency.joins_for_table_name(table)
}.flatten.compact.uniq
+ order = options[:order]
+ if scoped_order = (scope && scope[:order])
+ order = order ? "#{order}, #{scoped_order}" : scoped_order
+ end
+
is_distinct = !options[:joins].blank? || include_eager_conditions?(options, tables_from_conditions) || include_eager_order?(options, tables_from_order)
sql = "SELECT "
if is_distinct
- sql << connection.distinct("#{connection.quote_table_name table_name}.#{primary_key}", options[:order])
+ sql << connection.distinct("#{connection.quote_table_name table_name}.#{primary_key}", order)
else
sql << primary_key
end
@@ -1503,8 +1508,8 @@ module ActiveRecord
add_conditions!(sql, options[:conditions], scope)
add_group!(sql, options[:group], scope)
- if options[:order] && is_distinct
- connection.add_order_by_for_association_limiting!(sql, options)
+ if order && is_distinct
+ connection.add_order_by_for_association_limiting!(sql, :order => order)
else
add_order!(sql, options[:order], scope)
end
--
cgit v1.2.3
From c1531ae00dbd3ac804bce02733e050ec43400607 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tarmo=20T=C3=A4nav?=
Date: Tue, 15 Jul 2008 05:24:24 +0300
Subject: SQLite: rename_column raises if the column doesn't exist.
[#622 state:resolved]
---
activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb | 3 +++
1 file changed, 3 insertions(+)
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
index f4d387cfb4..84f8c0284e 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
@@ -260,6 +260,9 @@ module ActiveRecord
end
def rename_column(table_name, column_name, new_column_name) #:nodoc:
+ unless columns(table_name).detect{|c| c.name == column_name.to_s }
+ raise ActiveRecord::ActiveRecordError, "Missing column #{table_name}.#{column_name}"
+ end
alter_table(table_name, :rename => {column_name.to_s => new_column_name.to_s})
end
--
cgit v1.2.3
From fc89a951933638b051bb1f9e1339ee6ae7c94cda Mon Sep 17 00:00:00 2001
From: Adrian Mugnolo
Date: Tue, 15 Jul 2008 01:17:03 -0300
Subject: Add in_groups to ActiveSupport::CoreExtensions::Array::Grouping.
[#579 state:resolved]
Signed-off-by: Pratik Naik
---
activesupport/CHANGELOG | 6 +++
.../lib/active_support/core_ext/array/grouping.rb | 47 +++++++++++++++++++-
activesupport/test/core_ext/array_ext_test.rb | 50 ++++++++++++++++++++--
3 files changed, 97 insertions(+), 6 deletions(-)
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index a7b33c09ad..8d3b136d80 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -1,5 +1,11 @@
*Edge*
+* Add Array#in_groups which splits or iterates over the array in specified number of groups. #579. [Adrian Mugnolo] Example:
+
+ a = (1..10).to_a
+ a.in_groups(3) #=> [[1, 2, 3, 4], [5, 6, 7, nil], [8, 9, 10, nil]]
+ a.in_groups(3, false) #=> [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
+
* Fix TimeWithZone unmarshaling: coerce unmarshaled Time instances to utc, because Ruby's marshaling of Time instances doesn't respect the zone [Geoff Buesing]
* Added Memoizable mixin for caching simple lazy loaded attributes [Josh Peek]
diff --git a/activesupport/lib/active_support/core_ext/array/grouping.rb b/activesupport/lib/active_support/core_ext/array/grouping.rb
index 767acc4e07..df37afb053 100644
--- a/activesupport/lib/active_support/core_ext/array/grouping.rb
+++ b/activesupport/lib/active_support/core_ext/array/grouping.rb
@@ -4,8 +4,8 @@ module ActiveSupport #:nodoc:
module CoreExtensions #:nodoc:
module Array #:nodoc:
module Grouping
- # Iterates over the array in groups of size +number+, padding any remaining
- # slots with +fill_with+ unless it is +false+.
+ # Splits or iterates over the array in groups of size +number+,
+ # padding any remaining slots with +fill_with+ unless it is +false+.
#
# %w(1 2 3 4 5 6 7).in_groups_of(3) {|g| p g}
# ["1", "2", "3"]
@@ -39,6 +39,49 @@ module ActiveSupport #:nodoc:
end
end
+ # Splits or iterates over the array in +number+ of groups, padding any
+ # remaining slots with +fill_with+ unless it is +false+.
+ #
+ # %w(1 2 3 4 5 6 7 8 9 10).in_groups(3) {|g| p g}
+ # ["1", "2", "3", "4"]
+ # ["5", "6", "7", nil]
+ # ["8", "9", "10", nil]
+ #
+ # %w(1 2 3 4 5 6 7).in_groups(3, ' ') {|g| p g}
+ # ["1", "2", "3"]
+ # ["4", "5", " "]
+ # ["6", "7", " "]
+ #
+ # %w(1 2 3 4 5 6 7).in_groups(3, false) {|g| p g}
+ # ["1", "2", "3"]
+ # ["4", "5"]
+ # ["6", "7"]
+ def in_groups(number, fill_with = nil)
+ # size / number gives minor group size;
+ # size % number gives how many objects need extra accomodation;
+ # each group hold either division or division + 1 items.
+ division = size / number
+ modulo = size % number
+
+ # create a new array avoiding dup
+ groups = []
+ start = 0
+
+ number.times do |index|
+ length = division + (modulo > 0 && modulo > index ? 1 : 0)
+ padding = fill_with != false &&
+ modulo > 0 && length == division ? 1 : 0
+ groups << slice(start, length).concat([fill_with] * padding)
+ start += length
+ end
+
+ if block_given?
+ groups.each{|g| yield(g) }
+ else
+ groups
+ end
+ end
+
# Divides the array into one or more subarrays based on a delimiting +value+
# or the result of an optional block.
#
diff --git a/activesupport/test/core_ext/array_ext_test.rb b/activesupport/test/core_ext/array_ext_test.rb
index 7563be44f8..62a1f61d53 100644
--- a/activesupport/test/core_ext/array_ext_test.rb
+++ b/activesupport/test/core_ext/array_ext_test.rb
@@ -99,7 +99,7 @@ class ArrayExtToSTests < Test::Unit::TestCase
end
class ArrayExtGroupingTests < Test::Unit::TestCase
- def test_group_by_with_perfect_fit
+ def test_in_groups_of_with_perfect_fit
groups = []
('a'..'i').to_a.in_groups_of(3) do |group|
groups << group
@@ -109,7 +109,7 @@ class ArrayExtGroupingTests < Test::Unit::TestCase
assert_equal [%w(a b c), %w(d e f), %w(g h i)], ('a'..'i').to_a.in_groups_of(3)
end
- def test_group_by_with_padding
+ def test_in_groups_of_with_padding
groups = []
('a'..'g').to_a.in_groups_of(3) do |group|
groups << group
@@ -118,7 +118,7 @@ class ArrayExtGroupingTests < Test::Unit::TestCase
assert_equal [%w(a b c), %w(d e f), ['g', nil, nil]], groups
end
- def test_group_by_pads_with_specified_values
+ def test_in_groups_of_pads_with_specified_values
groups = []
('a'..'g').to_a.in_groups_of(3, 'foo') do |group|
@@ -128,7 +128,7 @@ class ArrayExtGroupingTests < Test::Unit::TestCase
assert_equal [%w(a b c), %w(d e f), ['g', 'foo', 'foo']], groups
end
- def test_group_without_padding
+ def test_in_groups_of_without_padding
groups = []
('a'..'g').to_a.in_groups_of(3, false) do |group|
@@ -137,6 +137,48 @@ class ArrayExtGroupingTests < Test::Unit::TestCase
assert_equal [%w(a b c), %w(d e f), ['g']], groups
end
+
+ def test_in_groups_returned_array_size
+ array = (1..7).to_a
+
+ 1.upto(array.size + 1) do |number|
+ assert_equal number, array.in_groups(number).size
+ end
+ end
+
+ def test_in_groups_with_empty_array
+ assert_equal [[], [], []], [].in_groups(3)
+ end
+
+ def test_in_groups_with_block
+ array = (1..9).to_a
+ groups = []
+
+ array.in_groups(3) do |group|
+ groups << group
+ end
+
+ assert_equal array.in_groups(3), groups
+ end
+
+ def test_in_groups_with_perfect_fit
+ assert_equal [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
+ (1..9).to_a.in_groups(3)
+ end
+
+ def test_in_groups_with_padding
+ array = (1..7).to_a
+
+ assert_equal [[1, 2, 3], [4, 5, nil], [6, 7, nil]],
+ array.in_groups(3)
+ assert_equal [[1, 2, 3], [4, 5, 'foo'], [6, 7, 'foo']],
+ array.in_groups(3, 'foo')
+ end
+
+ def test_in_groups_without_padding
+ assert_equal [[1, 2, 3], [4, 5], [6, 7]],
+ (1..7).to_a.in_groups(3, false)
+ end
end
class ArraySplitTests < Test::Unit::TestCase
--
cgit v1.2.3
From bb33432b0f5bf644713e696e4dafc7e7d3cc5808 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9D=BE=E7=94=B0=20=E6=98=8E?=
Date: Tue, 15 Jul 2008 21:30:20 +0900
Subject: Ruby 1.9 compat: call Proc#binding explicitly. [#623 state:resolved]
---
actionpack/lib/action_view/helpers/tag_helper.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb
index aeafd3906d..e9b6dd6e43 100644
--- a/actionpack/lib/action_view/helpers/tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/tag_helper.rb
@@ -115,7 +115,7 @@ module ActionView
# can't take an <% end %> later on, so we have to use <% ... %>
# and implicitly concat.
def block_called_from_erb?(block)
- block && eval(BLOCK_CALLED_FROM_ERB, block)
+ block && eval(BLOCK_CALLED_FROM_ERB, block.binding)
end
def content_tag_string(name, content, options, escape = true)
--
cgit v1.2.3
From 4d76bad387036d96a955eae7c260a9633e915d11 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Tue, 15 Jul 2008 10:40:33 -0700
Subject: Ruby 1.9 compat: account for different String#hash
---
actionpack/test/template/asset_tag_helper_test.rb | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb
index 020e112fd0..3cfc8fa4ed 100644
--- a/actionpack/test/template/asset_tag_helper_test.rb
+++ b/actionpack/test/template/asset_tag_helper_test.rb
@@ -335,8 +335,9 @@ class AssetTagHelperTest < ActionView::TestCase
ActionController::Base.asset_host = 'http://a%d.example.com'
ActionController::Base.perform_caching = true
+ hash = '/javascripts/cache/money.js'.hash % 4
assert_dom_equal(
- %(),
+ %(),
javascript_include_tag(:all, :cache => "cache/money")
)
--
cgit v1.2.3
From 3c282f3a0a7c1d5ab91241674251794ead5fa41d Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Tue, 15 Jul 2008 10:42:50 -0700
Subject: Ruby 1.9 compat: only eval with block.binding in 1.9, uses more
memory than eval with block
---
actionpack/lib/action_view/helpers/tag_helper.rb | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/actionpack/lib/action_view/helpers/tag_helper.rb b/actionpack/lib/action_view/helpers/tag_helper.rb
index e9b6dd6e43..5a296da247 100644
--- a/actionpack/lib/action_view/helpers/tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/tag_helper.rb
@@ -110,12 +110,18 @@ module ActionView
private
BLOCK_CALLED_FROM_ERB = 'defined? __in_erb_template'
- # Check whether we're called from an erb template.
- # We'd return a string in any other case, but erb <%= ... %>
- # can't take an <% end %> later on, so we have to use <% ... %>
- # and implicitly concat.
- def block_called_from_erb?(block)
- block && eval(BLOCK_CALLED_FROM_ERB, block.binding)
+ if RUBY_VERSION < '1.9.0'
+ # Check whether we're called from an erb template.
+ # We'd return a string in any other case, but erb <%= ... %>
+ # can't take an <% end %> later on, so we have to use <% ... %>
+ # and implicitly concat.
+ def block_called_from_erb?(block)
+ block && eval(BLOCK_CALLED_FROM_ERB, block)
+ end
+ else
+ def block_called_from_erb?(block)
+ block && eval(BLOCK_CALLED_FROM_ERB, block.binding)
+ end
end
def content_tag_string(name, content, options, escape = true)
--
cgit v1.2.3
From 24a8ae4e08fcd15a8c3792990d1d0981d004d339 Mon Sep 17 00:00:00 2001
From: Michael Koziarski
Date: Tue, 15 Jul 2008 20:39:36 +0200
Subject: Try to get more useful errors out of the test_line_offset failures
---
actionpack/test/controller/render_test.rb | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index a857810b78..9a94db4b00 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -101,12 +101,7 @@ class TestController < ActionController::Base
end
def render_line_offset
- begin
- render :inline => '<% raise %>', :locals => {:foo => 'bar'}
- rescue RuntimeError => exc
- end
- line = exc.backtrace.first
- render :text => line
+ render :inline => '<% raise %>', :locals => {:foo => 'bar'}
end
def heading
@@ -238,10 +233,15 @@ class RenderTest < Test::Unit::TestCase
end
def test_line_offset
- get :render_line_offset
- line = @response.body
- assert(line =~ %r{:(\d+):})
- assert_equal "1", $1
+ begin
+ get :render_line_offset
+ flunk "the action should have raised an exception"
+ rescue RuntimeError => exc
+ line = exc.backtrace.first
+ assert(line =~ %r{:(\d+):})
+ assert_equal "1", $1,
+ "The line offset is wrong, perhaps the wrong exception has been raised, exception was: #{exc.inspect}"
+ end
end
def test_render_with_forward_slash
--
cgit v1.2.3
From 4f72feb84c25b54f66c7192c788b7fd965f2d493 Mon Sep 17 00:00:00 2001
From: Jonathan Viney
Date: Wed, 2 Jul 2008 16:01:26 +1200
Subject: Move the transaction counter to the connection object rather than
maintaining it on the current Thread.
Signed-off-by: Michael Koziarski
[#533 state:resolved]
---
.../connection_adapters/abstract_adapter.rb | 13 +++++++++++
activerecord/lib/active_record/fixtures.rb | 8 +++----
activerecord/lib/active_record/transactions.rb | 17 +++------------
activerecord/test/cases/fixtures_test.rb | 6 +++---
activerecord/test/cases/multiple_db_test.rb | 25 ++++++++++++++++++++++
5 files changed, 48 insertions(+), 21 deletions(-)
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
index f48b107a2a..47dbf5a5f3 100755
--- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
@@ -118,6 +118,19 @@ module ActiveRecord
@connection
end
+ def open_transactions
+ @open_transactions ||= 0
+ end
+
+ def increment_open_transactions
+ @open_transactions ||= 0
+ @open_transactions += 1
+ end
+
+ def decrement_open_transactions
+ @open_transactions -= 1
+ end
+
def log_info(sql, name, runtime)
if @logger && @logger.debug?
name = "#{name.nil? ? "SQL" : name} (#{sprintf("%f", runtime)})"
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index 17fb9355c4..622cfc3c3f 100755
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -515,7 +515,7 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
all_loaded_fixtures.update(fixtures_map)
- connection.transaction(Thread.current['open_transactions'].to_i == 0) do
+ connection.transaction(connection.open_transactions.zero?) do
fixtures.reverse.each { |fixture| fixture.delete_existing_fixtures }
fixtures.each { |fixture| fixture.insert_fixtures }
@@ -930,7 +930,7 @@ module Test #:nodoc:
load_fixtures
@@already_loaded_fixtures[self.class] = @loaded_fixtures
end
- ActiveRecord::Base.send :increment_open_transactions
+ ActiveRecord::Base.connection.increment_open_transactions
ActiveRecord::Base.connection.begin_db_transaction
# Load fixtures for every test.
else
@@ -951,9 +951,9 @@ module Test #:nodoc:
end
# Rollback changes if a transaction is active.
- if use_transactional_fixtures? && Thread.current['open_transactions'] != 0
+ if use_transactional_fixtures? && ActiveRecord::Base.connection.open_transactions != 0
ActiveRecord::Base.connection.rollback_db_transaction
- Thread.current['open_transactions'] = 0
+ ActiveRecord::Base.connection.decrement_open_transactions
end
ActiveRecord::Base.verify_active_connections!
end
diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb
index 3b6835762c..354a6c83a2 100644
--- a/activerecord/lib/active_record/transactions.rb
+++ b/activerecord/lib/active_record/transactions.rb
@@ -73,25 +73,14 @@ module ActiveRecord
# trigger a ROLLBACK when raised, but not be re-raised by the transaction block.
module ClassMethods
def transaction(&block)
- increment_open_transactions
+ connection.increment_open_transactions
begin
- connection.transaction(Thread.current['start_db_transaction'], &block)
+ connection.transaction(connection.open_transactions == 1, &block)
ensure
- decrement_open_transactions
+ connection.decrement_open_transactions
end
end
-
- private
- def increment_open_transactions #:nodoc:
- open = Thread.current['open_transactions'] ||= 0
- Thread.current['start_db_transaction'] = open.zero?
- Thread.current['open_transactions'] = open + 1
- end
-
- def decrement_open_transactions #:nodoc:
- Thread.current['open_transactions'] -= 1
- end
end
def transaction(&block)
diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb
index 0ea24868f1..6ba7597f56 100755
--- a/activerecord/test/cases/fixtures_test.rb
+++ b/activerecord/test/cases/fixtures_test.rb
@@ -461,11 +461,11 @@ class FixturesBrokenRollbackTest < ActiveRecord::TestCase
alias_method :teardown, :blank_teardown
def test_no_rollback_in_teardown_unless_transaction_active
- assert_equal 0, Thread.current['open_transactions']
+ assert_equal 0, ActiveRecord::Base.connection.open_transactions
assert_raise(RuntimeError) { ar_setup_fixtures }
- assert_equal 0, Thread.current['open_transactions']
+ assert_equal 0, ActiveRecord::Base.connection.open_transactions
assert_nothing_raised { ar_teardown_fixtures }
- assert_equal 0, Thread.current['open_transactions']
+ assert_equal 0, ActiveRecord::Base.connection.open_transactions
end
private
diff --git a/activerecord/test/cases/multiple_db_test.rb b/activerecord/test/cases/multiple_db_test.rb
index eb3e43c8ac..7c3e0f2ca6 100644
--- a/activerecord/test/cases/multiple_db_test.rb
+++ b/activerecord/test/cases/multiple_db_test.rb
@@ -57,4 +57,29 @@ class MultipleDbTest < ActiveRecord::TestCase
assert Course.connection
end
+
+ def test_transactions_across_databases
+ c1 = Course.find(1)
+ e1 = Entrant.find(1)
+
+ begin
+ Course.transaction do
+ Entrant.transaction do
+ c1.name = "Typo"
+ e1.name = "Typo"
+ c1.save
+ e1.save
+ raise "No I messed up."
+ end
+ end
+ rescue
+ # Yup caught it
+ end
+
+ assert_equal "Typo", c1.name
+ assert_equal "Typo", e1.name
+
+ assert_equal "Ruby Development", Course.find(1).name
+ assert_equal "Ruby Developer", Entrant.find(1).name
+ end
end
--
cgit v1.2.3
From aca246ab25497bb6787d2e18680e9f73ad13d223 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Tue, 15 Jul 2008 14:41:38 -0500
Subject: Get buffer for fragment cache from template's @output_buffer
---
actionpack/CHANGELOG | 2 +
.../lib/action_controller/caching/fragments.rb | 4 +-
actionpack/lib/action_view/helpers/cache_helper.rb | 2 +-
.../lib/action_view/helpers/prototype_helper.rb | 375 +++++++++++----------
actionpack/lib/action_view/template_handler.rb | 4 -
.../lib/action_view/template_handlers/builder.rb | 7 +-
.../lib/action_view/template_handlers/erb.rb | 6 -
.../lib/action_view/template_handlers/rjs.rb | 11 -
actionpack/test/controller/caching_test.rb | 43 +--
actionpack/test/template/javascript_helper_test.rb | 2 +
actionpack/test/template/prototype_helper_test.rb | 2 +-
11 files changed, 198 insertions(+), 260 deletions(-)
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index 5b7bfe9c30..52d00a417c 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,5 +1,7 @@
*Edge*
+* Get buffer for fragment cache from template's @output_buffer [Josh Peek]
+
* Set config.action_view.warn_cache_misses = true to receive a warning if you perform an action that results in an expensive disk operation that could be cached [Josh Peek]
* Refactor template preloading. New abstractions include Renderable mixins and a refactored Template class [Josh Peek]
diff --git a/actionpack/lib/action_controller/caching/fragments.rb b/actionpack/lib/action_controller/caching/fragments.rb
index 57b31ec9d1..b1f25fdf5c 100644
--- a/actionpack/lib/action_controller/caching/fragments.rb
+++ b/actionpack/lib/action_controller/caching/fragments.rb
@@ -60,10 +60,8 @@ module ActionController #:nodoc:
ActiveSupport::Cache.expand_cache_key(key.is_a?(Hash) ? url_for(key).split("://").last : key, :views)
end
- def fragment_for(block, name = {}, options = nil) #:nodoc:
+ def fragment_for(buffer, name = {}, options = nil, &block) #:nodoc:
if perform_caching
- buffer = yield
-
if cache = read_fragment(name, options)
buffer.concat(cache)
else
diff --git a/actionpack/lib/action_view/helpers/cache_helper.rb b/actionpack/lib/action_view/helpers/cache_helper.rb
index 2cdbae6e40..64d1ad2715 100644
--- a/actionpack/lib/action_view/helpers/cache_helper.rb
+++ b/actionpack/lib/action_view/helpers/cache_helper.rb
@@ -32,7 +32,7 @@ module ActionView
# Topics listed alphabetically
# <% end %>
def cache(name = {}, options = nil, &block)
- _last_render.handler.new(@controller).cache_fragment(block, name, options)
+ @controller.fragment_for(output_buffer, name, options, &block)
end
end
end
diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb
index d0c281c803..edb43844a4 100644
--- a/actionpack/lib/action_view/helpers/prototype_helper.rb
+++ b/actionpack/lib/action_view/helpers/prototype_helper.rb
@@ -3,25 +3,25 @@ require 'set'
module ActionView
module Helpers
# Prototype[http://www.prototypejs.org/] is a JavaScript library that provides
- # DOM[http://en.wikipedia.org/wiki/Document_Object_Model] manipulation,
+ # DOM[http://en.wikipedia.org/wiki/Document_Object_Model] manipulation,
# Ajax[http://www.adaptivepath.com/publications/essays/archives/000385.php]
- # functionality, and more traditional object-oriented facilities for JavaScript.
+ # functionality, and more traditional object-oriented facilities for JavaScript.
# This module provides a set of helpers to make it more convenient to call
- # functions from Prototype using Rails, including functionality to call remote
- # Rails methods (that is, making a background request to a Rails action) using Ajax.
- # This means that you can call actions in your controllers without
- # reloading the page, but still update certain parts of it using
+ # functions from Prototype using Rails, including functionality to call remote
+ # Rails methods (that is, making a background request to a Rails action) using Ajax.
+ # This means that you can call actions in your controllers without
+ # reloading the page, but still update certain parts of it using
# injections into the DOM. A common use case is having a form that adds
# a new element to a list without reloading the page or updating a shopping
# cart total when a new item is added.
#
# == Usage
- # To be able to use these helpers, you must first include the Prototype
- # JavaScript framework in your pages.
+ # To be able to use these helpers, you must first include the Prototype
+ # JavaScript framework in your pages.
#
# javascript_include_tag 'prototype'
#
- # (See the documentation for
+ # (See the documentation for
# ActionView::Helpers::JavaScriptHelper for more information on including
# this and other JavaScript files in your Rails templates.)
#
@@ -29,7 +29,7 @@ module ActionView
#
# link_to_remote "Add to cart",
# :url => { :action => "add", :id => product.id },
- # :update => { :success => "cart", :failure => "error" }
+ # :update => { :success => "cart", :failure => "error" }
#
# ...through a form...
#
@@ -50,8 +50,8 @@ module ActionView
# :update => :hits,
# :with => 'query'
# %>
- #
- # As you can see, there are numerous ways to use Prototype's Ajax functions (and actually more than
+ #
+ # As you can see, there are numerous ways to use Prototype's Ajax functions (and actually more than
# are listed here); check out the documentation for each method to find out more about its usage and options.
#
# === Common Options
@@ -63,7 +63,7 @@ module ActionView
# When building your action handlers (that is, the Rails actions that receive your background requests), it's
# important to remember a few things. First, whatever your action would normall return to the browser, it will
# return to the Ajax call. As such, you typically don't want to render with a layout. This call will cause
- # the layout to be transmitted back to your page, and, if you have a full HTML/CSS, will likely mess a lot of things up.
+ # the layout to be transmitted back to your page, and, if you have a full HTML/CSS, will likely mess a lot of things up.
# You can turn the layout off on particular actions by doing the following:
#
# class SiteController < ActionController::Base
@@ -74,8 +74,8 @@ module ActionView
#
# render :layout => false
#
- # You can tell the type of request from within your action using the request.xhr? (XmlHttpRequest, the
- # method that Ajax uses to make background requests) method.
+ # You can tell the type of request from within your action using the request.xhr? (XmlHttpRequest, the
+ # method that Ajax uses to make background requests) method.
# def name
# # Is this an XmlHttpRequest request?
# if (request.xhr?)
@@ -93,7 +93,7 @@ module ActionView
#
# Dropping this in your ApplicationController turns the layout off for every request that is an "xhr" request.
#
- # If you are just returning a little data or don't want to build a template for your output, you may opt to simply
+ # If you are just returning a little data or don't want to build a template for your output, you may opt to simply
# render text output, like this:
#
# render :text => 'Return this from my method!'
@@ -103,7 +103,7 @@ module ActionView
#
# == Updating multiple elements
# See JavaScriptGenerator for information on updating multiple elements
- # on the page in an Ajax response.
+ # on the page in an Ajax response.
module PrototypeHelper
unless const_defined? :CALLBACKS
CALLBACKS = Set.new([ :uninitialized, :loading, :loaded,
@@ -114,64 +114,64 @@ module ActionView
:form, :with, :update, :script ]).merge(CALLBACKS)
end
- # Returns a link to a remote action defined by options[:url]
- # (using the url_for format) that's called in the background using
+ # Returns a link to a remote action defined by options[:url]
+ # (using the url_for format) that's called in the background using
# XMLHttpRequest. The result of that request can then be inserted into a
- # DOM object whose id can be specified with options[:update] .
+ # DOM object whose id can be specified with options[:update] .
# Usually, the result would be a partial prepared by the controller with
- # render :partial.
+ # render :partial.
#
# Examples:
- # # Generates: Delete this post
- # link_to_remote "Delete this post", :update => "posts",
+ # link_to_remote "Delete this post", :update => "posts",
# :url => { :action => "destroy", :id => post.id }
#
- # # Generates:
- # link_to_remote(image_tag("refresh"), :update => "emails",
+ # link_to_remote(image_tag("refresh"), :update => "emails",
# :url => { :action => "list_emails" })
- #
+ #
# You can override the generated HTML options by specifying a hash in
# options[:html] .
- #
+ #
# link_to_remote "Delete this post", :update => "posts",
- # :url => post_url(@post), :method => :delete,
- # :html => { :class => "destructive" }
+ # :url => post_url(@post), :method => :delete,
+ # :html => { :class => "destructive" }
#
# You can also specify a hash for options[:update] to allow for
- # easy redirection of output to an other DOM element if a server-side
+ # easy redirection of output to an other DOM element if a server-side
# error occurs:
#
# Example:
- # # Generates: Delete this post
# link_to_remote "Delete this post",
# :url => { :action => "destroy", :id => post.id },
# :update => { :success => "posts", :failure => "error" }
#
- # Optionally, you can use the options[:position] parameter to
- # influence how the target DOM element is updated. It must be one of
+ # Optionally, you can use the options[:position] parameter to
+ # influence how the target DOM element is updated. It must be one of
# :before , :top , :bottom , or :after .
#
# The method used is by default POST. You can also specify GET or you
# can simulate PUT or DELETE over POST. All specified with options[:method]
#
# Example:
- # # Generates: Destroy
# link_to_remote "Destroy", :url => person_url(:id => person), :method => :delete
#
- # By default, these remote requests are processed asynchronous during
- # which various JavaScript callbacks can be triggered (for progress
- # indicators and the likes). All callbacks get access to the
- # request object, which holds the underlying XMLHttpRequest.
+ # By default, these remote requests are processed asynchronous during
+ # which various JavaScript callbacks can be triggered (for progress
+ # indicators and the likes). All callbacks get access to the
+ # request object, which holds the underlying XMLHttpRequest.
#
# To access the server response, use request.responseText , to
# find out the HTTP status, use request.status .
#
# Example:
- # # Generates: hello
# word = 'hello'
# link_to_remote word,
@@ -180,43 +180,43 @@ module ActionView
#
# The callbacks that may be specified are (in order):
#
- # :loading :: Called when the remote document is being
+ # :loading :: Called when the remote document is being
# loaded with data by the browser.
# :loaded :: Called when the browser has finished loading
# the remote document.
- # :interactive :: Called when the user can interact with the
- # remote document, even though it has not
+ # :interactive :: Called when the user can interact with the
+ # remote document, even though it has not
# finished loading.
# :success :: Called when the XMLHttpRequest is completed,
# and the HTTP status code is in the 2XX range.
# :failure :: Called when the XMLHttpRequest is completed,
# and the HTTP status code is not in the 2XX
# range.
- # :complete :: Called when the XMLHttpRequest is complete
- # (fires after success/failure if they are
+ # :complete :: Called when the XMLHttpRequest is complete
+ # (fires after success/failure if they are
# present).
- #
- # You can further refine :success and :failure by
+ #
+ # You can further refine :success and :failure by
# adding additional callbacks for specific status codes.
#
# Example:
- # # Generates: hello
# link_to_remote word,
# :url => { :action => "action" },
# 404 => "alert('Not found...? Wrong URL...?')",
# :failure => "alert('HTTP Error ' + request.status + '!')"
#
- # A status code callback overrides the success/failure handlers if
+ # A status code callback overrides the success/failure handlers if
# present.
#
# If you for some reason or another need synchronous processing (that'll
- # block the browser while the request is happening), you can specify
+ # block the browser while the request is happening), you can specify
# options[:type] = :synchronous .
#
# You can customize further browser side call logic by passing in
- # JavaScript code snippets via some optional parameters. In their order
+ # JavaScript code snippets via some optional parameters. In their order
# of use these are:
#
# :confirm :: Adds confirmation dialog.
@@ -228,7 +228,7 @@ module ActionView
# :after :: Called immediately after request was
# initiated and before :loading .
# :submit :: Specifies the DOM element ID that's used
- # as the parent of the form elements. By
+ # as the parent of the form elements. By
# default this is the current form, but
# it could just as well be the ID of a
# table row or any other DOM element.
@@ -238,10 +238,10 @@ module ActionView
# URL query string.
#
# Example:
- #
+ #
# :with => "'name=' + $('name').value"
#
- # You can generate a link that uses AJAX in the general case, while
+ # You can generate a link that uses AJAX in the general case, while
# degrading gracefully to plain link behavior in the absence of
# JavaScript by setting html_options[:href] to an alternate URL.
# Note the extra curly braces around the options hash separate
@@ -251,7 +251,7 @@ module ActionView
# link_to_remote "Delete this post",
# { :update => "posts", :url => { :action => "destroy", :id => post.id } },
# :href => url_for(:action => "destroy", :id => post.id)
- def link_to_remote(name, options = {}, html_options = nil)
+ def link_to_remote(name, options = {}, html_options = nil)
link_to_function(name, remote_function(options), html_options || options.delete(:html))
end
@@ -262,15 +262,15 @@ module ActionView
# and defining callbacks is the same as link_to_remote.
# Examples:
# # Call get_averages and put its results in 'avg' every 10 seconds
- # # Generates:
- # # new PeriodicalExecuter(function() {new Ajax.Updater('avg', '/grades/get_averages',
+ # # Generates:
+ # # new PeriodicalExecuter(function() {new Ajax.Updater('avg', '/grades/get_averages',
# # {asynchronous:true, evalScripts:true})}, 10)
# periodically_call_remote(:url => { :action => 'get_averages' }, :update => 'avg')
#
# # Call invoice every 10 seconds with the id of the customer
# # If it succeeds, update the invoice DIV; if it fails, update the error DIV
# # Generates:
- # # new PeriodicalExecuter(function() {new Ajax.Updater({success:'invoice',failure:'error'},
+ # # new PeriodicalExecuter(function() {new Ajax.Updater({success:'invoice',failure:'error'},
# # '/testing/invoice/16', {asynchronous:true, evalScripts:true})}, 10)
# periodically_call_remote(:url => { :action => 'invoice', :id => customer.id },
# :update => { :success => "invoice", :failure => "error" }
@@ -286,11 +286,11 @@ module ActionView
javascript_tag(code)
end
- # Returns a form tag that will submit using XMLHttpRequest in the
- # background instead of the regular reloading POST arrangement. Even
+ # Returns a form tag that will submit using XMLHttpRequest in the
+ # background instead of the regular reloading POST arrangement. Even
# though it's using JavaScript to serialize the form elements, the form
# submission will work just like a regular submission as viewed by the
- # receiving side (all elements available in params ). The options for
+ # receiving side (all elements available in params ). The options for
# specifying the target with :url and defining callbacks is the same as
# +link_to_remote+.
#
@@ -299,21 +299,21 @@ module ActionView
#
# Example:
# # Generates:
- # #
# <% form_remote_tag :url => '/posts' do -%>
@@ -323,19 +323,19 @@ module ActionView
options[:form] = true
options[:html] ||= {}
- options[:html][:onsubmit] =
- (options[:html][:onsubmit] ? options[:html][:onsubmit] + "; " : "") +
+ options[:html][:onsubmit] =
+ (options[:html][:onsubmit] ? options[:html][:onsubmit] + "; " : "") +
"#{remote_function(options)}; return false;"
form_tag(options[:html].delete(:action) || url_for(options[:url]), options[:html], &block)
end
- # Creates a form that will submit using XMLHttpRequest in the background
- # instead of the regular reloading POST arrangement and a scope around a
+ # Creates a form that will submit using XMLHttpRequest in the background
+ # instead of the regular reloading POST arrangement and a scope around a
# specific resource that is used as a base for questioning about
- # values for the fields.
+ # values for the fields.
#
- # === Resource
+ # === Resource
#
# Example:
# <% remote_form_for(@post) do |f| %>
@@ -348,7 +348,7 @@ module ActionView
# ...
# <% end %>
#
- # === Nested Resource
+ # === Nested Resource
#
# Example:
# <% remote_form_for([@post, @comment]) do |f| %>
@@ -387,23 +387,23 @@ module ActionView
concat('')
end
alias_method :form_remote_for, :remote_form_for
-
+
# Returns a button input tag with the element name of +name+ and a value (i.e., display text) of +value+
# that will submit form using XMLHttpRequest in the background instead of a regular POST request that
- # reloads the page.
+ # reloads the page.
#
# # Create a button that submits to the create action
- # #
- # # Generates:
# <%= button_to_remote 'create_btn', 'Create', :url => { :action => 'create' } %>
#
# # Submit to the remote action update and update the DIV succeed or fail based
# # on the success or failure of the request
# #
- # # Generates:
# <%= button_to_remote 'update_btn', 'Update', :url => { :action => 'update' },
# :update => { :success => "succeed", :failure => "fail" }
@@ -423,7 +423,7 @@ module ActionView
tag("input", options[:html], false)
end
alias_method :submit_to_remote, :button_to_remote
-
+
# Returns 'eval(request.responseText) ' which is the JavaScript function
# that +form_remote_tag+ can call in :complete to evaluate a multiple
# update return document using +update_element_function+ calls.
@@ -433,11 +433,11 @@ module ActionView
# Returns the JavaScript needed for a remote function.
# Takes the same arguments as link_to_remote.
- #
+ #
# Example:
- # # Generates:
- # { :action => :update_options }) %>">
# Hello
# World
@@ -455,7 +455,7 @@ module ActionView
update << "'#{options[:update]}'"
end
- function = update.empty? ?
+ function = update.empty? ?
"new Ajax.Request(" :
"new Ajax.Updater(#{update}, "
@@ -476,9 +476,9 @@ module ActionView
# callback when its contents have changed. The default callback is an
# Ajax call. By default the value of the observed field is sent as a
# parameter with the Ajax call.
- #
+ #
# Example:
- # # Generates: new Form.Element.Observer('suggest', 0.25, function(element, value) {new Ajax.Updater('suggest',
+ # # Generates: new Form.Element.Observer('suggest', 0.25, function(element, value) {new Ajax.Updater('suggest',
# # '/testing/find_suggestion', {asynchronous:true, evalScripts:true, parameters:'q=' + value})})
# <%= observe_field :suggest, :url => { :action => :find_suggestion },
# :frequency => 0.25,
@@ -500,14 +500,14 @@ module ActionView
# new Form.Element.Observer('glass', 1, function(element, value) {alert('Element changed')})
# The element parameter is the DOM element being observed, and the value is its value at the
# time the observer is triggered.
- #
+ #
# Additional options are:
# :frequency :: The frequency (in seconds) at which changes to
# this field will be detected. Not setting this
# option at all or to a value equal to or less than
# zero will use event based observation instead of
# time based observation.
- # :update :: Specifies the DOM ID of the element whose
+ # :update :: Specifies the DOM ID of the element whose
# innerHTML should be updated with the
# XMLHttpRequest response text.
# :with :: A JavaScript expression specifying the parameters
@@ -518,7 +518,7 @@ module ActionView
# variable +value+.
#
# Examples
- #
+ #
# :with => "'my_custom_key=' + value"
# :with => "'person[name]=' + prompt('New name')"
# :with => "Form.Element.serialize('other-field')"
@@ -544,7 +544,7 @@ module ActionView
# observe_field 'book_title',
# :url => 'http://example.com/books/edit/1',
# :with => 'title'
- #
+ #
# # Sends params: {:book_title => 'Title of the book'} when the focus leaves
# # the input field.
# observe_field 'book_title',
@@ -558,7 +558,7 @@ module ActionView
build_observer('Form.Element.EventObserver', field_id, options)
end
end
-
+
# Observes the form with the DOM ID specified by +form_id+ and calls a
# callback when its contents have changed. The default callback is an
# Ajax call. By default all fields of the observed field are sent as
@@ -574,16 +574,17 @@ module ActionView
build_observer('Form.EventObserver', form_id, options)
end
end
-
- # All the methods were moved to GeneratorMethods so that
+
+ # All the methods were moved to GeneratorMethods so that
# #include_helpers_from_context has nothing to overwrite.
class JavaScriptGenerator #:nodoc:
def initialize(context, &block) #:nodoc:
@context, @lines = context, []
+ @context.output_buffer = @lines if @context
include_helpers_from_context
@context.instance_exec(self, &block)
end
-
+
private
def include_helpers_from_context
@context.extended_by.each do |mod|
@@ -591,17 +592,17 @@ module ActionView
end
extend GeneratorMethods
end
-
- # JavaScriptGenerator generates blocks of JavaScript code that allow you
- # to change the content and presentation of multiple DOM elements. Use
+
+ # JavaScriptGenerator generates blocks of JavaScript code that allow you
+ # to change the content and presentation of multiple DOM elements. Use
# this in your Ajax response bodies, either in a \n\n\n\n), javascript_include_tag(:defaults))
--
cgit v1.2.3
From 1e0f94a77c717dd06a86edda97de5a4c4ad919a8 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Thu, 17 Jul 2008 14:45:14 -0700
Subject: Introduce simple internationalization support
---
actionpack/test/i18n_coverage | 9 ---------
activerecord/test/i18n_coverage | 6 ------
railties/CHANGELOG | 2 ++
3 files changed, 2 insertions(+), 15 deletions(-)
delete mode 100755 actionpack/test/i18n_coverage
delete mode 100755 activerecord/test/i18n_coverage
diff --git a/actionpack/test/i18n_coverage b/actionpack/test/i18n_coverage
deleted file mode 100755
index 57b54e9d47..0000000000
--- a/actionpack/test/i18n_coverage
+++ /dev/null
@@ -1,9 +0,0 @@
-rcov -x abstract_unit.rb \
--i action_view/helpers/number_helper.rb,action_view/helpers/date_helper.rb,action_view/helpers/active_record_helper.rb \
-template/number_helper_i18n_test.rb \
-template/date_helper_i18n_test.rb \
-template/active_record_helper_i18n_test.rb \
-
-# template/number_helper_test.rb \
-# template/date_helper_test.rb \
-# template/active_record_helper_test.rb
\ No newline at end of file
diff --git a/activerecord/test/i18n_coverage b/activerecord/test/i18n_coverage
deleted file mode 100755
index 1589a6c06f..0000000000
--- a/activerecord/test/i18n_coverage
+++ /dev/null
@@ -1,6 +0,0 @@
-rcov -I connections/native_mysql \
--x cases/helper,config,connection,models \
--i active_record/validations.rb \
-cases/validations_i18n_test.rb \
-
-# cases/validations_test.rb
\ No newline at end of file
diff --git a/railties/CHANGELOG b/railties/CHANGELOG
index b5c5aba460..9c5e5b59c6 100644
--- a/railties/CHANGELOG
+++ b/railties/CHANGELOG
@@ -1,5 +1,7 @@
*Edge*
+* Introduce simple internationalization support. [Ruby i18n team]
+
* Make script/plugin install -r option work with git based plugins. #257. [Tim Pope Jakub Kuźma]. Example:
script/plugin install git://github.com/mislav/will_paginate.git -r agnostic # Installs 'agnostic' branch
--
cgit v1.2.3
From a1fcbd971d681e44de5ea33e6a8470ff8b8144c0 Mon Sep 17 00:00:00 2001
From: Joachim Garth
Date: Fri, 27 Jun 2008 20:03:51 +0200
Subject: Make sure association preloading works with full STI class name [#465
state:Resolved]
Signed-off-by: Pratik Naik
---
.../lib/active_record/association_preload.rb | 2 +-
.../eager_load_includes_full_sti_class_test.rb | 36 ++++++++++++++++++++++
2 files changed, 37 insertions(+), 1 deletion(-)
create mode 100644 activerecord/test/cases/associations/eager_load_includes_full_sti_class_test.rb
diff --git a/activerecord/lib/active_record/association_preload.rb b/activerecord/lib/active_record/association_preload.rb
index 64888f9110..c7594809b7 100644
--- a/activerecord/lib/active_record/association_preload.rb
+++ b/activerecord/lib/active_record/association_preload.rb
@@ -252,7 +252,7 @@ module ActiveRecord
table_name = reflection.klass.quoted_table_name
if interface = reflection.options[:as]
- conditions = "#{reflection.klass.quoted_table_name}.#{connection.quote_column_name "#{interface}_id"} IN (?) and #{reflection.klass.quoted_table_name}.#{connection.quote_column_name "#{interface}_type"} = '#{self.base_class.name.demodulize}'"
+ conditions = "#{reflection.klass.quoted_table_name}.#{connection.quote_column_name "#{interface}_id"} IN (?) and #{reflection.klass.quoted_table_name}.#{connection.quote_column_name "#{interface}_type"} = '#{self.base_class.sti_name}'"
else
foreign_key = reflection.primary_key_name
conditions = "#{reflection.klass.quoted_table_name}.#{foreign_key} IN (?)"
diff --git a/activerecord/test/cases/associations/eager_load_includes_full_sti_class_test.rb b/activerecord/test/cases/associations/eager_load_includes_full_sti_class_test.rb
new file mode 100644
index 0000000000..7c470616a5
--- /dev/null
+++ b/activerecord/test/cases/associations/eager_load_includes_full_sti_class_test.rb
@@ -0,0 +1,36 @@
+require 'cases/helper'
+require 'models/post'
+require 'models/tagging'
+
+module Namespaced
+ class Post < ActiveRecord::Base
+ set_table_name 'posts'
+ has_one :tagging, :as => :taggable, :class_name => 'Tagging'
+ end
+end
+
+class EagerLoadIncludeFullStiClassNamesTest < ActiveRecord::TestCase
+
+ def setup
+ generate_test_objects
+ end
+
+ def generate_test_objects
+ post = Namespaced::Post.create( :title => 'Great stuff', :body => 'This is not', :author_id => 1 )
+ tagging = Tagging.create( :taggable => post )
+ end
+
+ def test_class_names
+ old = ActiveRecord::Base.store_full_sti_class
+
+ ActiveRecord::Base.store_full_sti_class = false
+ post = Namespaced::Post.find_by_title( 'Great stuff', :include => :tagging )
+ assert_nil post.tagging
+
+ ActiveRecord::Base.store_full_sti_class = true
+ post = Namespaced::Post.find_by_title( 'Great stuff', :include => :tagging )
+ assert_equal 'Tagging', post.tagging.class.name
+ ensure
+ ActiveRecord::Base.store_full_sti_class = old
+ end
+end
--
cgit v1.2.3
From 57a2780f14447152ece1b1301fc6c25b2ec43da5 Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 16 Jul 2008 04:32:15 -0700
Subject: etag! and last_modified! conditional GET helpers
---
actionpack/CHANGELOG | 4 +
actionpack/lib/action_controller/base.rb | 15 ++-
actionpack/lib/action_controller/response.rb | 40 +++++--
actionpack/test/controller/render_test.rb | 152 +++++++++++++++++----------
4 files changed, 150 insertions(+), 61 deletions(-)
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index da9fdbfd9d..f6432fe0be 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,5 +1,9 @@
*Edge*
+* Conditional GET utility methods. [Jeremy Kemper]
+ * etag!([:admin, post, current_user]) sets the ETag response header and returns head(:not_modified) if it matches the If-None-Match request header.
+ * last_modified!(post.updated_at) sets Last-Modified and returns head(:not_modified) if it's no later than If-Modified-Since.
+
* All 2xx requests are considered successful [Josh Peek]
* Fixed that AssetTagHelper#compute_public_path shouldn't cache the asset_host along with the source or per-request proc's won't run [DHH]
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index c56812c2d9..50727c67c4 100755
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -519,6 +519,8 @@ module ActionController #:nodoc:
public
# Extracts the action_name from the request parameters and performs that action.
def process(request, response, method = :perform_action, *arguments) #:nodoc:
+ response.request = request
+
initialize_template_class(response)
assign_shortcuts(request, response)
initialize_current_url
@@ -529,8 +531,6 @@ module ActionController #:nodoc:
send(method, *arguments)
assign_default_content_type_and_charset
-
- response.request = request
response.prepare! unless component_request?
response
ensure
@@ -968,6 +968,17 @@ module ActionController #:nodoc:
render :nothing => true, :status => status
end
+ # Sets the Last-Modified response header. Returns 304 Not Modified if the
+ # If-Modified-Since request header is <= last modified.
+ def last_modified!(utc_time)
+ head(:not_modified) if response.last_modified!(utc_time)
+ end
+
+ # Sets the ETag response header. Returns 304 Not Modified if the
+ # If-None-Match request header matches.
+ def etag!(etag)
+ head(:not_modified) if response.etag!(etag)
+ end
# Clears the rendered results, allowing for another render to be performed.
def erase_render_results #:nodoc:
diff --git a/actionpack/lib/action_controller/response.rb b/actionpack/lib/action_controller/response.rb
index 1d9f6676ba..9955532844 100755
--- a/actionpack/lib/action_controller/response.rb
+++ b/actionpack/lib/action_controller/response.rb
@@ -41,20 +41,48 @@ module ActionController
set_content_length!
end
+ # Sets the Last-Modified response header. Returns whether it's older than
+ # the If-Modified-Since request header.
+ def last_modified!(utc_time)
+ headers['Last-Modified'] ||= utc_time.httpdate
+ if request && since = request.headers['HTTP_IF_MODIFIED_SINCE']
+ utc_time <= Time.rfc2822(since)
+ end
+ end
+
+ # Sets the ETag response header. Returns whether it matches the
+ # If-None-Match request header.
+ def etag!(tag)
+ headers['ETag'] ||= %("#{Digest::MD5.hexdigest(ActiveSupport::Cache.expand_cache_key(tag))}")
+ if request && request.headers['HTTP_IF_NONE_MATCH'] == headers['ETag']
+ true
+ end
+ end
private
def handle_conditional_get!
- if body.is_a?(String) && (headers['Status'] ? headers['Status'][0..2] == '200' : true) && !body.empty?
- self.headers['ETag'] ||= %("#{Digest::MD5.hexdigest(body)}")
- self.headers['Cache-Control'] = 'private, max-age=0, must-revalidate' if headers['Cache-Control'] == DEFAULT_HEADERS['Cache-Control']
+ if nonempty_ok_response?
+ set_conditional_cache_control!
- if request.headers['HTTP_IF_NONE_MATCH'] == headers['ETag']
- self.headers['Status'] = '304 Not Modified'
+ if etag!(body)
+ headers['Status'] = '304 Not Modified'
self.body = ''
end
end
end
+ def nonempty_ok_response?
+ status = headers['Status']
+ ok = !status || status[0..2] == '200'
+ ok && body.is_a?(String) && !body.empty?
+ end
+
+ def set_conditional_cache_control!
+ if headers['Cache-Control'] == DEFAULT_HEADERS['Cache-Control']
+ headers['Cache-Control'] = 'private, max-age=0, must-revalidate'
+ end
+ end
+
def convert_content_type!
if content_type = headers.delete("Content-Type")
self.headers["type"] = content_type
@@ -73,4 +101,4 @@ module ActionController
self.headers["Content-Length"] = body.size unless body.respond_to?(:call)
end
end
-end
\ No newline at end of file
+end
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index 9a94db4b00..041c54c7fd 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -8,14 +8,18 @@ module Fun
end
end
-
-# FIXME: crashes Ruby 1.9
class TestController < ActionController::Base
layout :determine_layout
def hello_world
end
+ def conditional_hello
+ etag! [:foo, 123]
+ last_modified! Time.now.utc.beginning_of_day
+ render :action => 'hello_world' unless performed?
+ end
+
def render_hello_world
render :template => "test/hello_world"
end
@@ -408,6 +412,72 @@ class RenderTest < Test::Unit::TestCase
assert_equal "Goodbye, Local David", @response.body
end
+ def test_should_render_formatted_template
+ get :formatted_html_erb
+ assert_equal 'formatted html erb', @response.body
+ end
+
+ def test_should_render_formatted_xml_erb_template
+ get :formatted_xml_erb, :format => :xml
+ assert_equal 'passed formatted xml erb ', @response.body
+ end
+
+ def test_should_render_formatted_html_erb_template
+ get :formatted_xml_erb
+ assert_equal 'passed formatted html erb ', @response.body
+ end
+
+ def test_should_render_formatted_html_erb_template_with_faulty_accepts_header
+ @request.env["HTTP_ACCEPT"] = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, appliction/x-shockwave-flash, */*"
+ get :formatted_xml_erb
+ assert_equal 'passed formatted html erb ', @response.body
+ end
+
+ def test_should_render_html_formatted_partial
+ get :partial
+ assert_equal 'partial html', @response.body
+ end
+
+ def test_should_render_html_partial_with_dot
+ get :partial_dot_html
+ assert_equal 'partial html', @response.body
+ end
+
+ def test_should_render_html_formatted_partial_with_rjs
+ xhr :get, :partial_as_rjs
+ assert_equal %(Element.replace("foo", "partial html");), @response.body
+ end
+
+ def test_should_render_html_formatted_partial_with_rjs_and_js_format
+ xhr :get, :respond_to_partial_as_rjs
+ assert_equal %(Element.replace("foo", "partial html");), @response.body
+ end
+
+ def test_should_render_js_partial
+ xhr :get, :partial, :format => 'js'
+ assert_equal 'partial js', @response.body
+ end
+
+ def test_should_render_with_alternate_default_render
+ xhr :get, :render_alternate_default
+ assert_equal %(Element.replace("foo", "partial html");), @response.body
+ end
+
+ def test_should_render_xml_but_keep_custom_content_type
+ get :render_xml_with_custom_content_type
+ assert_equal "application/atomsvc+xml", @response.content_type
+ end
+end
+
+class EtagRenderTest < Test::Unit::TestCase
+ def setup
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
+ @controller = TestController.new
+
+ @request.host = "www.nextangle.com"
+ end
+
def test_render_200_should_set_etag
get :render_hello_world_from_variable
assert_equal etag_for("hello david"), @response.headers['ETag']
@@ -460,64 +530,40 @@ class RenderTest < Test::Unit::TestCase
assert_equal etag_for("\n\n Hello
\nThis is grand!
\n\n \n"), @response.headers['ETag']
end
- def test_should_render_formatted_template
- get :formatted_html_erb
- assert_equal 'formatted html erb', @response.body
- end
-
- def test_should_render_formatted_xml_erb_template
- get :formatted_xml_erb, :format => :xml
- assert_equal 'passed formatted xml erb ', @response.body
- end
-
- def test_should_render_formatted_html_erb_template
- get :formatted_xml_erb
- assert_equal 'passed formatted html erb ', @response.body
- end
-
- def test_should_render_formatted_html_erb_template_with_faulty_accepts_header
- @request.env["HTTP_ACCEPT"] = "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, appliction/x-shockwave-flash, */*"
- get :formatted_xml_erb
- assert_equal 'passed formatted html erb ', @response.body
- end
-
- def test_should_render_html_formatted_partial
- get :partial
- assert_equal 'partial html', @response.body
- end
-
- def test_should_render_html_partial_with_dot
- get :partial_dot_html
- assert_equal 'partial html', @response.body
- end
+ protected
+ def etag_for(text)
+ %("#{Digest::MD5.hexdigest(text)}")
+ end
+end
- def test_should_render_html_formatted_partial_with_rjs
- xhr :get, :partial_as_rjs
- assert_equal %(Element.replace("foo", "partial html");), @response.body
- end
+class LastModifiedRenderTest < Test::Unit::TestCase
+ def setup
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
+ @controller = TestController.new
- def test_should_render_html_formatted_partial_with_rjs_and_js_format
- xhr :get, :respond_to_partial_as_rjs
- assert_equal %(Element.replace("foo", "partial html");), @response.body
+ @request.host = "www.nextangle.com"
+ @last_modified = Time.now.utc.beginning_of_day.httpdate
end
- def test_should_render_js_partial
- xhr :get, :partial, :format => 'js'
- assert_equal 'partial js', @response.body
+ def test_responds_with_last_modified
+ get :conditional_hello
+ assert_equal @last_modified, @response.headers['Last-Modified']
end
- def test_should_render_with_alternate_default_render
- xhr :get, :render_alternate_default
- assert_equal %(Element.replace("foo", "partial html");), @response.body
+ def test_request_not_modified
+ @request.headers["HTTP_IF_MODIFIED_SINCE"] = @last_modified
+ get :conditional_hello
+ assert_equal "304 Not Modified", @response.headers['Status']
+ assert @response.body.blank?, @response.body
+ assert_equal @last_modified, @response.headers['Last-Modified']
end
- def test_should_render_xml_but_keep_custom_content_type
- get :render_xml_with_custom_content_type
- assert_equal "application/atomsvc+xml", @response.content_type
+ def test_request_modified
+ @request.headers["HTTP_IF_MODIFIED_SINCE"] = 'Thu, 16 Jul 2008 00:00:00 GMT'
+ get :conditional_hello
+ assert_equal "200 OK", @response.headers['Status']
+ assert !@response.body.blank?
+ assert_equal @last_modified, @response.headers['Last-Modified']
end
-
- protected
- def etag_for(text)
- %("#{Digest::MD5.hexdigest(text)}")
- end
end
--
cgit v1.2.3
From 7430c4168fad07b480dbf80c8ac75ba7db8c634f Mon Sep 17 00:00:00 2001
From: Jeremy Kemper
Date: Wed, 16 Jul 2008 22:27:04 -0700
Subject: Decrease default benchmark runs from 10 to 4
---
activesupport/lib/active_support/testing/performance.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb
index 5f2027eb3b..71d6f4d9c6 100644
--- a/activesupport/lib/active_support/testing/performance.rb
+++ b/activesupport/lib/active_support/testing/performance.rb
@@ -11,7 +11,7 @@ module ActiveSupport
DEFAULTS =
if benchmark = ARGV.include?('--benchmark') # HAX for rake test
{ :benchmark => true,
- :runs => 10,
+ :runs => 4,
:metrics => [:process_time, :memory, :objects, :gc_runs, :gc_time],
:output => 'tmp/performance' }
else
--
cgit v1.2.3
From e1f23da53cef20a60e4bf458d959fe2bfe7d52ea Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Fri, 18 Jul 2008 11:18:16 -0500
Subject: Allow memoized methods to be reloaded and allow multiple symbols
---
activesupport/lib/active_support/memoizable.rb | 32 +++++++++++----------
activesupport/test/memoizable_test.rb | 39 +++++++++++++++++---------
2 files changed, 43 insertions(+), 28 deletions(-)
diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb
index d06250171a..c41feef4c7 100644
--- a/activesupport/lib/active_support/memoizable.rb
+++ b/activesupport/lib/active_support/memoizable.rb
@@ -5,28 +5,30 @@ module ActiveSupport
end
module ClassMethods
- def memoize(symbol)
- original_method = "_unmemoized_#{symbol}"
- memoized_ivar = "@_memoized_#{symbol}"
- raise "Already memoized #{symbol}" if instance_methods.map(&:to_s).include?(original_method)
+ def memoize(*symbols)
+ symbols.each do |symbol|
+ original_method = "unmemoized_#{symbol}"
+ memoized_ivar = "@#{symbol}"
+ raise "Already memoized #{symbol}" if instance_methods.map(&:to_s).include?(original_method)
- alias_method original_method, symbol
- class_eval <<-EOS, __FILE__, __LINE__
- def #{symbol}
- if defined? #{memoized_ivar}
- #{memoized_ivar}
- else
- #{memoized_ivar} = #{original_method}
+ alias_method original_method, symbol
+ class_eval <<-EOS, __FILE__, __LINE__
+ def #{symbol}(reload = false)
+ if !reload && defined? #{memoized_ivar}
+ #{memoized_ivar}
+ else
+ #{memoized_ivar} = #{original_method}.freeze
+ end
end
- end
- EOS
+ EOS
+ end
end
end
def freeze
methods.each do |method|
- if m = method.to_s.match(/\A_unmemoized_(.*)/)
- send(m[1]).freeze
+ if m = method.to_s.match(/\Aunmemoized_(.*)/)
+ send(m[1])
end
end
super
diff --git a/activesupport/test/memoizable_test.rb b/activesupport/test/memoizable_test.rb
index fc24a2942d..b649b31455 100644
--- a/activesupport/test/memoizable_test.rb
+++ b/activesupport/test/memoizable_test.rb
@@ -8,12 +8,16 @@ uses_mocha 'Memoizable' do
def name
fetch_name_from_floppy
end
- memoize :name
def age
nil
end
- memoize :age
+
+ def random
+ rand(0)
+ end
+
+ memoize :name, :age, :random
private
def fetch_name_from_floppy
@@ -21,25 +25,34 @@ uses_mocha 'Memoizable' do
end
end
+ def setup
+ @person = Person.new
+ end
+
def test_memoization
- person = Person.new
- assert_equal "Josh", person.name
+ assert_equal "Josh", @person.name
+
+ @person.expects(:fetch_name_from_floppy).never
+ 2.times { assert_equal "Josh", @person.name }
+ end
- person.expects(:fetch_name_from_floppy).never
- 2.times { assert_equal "Josh", person.name }
+ def test_reloadable
+ random = @person.random
+ assert_equal random, @person.random
+ assert_not_equal random, @person.random(:reload)
end
def test_memoized_methods_are_frozen
- person = Person.new
- person.freeze
- assert_equal "Josh", person.name
- assert_equal true, person.name.frozen?
+ assert_equal true, @person.name.frozen?
+
+ @person.freeze
+ assert_equal "Josh", @person.name
+ assert_equal true, @person.name.frozen?
end
def test_memoization_frozen_with_nil_value
- person = Person.new
- person.freeze
- assert_equal nil, person.age
+ @person.freeze
+ assert_equal nil, @person.age
end
def test_double_memoization
--
cgit v1.2.3
From ef6f6625c91ea789a033799f649e4388e4a71045 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Fri, 18 Jul 2008 15:32:28 -0500
Subject: Changed ActiveSupport::Memoizable API to extend since it mainly adds
the memoize class method
---
actionpack/lib/action_view/renderable.rb | 4 +-
actionpack/lib/action_view/renderable_partial.rb | 2 +-
actionpack/lib/action_view/template.rb | 2 +-
activesupport/lib/active_support/memoizable.rb | 55 ++++++++++++------------
activesupport/test/memoizable_test.rb | 42 +++++++++++++++---
5 files changed, 67 insertions(+), 38 deletions(-)
diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb
index 46193670f3..5090d0160a 100644
--- a/actionpack/lib/action_view/renderable.rb
+++ b/actionpack/lib/action_view/renderable.rb
@@ -3,12 +3,12 @@ module ActionView
# NOTE: The template that this mixin is beening include into is frozen
# So you can not set or modify any instance variables
+ extend ActiveSupport::Memoizable
+
def self.included(base)
@@mutex = Mutex.new
end
- include ActiveSupport::Memoizable
-
def filename
'compiled-template'
end
diff --git a/actionpack/lib/action_view/renderable_partial.rb b/actionpack/lib/action_view/renderable_partial.rb
index fdb1a5e6a7..342850f0f0 100644
--- a/actionpack/lib/action_view/renderable_partial.rb
+++ b/actionpack/lib/action_view/renderable_partial.rb
@@ -3,7 +3,7 @@ module ActionView
# NOTE: The template that this mixin is beening include into is frozen
# So you can not set or modify any instance variables
- include ActiveSupport::Memoizable
+ extend ActiveSupport::Memoizable
def variable_name
name.sub(/\A_/, '').to_sym
diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb
index 304aec3a4c..eba42518d7 100644
--- a/actionpack/lib/action_view/template.rb
+++ b/actionpack/lib/action_view/template.rb
@@ -1,7 +1,7 @@
module ActionView #:nodoc:
class Template
extend TemplateHandlers
- include ActiveSupport::Memoizable
+ extend ActiveSupport::Memoizable
include Renderable
attr_accessor :filename, :load_path, :base_path, :name, :format, :extension
diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb
index c41feef4c7..59fecbecb1 100644
--- a/activesupport/lib/active_support/memoizable.rb
+++ b/activesupport/lib/active_support/memoizable.rb
@@ -1,37 +1,38 @@
module ActiveSupport
- module Memoizable
- def self.included(base) #:nodoc:
- base.extend(ClassMethods)
- end
-
- module ClassMethods
- def memoize(*symbols)
- symbols.each do |symbol|
- original_method = "unmemoized_#{symbol}"
- memoized_ivar = "@#{symbol}"
- raise "Already memoized #{symbol}" if instance_methods.map(&:to_s).include?(original_method)
-
- alias_method original_method, symbol
- class_eval <<-EOS, __FILE__, __LINE__
- def #{symbol}(reload = false)
- if !reload && defined? #{memoized_ivar}
- #{memoized_ivar}
- else
- #{memoized_ivar} = #{original_method}.freeze
- end
+ module Memoizable #:nodoc:
+ def self.extended(obj)
+ klass = obj.respond_to?(:class_eval) ? obj : obj.metaclass
+ klass.class_eval do
+ def freeze
+ methods.each do |method|
+ if m = method.to_s.match(/^unmemoized_(.*)/)
+ send(m[1])
end
- EOS
+ end
+ super
end
end
end
- def freeze
- methods.each do |method|
- if m = method.to_s.match(/\Aunmemoized_(.*)/)
- send(m[1])
- end
+ def memoize(*symbols)
+ symbols.each do |symbol|
+ original_method = "unmemoized_#{symbol}"
+ memoized_ivar = "@#{symbol}"
+
+ klass = respond_to?(:class_eval) ? self : self.metaclass
+ raise "Already memoized #{symbol}" if klass.instance_methods.map(&:to_s).include?(original_method)
+
+ klass.class_eval <<-EOS, __FILE__, __LINE__
+ alias_method :#{original_method}, :#{symbol}
+ def #{symbol}(reload = false)
+ if !reload && defined? #{memoized_ivar}
+ #{memoized_ivar}
+ else
+ #{memoized_ivar} = #{original_method}.freeze
+ end
+ end
+ EOS
end
- super
end
end
end
diff --git a/activesupport/test/memoizable_test.rb b/activesupport/test/memoizable_test.rb
index b649b31455..79769631ad 100644
--- a/activesupport/test/memoizable_test.rb
+++ b/activesupport/test/memoizable_test.rb
@@ -3,21 +3,24 @@ require 'abstract_unit'
uses_mocha 'Memoizable' do
class MemoizableTest < Test::Unit::TestCase
class Person
- include ActiveSupport::Memoizable
+ extend ActiveSupport::Memoizable
def name
fetch_name_from_floppy
end
+ memoize :name
+
def age
nil
end
- def random
- rand(0)
+ def counter
+ @counter ||= 0
+ @counter += 1
end
- memoize :name, :age, :random
+ memoize :age, :counter
private
def fetch_name_from_floppy
@@ -37,9 +40,9 @@ uses_mocha 'Memoizable' do
end
def test_reloadable
- random = @person.random
- assert_equal random, @person.random
- assert_not_equal random, @person.random(:reload)
+ counter = @person.counter
+ assert_equal 1, @person.counter
+ assert_equal 2, @person.counter(:reload)
end
def test_memoized_methods_are_frozen
@@ -58,5 +61,30 @@ uses_mocha 'Memoizable' do
def test_double_memoization
assert_raise(RuntimeError) { Person.memoize :name }
end
+
+ class Company
+ def name
+ lookup_name
+ end
+
+ def lookup_name
+ "37signals"
+ end
+ end
+
+ def test_object_memoization
+ company = Company.new
+ company.extend ActiveSupport::Memoizable
+ company.memoize :name
+
+ assert_equal "37signals", company.name
+ # Mocha doesn't play well with frozen objects
+ company.metaclass.instance_eval { define_method(:lookup_name) { b00m } }
+ assert_equal "37signals", company.name
+
+ assert_equal true, company.name.frozen?
+ company.freeze
+ assert_equal true, company.name.frozen?
+ end
end
end
--
cgit v1.2.3
From d2ccb852d4e1f6f1b01e43f32213053ae3bef408 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Fri, 18 Jul 2008 16:00:20 -0500
Subject: Removed lagacy TemplateHandler#render API. Left in a legacy
TemplateHandler and Compilable stub so plugins will not have to change
anything.
---
actionpack/lib/action_view/base.rb | 4 +--
actionpack/lib/action_view/renderable.rb | 6 ++---
actionpack/lib/action_view/template_handler.rb | 23 ++++++-----------
actionpack/lib/action_view/template_handlers.rb | 1 -
.../action_view/template_handlers/compilable.rb | 20 ---------------
actionpack/test/controller/layout_test.rb | 12 ++-------
actionpack/test/template/render_test.rb | 30 ++++------------------
7 files changed, 20 insertions(+), 76 deletions(-)
delete mode 100644 actionpack/lib/action_view/template_handlers/compilable.rb
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index a6872b1a47..ae6b284854 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -379,8 +379,8 @@ module ActionView #:nodoc:
@assigns.each { |key, value| instance_variable_set("@#{key}", value) }
end
- def execute(template, local_assigns = {})
- send(template.method(local_assigns), local_assigns) do |*names|
+ def execute(method, local_assigns = {})
+ send(method, local_assigns) do |*names|
instance_variable_get "@content_for_#{names.first || 'layout'}"
end
end
diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb
index 5090d0160a..4f865cbced 100644
--- a/actionpack/lib/action_view/renderable.rb
+++ b/actionpack/lib/action_view/renderable.rb
@@ -19,7 +19,7 @@ module ActionView
memoize :handler
def compiled_source
- handler.new(nil).compile(self) if handler.compilable?
+ handler.call(self)
end
memoize :compiled_source
@@ -27,8 +27,8 @@ module ActionView
view._first_render ||= self
view._last_render = self
view.send(:evaluate_assigns)
- compile(local_assigns) if handler.compilable?
- handler.new(view).render(self, local_assigns)
+ compile(local_assigns)
+ view.send(:execute, method(local_assigns), local_assigns)
end
def method(local_assigns)
diff --git a/actionpack/lib/action_view/template_handler.rb b/actionpack/lib/action_view/template_handler.rb
index e2dd305f93..d7e7c9b199 100644
--- a/actionpack/lib/action_view/template_handler.rb
+++ b/actionpack/lib/action_view/template_handler.rb
@@ -1,21 +1,14 @@
-module ActionView
- class TemplateHandler
- def self.compilable?
- false
- end
-
- def initialize(view)
- @view = view
- end
+# Legacy TemplateHandler stub
- def render(template, local_assigns = {})
- end
-
- def compile(template)
+module ActionView
+ module TemplateHandlers
+ module Compilable
end
+ end
- def compilable?
- self.class.compilable?
+ class TemplateHandler
+ def self.call(template)
+ new.compile(template)
end
end
end
diff --git a/actionpack/lib/action_view/template_handlers.rb b/actionpack/lib/action_view/template_handlers.rb
index 1471e99e01..6c8aa4c2a7 100644
--- a/actionpack/lib/action_view/template_handlers.rb
+++ b/actionpack/lib/action_view/template_handlers.rb
@@ -1,5 +1,4 @@
require 'action_view/template_handler'
-require 'action_view/template_handlers/compilable'
require 'action_view/template_handlers/builder'
require 'action_view/template_handlers/erb'
require 'action_view/template_handlers/rjs'
diff --git a/actionpack/lib/action_view/template_handlers/compilable.rb b/actionpack/lib/action_view/template_handlers/compilable.rb
deleted file mode 100644
index a0ebaefeef..0000000000
--- a/actionpack/lib/action_view/template_handlers/compilable.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-module ActionView
- module TemplateHandlers
- module Compilable
- def self.included(base)
- base.extend ClassMethod
- end
-
- module ClassMethod
- # If a handler is mixin this module, set compilable to true
- def compilable?
- true
- end
- end
-
- def render(template, local_assigns = {})
- @view.send(:execute, template, local_assigns)
- end
- end
- end
-end
diff --git a/actionpack/test/controller/layout_test.rb b/actionpack/test/controller/layout_test.rb
index 92b6aa4f2f..72c01a9102 100644
--- a/actionpack/test/controller/layout_test.rb
+++ b/actionpack/test/controller/layout_test.rb
@@ -31,16 +31,8 @@ end
class MultipleExtensions < LayoutTest
end
-class MabView < ActionView::TemplateHandler
- def initialize(view)
- end
-
- def render(template, local_assigns)
- template.source
- end
-end
-
-ActionView::Template::register_template_handler :mab, MabView
+ActionView::Template::register_template_handler :mab,
+ lambda { |template| template.source.inspect }
class LayoutAutoDiscoveryTest < Test::Unit::TestCase
def setup
diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb
index cc5b4900dc..b1af043099 100644
--- a/actionpack/test/template/render_test.rb
+++ b/actionpack/test/template/render_test.rb
@@ -94,38 +94,18 @@ class ViewRenderTest < Test::Unit::TestCase
assert_equal "Hello, World!", @view.render(:inline => "Hello, World!", :type => :foo)
end
- class CustomHandler < ActionView::TemplateHandler
- def render(template, local_assigns)
- [template.source, local_assigns].inspect
- end
- end
-
- def test_render_inline_with_custom_type
- ActionView::Template.register_template_handler :foo, CustomHandler
- assert_equal '["Hello, World!", {}]', @view.render(:inline => "Hello, World!", :type => :foo)
- end
-
- def test_render_inline_with_locals_and_custom_type
- ActionView::Template.register_template_handler :foo, CustomHandler
- assert_equal '["Hello, <%= name %>!", {:name=>"Josh"}]', @view.render(:inline => "Hello, <%= name %>!", :locals => { :name => "Josh" }, :type => :foo)
- end
-
- class CompilableCustomHandler < ActionView::TemplateHandler
- include ActionView::TemplateHandlers::Compilable
-
- def compile(template)
- "@output_buffer = ''\n" +
- "@output_buffer << 'source: #{template.source.inspect}'\n"
- end
+ CustomHandler = lambda do |template|
+ "@output_buffer = ''\n" +
+ "@output_buffer << 'source: #{template.source.inspect}'\n"
end
def test_render_inline_with_compilable_custom_type
- ActionView::Template.register_template_handler :foo, CompilableCustomHandler
+ ActionView::Template.register_template_handler :foo, CustomHandler
assert_equal 'source: "Hello, World!"', @view.render(:inline => "Hello, World!", :type => :foo)
end
def test_render_inline_with_locals_and_compilable_custom_type
- ActionView::Template.register_template_handler :foo, CompilableCustomHandler
+ ActionView::Template.register_template_handler :foo, CustomHandler
assert_equal 'source: "Hello, <%= name %>!"', @view.render(:inline => "Hello, <%= name %>!", :locals => { :name => "Josh" }, :type => :foo)
end
end
--
cgit v1.2.3
From c3d1fda555c4bd5f8821d830c685ae5d0e7e52d0 Mon Sep 17 00:00:00 2001
From: Tom Ward
Date: Fri, 18 Jul 2008 20:14:12 -0500
Subject: Set the response content type to that of found template if not
explicitly set elsewhere [#444 state:resolved]
Signed-off-by: Joshua Peek
---
actionpack/lib/action_view/base.rb | 6 ++++++
actionpack/lib/action_view/renderable.rb | 5 ++++-
actionpack/lib/action_view/template.rb | 5 +++++
actionpack/lib/action_view/template_handlers/builder.rb | 3 +--
actionpack/test/controller/render_test.rb | 15 ++++++++++-----
.../test/fixtures/test/implicit_content_type.atom.builder | 2 ++
6 files changed, 28 insertions(+), 8 deletions(-)
create mode 100644 actionpack/test/fixtures/test/implicit_content_type.atom.builder
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index ae6b284854..fe51af62e6 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -379,6 +379,12 @@ module ActionView #:nodoc:
@assigns.each { |key, value| instance_variable_set("@#{key}", value) }
end
+ def set_controller_content_type(content_type)
+ if controller.respond_to?(:response)
+ controller.response.content_type ||= content_type
+ end
+ end
+
def execute(method, local_assigns = {})
send(method, local_assigns) do |*names|
instance_variable_get "@content_for_#{names.first || 'layout'}"
diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb
index 4f865cbced..2b825ac4e9 100644
--- a/actionpack/lib/action_view/renderable.rb
+++ b/actionpack/lib/action_view/renderable.rb
@@ -24,10 +24,13 @@ module ActionView
memoize :compiled_source
def render(view, local_assigns = {})
+ compile(local_assigns)
+
view._first_render ||= self
view._last_render = self
+
view.send(:evaluate_assigns)
- compile(local_assigns)
+ view.send(:set_controller_content_type, mime_type) if respond_to?(:mime_type)
view.send(:execute, method(local_assigns), local_assigns)
end
diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb
index eba42518d7..1f528dd900 100644
--- a/actionpack/lib/action_view/template.rb
+++ b/actionpack/lib/action_view/template.rb
@@ -22,6 +22,11 @@ module ActionView #:nodoc:
end
memoize :format_and_extension
+ def mime_type
+ Mime::Type.lookup_by_extension(format) if format
+ end
+ memoize :mime_type
+
def path
[base_path, [name, format, extension].compact.join('.')].compact.join('/')
end
diff --git a/actionpack/lib/action_view/template_handlers/builder.rb b/actionpack/lib/action_view/template_handlers/builder.rb
index 335ec1abb4..7d24a5c423 100644
--- a/actionpack/lib/action_view/template_handlers/builder.rb
+++ b/actionpack/lib/action_view/template_handlers/builder.rb
@@ -6,8 +6,7 @@ module ActionView
include Compilable
def compile(template)
- # ActionMailer does not have a response
- "controller.respond_to?(:response) && controller.response.content_type ||= Mime::XML;" +
+ "set_controller_content_type(Mime::XML);" +
"xml = ::Builder::XmlMarkup.new(:indent => 2);" +
"self.output_buffer = xml.target!;" +
template.source +
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index 041c54c7fd..76832f5713 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -197,11 +197,11 @@ class TestController < ActionController::Base
def render_alternate_default
# For this test, the method "default_render" is overridden:
- @alternate_default_render = lambda {
- render :update do |page|
- page.replace :foo, :partial => 'partial'
- end
- }
+ @alternate_default_render = lambda do
+ render :update do |page|
+ page.replace :foo, :partial => 'partial'
+ end
+ end
end
def rescue_action(e) raise end
@@ -467,6 +467,11 @@ class RenderTest < Test::Unit::TestCase
get :render_xml_with_custom_content_type
assert_equal "application/atomsvc+xml", @response.content_type
end
+
+ def test_should_use_implicit_content_type
+ get :implicit_content_type, :format => 'atom'
+ assert_equal Mime::ATOM, @response.content_type
+ end
end
class EtagRenderTest < Test::Unit::TestCase
diff --git a/actionpack/test/fixtures/test/implicit_content_type.atom.builder b/actionpack/test/fixtures/test/implicit_content_type.atom.builder
new file mode 100644
index 0000000000..2fcb32d247
--- /dev/null
+++ b/actionpack/test/fixtures/test/implicit_content_type.atom.builder
@@ -0,0 +1,2 @@
+xml.atom do
+end
--
cgit v1.2.3
From d39485078ec56e25a96e97d44b53498d8a1c7426 Mon Sep 17 00:00:00 2001
From: Tom Ward
Date: Fri, 18 Jul 2008 20:19:03 -0500
Subject: Raise ArgumentError if an invalid method is specified as part of a
route's conditions. Also raise an error if HEAD is specified as the method,
as rails routes all HEAD requests through the equivalent GET, though doesn't
return the response body [#182 state:resolved]
Signed-off-by: Joshua Peek
---
actionpack/lib/action_controller/resources.rb | 9 +++++----
actionpack/lib/action_controller/routing/builder.rb | 15 +++++++++++++++
actionpack/test/controller/resources_test.rb | 20 ++++++++++++++++++++
actionpack/test/controller/routing_test.rb | 16 ++++++++++++++++
4 files changed, 56 insertions(+), 4 deletions(-)
diff --git a/actionpack/lib/action_controller/resources.rb b/actionpack/lib/action_controller/resources.rb
index b11aa5625b..0614b9a4d9 100644
--- a/actionpack/lib/action_controller/resources.rb
+++ b/actionpack/lib/action_controller/resources.rb
@@ -307,13 +307,13 @@ module ActionController
# map.resources :tags, :path_prefix => '/toys/:toy_id', :name_prefix => 'toy_'
#
# You may also use :name_prefix to override the generic named routes in a nested resource:
- #
+ #
# map.resources :articles do |article|
# article.resources :comments, :name_prefix => nil
- # end
- #
+ # end
+ #
# This will yield named resources like so:
- #
+ #
# comments_url(@article)
# comment_url(@article, @comment)
#
@@ -559,6 +559,7 @@ module ActionController
def action_options_for(action, resource, method = nil)
default_options = { :action => action.to_s }
require_id = !resource.kind_of?(SingletonResource)
+
case default_options[:action]
when "index", "new"; default_options.merge(add_conditions_for(resource.conditions, method || :get)).merge(resource.requirements)
when "create"; default_options.merge(add_conditions_for(resource.conditions, method || :post)).merge(resource.requirements)
diff --git a/actionpack/lib/action_controller/routing/builder.rb b/actionpack/lib/action_controller/routing/builder.rb
index b8323847fd..912999d845 100644
--- a/actionpack/lib/action_controller/routing/builder.rb
+++ b/actionpack/lib/action_controller/routing/builder.rb
@@ -76,6 +76,8 @@ module ActionController
defaults = (options.delete(:defaults) || {}).dup
conditions = (options.delete(:conditions) || {}).dup
+ validate_route_conditions(conditions)
+
path_keys = segments.collect { |segment| segment.key if segment.respond_to?(:key) }.compact
options.each do |key, value|
hash = (path_keys.include?(key) && ! value.is_a?(Regexp)) ? defaults : requirements
@@ -198,6 +200,19 @@ module ActionController
route
end
+
+ private
+ def validate_route_conditions(conditions)
+ if method = conditions[:method]
+ if method == :head
+ raise ArgumentError, "HTTP method HEAD is invalid in route conditions. Rails processes HEAD requests the same as GETs, returning just the response headers"
+ end
+
+ unless HTTP_METHODS.include?(method.to_sym)
+ raise ArgumentError, "Invalid HTTP method specified in route conditions: #{conditions.inspect}"
+ end
+ end
+ end
end
end
end
diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb
index 0f7924649a..e153b0cc98 100644
--- a/actionpack/test/controller/resources_test.rb
+++ b/actionpack/test/controller/resources_test.rb
@@ -516,6 +516,26 @@ class ResourcesTest < Test::Unit::TestCase
end
end
+ def test_should_not_allow_invalid_head_method_for_member_routes
+ with_routing do |set|
+ set.draw do |map|
+ assert_raises(ArgumentError) do
+ map.resources :messages, :member => {:something => :head}
+ end
+ end
+ end
+ end
+
+ def test_should_not_allow_invalid_http_methods_for_member_routes
+ with_routing do |set|
+ set.draw do |map|
+ assert_raises(ArgumentError) do
+ map.resources :messages, :member => {:something => :invalid}
+ end
+ end
+ end
+ end
+
def test_resource_action_separator
with_routing do |set|
set.draw do |map|
diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb
index c5ccb71582..079189d7b3 100644
--- a/actionpack/test/controller/routing_test.rb
+++ b/actionpack/test/controller/routing_test.rb
@@ -1801,6 +1801,22 @@ uses_mocha 'LegacyRouteSet, Route, RouteSet and RouteLoading' do
end
end
+ def test_route_requirements_with_invalid_http_method_is_invalid
+ assert_raises ArgumentError do
+ set.draw do |map|
+ map.connect 'valid/route', :controller => 'pages', :action => 'show', :conditions => {:method => :invalid}
+ end
+ end
+ end
+
+ def test_route_requirements_with_head_method_condition_is_invalid
+ assert_raises ArgumentError do
+ set.draw do |map|
+ map.connect 'valid/route', :controller => 'pages', :action => 'show', :conditions => {:method => :head}
+ end
+ end
+ end
+
def test_non_path_route_requirements_match_all
set.draw do |map|
map.connect 'page/37s', :controller => 'pages', :action => 'show', :name => /(jamis|david)/
--
cgit v1.2.3
From c609be45966316bb107e0bad2b0935ac4a0d0c41 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Fri, 18 Jul 2008 23:30:36 -0500
Subject: Ruby 1.9: Ensure Memoizable#freeze is only overriden once to avoid an
endless loop
---
activesupport/lib/active_support/memoizable.rb | 26 ++++++++++++--------------
1 file changed, 12 insertions(+), 14 deletions(-)
diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb
index 59fecbecb1..f7cd73d39c 100644
--- a/activesupport/lib/active_support/memoizable.rb
+++ b/activesupport/lib/active_support/memoizable.rb
@@ -1,19 +1,5 @@
module ActiveSupport
module Memoizable #:nodoc:
- def self.extended(obj)
- klass = obj.respond_to?(:class_eval) ? obj : obj.metaclass
- klass.class_eval do
- def freeze
- methods.each do |method|
- if m = method.to_s.match(/^unmemoized_(.*)/)
- send(m[1])
- end
- end
- super
- end
- end
- end
-
def memoize(*symbols)
symbols.each do |symbol|
original_method = "unmemoized_#{symbol}"
@@ -23,6 +9,18 @@ module ActiveSupport
raise "Already memoized #{symbol}" if klass.instance_methods.map(&:to_s).include?(original_method)
klass.class_eval <<-EOS, __FILE__, __LINE__
+ unless instance_methods.map(&:to_s).include?("freeze_without_memoizable")
+ alias_method :freeze_without_memoizable, :freeze
+ def freeze
+ methods.each do |method|
+ if m = method.to_s.match(/^unmemoized_(.*)/)
+ send(m[1])
+ end
+ end
+ freeze_without_memoizable
+ end
+ end
+
alias_method :#{original_method}, :#{symbol}
def #{symbol}(reload = false)
if !reload && defined? #{memoized_ivar}
--
cgit v1.2.3
From 108ed4a5660d4ebdc52563250463c762e3f27988 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sat, 19 Jul 2008 00:24:02 -0500
Subject: Ruby 1.9: Strip encoding from ERB source since you can not change
character encoding during a method
---
actionpack/lib/action_view/template_handlers/erb.rb | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/actionpack/lib/action_view/template_handlers/erb.rb b/actionpack/lib/action_view/template_handlers/erb.rb
index 2f2febaa52..3def949f1e 100644
--- a/actionpack/lib/action_view/template_handlers/erb.rb
+++ b/actionpack/lib/action_view/template_handlers/erb.rb
@@ -48,8 +48,11 @@ module ActionView
self.erb_trim_mode = '-'
def compile(template)
- src = ::ERB.new(template.source, nil, erb_trim_mode, '@output_buffer').src
- "__in_erb_template=true;#{src}"
+ src = ::ERB.new("<% __in_erb_template=true %>#{template.source}", nil, erb_trim_mode, '@output_buffer').src
+
+ # Ruby 1.9 prepends an encoding to the source. However this is
+ # useless because you can only set an encoding on the first line
+ RUBY_VERSION >= '1.9' ? src.sub(/\A#coding:.*\n/, '') : src
end
end
end
--
cgit v1.2.3
From cab168ac9bbe24e5842fb7677d3fac820ddbc18c Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sat, 19 Jul 2008 00:46:02 -0500
Subject: Ruby 1.9: Fixed regexp warning by replacing nested repeat operator +
and ? with '*'
---
actionpack/lib/action_view/helpers/text_helper.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb
index 3e3452b615..9342b38680 100644
--- a/actionpack/lib/action_view/helpers/text_helper.rb
+++ b/actionpack/lib/action_view/helpers/text_helper.rb
@@ -468,7 +468,7 @@ module ActionView
[-\w]+ # subdomain or domain
(?:\.[-\w]+)* # remaining subdomains or domain
(?::\d+)? # port
- (?:/(?:(?:[~\w\+@%=\(\)-]|(?:[,.;:'][^\s$]))+)?)* # path
+ (?:/(?:(?:[~\w\+@%=\(\)-]|(?:[,.;:'][^\s$])))*)* # path
(?:\?[\w\+@%&=.;-]+)? # query string
(?:\#[\w\-]*)? # trailing anchor
)
--
cgit v1.2.3
From f2059393481ceb632abc7a9d92670e409020d5bd Mon Sep 17 00:00:00 2001
From: Tom Ward
Date: Sat, 19 Jul 2008 09:58:09 +0100
Subject: Ensure checked value is a string when validating case-sensitive
uniqueness [#361 state:resolved]
Signed-off-by: Pratik Naik
---
activerecord/lib/active_record/validations.rb | 2 +-
activerecord/test/cases/validations_test.rb | 9 +++++++++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb
index 3eec1305e4..b957ee3b9e 100755
--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -664,7 +664,7 @@ module ActiveRecord
# As MySQL/Postgres don't have case sensitive SELECT queries, we try to find duplicate
# column in ruby when case sensitive option
if configuration[:case_sensitive] && finder_class.columns_hash[attr_name.to_s].text?
- found = results.any? { |a| a[attr_name.to_s] == value }
+ found = results.any? { |a| a[attr_name.to_s] == value.to_s }
end
if found
diff --git a/activerecord/test/cases/validations_test.rb b/activerecord/test/cases/validations_test.rb
index 60b00b3e8f..4b2d28c80b 100755
--- a/activerecord/test/cases/validations_test.rb
+++ b/activerecord/test/cases/validations_test.rb
@@ -477,6 +477,15 @@ class ValidationsTest < ActiveRecord::TestCase
assert_not_equal "has already been taken", t3.errors.on(:title)
end
+ def test_validate_case_sensitive_uniqueness_with_attribute_passed_as_integer
+ Topic.validates_uniqueness_of(:title, :case_sensitve => true)
+ t = Topic.create!('title' => 101)
+
+ t2 = Topic.new('title' => 101)
+ assert !t2.valid?
+ assert t2.errors.on(:title)
+ end
+
def test_validate_uniqueness_with_non_standard_table_names
i1 = WarehouseThing.create(:value => 1000)
assert !i1.valid?, "i1 should not be valid"
--
cgit v1.2.3
From d84d99a8f7dc672b050a6ab891c1680a323a7c97 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sat, 19 Jul 2008 10:52:30 -0500
Subject: Undefine old run method
---
activesupport/lib/active_support/testing/setup_and_teardown.rb | 3 +++
1 file changed, 3 insertions(+)
diff --git a/activesupport/lib/active_support/testing/setup_and_teardown.rb b/activesupport/lib/active_support/testing/setup_and_teardown.rb
index 21d71eb92a..a514b61fea 100644
--- a/activesupport/lib/active_support/testing/setup_and_teardown.rb
+++ b/activesupport/lib/active_support/testing/setup_and_teardown.rb
@@ -15,12 +15,15 @@ module ActiveSupport
define_callbacks :setup, :teardown
if defined?(::Mini)
+ undef_method :run
alias_method :run, :run_with_callbacks_and_miniunit
else
begin
require 'mocha'
+ undef_method :run
alias_method :run, :run_with_callbacks_and_mocha
rescue LoadError
+ undef_method :run
alias_method :run, :run_with_callbacks_and_testunit
end
end
--
cgit v1.2.3
From 8c2e839e5a0fb1662ae867c70114c3fc91850a55 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sat, 19 Jul 2008 11:04:23 -0500
Subject: Fix some warnings in i18n lib
---
activesupport/lib/active_support/vendor/i18n-0.0.1/lib/i18n.rb | 6 +++---
.../lib/active_support/vendor/i18n-0.0.1/lib/i18n/backend/simple.rb | 4 ++--
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/activesupport/lib/active_support/vendor/i18n-0.0.1/lib/i18n.rb b/activesupport/lib/active_support/vendor/i18n-0.0.1/lib/i18n.rb
index 2185194da9..1bb65263a3 100755
--- a/activesupport/lib/active_support/vendor/i18n-0.0.1/lib/i18n.rb
+++ b/activesupport/lib/active_support/vendor/i18n-0.0.1/lib/i18n.rb
@@ -53,7 +53,7 @@ module I18n
# storage. Decoupled for backends like a db backend that persist their
# translations, so the backend can decide whether/when to yield or not.
def populate(&block)
- backend.populate &block
+ backend.populate(&block)
end
# Stores translations for the given locale in the backend.
@@ -173,8 +173,8 @@ module I18n
# keys are Symbols.
def normalize_translation_keys(locale, key, scope)
keys = [locale] + Array(scope) + [key]
- keys = keys.map{|key| key.to_s.split(/\./) }
- keys.flatten.map{|key| key.to_sym}
+ keys = keys.map{|k| k.to_s.split(/\./) }
+ keys.flatten.map{|k| k.to_sym}
end
end
end
diff --git a/activesupport/lib/active_support/vendor/i18n-0.0.1/lib/i18n/backend/simple.rb b/activesupport/lib/active_support/vendor/i18n-0.0.1/lib/i18n/backend/simple.rb
index 284f2bfcbd..b8be1cecfb 100644
--- a/activesupport/lib/active_support/vendor/i18n-0.0.1/lib/i18n/backend/simple.rb
+++ b/activesupport/lib/active_support/vendor/i18n-0.0.1/lib/i18n/backend/simple.rb
@@ -23,7 +23,7 @@ module I18n
def translate(locale, key, options = {})
raise InvalidLocale.new(locale) if locale.nil?
- return key.map{|key| translate locale, key, options } if key.is_a? Array
+ return key.map{|k| translate locale, k, options } if key.is_a? Array
reserved = :scope, :default
count, scope, default = options.values_at(:count, *reserved)
@@ -66,7 +66,7 @@ module I18n
def lookup(locale, key, scope = [])
return unless key
keys = I18n.send :normalize_translation_keys, locale, key, scope
- keys.inject(@@translations){|result, key| result[key.to_sym] or return nil }
+ keys.inject(@@translations){|result, k| result[k.to_sym] or return nil }
end
# Evaluates a default translation.
--
cgit v1.2.3
From b74b97fef5d94f91d6fbf9aec20516c7fe4ce24d Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sat, 19 Jul 2008 11:14:12 -0500
Subject: Update uses_mocha in ActionMailer and ActiveResource
---
actionmailer/test/abstract_unit.rb | 18 +++++++++++++-----
activeresource/test/abstract_unit.rb | 22 +++++++++++++---------
2 files changed, 26 insertions(+), 14 deletions(-)
diff --git a/actionmailer/test/abstract_unit.rb b/actionmailer/test/abstract_unit.rb
index 11058a770d..107b2e8bbe 100644
--- a/actionmailer/test/abstract_unit.rb
+++ b/actionmailer/test/abstract_unit.rb
@@ -30,12 +30,20 @@ class Net::SMTP
end
end
-# Wrap tests that use Mocha and skip if unavailable.
-def uses_mocha(test_name)
- gem 'mocha', ">=0.9.0"
+def uses_gem(gem_name, test_name, version = '> 0')
+ require 'rubygems'
+ gem gem_name.to_s, version
+ require gem_name.to_s
yield
-rescue Gem::LoadError
- $stderr.puts "Skipping #{test_name} tests (Mocha >= 0.5 is required). `gem install mocha` and try again."
+rescue LoadError
+ $stderr.puts "Skipping #{test_name} tests. `gem install #{gem_name}` and try again."
+end
+
+# Wrap tests that use Mocha and skip if unavailable.
+unless defined? uses_mocha
+ def uses_mocha(test_name, &block)
+ uses_gem('mocha', test_name, '>= 0.5.5', &block)
+ end
end
def set_delivery_method(delivery_method)
diff --git a/activeresource/test/abstract_unit.rb b/activeresource/test/abstract_unit.rb
index 615a6d9222..e612412033 100644
--- a/activeresource/test/abstract_unit.rb
+++ b/activeresource/test/abstract_unit.rb
@@ -9,14 +9,18 @@ require 'setter_trap'
ActiveResource::Base.logger = Logger.new("#{File.dirname(__FILE__)}/debug.log")
+def uses_gem(gem_name, test_name, version = '> 0')
+ require 'rubygems'
+ gem gem_name.to_s, version
+ require gem_name.to_s
+ yield
+rescue LoadError
+ $stderr.puts "Skipping #{test_name} tests. `gem install #{gem_name}` and try again."
+end
+
# Wrap tests that use Mocha and skip if unavailable.
-def uses_mocha(test_name)
- unless Object.const_defined?(:Mocha)
- require 'mocha'
- require 'stubba'
+unless defined? uses_mocha
+ def uses_mocha(test_name, &block)
+ uses_gem('mocha', test_name, '>= 0.5.5', &block)
end
- yield
-rescue LoadError => load_error
- raise unless load_error.message =~ /mocha/i
- $stderr.puts "Skipping #{test_name} tests. `gem install mocha` and try again."
-end
\ No newline at end of file
+end
--
cgit v1.2.3
From 3fdd1acab61a46ab4823d63ad0bab4879d2bb446 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sat, 19 Jul 2008 11:30:15 -0500
Subject: Dropped SQLite 2 from default test runner
---
activerecord/Rakefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/activerecord/Rakefile b/activerecord/Rakefile
index 60b17e02b9..983528aff7 100755
--- a/activerecord/Rakefile
+++ b/activerecord/Rakefile
@@ -30,7 +30,7 @@ desc 'Run mysql, sqlite, and postgresql tests by default'
task :default => :test
desc 'Run mysql, sqlite, and postgresql tests'
-task :test => %w(test_mysql test_sqlite test_sqlite3 test_postgresql)
+task :test => %w(test_mysql test_sqlite3 test_postgresql)
for adapter in %w( mysql postgresql sqlite sqlite3 firebird db2 oracle sybase openbase frontbase )
Rake::TestTask.new("test_#{adapter}") { |t|
--
cgit v1.2.3
From 576cae004342899b0506a7834edc524a02a7d9ef Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sat, 19 Jul 2008 11:34:32 -0500
Subject: Stub out timestamped_migrations in generator tests
---
railties/test/generators/generator_test_helper.rb | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/railties/test/generators/generator_test_helper.rb b/railties/test/generators/generator_test_helper.rb
index 80d5b145be..0901b215e4 100644
--- a/railties/test/generators/generator_test_helper.rb
+++ b/railties/test/generators/generator_test_helper.rb
@@ -5,9 +5,10 @@ require 'fileutils'
module ActiveRecord
class Base
class << self
- attr_accessor :pluralize_table_names
+ attr_accessor :pluralize_table_names, :timestamped_migrations
end
self.pluralize_table_names = true
+ self.timestamped_migrations = true
end
module ConnectionAdapters
--
cgit v1.2.3
From e0d7bace4ecb9152fac112e809af521e36fbc6a5 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sat, 19 Jul 2008 11:42:27 -0500
Subject: Prefer Mongrel over Thin [#658 state:resolved]
---
railties/lib/commands/server.rb | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/railties/lib/commands/server.rb b/railties/lib/commands/server.rb
index 7306c248fb..15f417b5be 100644
--- a/railties/lib/commands/server.rb
+++ b/railties/lib/commands/server.rb
@@ -23,10 +23,10 @@ server = case ARGV.first
when "lighttpd", "mongrel", "new_mongrel", "webrick", "thin"
ARGV.shift
else
- if defined?(Thin)
- "thin"
- elsif defined?(Mongrel)
+ if defined?(Mongrel)
"mongrel"
+ elsif defined?(Thin)
+ "thin"
elsif RUBY_PLATFORM !~ /(:?mswin|mingw)/ && !silence_stderr { `lighttpd -version` }.blank? && defined?(FCGI)
"lighttpd"
else
--
cgit v1.2.3
From 746122735269b9077c7d5d99d88e8b22d88ad8d5 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sat, 19 Jul 2008 12:23:08 -0500
Subject: Ruby 1.9: Call join on template_root instead of to_s
---
actionmailer/lib/action_mailer/base.rb | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index 5a71935009..e4920f0c86 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -529,7 +529,7 @@ module ActionMailer #:nodoc:
end
def render_message(method_name, body)
- render :file => method_name, :body => body, :use_full_path => true
+ render :file => method_name, :body => body
end
def render(opts)
@@ -537,12 +537,11 @@ module ActionMailer #:nodoc:
if opts[:file] && opts[:file] !~ /\//
opts[:file] = "#{mailer_name}/#{opts[:file]}"
end
- opts[:use_full_path] = true
initialize_template_class(body).render(opts)
end
def template_path
- "#{template_root}/#{mailer_name}"
+ "#{template_root.join}/#{mailer_name}"
end
def initialize_template_class(assigns)
--
cgit v1.2.3
From e23156e87bd32206a5ea529fbecc04fdf37d7bc2 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sat, 19 Jul 2008 12:35:42 -0500
Subject: Only create a path for ActionMailer template root instead of a path
set. Better fix than 7461227
---
actionmailer/lib/action_mailer/base.rb | 4 ++--
actionmailer/test/mail_service_test.rb | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index e4920f0c86..bf60e2f3d5 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -426,7 +426,7 @@ module ActionMailer #:nodoc:
end
def template_root=(root)
- write_inheritable_attribute(:template_root, ActionView::PathSet.new(Array(root)))
+ write_inheritable_attribute(:template_root, ActionView::PathSet::Path.new(root))
end
end
@@ -541,7 +541,7 @@ module ActionMailer #:nodoc:
end
def template_path
- "#{template_root.join}/#{mailer_name}"
+ "#{template_root}/#{mailer_name}"
end
def initialize_template_class(assigns)
diff --git a/actionmailer/test/mail_service_test.rb b/actionmailer/test/mail_service_test.rb
index 7f4a8817ca..e5ecb0e254 100755
--- a/actionmailer/test/mail_service_test.rb
+++ b/actionmailer/test/mail_service_test.rb
@@ -942,13 +942,13 @@ end # uses_mocha
class InheritableTemplateRootTest < Test::Unit::TestCase
def test_attr
expected = "#{File.dirname(__FILE__)}/fixtures/path.with.dots"
- assert_equal [expected], FunkyPathMailer.template_root.map(&:to_s)
+ assert_equal expected, FunkyPathMailer.template_root
sub = Class.new(FunkyPathMailer)
sub.template_root = 'test/path'
- assert_equal ['test/path'], sub.template_root.map(&:to_s)
- assert_equal [expected], FunkyPathMailer.template_root.map(&:to_s)
+ assert_equal 'test/path', sub.template_root
+ assert_equal expected, FunkyPathMailer.template_root
end
end
--
cgit v1.2.3
From 938caf4e6b2448b45939d36824794ea0aa5e1804 Mon Sep 17 00:00:00 2001
From: Clemens Kofler
Date: Sat, 19 Jul 2008 12:40:30 -0500
Subject: Removed unused option from FormHelper#fields_for [#641
state:resolved]
Signed-off-by: Joshua Peek
---
actionpack/lib/action_view/helpers/form_helper.rb | 4 ----
1 file changed, 4 deletions(-)
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index fa26aa4640..4fa46d9ee3 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -304,10 +304,6 @@ module ActionView
when String, Symbol
object_name = record_or_name_or_array
object = args.first
- when Array
- object = record_or_name_or_array.last
- object_name = ActionController::RecordIdentifier.singular_class_name(object)
- apply_form_for_options!(record_or_name_or_array, options)
else
object = record_or_name_or_array
object_name = ActionController::RecordIdentifier.singular_class_name(object)
--
cgit v1.2.3
From c98692abcfd3576ee5fcde3910330d1eb39a18a5 Mon Sep 17 00:00:00 2001
From: Clemens Kofler
Date: Sat, 19 Jul 2008 13:06:43 -0500
Subject: Removed handling of string parameter in link_to to have all URL
generation done by url_for
Signed-off-by: Joshua Peek
---
actionpack/lib/action_view/helpers/url_helper.rb | 93 +++++++++++++-----------
actionpack/test/template/url_helper_test.rb | 11 ++-
2 files changed, 60 insertions(+), 44 deletions(-)
diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb
index 94e1f1d33a..f31502d99d 100644
--- a/actionpack/lib/action_view/helpers/url_helper.rb
+++ b/actionpack/lib/action_view/helpers/url_helper.rb
@@ -3,8 +3,8 @@ require 'action_view/helpers/javascript_helper'
module ActionView
module Helpers #:nodoc:
# Provides a set of methods for making links and getting URLs that
- # depend on the routing subsystem (see ActionController::Routing).
- # This allows you to use the same format for links in views
+ # depend on the routing subsystem (see ActionController::Routing).
+ # This allows you to use the same format for links in views
# and controllers.
module UrlHelper
include JavaScriptHelper
@@ -33,8 +33,8 @@ module ActionView
#
# If you instead of a hash pass a record (like an Active Record or Active Resource) as the options parameter,
# you'll trigger the named route for that record. The lookup will happen on the name of the class. So passing
- # a Workshop object will attempt to use the workshop_path route. If you have a nested route, such as
- # admin_workshop_path you'll have to call that explicitly (it's impossible for url_for to guess that route).
+ # a Workshop object will attempt to use the workshop_path route. If you have a nested route, such as
+ # admin_workshop_path you'll have to call that explicitly (it's impossible for url_for to guess that route).
#
# ==== Examples
# <%= url_for(:action => 'index') %>
@@ -62,19 +62,33 @@ module ActionView
# <%= url_for(@workshop) %>
# # calls @workshop.to_s
# # => /workshops/5
+ #
+ # <%= url_for("http://www.example.com") %>
+ # # => http://www.example.com
+ #
+ # <%= url_for(:back) %>
+ # # if request.env["HTTP_REFERER"] is set to "http://www.example.com"
+ # # => http://www.example.com
+ #
+ # <%= url_for(:back) %>
+ # # if request.env["HTTP_REFERER"] is not set or is blank
+ # # => javascript:history.back()
def url_for(options = {})
options ||= {}
- case options
+ url = case options
+ when String
+ escape = true
+ options
when Hash
options = { :only_path => options[:host].nil? }.update(options.symbolize_keys)
escape = options.key?(:escape) ? options.delete(:escape) : true
- url = @controller.send(:url_for, options)
- when String
- escape = true
- url = options
+ @controller.send(:url_for, options)
+ when :back
+ escape = false
+ @controller.request.env["HTTP_REFERER"] || 'javascript:history.back()'
else
escape = false
- url = polymorphic_path(options)
+ polymorphic_path(options)
end
escape ? escape_once(url) : url
@@ -116,8 +130,8 @@ module ActionView
#
# Note that if the user has JavaScript disabled, the request will fall back
# to using GET. If :href => '#' is used and the user has JavaScript disabled
- # clicking the link will have no effect. If you are relying on the POST
- # behavior, your should check for it in your controller's action by using the
+ # clicking the link will have no effect. If you are relying on the POST
+ # behavior, your should check for it in your controller's action by using the
# request object's methods for post? , delete? or put? .
#
# You can mix and match the +html_options+ with the exception of
@@ -141,8 +155,8 @@ module ActionView
#
# link_to "Profile", :controller => "profiles", :action => "show", :id => @profile
# # => Profile
- #
- # Similarly,
+ #
+ # Similarly,
#
# link_to "Profiles", profiles_path
# # => Profiles
@@ -197,9 +211,9 @@ module ActionView
# # => View Image
#
# link_to "Delete Image", @image, :confirm => "Are you sure?", :method => :delete
- # # => Delete Image
def link_to(*args, &block)
if block_given?
@@ -211,14 +225,7 @@ module ActionView
options = args.second || {}
html_options = args.third
- url = case options
- when String
- options
- when :back
- @controller.request.env["HTTP_REFERER"] || 'javascript:history.back()'
- else
- self.url_for(options)
- end
+ url = url_for(options)
if html_options
html_options = html_options.stringify_keys
@@ -228,7 +235,7 @@ module ActionView
else
tag_options = nil
end
-
+
href_attr = "href=\"#{url}\"" unless href
"#{name || url} "
end
@@ -260,7 +267,7 @@ module ActionView
# * :confirm - This will add a JavaScript confirm
# prompt with the question specified. If the user accepts, the link is
# processed normally, otherwise no action is taken.
- #
+ #
# ==== Examples
# <%= button_to "New", :action => "new" %>
# # => "", button_to("Hello", "http://www.example.com")
@@ -419,7 +429,6 @@ class LinkToUnlessCurrentWithControllerTest < ActionView::TestCase
end
end
-
class Workshop
attr_accessor :id, :new_record
--
cgit v1.2.3
From 706425e154a2a2581195c98309f30a18a0002a58 Mon Sep 17 00:00:00 2001
From: David Heinemeier Hansson
Date: Sat, 19 Jul 2008 13:56:38 -0500
Subject: Update Prototype to 1.6.0.2 (Patrick Joyce) [#599 status:committed]
---
actionpack/CHANGELOG | 2 +
.../action_view/helpers/javascripts/prototype.js | 304 ++++++++++-----------
railties/html/javascripts/prototype.js | 304 ++++++++++-----------
3 files changed, 302 insertions(+), 308 deletions(-)
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index f6432fe0be..ebe4c047b8 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,5 +1,7 @@
*Edge*
+* Update Prototype to 1.6.0.2 #599 [Patrick Joyce]
+
* Conditional GET utility methods. [Jeremy Kemper]
* etag!([:admin, post, current_user]) sets the ETag response header and returns head(:not_modified) if it matches the If-None-Match request header.
* last_modified!(post.updated_at) sets Last-Modified and returns head(:not_modified) if it's no later than If-Modified-Since.
diff --git a/actionpack/lib/action_view/helpers/javascripts/prototype.js b/actionpack/lib/action_view/helpers/javascripts/prototype.js
index 546f9fe449..2c70b8a7e8 100644
--- a/actionpack/lib/action_view/helpers/javascripts/prototype.js
+++ b/actionpack/lib/action_view/helpers/javascripts/prototype.js
@@ -1,5 +1,5 @@
-/* Prototype JavaScript framework, version 1.6.0.1
- * (c) 2005-2007 Sam Stephenson
+/* Prototype JavaScript framework, version 1.6.0.2
+ * (c) 2005-2008 Sam Stephenson
*
* Prototype is freely distributable under the terms of an MIT-style license.
* For details, see the Prototype web site: http://www.prototypejs.org/
@@ -7,7 +7,7 @@
*--------------------------------------------------------------------------*/
var Prototype = {
- Version: '1.6.0.1',
+ Version: '1.6.0.2',
Browser: {
IE: !!(window.attachEvent && !window.opera),
@@ -110,7 +110,7 @@ Object.extend(Object, {
try {
if (Object.isUndefined(object)) return 'undefined';
if (object === null) return 'null';
- return object.inspect ? object.inspect() : object.toString();
+ return object.inspect ? object.inspect() : String(object);
} catch (e) {
if (e instanceof RangeError) return '...';
throw e;
@@ -171,7 +171,8 @@ Object.extend(Object, {
},
isArray: function(object) {
- return object && object.constructor === Array;
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
},
isHash: function(object) {
@@ -578,7 +579,7 @@ var Template = Class.create({
}
return before + String.interpret(ctx);
- }.bind(this));
+ });
}
});
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
@@ -806,20 +807,20 @@ Object.extend(Enumerable, {
function $A(iterable) {
if (!iterable) return [];
if (iterable.toArray) return iterable.toArray();
- var length = iterable.length, results = new Array(length);
+ var length = iterable.length || 0, results = new Array(length);
while (length--) results[length] = iterable[length];
return results;
}
if (Prototype.Browser.WebKit) {
- function $A(iterable) {
+ $A = function(iterable) {
if (!iterable) return [];
if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
iterable.toArray) return iterable.toArray();
- var length = iterable.length, results = new Array(length);
+ var length = iterable.length || 0, results = new Array(length);
while (length--) results[length] = iterable[length];
return results;
- }
+ };
}
Array.from = $A;
@@ -1298,7 +1299,7 @@ Ajax.Request = Class.create(Ajax.Base, {
var contentType = response.getHeader('Content-type');
if (this.options.evalJS == 'force'
- || (this.options.evalJS && contentType
+ || (this.options.evalJS && this.isSameOrigin() && contentType
&& contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
this.evalResponse();
}
@@ -1316,9 +1317,18 @@ Ajax.Request = Class.create(Ajax.Base, {
}
},
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
+ },
+
getHeader: function(name) {
try {
- return this.transport.getResponseHeader(name);
+ return this.transport.getResponseHeader(name) || null;
} catch (e) { return null }
},
@@ -1391,7 +1401,8 @@ Ajax.Response = Class.create({
if (!json) return null;
json = decodeURIComponent(escape(json));
try {
- return json.evalJSON(this.request.options.sanitizeJSON);
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
} catch (e) {
this.request.dispatchException(e);
}
@@ -1404,7 +1415,8 @@ Ajax.Response = Class.create({
this.responseText.blank())
return null;
try {
- return this.responseText.evalJSON(options.sanitizeJSON);
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
} catch (e) {
this.request.dispatchException(e);
}
@@ -1608,24 +1620,28 @@ Element.Methods = {
Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
insertions = {bottom:insertions};
- var content, t, range;
+ var content, insert, tagName, childNodes;
- for (position in insertions) {
+ for (var position in insertions) {
content = insertions[position];
position = position.toLowerCase();
- t = Element._insertionTranslations[position];
+ insert = Element._insertionTranslations[position];
if (content && content.toElement) content = content.toElement();
if (Object.isElement(content)) {
- t.insert(element, content);
+ insert(element, content);
continue;
}
content = Object.toHTML(content);
- range = element.ownerDocument.createRange();
- t.initializeRange(element, range);
- t.insert(element, range.createContextualFragment(content.stripScripts()));
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+ if (position == 'top' || position == 'after') childNodes.reverse();
+ childNodes.each(insert.curry(element));
content.evalScripts.bind(content).defer();
}
@@ -1670,7 +1686,7 @@ Element.Methods = {
},
descendants: function(element) {
- return $(element).getElementsBySelector("*");
+ return $(element).select("*");
},
firstDescendant: function(element) {
@@ -1709,32 +1725,31 @@ Element.Methods = {
element = $(element);
if (arguments.length == 1) return $(element.parentNode);
var ancestors = element.ancestors();
- return expression ? Selector.findElement(ancestors, expression, index) :
- ancestors[index || 0];
+ return Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
},
down: function(element, expression, index) {
element = $(element);
if (arguments.length == 1) return element.firstDescendant();
- var descendants = element.descendants();
- return expression ? Selector.findElement(descendants, expression, index) :
- descendants[index || 0];
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ element.select(expression)[index || 0];
},
previous: function(element, expression, index) {
element = $(element);
if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
var previousSiblings = element.previousSiblings();
- return expression ? Selector.findElement(previousSiblings, expression, index) :
- previousSiblings[index || 0];
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
},
next: function(element, expression, index) {
element = $(element);
if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
var nextSiblings = element.nextSiblings();
- return expression ? Selector.findElement(nextSiblings, expression, index) :
- nextSiblings[index || 0];
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
},
select: function() {
@@ -1860,7 +1875,8 @@ Element.Methods = {
do { ancestor = ancestor.parentNode; }
while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
}
- if (nextAncestor) return (e > a && e < nextAncestor.sourceIndex);
+ if (nextAncestor && nextAncestor.sourceIndex)
+ return (e > a && e < nextAncestor.sourceIndex);
}
while (element = element.parentNode)
@@ -2004,7 +2020,7 @@ Element.Methods = {
if (element) {
if (element.tagName == 'BODY') break;
var p = Element.getStyle(element, 'position');
- if (p == 'relative' || p == 'absolute') break;
+ if (p !== 'static') break;
}
} while (element);
return Element._returnOffset(valueL, valueT);
@@ -2153,46 +2169,6 @@ Element._attributeTranslations = {
}
};
-
-if (!document.createRange || Prototype.Browser.Opera) {
- Element.Methods.insert = function(element, insertions) {
- element = $(element);
-
- if (Object.isString(insertions) || Object.isNumber(insertions) ||
- Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
- insertions = { bottom: insertions };
-
- var t = Element._insertionTranslations, content, position, pos, tagName;
-
- for (position in insertions) {
- content = insertions[position];
- position = position.toLowerCase();
- pos = t[position];
-
- if (content && content.toElement) content = content.toElement();
- if (Object.isElement(content)) {
- pos.insert(element, content);
- continue;
- }
-
- content = Object.toHTML(content);
- tagName = ((position == 'before' || position == 'after')
- ? element.parentNode : element).tagName.toUpperCase();
-
- if (t.tags[tagName]) {
- var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
- if (position == 'top' || position == 'after') fragments.reverse();
- fragments.each(pos.insert.curry(element));
- }
- else element.insertAdjacentHTML(pos.adjacency, content.stripScripts());
-
- content.evalScripts.bind(content).defer();
- }
-
- return element;
- };
-}
-
if (Prototype.Browser.Opera) {
Element.Methods.getStyle = Element.Methods.getStyle.wrap(
function(proceed, element, style) {
@@ -2237,12 +2213,31 @@ if (Prototype.Browser.Opera) {
}
else if (Prototype.Browser.IE) {
- $w('positionedOffset getOffsetParent viewportOffset').each(function(method) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ 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);
var position = element.getStyle('position');
- if (position != 'static') return proceed(element);
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ 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 });
@@ -2324,7 +2319,10 @@ else if (Prototype.Browser.IE) {
};
Element._attributeTranslations.write = {
- names: Object.clone(Element._attributeTranslations.read.names),
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
values: {
checked: function(element, value) {
element.checked = !!value;
@@ -2444,7 +2442,7 @@ if (Prototype.Browser.IE || Prototype.Browser.Opera) {
};
}
-if (document.createElement('div').outerHTML) {
+if ('outerHTML' in document.createElement('div')) {
Element.Methods.replace = function(element, content) {
element = $(element);
@@ -2482,45 +2480,25 @@ Element._returnOffset = function(l, t) {
Element._getContentFromAnonymousElement = function(tagName, html) {
var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
- div.innerHTML = t[0] + html + t[1];
- t[2].times(function() { div = div.firstChild });
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
return $A(div.childNodes);
};
Element._insertionTranslations = {
- before: {
- adjacency: 'beforeBegin',
- insert: function(element, node) {
- element.parentNode.insertBefore(node, element);
- },
- initializeRange: function(element, range) {
- range.setStartBefore(element);
- }
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
},
- top: {
- adjacency: 'afterBegin',
- insert: function(element, node) {
- element.insertBefore(node, element.firstChild);
- },
- initializeRange: function(element, range) {
- range.selectNodeContents(element);
- range.collapse(true);
- }
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
},
- bottom: {
- adjacency: 'beforeEnd',
- insert: function(element, node) {
- element.appendChild(node);
- }
+ bottom: function(element, node) {
+ element.appendChild(node);
},
- after: {
- adjacency: 'afterEnd',
- insert: function(element, node) {
- element.parentNode.insertBefore(node, element.nextSibling);
- },
- initializeRange: function(element, range) {
- range.setStartAfter(element);
- }
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
},
tags: {
TABLE: ['', 1],
@@ -2532,7 +2510,6 @@ Element._insertionTranslations = {
};
(function() {
- this.bottom.initializeRange = this.top.initializeRange;
Object.extend(this.tags, {
THEAD: this.tags.TBODY,
TFOOT: this.tags.TBODY,
@@ -2716,7 +2693,7 @@ document.viewport = {
window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
}
};
-/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
+/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
* part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
* license. Please see http://www.yui-ext.com/ for more information. */
@@ -2959,13 +2936,13 @@ Object.extend(Selector, {
},
criteria: {
- tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
- className: 'n = h.className(n, r, "#{1}", c); c = false;',
- id: 'n = h.id(n, r, "#{1}", c); c = false;',
- attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;',
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
attr: function(m) {
m[3] = (m[5] || m[6]);
- return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
},
pseudo: function(m) {
if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
@@ -2989,7 +2966,8 @@ Object.extend(Selector, {
tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
id: /^#([\w\-\*]+)(\b|$)/,
className: /^\.([\w\-\*]+)(\b|$)/,
- pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s)|(?=:))/,
+ pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
attrPresence: /^\[([\w]+)\]/,
attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
},
@@ -3014,7 +2992,7 @@ Object.extend(Selector, {
attr: function(element, matches) {
var nodeValue = Element.readAttribute(element, matches[1]);
- return Selector.operators[matches[2]](nodeValue, matches[3]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
}
},
@@ -3029,14 +3007,15 @@ Object.extend(Selector, {
// marks an array of nodes for counting
mark: function(nodes) {
+ var _true = Prototype.emptyFunction;
for (var i = 0, node; node = nodes[i]; i++)
- node._counted = true;
+ node._countedByPrototype = _true;
return nodes;
},
unmark: function(nodes) {
for (var i = 0, node; node = nodes[i]; i++)
- node._counted = undefined;
+ node._countedByPrototype = undefined;
return nodes;
},
@@ -3044,15 +3023,15 @@ Object.extend(Selector, {
// "ofType" flag indicates whether we're indexing for nth-of-type
// rather than nth-child
index: function(parentNode, reverse, ofType) {
- parentNode._counted = true;
+ parentNode._countedByPrototype = Prototype.emptyFunction;
if (reverse) {
for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
var node = nodes[i];
- if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
}
} else {
for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
- if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
}
},
@@ -3061,8 +3040,8 @@ Object.extend(Selector, {
if (nodes.length == 0) return nodes;
var results = [], n;
for (var i = 0, l = nodes.length; i < l; i++)
- if (!(n = nodes[i])._counted) {
- n._counted = true;
+ if (!(n = nodes[i])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
results.push(Element.extend(n));
}
return Selector.handlers.unmark(results);
@@ -3114,7 +3093,7 @@ Object.extend(Selector, {
// TOKEN FUNCTIONS
tagName: function(nodes, root, tagName, combinator) {
- tagName = tagName.toUpperCase();
+ var uTagName = tagName.toUpperCase();
var results = [], h = Selector.handlers;
if (nodes) {
if (combinator) {
@@ -3127,7 +3106,7 @@ Object.extend(Selector, {
if (tagName == "*") return nodes;
}
for (var i = 0, node; node = nodes[i]; i++)
- if (node.tagName.toUpperCase() == tagName) results.push(node);
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
return results;
} else return root.getElementsByTagName(tagName);
},
@@ -3174,16 +3153,18 @@ Object.extend(Selector, {
return results;
},
- attrPresence: function(nodes, root, attr) {
+ attrPresence: function(nodes, root, attr, combinator) {
if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
var results = [];
for (var i = 0, node; node = nodes[i]; i++)
if (Element.hasAttribute(node, attr)) results.push(node);
return results;
},
- attr: function(nodes, root, attr, value, operator) {
+ attr: function(nodes, root, attr, value, operator, combinator) {
if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
var handler = Selector.operators[operator], results = [];
for (var i = 0, node; node = nodes[i]; i++) {
var nodeValue = Element.readAttribute(node, attr);
@@ -3262,7 +3243,7 @@ Object.extend(Selector, {
var h = Selector.handlers, results = [], indexed = [], m;
h.mark(nodes);
for (var i = 0, node; node = nodes[i]; i++) {
- if (!node.parentNode._counted) {
+ if (!node.parentNode._countedByPrototype) {
h.index(node.parentNode, reverse, ofType);
indexed.push(node.parentNode);
}
@@ -3300,7 +3281,7 @@ Object.extend(Selector, {
var exclusions = new Selector(selector).findElements(root);
h.mark(exclusions);
for (var i = 0, results = [], node; node = nodes[i]; i++)
- if (!node._counted) results.push(node);
+ if (!node._countedByPrototype) results.push(node);
h.unmark(exclusions);
return results;
},
@@ -3334,11 +3315,19 @@ Object.extend(Selector, {
'|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
},
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
matchElements: function(elements, expression) {
- var matches = new Selector(expression).findElements(), h = Selector.handlers;
+ var matches = $$(expression), h = Selector.handlers;
h.mark(matches);
for (var i = 0, results = [], element; element = elements[i]; i++)
- if (element._counted) results.push(element);
+ if (element._countedByPrototype) results.push(element);
h.unmark(matches);
return results;
},
@@ -3351,11 +3340,7 @@ Object.extend(Selector, {
},
findChildElements: function(element, expressions) {
- var exprs = expressions.join(',');
- expressions = [];
- exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
- expressions.push(m[1].strip());
- });
+ expressions = Selector.split(expressions.join(','));
var results = [], h = Selector.handlers;
for (var i = 0, l = expressions.length, selector; i < l; i++) {
selector = new Selector(expressions[i].strip());
@@ -3366,13 +3351,22 @@ Object.extend(Selector, {
});
if (Prototype.Browser.IE) {
- // IE returns comment nodes on getElementsByTagName("*").
- // Filter them out.
- Selector.handlers.concat = function(a, b) {
- for (var i = 0, node; node = b[i]; i++)
- if (node.tagName !== "!") a.push(node);
- return a;
- };
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
}
function $$() {
@@ -3850,9 +3844,9 @@ Object.extend(Event, (function() {
var cache = Event.cache;
function getEventID(element) {
- if (element._eventID) return element._eventID;
+ if (element._prototypeEventID) return element._prototypeEventID[0];
arguments.callee.id = arguments.callee.id || 1;
- return element._eventID = ++arguments.callee.id;
+ return element._prototypeEventID = [++arguments.callee.id];
}
function getDOMEventName(eventName) {
@@ -3880,7 +3874,7 @@ Object.extend(Event, (function() {
return false;
Event.extend(event);
- handler.call(element, event)
+ handler.call(element, event);
};
wrapper.handler = handler;
@@ -3962,11 +3956,12 @@ Object.extend(Event, (function() {
if (element == document && document.createEvent && !element.dispatchEvent)
element = document.documentElement;
+ var event;
if (document.createEvent) {
- var event = document.createEvent("HTMLEvents");
+ event = document.createEvent("HTMLEvents");
event.initEvent("dataavailable", true, true);
} else {
- var event = document.createEventObject();
+ event = document.createEventObject();
event.eventType = "ondataavailable";
}
@@ -3995,20 +3990,21 @@ Element.addMethods({
Object.extend(document, {
fire: Element.Methods.fire.methodize(),
observe: Element.Methods.observe.methodize(),
- stopObserving: Element.Methods.stopObserving.methodize()
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
});
(function() {
/* Support for the DOMContentLoaded event is based on work by Dan Webb,
Matthias Miller, Dean Edwards and John Resig. */
- var timer, fired = false;
+ var timer;
function fireContentLoadedEvent() {
- if (fired) return;
+ if (document.loaded) return;
if (timer) window.clearInterval(timer);
document.fire("dom:loaded");
- fired = true;
+ document.loaded = true;
}
if (document.addEventListener) {
diff --git a/railties/html/javascripts/prototype.js b/railties/html/javascripts/prototype.js
index 546f9fe449..2c70b8a7e8 100644
--- a/railties/html/javascripts/prototype.js
+++ b/railties/html/javascripts/prototype.js
@@ -1,5 +1,5 @@
-/* Prototype JavaScript framework, version 1.6.0.1
- * (c) 2005-2007 Sam Stephenson
+/* Prototype JavaScript framework, version 1.6.0.2
+ * (c) 2005-2008 Sam Stephenson
*
* Prototype is freely distributable under the terms of an MIT-style license.
* For details, see the Prototype web site: http://www.prototypejs.org/
@@ -7,7 +7,7 @@
*--------------------------------------------------------------------------*/
var Prototype = {
- Version: '1.6.0.1',
+ Version: '1.6.0.2',
Browser: {
IE: !!(window.attachEvent && !window.opera),
@@ -110,7 +110,7 @@ Object.extend(Object, {
try {
if (Object.isUndefined(object)) return 'undefined';
if (object === null) return 'null';
- return object.inspect ? object.inspect() : object.toString();
+ return object.inspect ? object.inspect() : String(object);
} catch (e) {
if (e instanceof RangeError) return '...';
throw e;
@@ -171,7 +171,8 @@ Object.extend(Object, {
},
isArray: function(object) {
- return object && object.constructor === Array;
+ return object != null && typeof object == "object" &&
+ 'splice' in object && 'join' in object;
},
isHash: function(object) {
@@ -578,7 +579,7 @@ var Template = Class.create({
}
return before + String.interpret(ctx);
- }.bind(this));
+ });
}
});
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
@@ -806,20 +807,20 @@ Object.extend(Enumerable, {
function $A(iterable) {
if (!iterable) return [];
if (iterable.toArray) return iterable.toArray();
- var length = iterable.length, results = new Array(length);
+ var length = iterable.length || 0, results = new Array(length);
while (length--) results[length] = iterable[length];
return results;
}
if (Prototype.Browser.WebKit) {
- function $A(iterable) {
+ $A = function(iterable) {
if (!iterable) return [];
if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') &&
iterable.toArray) return iterable.toArray();
- var length = iterable.length, results = new Array(length);
+ var length = iterable.length || 0, results = new Array(length);
while (length--) results[length] = iterable[length];
return results;
- }
+ };
}
Array.from = $A;
@@ -1298,7 +1299,7 @@ Ajax.Request = Class.create(Ajax.Base, {
var contentType = response.getHeader('Content-type');
if (this.options.evalJS == 'force'
- || (this.options.evalJS && contentType
+ || (this.options.evalJS && this.isSameOrigin() && contentType
&& contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
this.evalResponse();
}
@@ -1316,9 +1317,18 @@ Ajax.Request = Class.create(Ajax.Base, {
}
},
+ isSameOrigin: function() {
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
+ protocol: location.protocol,
+ domain: document.domain,
+ port: location.port ? ':' + location.port : ''
+ }));
+ },
+
getHeader: function(name) {
try {
- return this.transport.getResponseHeader(name);
+ return this.transport.getResponseHeader(name) || null;
} catch (e) { return null }
},
@@ -1391,7 +1401,8 @@ Ajax.Response = Class.create({
if (!json) return null;
json = decodeURIComponent(escape(json));
try {
- return json.evalJSON(this.request.options.sanitizeJSON);
+ return json.evalJSON(this.request.options.sanitizeJSON ||
+ !this.request.isSameOrigin());
} catch (e) {
this.request.dispatchException(e);
}
@@ -1404,7 +1415,8 @@ Ajax.Response = Class.create({
this.responseText.blank())
return null;
try {
- return this.responseText.evalJSON(options.sanitizeJSON);
+ return this.responseText.evalJSON(options.sanitizeJSON ||
+ !this.request.isSameOrigin());
} catch (e) {
this.request.dispatchException(e);
}
@@ -1608,24 +1620,28 @@ Element.Methods = {
Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
insertions = {bottom:insertions};
- var content, t, range;
+ var content, insert, tagName, childNodes;
- for (position in insertions) {
+ for (var position in insertions) {
content = insertions[position];
position = position.toLowerCase();
- t = Element._insertionTranslations[position];
+ insert = Element._insertionTranslations[position];
if (content && content.toElement) content = content.toElement();
if (Object.isElement(content)) {
- t.insert(element, content);
+ insert(element, content);
continue;
}
content = Object.toHTML(content);
- range = element.ownerDocument.createRange();
- t.initializeRange(element, range);
- t.insert(element, range.createContextualFragment(content.stripScripts()));
+ tagName = ((position == 'before' || position == 'after')
+ ? element.parentNode : element).tagName.toUpperCase();
+
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
+
+ if (position == 'top' || position == 'after') childNodes.reverse();
+ childNodes.each(insert.curry(element));
content.evalScripts.bind(content).defer();
}
@@ -1670,7 +1686,7 @@ Element.Methods = {
},
descendants: function(element) {
- return $(element).getElementsBySelector("*");
+ return $(element).select("*");
},
firstDescendant: function(element) {
@@ -1709,32 +1725,31 @@ Element.Methods = {
element = $(element);
if (arguments.length == 1) return $(element.parentNode);
var ancestors = element.ancestors();
- return expression ? Selector.findElement(ancestors, expression, index) :
- ancestors[index || 0];
+ return Object.isNumber(expression) ? ancestors[expression] :
+ Selector.findElement(ancestors, expression, index);
},
down: function(element, expression, index) {
element = $(element);
if (arguments.length == 1) return element.firstDescendant();
- var descendants = element.descendants();
- return expression ? Selector.findElement(descendants, expression, index) :
- descendants[index || 0];
+ return Object.isNumber(expression) ? element.descendants()[expression] :
+ element.select(expression)[index || 0];
},
previous: function(element, expression, index) {
element = $(element);
if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
var previousSiblings = element.previousSiblings();
- return expression ? Selector.findElement(previousSiblings, expression, index) :
- previousSiblings[index || 0];
+ return Object.isNumber(expression) ? previousSiblings[expression] :
+ Selector.findElement(previousSiblings, expression, index);
},
next: function(element, expression, index) {
element = $(element);
if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
var nextSiblings = element.nextSiblings();
- return expression ? Selector.findElement(nextSiblings, expression, index) :
- nextSiblings[index || 0];
+ return Object.isNumber(expression) ? nextSiblings[expression] :
+ Selector.findElement(nextSiblings, expression, index);
},
select: function() {
@@ -1860,7 +1875,8 @@ Element.Methods = {
do { ancestor = ancestor.parentNode; }
while (!(nextAncestor = ancestor.nextSibling) && ancestor.parentNode);
}
- if (nextAncestor) return (e > a && e < nextAncestor.sourceIndex);
+ if (nextAncestor && nextAncestor.sourceIndex)
+ return (e > a && e < nextAncestor.sourceIndex);
}
while (element = element.parentNode)
@@ -2004,7 +2020,7 @@ Element.Methods = {
if (element) {
if (element.tagName == 'BODY') break;
var p = Element.getStyle(element, 'position');
- if (p == 'relative' || p == 'absolute') break;
+ if (p !== 'static') break;
}
} while (element);
return Element._returnOffset(valueL, valueT);
@@ -2153,46 +2169,6 @@ Element._attributeTranslations = {
}
};
-
-if (!document.createRange || Prototype.Browser.Opera) {
- Element.Methods.insert = function(element, insertions) {
- element = $(element);
-
- if (Object.isString(insertions) || Object.isNumber(insertions) ||
- Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
- insertions = { bottom: insertions };
-
- var t = Element._insertionTranslations, content, position, pos, tagName;
-
- for (position in insertions) {
- content = insertions[position];
- position = position.toLowerCase();
- pos = t[position];
-
- if (content && content.toElement) content = content.toElement();
- if (Object.isElement(content)) {
- pos.insert(element, content);
- continue;
- }
-
- content = Object.toHTML(content);
- tagName = ((position == 'before' || position == 'after')
- ? element.parentNode : element).tagName.toUpperCase();
-
- if (t.tags[tagName]) {
- var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
- if (position == 'top' || position == 'after') fragments.reverse();
- fragments.each(pos.insert.curry(element));
- }
- else element.insertAdjacentHTML(pos.adjacency, content.stripScripts());
-
- content.evalScripts.bind(content).defer();
- }
-
- return element;
- };
-}
-
if (Prototype.Browser.Opera) {
Element.Methods.getStyle = Element.Methods.getStyle.wrap(
function(proceed, element, style) {
@@ -2237,12 +2213,31 @@ if (Prototype.Browser.Opera) {
}
else if (Prototype.Browser.IE) {
- $w('positionedOffset getOffsetParent viewportOffset').each(function(method) {
+ // IE doesn't report offsets correctly for static elements, so we change them
+ // to "relative" to get the values, then change them back.
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
+ function(proceed, element) {
+ element = $(element);
+ 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);
var position = element.getStyle('position');
- if (position != 'static') return proceed(element);
+ if (position !== 'static') return proceed(element);
+ // Trigger hasLayout on the offset parent so that IE6 reports
+ // accurate offsetTop and offsetLeft values for position: fixed.
+ 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 });
@@ -2324,7 +2319,10 @@ else if (Prototype.Browser.IE) {
};
Element._attributeTranslations.write = {
- names: Object.clone(Element._attributeTranslations.read.names),
+ names: Object.extend({
+ cellpadding: 'cellPadding',
+ cellspacing: 'cellSpacing'
+ }, Element._attributeTranslations.read.names),
values: {
checked: function(element, value) {
element.checked = !!value;
@@ -2444,7 +2442,7 @@ if (Prototype.Browser.IE || Prototype.Browser.Opera) {
};
}
-if (document.createElement('div').outerHTML) {
+if ('outerHTML' in document.createElement('div')) {
Element.Methods.replace = function(element, content) {
element = $(element);
@@ -2482,45 +2480,25 @@ Element._returnOffset = function(l, t) {
Element._getContentFromAnonymousElement = function(tagName, html) {
var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
- div.innerHTML = t[0] + html + t[1];
- t[2].times(function() { div = div.firstChild });
+ if (t) {
+ div.innerHTML = t[0] + html + t[1];
+ t[2].times(function() { div = div.firstChild });
+ } else div.innerHTML = html;
return $A(div.childNodes);
};
Element._insertionTranslations = {
- before: {
- adjacency: 'beforeBegin',
- insert: function(element, node) {
- element.parentNode.insertBefore(node, element);
- },
- initializeRange: function(element, range) {
- range.setStartBefore(element);
- }
+ before: function(element, node) {
+ element.parentNode.insertBefore(node, element);
},
- top: {
- adjacency: 'afterBegin',
- insert: function(element, node) {
- element.insertBefore(node, element.firstChild);
- },
- initializeRange: function(element, range) {
- range.selectNodeContents(element);
- range.collapse(true);
- }
+ top: function(element, node) {
+ element.insertBefore(node, element.firstChild);
},
- bottom: {
- adjacency: 'beforeEnd',
- insert: function(element, node) {
- element.appendChild(node);
- }
+ bottom: function(element, node) {
+ element.appendChild(node);
},
- after: {
- adjacency: 'afterEnd',
- insert: function(element, node) {
- element.parentNode.insertBefore(node, element.nextSibling);
- },
- initializeRange: function(element, range) {
- range.setStartAfter(element);
- }
+ after: function(element, node) {
+ element.parentNode.insertBefore(node, element.nextSibling);
},
tags: {
TABLE: ['', 1],
@@ -2532,7 +2510,6 @@ Element._insertionTranslations = {
};
(function() {
- this.bottom.initializeRange = this.top.initializeRange;
Object.extend(this.tags, {
THEAD: this.tags.TBODY,
TFOOT: this.tags.TBODY,
@@ -2716,7 +2693,7 @@ document.viewport = {
window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
}
};
-/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
+/* Portions of the Selector class are derived from Jack Slocum’s DomQuery,
* part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
* license. Please see http://www.yui-ext.com/ for more information. */
@@ -2959,13 +2936,13 @@ Object.extend(Selector, {
},
criteria: {
- tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
- className: 'n = h.className(n, r, "#{1}", c); c = false;',
- id: 'n = h.id(n, r, "#{1}", c); c = false;',
- attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;',
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
attr: function(m) {
m[3] = (m[5] || m[6]);
- return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m);
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
},
pseudo: function(m) {
if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
@@ -2989,7 +2966,8 @@ Object.extend(Selector, {
tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
id: /^#([\w\-\*]+)(\b|$)/,
className: /^\.([\w\-\*]+)(\b|$)/,
- pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s)|(?=:))/,
+ pseudo:
+/^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
attrPresence: /^\[([\w]+)\]/,
attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
},
@@ -3014,7 +2992,7 @@ Object.extend(Selector, {
attr: function(element, matches) {
var nodeValue = Element.readAttribute(element, matches[1]);
- return Selector.operators[matches[2]](nodeValue, matches[3]);
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
}
},
@@ -3029,14 +3007,15 @@ Object.extend(Selector, {
// marks an array of nodes for counting
mark: function(nodes) {
+ var _true = Prototype.emptyFunction;
for (var i = 0, node; node = nodes[i]; i++)
- node._counted = true;
+ node._countedByPrototype = _true;
return nodes;
},
unmark: function(nodes) {
for (var i = 0, node; node = nodes[i]; i++)
- node._counted = undefined;
+ node._countedByPrototype = undefined;
return nodes;
},
@@ -3044,15 +3023,15 @@ Object.extend(Selector, {
// "ofType" flag indicates whether we're indexing for nth-of-type
// rather than nth-child
index: function(parentNode, reverse, ofType) {
- parentNode._counted = true;
+ parentNode._countedByPrototype = Prototype.emptyFunction;
if (reverse) {
for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
var node = nodes[i];
- if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
}
} else {
for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
- if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++;
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
}
},
@@ -3061,8 +3040,8 @@ Object.extend(Selector, {
if (nodes.length == 0) return nodes;
var results = [], n;
for (var i = 0, l = nodes.length; i < l; i++)
- if (!(n = nodes[i])._counted) {
- n._counted = true;
+ if (!(n = nodes[i])._countedByPrototype) {
+ n._countedByPrototype = Prototype.emptyFunction;
results.push(Element.extend(n));
}
return Selector.handlers.unmark(results);
@@ -3114,7 +3093,7 @@ Object.extend(Selector, {
// TOKEN FUNCTIONS
tagName: function(nodes, root, tagName, combinator) {
- tagName = tagName.toUpperCase();
+ var uTagName = tagName.toUpperCase();
var results = [], h = Selector.handlers;
if (nodes) {
if (combinator) {
@@ -3127,7 +3106,7 @@ Object.extend(Selector, {
if (tagName == "*") return nodes;
}
for (var i = 0, node; node = nodes[i]; i++)
- if (node.tagName.toUpperCase() == tagName) results.push(node);
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
return results;
} else return root.getElementsByTagName(tagName);
},
@@ -3174,16 +3153,18 @@ Object.extend(Selector, {
return results;
},
- attrPresence: function(nodes, root, attr) {
+ attrPresence: function(nodes, root, attr, combinator) {
if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
var results = [];
for (var i = 0, node; node = nodes[i]; i++)
if (Element.hasAttribute(node, attr)) results.push(node);
return results;
},
- attr: function(nodes, root, attr, value, operator) {
+ attr: function(nodes, root, attr, value, operator, combinator) {
if (!nodes) nodes = root.getElementsByTagName("*");
+ if (nodes && combinator) nodes = this[combinator](nodes);
var handler = Selector.operators[operator], results = [];
for (var i = 0, node; node = nodes[i]; i++) {
var nodeValue = Element.readAttribute(node, attr);
@@ -3262,7 +3243,7 @@ Object.extend(Selector, {
var h = Selector.handlers, results = [], indexed = [], m;
h.mark(nodes);
for (var i = 0, node; node = nodes[i]; i++) {
- if (!node.parentNode._counted) {
+ if (!node.parentNode._countedByPrototype) {
h.index(node.parentNode, reverse, ofType);
indexed.push(node.parentNode);
}
@@ -3300,7 +3281,7 @@ Object.extend(Selector, {
var exclusions = new Selector(selector).findElements(root);
h.mark(exclusions);
for (var i = 0, results = [], node; node = nodes[i]; i++)
- if (!node._counted) results.push(node);
+ if (!node._countedByPrototype) results.push(node);
h.unmark(exclusions);
return results;
},
@@ -3334,11 +3315,19 @@ Object.extend(Selector, {
'|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); }
},
+ split: function(expression) {
+ var expressions = [];
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
+ expressions.push(m[1].strip());
+ });
+ return expressions;
+ },
+
matchElements: function(elements, expression) {
- var matches = new Selector(expression).findElements(), h = Selector.handlers;
+ var matches = $$(expression), h = Selector.handlers;
h.mark(matches);
for (var i = 0, results = [], element; element = elements[i]; i++)
- if (element._counted) results.push(element);
+ if (element._countedByPrototype) results.push(element);
h.unmark(matches);
return results;
},
@@ -3351,11 +3340,7 @@ Object.extend(Selector, {
},
findChildElements: function(element, expressions) {
- var exprs = expressions.join(',');
- expressions = [];
- exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
- expressions.push(m[1].strip());
- });
+ expressions = Selector.split(expressions.join(','));
var results = [], h = Selector.handlers;
for (var i = 0, l = expressions.length, selector; i < l; i++) {
selector = new Selector(expressions[i].strip());
@@ -3366,13 +3351,22 @@ Object.extend(Selector, {
});
if (Prototype.Browser.IE) {
- // IE returns comment nodes on getElementsByTagName("*").
- // Filter them out.
- Selector.handlers.concat = function(a, b) {
- for (var i = 0, node; node = b[i]; i++)
- if (node.tagName !== "!") a.push(node);
- return a;
- };
+ Object.extend(Selector.handlers, {
+ // IE returns comment nodes on getElementsByTagName("*").
+ // Filter them out.
+ concat: function(a, b) {
+ for (var i = 0, node; node = b[i]; i++)
+ if (node.tagName !== "!") a.push(node);
+ return a;
+ },
+
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
+ unmark: function(nodes) {
+ for (var i = 0, node; node = nodes[i]; i++)
+ node.removeAttribute('_countedByPrototype');
+ return nodes;
+ }
+ });
}
function $$() {
@@ -3850,9 +3844,9 @@ Object.extend(Event, (function() {
var cache = Event.cache;
function getEventID(element) {
- if (element._eventID) return element._eventID;
+ if (element._prototypeEventID) return element._prototypeEventID[0];
arguments.callee.id = arguments.callee.id || 1;
- return element._eventID = ++arguments.callee.id;
+ return element._prototypeEventID = [++arguments.callee.id];
}
function getDOMEventName(eventName) {
@@ -3880,7 +3874,7 @@ Object.extend(Event, (function() {
return false;
Event.extend(event);
- handler.call(element, event)
+ handler.call(element, event);
};
wrapper.handler = handler;
@@ -3962,11 +3956,12 @@ Object.extend(Event, (function() {
if (element == document && document.createEvent && !element.dispatchEvent)
element = document.documentElement;
+ var event;
if (document.createEvent) {
- var event = document.createEvent("HTMLEvents");
+ event = document.createEvent("HTMLEvents");
event.initEvent("dataavailable", true, true);
} else {
- var event = document.createEventObject();
+ event = document.createEventObject();
event.eventType = "ondataavailable";
}
@@ -3995,20 +3990,21 @@ Element.addMethods({
Object.extend(document, {
fire: Element.Methods.fire.methodize(),
observe: Element.Methods.observe.methodize(),
- stopObserving: Element.Methods.stopObserving.methodize()
+ stopObserving: Element.Methods.stopObserving.methodize(),
+ loaded: false
});
(function() {
/* Support for the DOMContentLoaded event is based on work by Dan Webb,
Matthias Miller, Dean Edwards and John Resig. */
- var timer, fired = false;
+ var timer;
function fireContentLoadedEvent() {
- if (fired) return;
+ if (document.loaded) return;
if (timer) window.clearInterval(timer);
document.fire("dom:loaded");
- fired = true;
+ document.loaded = true;
}
if (document.addEventListener) {
--
cgit v1.2.3
From 1b4b1aa725a4f44c3473ae99b36d7cededba2bea Mon Sep 17 00:00:00 2001
From: Kevin Glowacz
Date: Sat, 19 Jul 2008 15:08:53 -0500
Subject: Fixed index and auto index for nested fields_for [#327
state:resolved]
Signed-off-by: Joshua Peek
---
actionpack/lib/action_view/helpers/form_helper.rb | 30 ++++--
actionpack/test/template/form_helper_test.rb | 116 +++++++++++++++++++++-
2 files changed, 136 insertions(+), 10 deletions(-)
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index 4fa46d9ee3..ada6fa2ea8 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -528,10 +528,10 @@ module ActionView
def initialize(object_name, method_name, template_object, object = nil)
@object_name, @method_name = object_name.to_s.dup, method_name.to_s.dup
- @template_object= template_object
+ @template_object = template_object
@object = object
- if @object_name.sub!(/\[\]$/,"")
- if object ||= @template_object.instance_variable_get("@#{Regexp.last_match.pre_match}") and object.respond_to?(:to_param)
+ if @object_name.sub!(/\[\]$/,"") || @object_name.sub!(/\[\]\]$/,"]")
+ if (object ||= @template_object.instance_variable_get("@#{Regexp.last_match.pre_match}")) && object.respond_to?(:to_param)
@auto_index = object.to_param
else
raise ArgumentError, "object[] naming but object param and @object var don't exist or don't respond to to_param: #{object.inspect}"
@@ -708,7 +708,7 @@ module ActionView
end
def sanitized_object_name
- @sanitized_object_name ||= @object_name.gsub(/[^-a-zA-Z0-9:.]/, "_").sub(/_$/, "")
+ @sanitized_object_name ||= @object_name.gsub(/\]\[|[^-a-zA-Z0-9:.]/, "_").sub(/_$/, "")
end
def sanitized_method_name
@@ -726,6 +726,13 @@ module ActionView
def initialize(object_name, object, template, options, proc)
@object_name, @object, @template, @options, @proc = object_name, object, template, options, proc
@default_options = @options ? @options.slice(:index) : {}
+ if @object_name.to_s.match(/\[\]$/)
+ if object ||= @template.instance_variable_get("@#{Regexp.last_match.pre_match}") and object.respond_to?(:to_param)
+ @auto_index = object.to_param
+ else
+ raise ArgumentError, "object[] naming but object param and @object var don't exist or don't respond to to_param: #{object.inspect}"
+ end
+ end
end
(field_helpers - %w(label check_box radio_button fields_for)).each do |selector|
@@ -738,16 +745,25 @@ module ActionView
end
def fields_for(record_or_name_or_array, *args, &block)
+ if options.has_key?(:index)
+ index = "[#{options[:index]}]"
+ elsif defined?(@auto_index)
+ self.object_name = @object_name.to_s.sub(/\[\]$/,"")
+ index = "[#{@auto_index}]"
+ else
+ index = ""
+ end
+
case record_or_name_or_array
when String, Symbol
- name = "#{object_name}[#{record_or_name_or_array}]"
+ name = "#{object_name}#{index}[#{record_or_name_or_array}]"
when Array
object = record_or_name_or_array.last
- name = "#{object_name}[#{ActionController::RecordIdentifier.singular_class_name(object)}]"
+ name = "#{object_name}#{index}[#{ActionController::RecordIdentifier.singular_class_name(object)}]"
args.unshift(object)
else
object = record_or_name_or_array
- name = "#{object_name}[#{ActionController::RecordIdentifier.singular_class_name(object)}]"
+ name = "#{object_name}#{index}[#{ActionController::RecordIdentifier.singular_class_name(object)}]"
args.unshift(object)
end
diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb
index 39649c3622..52e8bf376a 100644
--- a/actionpack/test/template/form_helper_test.rb
+++ b/actionpack/test/template/form_helper_test.rb
@@ -6,7 +6,7 @@ silence_warnings do
alias_method :title_before_type_cast, :title unless respond_to?(:title_before_type_cast)
alias_method :body_before_type_cast, :body unless respond_to?(:body_before_type_cast)
alias_method :author_name_before_type_cast, :author_name unless respond_to?(:author_name_before_type_cast)
- alias_method :secret?, :secret
+ alias_method :secret?, :secret
def new_record=(boolean)
@new_record = boolean
@@ -22,6 +22,7 @@ silence_warnings do
attr_reader :post_id
def save; @id = 1; @post_id = 1 end
def new_record?; @id.nil? end
+ def to_param; @id; end
def name
@id.nil? ? 'new comment' : "comment ##{@id}"
end
@@ -30,7 +31,6 @@ end
class Comment::Nested < Comment; end
-
class FormHelperTest < ActionView::TestCase
tests ActionView::Helpers::FormHelper
@@ -447,6 +447,117 @@ class FormHelperTest < ActionView::TestCase
assert_dom_equal expected, output_buffer
end
+ def test_nested_fields_for_with_nested_collections
+ form_for('post[]', @post) do |f|
+ concat f.text_field(:title)
+ f.fields_for('comment[]', @comment) do |c|
+ concat c.text_field(:name)
+ end
+ end
+
+ expected = ""
+
+ assert_dom_equal expected, output_buffer
+ end
+
+ def test_nested_fields_for_with_index
+ form_for('post', @post, :index => 1) do |c|
+ concat c.text_field(:title)
+ c.fields_for('comment', @comment, :index => 1) do |r|
+ concat r.text_field(:name)
+ end
+ end
+
+ expected = ""
+
+ assert_dom_equal expected, output_buffer
+ end
+
+ def test_nested_fields_for_with_index
+ form_for(:post, @post, :index => 1) do |f|
+ f.fields_for(:comment, @post) do |c|
+ concat c.text_field(:title)
+ end
+ end
+
+ expected = ""
+
+ assert_dom_equal expected, output_buffer
+ end
+
+ def test_nested_fields_for_with_index_on_both
+ form_for(:post, @post, :index => 1) do |f|
+ f.fields_for(:comment, @post, :index => 5) do |c|
+ concat c.text_field(:title)
+ end
+ end
+
+ expected = ""
+
+ assert_dom_equal expected, output_buffer
+ end
+
+ def test_nested_fields_for_with_auto_index
+ form_for("post[]", @post) do |f|
+ f.fields_for(:comment, @post) do |c|
+ concat c.text_field(:title)
+ end
+ end
+
+ expected = ""
+
+ assert_dom_equal expected, output_buffer
+ end
+
+ def test_nested_fields_for_with_auto_index_on_both
+ form_for("post[]", @post) do |f|
+ f.fields_for("comment[]", @post) do |c|
+ concat c.text_field(:title)
+ end
+ end
+
+ expected = ""
+
+ assert_dom_equal expected, output_buffer
+ end
+
+ def test_nested_fields_for_with_index_and_auto_index
+ form_for("post[]", @post) do |f|
+ f.fields_for(:comment, @post, :index => 5) do |c|
+ concat c.text_field(:title)
+ end
+ end
+
+ form_for(:post, @post, :index => 1) do |f|
+ f.fields_for("comment[]", @post) do |c|
+ concat c.text_field(:title)
+ end
+ end
+
+ expected = "" +
+ ""
+
+ assert_dom_equal expected, output_buffer
+ end
+
def test_fields_for
fields_for(:post, @post) do |f|
concat f.text_field(:title)
@@ -831,7 +942,6 @@ class FormHelperTest < ActionView::TestCase
assert_dom_equal expected, output_buffer
end
-
protected
def comments_path(post)
"/posts/#{post.id}/comments"
--
cgit v1.2.3
From 55bfe6be52da1130abb1c148f10d8e9a11368ffd Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sat, 19 Jul 2008 15:27:55 -0500
Subject: Ensure ActionView::PathSet::Path is not initialized with a
precompiled path
---
actionmailer/lib/action_mailer/base.rb | 3 ++-
actionpack/lib/action_view/paths.rb | 2 ++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index bf60e2f3d5..a43296461b 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -426,7 +426,8 @@ module ActionMailer #:nodoc:
end
def template_root=(root)
- write_inheritable_attribute(:template_root, ActionView::PathSet::Path.new(root))
+ root = ActionView::PathSet::Path.new(root) if root.is_a?(String)
+ write_inheritable_attribute(:template_root, root)
end
end
diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb
index c7a5df762f..78548d4aa2 100644
--- a/actionpack/lib/action_view/paths.rb
+++ b/actionpack/lib/action_view/paths.rb
@@ -28,6 +28,8 @@ module ActionView #:nodoc:
delegate :to_s, :to_str, :inspect, :to => :path
def initialize(path)
+ raise ArgumentError, "path already is a Path class" if path.is_a?(Path)
+
@path = path.freeze
reload!
end
--
cgit v1.2.3
From 598b4546fd505efd98c4955f4881b4fd5b953588 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sat, 19 Jul 2008 15:43:39 -0500
Subject: Fixed spelling mistake in deprecation warning [#381 state:resolved]
---
actionpack/lib/action_view/base.rb | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index fe51af62e6..619a4270f8 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -172,13 +172,15 @@ module ActionView #:nodoc:
end
def self.cache_template_loading=(*args)
- ActiveSupport::Deprecation.warn("config.action_view.cache_template_loading option has been deprecated and has no affect. " <<
- "Please remove it from your config files.", caller)
+ ActiveSupport::Deprecation.warn(
+ "config.action_view.cache_template_loading option has been deprecated" +
+ "and has no effect. Please remove it from your config files.", caller)
end
def self.cache_template_extensions=(*args)
- ActiveSupport::Deprecation.warn("config.action_view.cache_template_extensions option has been deprecated and has no effect. " <<
- "Please remove it from your config files.", caller)
+ ActiveSupport::Deprecation.warn(
+ "config.action_view.cache_template_extensions option has been" +
+ "deprecated and has no effect. Please remove it from your config files.", caller)
end
# Specify whether RJS responses should be wrapped in a try/catch block
--
cgit v1.2.3
From da85251f85420d3a906a1eb949b73bb286122ea9 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sat, 19 Jul 2008 17:32:22 -0500
Subject: Refactor ActiveSupport::Dependencies injector so it would be possible
to disable it
---
activesupport/lib/active_support/dependencies.rb | 218 ++++++++++++-----------
1 file changed, 114 insertions(+), 104 deletions(-)
diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb
index 2f3fa72bb4..e3d4f3d7eb 100644
--- a/activesupport/lib/active_support/dependencies.rb
+++ b/activesupport/lib/active_support/dependencies.rb
@@ -1,8 +1,3 @@
-require 'set'
-require 'active_support/core_ext/module/attribute_accessors'
-require 'active_support/core_ext/load_error'
-require 'active_support/core_ext/kernel'
-
module ActiveSupport #:nodoc:
module Dependencies #:nodoc:
extend self
@@ -52,6 +47,119 @@ module ActiveSupport #:nodoc:
mattr_accessor :constant_watch_stack
self.constant_watch_stack = []
+ # Module includes this module
+ module ModuleConstMissing #:nodoc:
+ def self.included(base) #:nodoc:
+ base.class_eval do
+ # Rename the original handler so we can chain it to the new one
+ alias_method :rails_original_const_missing, :const_missing
+
+ # Use const_missing to autoload associations so we don't have to
+ # require_association when using single-table inheritance.
+ def const_missing(class_id)
+ ActiveSupport::Dependencies.load_missing_constant self, class_id
+ end
+ end
+ end
+
+ def unloadable(const_desc = self)
+ super(const_desc)
+ end
+ end
+
+ # Class includes this module
+ module ClassConstMissing #:nodoc:
+ def const_missing(const_name)
+ if [Object, Kernel].include?(self) || parent == self
+ super
+ else
+ begin
+ begin
+ Dependencies.load_missing_constant self, const_name
+ rescue NameError
+ parent.send :const_missing, const_name
+ end
+ rescue NameError => e
+ # Make sure that the name we are missing is the one that caused the error
+ parent_qualified_name = Dependencies.qualified_name_for parent, const_name
+ raise unless e.missing_name? parent_qualified_name
+ qualified_name = Dependencies.qualified_name_for self, const_name
+ raise NameError.new("uninitialized constant #{qualified_name}").copy_blame!(e)
+ end
+ end
+ end
+ end
+
+ # Object includes this module
+ module Loadable #:nodoc:
+ def load(file, *extras) #:nodoc:
+ Dependencies.new_constants_in(Object) { super }
+ rescue Exception => exception # errors from loading file
+ exception.blame_file! file
+ raise
+ end
+
+ def require(file, *extras) #:nodoc:
+ Dependencies.new_constants_in(Object) { super }
+ rescue Exception => exception # errors from required file
+ exception.blame_file! file
+ raise
+ end
+
+ # Mark the given constant as unloadable. Unloadable constants are removed each
+ # time dependencies are cleared.
+ #
+ # Note that marking a constant for unloading need only be done once. Setup
+ # or init scripts may list each unloadable constant that may need unloading;
+ # each constant will be removed for every subsequent clear, as opposed to for
+ # the first clear.
+ #
+ # The provided constant descriptor may be a (non-anonymous) module or class,
+ # or a qualified constant name as a string or symbol.
+ #
+ # Returns true if the constant was not previously marked for unloading, false
+ # otherwise.
+ def unloadable(const_desc)
+ Dependencies.mark_for_unload const_desc
+ end
+ end
+
+ # Exception file-blaming
+ module Blamable #:nodoc:
+ def blame_file!(file)
+ (@blamed_files ||= []).unshift file
+ end
+
+ def blamed_files
+ @blamed_files ||= []
+ end
+
+ def describe_blame
+ return nil if blamed_files.empty?
+ "This error occurred while loading the following files:\n #{blamed_files.join "\n "}"
+ end
+
+ def copy_blame!(exc)
+ @blamed_files = exc.blamed_files.clone
+ self
+ end
+ end
+
+ def inject!
+ Object.instance_eval do
+ define_method(:require_or_load) { |file_name| Dependencies.require_or_load(file_name) } unless Object.respond_to?(:require_or_load)
+ define_method(:require_dependency) { |file_name| Dependencies.depend_on(file_name) } unless Object.respond_to?(:require_dependency)
+ define_method(:require_association) { |file_name| Dependencies.associate_with(file_name) } unless Object.respond_to?(:require_association)
+
+ alias_method :load_without_new_constant_marking, :load
+ include Loadable
+ end
+
+ Module.instance_eval { include ModuleConstMissing }
+ Class.instance_eval { include ClassConstMissing }
+ Exception.instance_eval { include Blamable }
+ end
+
def load?
mechanism == :load
end
@@ -452,102 +560,4 @@ module ActiveSupport #:nodoc:
end
end
-Object.instance_eval do
- define_method(:require_or_load) { |file_name| ActiveSupport::Dependencies.require_or_load(file_name) } unless Object.respond_to?(:require_or_load)
- define_method(:require_dependency) { |file_name| ActiveSupport::Dependencies.depend_on(file_name) } unless Object.respond_to?(:require_dependency)
- define_method(:require_association) { |file_name| ActiveSupport::Dependencies.associate_with(file_name) } unless Object.respond_to?(:require_association)
-end
-
-class Module #:nodoc:
- # Rename the original handler so we can chain it to the new one
- alias :rails_original_const_missing :const_missing
-
- # Use const_missing to autoload associations so we don't have to
- # require_association when using single-table inheritance.
- def const_missing(class_id)
- ActiveSupport::Dependencies.load_missing_constant self, class_id
- end
-
- def unloadable(const_desc = self)
- super(const_desc)
- end
-
-end
-
-class Class
- def const_missing(const_name)
- if [Object, Kernel].include?(self) || parent == self
- super
- else
- begin
- begin
- ActiveSupport::Dependencies.load_missing_constant self, const_name
- rescue NameError
- parent.send :const_missing, const_name
- end
- rescue NameError => e
- # Make sure that the name we are missing is the one that caused the error
- parent_qualified_name = ActiveSupport::Dependencies.qualified_name_for parent, const_name
- raise unless e.missing_name? parent_qualified_name
- qualified_name = ActiveSupport::Dependencies.qualified_name_for self, const_name
- raise NameError.new("uninitialized constant #{qualified_name}").copy_blame!(e)
- end
- end
- end
-end
-
-class Object
- alias_method :load_without_new_constant_marking, :load
-
- def load(file, *extras) #:nodoc:
- ActiveSupport::Dependencies.new_constants_in(Object) { super }
- rescue Exception => exception # errors from loading file
- exception.blame_file! file
- raise
- end
-
- def require(file, *extras) #:nodoc:
- ActiveSupport::Dependencies.new_constants_in(Object) { super }
- rescue Exception => exception # errors from required file
- exception.blame_file! file
- raise
- end
-
- # Mark the given constant as unloadable. Unloadable constants are removed each
- # time dependencies are cleared.
- #
- # Note that marking a constant for unloading need only be done once. Setup
- # or init scripts may list each unloadable constant that may need unloading;
- # each constant will be removed for every subsequent clear, as opposed to for
- # the first clear.
- #
- # The provided constant descriptor may be a (non-anonymous) module or class,
- # or a qualified constant name as a string or symbol.
- #
- # Returns true if the constant was not previously marked for unloading, false
- # otherwise.
- def unloadable(const_desc)
- ActiveSupport::Dependencies.mark_for_unload const_desc
- end
-end
-
-# Add file-blaming to exceptions
-class Exception #:nodoc:
- def blame_file!(file)
- (@blamed_files ||= []).unshift file
- end
-
- def blamed_files
- @blamed_files ||= []
- end
-
- def describe_blame
- return nil if blamed_files.empty?
- "This error occurred while loading the following files:\n #{blamed_files.join "\n "}"
- end
-
- def copy_blame!(exc)
- @blamed_files = exc.blamed_files.clone
- self
- end
-end
+ActiveSupport::Dependencies.inject!
--
cgit v1.2.3
From 006cbb8fde3f20a684eabcfd11c53ae762cf8435 Mon Sep 17 00:00:00 2001
From: Michael Koziarski
Date: Sun, 20 Jul 2008 21:23:18 +0200
Subject: Handle the case where 64bit time_t won't overflow.
---
activesupport/test/core_ext/time_ext_test.rb | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb
index 17a0968c0e..14309f4e2d 100644
--- a/activesupport/test/core_ext/time_ext_test.rb
+++ b/activesupport/test/core_ext/time_ext_test.rb
@@ -528,7 +528,12 @@ class TimeExtCalculationsTest < Test::Unit::TestCase
assert_equal Time.time_with_datetime_fallback(:utc, 2005), Time.utc(2005)
assert_equal Time.time_with_datetime_fallback(:utc, 2039), DateTime.civil(2039, 1, 1, 0, 0, 0, 0, 0)
assert_equal Time.time_with_datetime_fallback(:utc, 2005, 2, 21, 17, 44, 30, 1), Time.utc(2005, 2, 21, 17, 44, 30, 1) #with usec
- assert_equal Time.time_with_datetime_fallback(:utc, 2039, 2, 21, 17, 44, 30, 1), DateTime.civil(2039, 2, 21, 17, 44, 30, 0, 0)
+ # This won't overflow on 64bit linux
+ expected_to_overflow = Time.time_with_datetime_fallback(:utc, 2039, 2, 21, 17, 44, 30, 1)
+ unless expected_to_overflow.is_a?(Time)
+ assert_equal Time.time_with_datetime_fallback(:utc, 2039, 2, 21, 17, 44, 30, 1),
+ DateTime.civil(2039, 2, 21, 17, 44, 30, 0, 0)
+ end
assert_equal ::Date::ITALY, Time.time_with_datetime_fallback(:utc, 2039, 2, 21, 17, 44, 30, 1).start # use Ruby's default start value
end
--
cgit v1.2.3
From 5bec5848b22527ee77c007565f7eea336e5c864f Mon Sep 17 00:00:00 2001
From: Michael Koziarski
Date: Sun, 20 Jul 2008 21:25:31 +0200
Subject: If it doesn't overflow, it won't have a .start method. So don't run
the second assertion either
---
activesupport/test/core_ext/time_ext_test.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb
index 14309f4e2d..8740497b3d 100644
--- a/activesupport/test/core_ext/time_ext_test.rb
+++ b/activesupport/test/core_ext/time_ext_test.rb
@@ -533,8 +533,8 @@ class TimeExtCalculationsTest < Test::Unit::TestCase
unless expected_to_overflow.is_a?(Time)
assert_equal Time.time_with_datetime_fallback(:utc, 2039, 2, 21, 17, 44, 30, 1),
DateTime.civil(2039, 2, 21, 17, 44, 30, 0, 0)
+ assert_equal ::Date::ITALY, Time.time_with_datetime_fallback(:utc, 2039, 2, 21, 17, 44, 30, 1).start # use Ruby's default start value
end
- assert_equal ::Date::ITALY, Time.time_with_datetime_fallback(:utc, 2039, 2, 21, 17, 44, 30, 1).start # use Ruby's default start value
end
def test_utc_time
--
cgit v1.2.3
From ff9f6fcc75526d9fd89be834982dec8624c909c5 Mon Sep 17 00:00:00 2001
From: Clemens Kofler
Date: Mon, 21 Jul 2008 12:57:15 -0500
Subject: Refactor DateHelper and improve test coverage [#665 state:resolved]
Signed-off-by: Joshua Peek
---
actionpack/lib/action_view/helpers/date_helper.rb | 298 +++++++++++-----------
actionpack/test/template/date_helper_test.rb | 144 +++++++----
2 files changed, 238 insertions(+), 204 deletions(-)
diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb
index 2cdb9a224e..c7a1d40ff2 100755
--- a/actionpack/lib/action_view/helpers/date_helper.rb
+++ b/actionpack/lib/action_view/helpers/date_helper.rb
@@ -3,14 +3,15 @@ require 'action_view/helpers/tag_helper'
module ActionView
module Helpers
- # The Date Helper primarily creates select/option tags for different kinds of dates and date elements. All of the select-type methods
- # share a number of common options that are as follows:
+ # The Date Helper primarily creates select/option tags for different kinds of dates and date elements. All of the
+ # select-type methods share a number of common options that are as follows:
#
- # * :prefix - overwrites the default prefix of "date" used for the select names. So specifying "birthday" would give
- # birthday[month] instead of date[month] if passed to the select_month method.
+ # * :prefix - overwrites the default prefix of "date" used for the select names. So specifying "birthday"
+ # would give birthday[month] instead of date[month] if passed to the select_month method.
# * :include_blank - set to true if it should be possible to set an empty date.
- # * :discard_type - set to true if you want to discard the type part of the select name. If set to true, the select_month
- # method would use simply "date" (which can be overwritten using :prefix ) instead of "date[month]".
+ # * :discard_type - set to true if you want to discard the type part of the select name. If set to true,
+ # the select_month method would use simply "date" (which can be overwritten using :prefix ) instead of
+ # "date[month]".
module DateHelper
include ActionView::Helpers::TagHelper
DEFAULT_PREFIX = 'date' unless const_defined?('DEFAULT_PREFIX')
@@ -67,7 +68,7 @@ module ActionView
I18n.with_options :locale => options[:locale], :scope => :'datetime.distance_in_words' do |locale|
case distance_in_minutes
when 0..1
- return distance_in_minutes == 0 ?
+ return distance_in_minutes == 0 ?
locale.t(:less_than_x_minutes, :count => 1) :
locale.t(:x_minutes, :count => distance_in_minutes) unless include_seconds
@@ -91,7 +92,7 @@ module ActionView
else locale.t :over_x_years, :count => (distance_in_minutes / 525600).round
end
end
- end
+ end
# Like distance_of_time_in_words, but where to_time is fixed to Time.now .
#
@@ -107,15 +108,18 @@ module ActionView
alias_method :distance_of_time_in_words_to_now, :time_ago_in_words
- # Returns a set of select tags (one for year, month, and day) pre-selected for accessing a specified date-based attribute (identified by
- # +method+) on an object assigned to the template (identified by +object+). It's possible to tailor the selects through the +options+ hash,
- # which accepts all the keys that each of the individual select builders do (like :use_month_numbers for select_month) as well as a range of
- # discard options. The discard options are :discard_year , :discard_month and :discard_day . Set to true, they'll
- # drop the respective select. Discarding the month select will also automatically discard the day select. It's also possible to explicitly
- # set the order of the tags using the :order option with an array of symbols :year , :month and :day in
- # the desired order. Symbols may be omitted and the respective select is not included.
+ # Returns a set of select tags (one for year, month, and day) pre-selected for accessing a specified date-based
+ # attribute (identified by +method+) on an object assigned to the template (identified by +object+). It's
+ # possible to tailor the selects through the +options+ hash, which accepts all the keys that each of the
+ # individual select builders do (like :use_month_numbers for select_month) as well as a range of discard
+ # options. The discard options are :discard_year , :discard_month and :discard_day . Set
+ # to true, they'll drop the respective select. Discarding the month select will also automatically discard the
+ # day select. It's also possible to explicitly set the order of the tags using the :order option with an
+ # array of symbols :year , :month and :day in the desired order. Symbols may be omitted
+ # and the respective select is not included.
#
- # Pass the :default option to set the default date. Use a Time object or a Hash of :year , :month , :day , :hour , :minute , and :second .
+ # Pass the :default option to set the default date. Use a Time object or a Hash of :year ,
+ # :month , :day , :hour , :minute , and :second .
#
# Passing :disabled => true as part of the +options+ will make elements inaccessible for change.
#
@@ -133,7 +137,7 @@ module ActionView
#
# # Generates a date select that when POSTed is stored in the post variable, in the written_on attribute,
# # with the year in the year drop down box starting at 1995, numbers used for months instead of words,
- # # and without a day select box.
+ # # and without a day select box.
# date_select("post", "written_on", :start_year => 1995, :use_month_numbers => true,
# :discard_day => true, :include_blank => true)
#
@@ -155,8 +159,8 @@ module ActionView
#
# The selects are prepared for multi-parameter assignment to an Active Record object.
#
- # Note: If the day is not included as an option but the month is, the day will be set to the 1st to ensure that all month
- # choices are valid.
+ # Note: If the day is not included as an option but the month is, the day will be set to the 1st to ensure that
+ # all month choices are valid.
def date_select(object_name, method, options = {}, html_options = {})
InstanceTag.new(object_name, method, self, options.delete(:object)).to_date_select_tag(options, html_options)
end
@@ -180,12 +184,12 @@ module ActionView
# # Creates a time select tag that, when POSTed, will be stored in the mail variable in the sent_at attribute
# time_select("mail", "sent_at")
#
- # # Creates a time select tag with a seconds field that, when POSTed, will be stored in the post variables in
- # # the sunrise attribute.
+ # # Creates a time select tag with a seconds field that, when POSTed, will be stored in the post variables in
+ # # the sunrise attribute.
# time_select("post", "start_time", :include_seconds => true)
#
- # # Creates a time select tag with a seconds field that, when POSTed, will be stored in the entry variables in
- # # the submission_time attribute.
+ # # Creates a time select tag with a seconds field that, when POSTed, will be stored in the entry variables in
+ # # the submission_time attribute.
# time_select("entry", "submission_time", :include_seconds => true)
#
# # You can set the :minute_step to 15 which will give you: 00, 15, 30 and 45.
@@ -193,14 +197,15 @@ module ActionView
#
# The selects are prepared for multi-parameter assignment to an Active Record object.
#
- # Note: If the day is not included as an option but the month is, the day will be set to the 1st to ensure that all month
- # choices are valid.
+ # Note: If the day is not included as an option but the month is, the day will be set to the 1st to ensure that
+ # all month choices are valid.
def time_select(object_name, method, options = {}, html_options = {})
InstanceTag.new(object_name, method, self, options.delete(:object)).to_time_select_tag(options, html_options)
end
- # Returns a set of select tags (one for year, month, day, hour, and minute) pre-selected for accessing a specified datetime-based
- # attribute (identified by +method+) on an object assigned to the template (identified by +object+). Examples:
+ # Returns a set of select tags (one for year, month, day, hour, and minute) pre-selected for accessing a
+ # specified datetime-based attribute (identified by +method+) on an object assigned to the template (identified
+ # by +object+). Examples:
#
# If anything is passed in the html_options hash it will be applied to every select tag in the set.
#
@@ -208,16 +213,16 @@ module ActionView
# # Generates a datetime select that, when POSTed, will be stored in the post variable in the written_on attribute
# datetime_select("post", "written_on")
#
- # # Generates a datetime select with a year select that starts at 1995 that, when POSTed, will be stored in the
+ # # Generates a datetime select with a year select that starts at 1995 that, when POSTed, will be stored in the
# # post variable in the written_on attribute.
# datetime_select("post", "written_on", :start_year => 1995)
#
- # # Generates a datetime select with a default value of 3 days from the current time that, when POSTed, will be stored in the
- # # trip variable in the departing attribute.
+ # # Generates a datetime select with a default value of 3 days from the current time that, when POSTed, will
+ # # be stored in the trip variable in the departing attribute.
# datetime_select("trip", "departing", :default => 3.days.from_now)
#
- # # Generates a datetime select that discards the type that, when POSTed, will be stored in the post variable as the written_on
- # # attribute.
+ # # Generates a datetime select that discards the type that, when POSTed, will be stored in the post variable
+ # # as the written_on attribute.
# datetime_select("post", "written_on", :discard_type => true)
#
# The selects are prepared for multi-parameter assignment to an Active Record object.
@@ -227,9 +232,10 @@ module ActionView
# Returns a set of html select-tags (one for year, month, day, hour, and minute) pre-selected with the +datetime+.
# It's also possible to explicitly set the order of the tags using the :order option with an array of
- # symbols :year , :month and :day in the desired order. If you do not supply a Symbol, it
- # will be appended onto the :order passed in. You can also add :date_separator and :time_separator
- # keys to the +options+ to control visual display of the elements.
+ # symbols :year , :month and :day in the desired order. If you do not supply a Symbol,
+ # it will be appended onto the :order passed in. You can also add :date_separator ,
+ # :datetime_separator and :time_separator keys to the +options+ to control visual display of
+ # the elements.
#
# If anything is passed in the html_options hash it will be applied to every select tag in the set.
#
@@ -250,7 +256,12 @@ module ActionView
# # with a '/' between each date field.
# select_datetime(my_date_time, :date_separator => '/')
#
- # # Generates a datetime select that discards the type of the field and defaults to the datetime in
+ # # Generates a datetime select that defaults to the datetime in my_date_time (four days after today)
+ # # with a date fields separated by '/', time fields separated by '' and the date and time fields
+ # # separated by a comma (',').
+ # select_datetime(my_date_time, :date_separator => '/', :time_separator => '', :datetime_separator => ',')
+ #
+ # # Generates a datetime select that discards the type of the field and defaults to the datetime in
# # my_date_time (four days after today)
# select_datetime(my_date_time, :discard_type => true)
#
@@ -261,7 +272,7 @@ module ActionView
def select_datetime(datetime = Time.current, options = {}, html_options = {})
separator = options[:datetime_separator] || ''
select_date(datetime, options, html_options) + separator + select_time(datetime, options, html_options)
- end
+ end
# Returns a set of html select-tags (one for year, month, and day) pre-selected with the +date+.
# It's possible to explicitly set the order of the tags using the :order option with an array of
@@ -283,27 +294,29 @@ module ActionView
# # with the fields ordered year, month, day rather than month, day, year.
# select_date(my_date, :order => [:year, :month, :day])
#
- # # Generates a date select that discards the type of the field and defaults to the date in
+ # # Generates a date select that discards the type of the field and defaults to the date in
# # my_date (six days after today)
# select_date(my_date, :discard_type => true)
#
+ # # Generates a date select that defaults to the date in my_date,
+ # # which has fields separated by '/'
+ # select_date(my_date, :date_separator => '/')
+ #
# # Generates a date select that defaults to the datetime in my_date (six days after today)
# # prefixed with 'payday' rather than 'date'
# select_date(my_date, :prefix => 'payday')
#
def select_date(date = Date.current, options = {}, html_options = {})
- options[:order] ||= []
+ options.reverse_merge!(:order => [], :date_separator => '')
[:year, :month, :day].each { |o| options[:order].push(o) unless options[:order].include?(o) }
- select_date = ''
- options[:order].each do |o|
- select_date << self.send("select_#{o}", date, options, html_options)
- end
- select_date
+ options[:order].inject([]) { |s, o|
+ s << self.send("select_#{o}", date, options, html_options)
+ }.join(options[:date_separator])
end
# Returns a set of html select-tags (one for hour and minute)
- # You can set :time_separator key to format the output, and
+ # You can set :time_separator key to format the output, and
# the :include_seconds option to include an input for seconds.
#
# If anything is passed in the html_options hash it will be applied to every select tag in the set.
@@ -318,7 +331,7 @@ module ActionView
# select_time()
#
# # Generates a time select that defaults to the time in my_time,
- # # which has fields separated by ':'
+ # # which has fields separated by ':'
# select_time(my_time, :time_separator => ':')
#
# # Generates a time select that defaults to the time in my_time,
@@ -331,7 +344,8 @@ module ActionView
#
def select_time(datetime = Time.current, options = {}, html_options = {})
separator = options[:time_separator] || ''
- select_hour(datetime, options, html_options) + separator + select_minute(datetime, options, html_options) + (options[:include_seconds] ? separator + select_second(datetime, options, html_options) : '')
+ select_hour(datetime, options, html_options) + separator + select_minute(datetime, options, html_options) +
+ (options[:include_seconds] ? separator + select_second(datetime, options, html_options) : '')
end
# Returns a select tag with options for each of the seconds 0 through 59 with the current second selected.
@@ -346,26 +360,16 @@ module ActionView
#
# # Generates a select field for seconds that defaults to the number given
# select_second(33)
- #
+ #
# # Generates a select field for seconds that defaults to the seconds for the time in my_time
# # that is named 'interval' rather than 'second'
# select_second(my_time, :field_name => 'interval')
#
def select_second(datetime, options = {}, html_options = {})
val = datetime ? (datetime.kind_of?(Fixnum) ? datetime : datetime.sec) : ''
- if options[:use_hidden]
- options[:include_seconds] ? hidden_html(options[:field_name] || 'second', val, options) : ''
- else
- second_options = []
- 0.upto(59) do |second|
- second_options << ((val == second) ?
- content_tag(:option, leading_zero_on_single_digits(second), :value => leading_zero_on_single_digits(second), :selected => "selected") :
- content_tag(:option, leading_zero_on_single_digits(second), :value => leading_zero_on_single_digits(second))
- )
- second_options << "\n"
- end
- select_html(options[:field_name] || 'second', second_options.join, options, html_options)
- end
+ options[:use_hidden] ?
+ (options[:include_seconds] ? _date_hidden_html(options[:field_name] || 'second', val, options) : '') :
+ _date_select_html(options[:field_name] || 'second', _date_build_options(val), options, html_options)
end
# Returns a select tag with options for each of the minutes 0 through 59 with the current minute selected.
@@ -381,26 +385,17 @@ module ActionView
#
# # Generates a select field for minutes that defaults to the number given
# select_minute(14)
- #
+ #
# # Generates a select field for minutes that defaults to the minutes for the time in my_time
# # that is named 'stride' rather than 'second'
# select_minute(my_time, :field_name => 'stride')
#
def select_minute(datetime, options = {}, html_options = {})
val = datetime ? (datetime.kind_of?(Fixnum) ? datetime : datetime.min) : ''
- if options[:use_hidden]
- hidden_html(options[:field_name] || 'minute', val, options)
- else
- minute_options = []
- 0.step(59, options[:minute_step] || 1) do |minute|
- minute_options << ((val == minute) ?
- content_tag(:option, leading_zero_on_single_digits(minute), :value => leading_zero_on_single_digits(minute), :selected => "selected") :
- content_tag(:option, leading_zero_on_single_digits(minute), :value => leading_zero_on_single_digits(minute))
- )
- minute_options << "\n"
- end
- select_html(options[:field_name] || 'minute', minute_options.join, options, html_options)
- end
+ options[:use_hidden] ?
+ _date_hidden_html(options[:field_name] || 'minute', val, options) :
+ _date_select_html(options[:field_name] || 'minute',
+ _date_build_options(val, :step => options[:minute_step]), options, html_options)
end
# Returns a select tag with options for each of the hours 0 through 23 with the current hour selected.
@@ -415,26 +410,15 @@ module ActionView
#
# # Generates a select field for minutes that defaults to the number given
# select_minute(14)
- #
+ #
# # Generates a select field for minutes that defaults to the minutes for the time in my_time
# # that is named 'stride' rather than 'second'
# select_minute(my_time, :field_name => 'stride')
#
def select_hour(datetime, options = {}, html_options = {})
val = datetime ? (datetime.kind_of?(Fixnum) ? datetime : datetime.hour) : ''
- if options[:use_hidden]
- hidden_html(options[:field_name] || 'hour', val, options)
- else
- hour_options = []
- 0.upto(23) do |hour|
- hour_options << ((val == hour) ?
- content_tag(:option, leading_zero_on_single_digits(hour), :value => leading_zero_on_single_digits(hour), :selected => "selected") :
- content_tag(:option, leading_zero_on_single_digits(hour), :value => leading_zero_on_single_digits(hour))
- )
- hour_options << "\n"
- end
- select_html(options[:field_name] || 'hour', hour_options.join, options, html_options)
- end
+ options[:use_hidden] ? _date_hidden_html(options[:field_name] || 'hour', val, options) :
+ _date_select_html(options[:field_name] || 'hour', _date_build_options(val, :end => 23), options, html_options)
end
# Returns a select tag with options for each of the days 1 through 31 with the current day selected.
@@ -449,36 +433,27 @@ module ActionView
#
# # Generates a select field for days that defaults to the number given
# select_day(5)
- #
+ #
# # Generates a select field for days that defaults to the day for the date in my_date
# # that is named 'due' rather than 'day'
# select_day(my_time, :field_name => 'due')
#
def select_day(date, options = {}, html_options = {})
val = date ? (date.kind_of?(Fixnum) ? date : date.day) : ''
- if options[:use_hidden]
- hidden_html(options[:field_name] || 'day', val, options)
- else
- day_options = []
- 1.upto(31) do |day|
- day_options << ((val == day) ?
- content_tag(:option, day, :value => day, :selected => "selected") :
- content_tag(:option, day, :value => day)
- )
- day_options << "\n"
- end
- select_html(options[:field_name] || 'day', day_options.join, options, html_options)
- end
+ options[:use_hidden] ? _date_hidden_html(options[:field_name] || 'day', val, options) :
+ _date_select_html(options[:field_name] || 'day',
+ _date_build_options(val, :start => 1, :end => 31, :leading_zeros => false),
+ options, html_options)
end
- # Returns a select tag with options for each of the months January through December with the current month selected.
- # The month names are presented as keys (what's shown to the user) and the month numbers (1-12) are used as values
- # (what's submitted to the server). It's also possible to use month numbers for the presentation instead of names --
- # set the :use_month_numbers key in +options+ to true for this to happen. If you want both numbers and names,
- # set the :add_month_numbers key in +options+ to true. If you would prefer to show month names as abbreviations,
- # set the :use_short_month key in +options+ to true. If you want to use your own month names, set the
- # :use_month_names key in +options+ to an array of 12 month names. Override the field name using the
- # :field_name option, 'month' by default.
+ # Returns a select tag with options for each of the months January through December with the current month
+ # selected. The month names are presented as keys (what's shown to the user) and the month numbers (1-12) are
+ # used as values (what's submitted to the server). It's also possible to use month numbers for the presentation
+ # instead of names -- set the :use_month_numbers key in +options+ to true for this to happen. If you
+ # want both numbers and names, set the :add_month_numbers key in +options+ to true. If you would prefer
+ # to show month names as abbreviations, set the :use_short_month key in +options+ to true. If you want
+ # to use your own month names, set the :use_month_names key in +options+ to an array of 12 month names.
+ # Override the field name using the :field_name option, 'month' by default.
#
# ==== Examples
# # Generates a select field for months that defaults to the current month that
@@ -490,7 +465,7 @@ module ActionView
# select_month(Date.today, :field_name => 'start')
#
# # Generates a select field for months that defaults to the current month that
- # # will use keys like "1", "3".
+ # # will use keys like "1", "3".
# select_month(Date.today, :use_month_numbers => true)
#
# # Generates a select field for months that defaults to the current month that
@@ -506,11 +481,11 @@ module ActionView
# select_month(Date.today, :use_month_names => %w(Januar Februar Marts ...))
#
def select_month(date, options = {}, html_options = {})
- locale = options[:locale]
+ locale = options[:locale]
val = date ? (date.kind_of?(Fixnum) ? date : date.month) : ''
if options[:use_hidden]
- hidden_html(options[:field_name] || 'month', val, options)
+ _date_hidden_html(options[:field_name] || 'month', val, options)
else
month_options = []
month_names = options[:use_month_names] || begin
@@ -534,14 +509,15 @@ module ActionView
)
month_options << "\n"
end
- select_html(options[:field_name] || 'month', month_options.join, options, html_options)
+ _date_select_html(options[:field_name] || 'month', month_options.join, options, html_options)
end
- end
+ end
- # Returns a select tag with options for each of the five years on each side of the current, which is selected. The five year radius
- # can be changed using the :start_year and :end_year keys in the +options+. Both ascending and descending year
- # lists are supported by making :start_year less than or greater than :end_year . The date can also be
- # substituted for a year given as a number. Override the field name using the :field_name option, 'year' by default.
+ # Returns a select tag with options for each of the five years on each side of the current, which is selected.
+ # The five year radius can be changed using the :start_year and :end_year keys in the
+ # +options+. Both ascending and descending year lists are supported by making :start_year less than or
+ # greater than :end_year . The date can also be substituted for a year given as a number.
+ # Override the field name using the :field_name option, 'year' by default.
#
# ==== Examples
# # Generates a select field for years that defaults to the current year that
@@ -562,38 +538,48 @@ module ActionView
#
def select_year(date, options = {}, html_options = {})
if !date || date == 0
- value = ''
+ val = ''
middle_year = Date.today.year
elsif date.kind_of?(Fixnum)
- value = middle_year = date
+ val = middle_year = date
else
- value = middle_year = date.year
+ val = middle_year = date.year
end
if options[:use_hidden]
- hidden_html(options[:field_name] || 'year', value, options)
+ _date_hidden_html(options[:field_name] || 'year', val, options)
else
- year_options = ''
- start_year = options[:start_year] || middle_year - 5
- end_year = options[:end_year] || middle_year + 5
- step_val = start_year < end_year ? 1 : -1
-
- start_year.step(end_year, step_val) do |year|
- if value == year
- year_options << content_tag(:option, year, :value => year, :selected => "selected")
- else
- year_options << content_tag(:option, year, :value => year)
- end
- year_options << "\n"
- end
- select_html(options[:field_name] || 'year', year_options, options, html_options)
+ options[:start_year] ||= middle_year - 5
+ options[:end_year] ||= middle_year + 5
+ step = options[:start_year] < options[:end_year] ? 1 : -1
+
+ _date_select_html(options[:field_name] || 'year',
+ _date_build_options(val,
+ :start => options[:start_year],
+ :end => options[:end_year],
+ :step => step,
+ :leading_zeros => false
+ ), options, html_options)
end
end
private
+ def _date_build_options(selected, options={})
+ options.reverse_merge!(:start => 0, :end => 59, :step => 1, :leading_zeros => true)
+
+ select_options = []
+ (options[:start] || 0).step((options[:end] || 59), options[:step] || 1) do |i|
+ value = options[:leading_zeros] ? sprintf("%02d", i) : i
+ tag_options = { :value => value }
+ tag_options[:selected] = "selected" if selected == i
+
+ select_options << content_tag(:option, value, tag_options)
+ end
+ select_options.join("\n") + "\n"
+ end
- def select_html(type, html_options, options, select_tag_options = {})
- name_and_id_from_options(options, type)
+ def _date_select_html(type, html_options, options, select_tag_options = {})
+ _date_name_and_id_from_options(options, type)
select_options = {:id => options[:id], :name => options[:name]}
select_options.merge!(:disabled => 'disabled') if options[:disabled]
select_options.merge!(select_tag_options) unless select_tag_options.empty?
@@ -603,19 +589,15 @@ module ActionView
content_tag(:select, select_html, select_options) + "\n"
end
- def hidden_html(type, value, options)
- name_and_id_from_options(options, type)
+ def _date_hidden_html(type, value, options)
+ _date_name_and_id_from_options(options, type)
hidden_html = tag(:input, :type => "hidden", :id => options[:id], :name => options[:name], :value => value) + "\n"
end
- def name_and_id_from_options(options, type)
+ def _date_name_and_id_from_options(options, type)
options[:name] = (options[:prefix] || DEFAULT_PREFIX) + (options[:discard_type] ? '' : "[#{type}]")
options[:id] = options[:name].gsub(/([\[\(])|(\]\[)/, '_').gsub(/[\]\)]/, '')
end
-
- def leading_zero_on_single_digits(number)
- number > 9 ? number : "0#{number}"
- end
end
class InstanceTag #:nodoc:
@@ -641,11 +623,11 @@ module ActionView
options = defaults.merge(options)
datetime = value(object)
datetime ||= default_time_from_options(options[:default]) unless options[:include_blank]
-
+
position = { :year => 1, :month => 2, :day => 3, :hour => 4, :minute => 5, :second => 6 }
order = options[:order] ||= I18n.translate(:'date.order', :locale => locale)
-
+
# Discard explicit and implicit by not being included in the :order
discard = {}
discard[:year] = true if options[:discard_year] or !order.include?(:year)
@@ -654,26 +636,30 @@ module ActionView
discard[:hour] = true if options[:discard_hour]
discard[:minute] = true if options[:discard_minute] or discard[:hour]
discard[:second] = true unless options[:include_seconds] && !discard[:minute]
-
+
# If the day is hidden and the month is visible, the day should be set to the 1st so all month choices are valid
# (otherwise it could be 31 and february wouldn't be a valid date)
if datetime && discard[:day] && !discard[:month]
datetime = datetime.change(:day => 1)
end
-
+
# Maintain valid dates by including hidden fields for discarded elements
[:day, :month, :year].each { |o| order.unshift(o) unless order.include?(o) }
-
+
# Ensure proper ordering of :hour, :minute and :second
[:hour, :minute, :second].each { |o| order.delete(o); order.push(o) }
-
+
date_or_time_select = ''
order.reverse.each do |param|
# Send hidden fields for discarded elements once output has started
# This ensures AR can reconstruct valid dates using ParseDate
next if discard[param] && (date_or_time_select.empty? || options[:ignore_date])
- date_or_time_select.insert(0, self.send("select_#{param}", datetime, options_with_prefix(position[param], options.merge(:use_hidden => discard[param])), html_options))
+ date_or_time_select.insert(0,
+ self.send("select_#{param}",
+ datetime,
+ options_with_prefix(position[param], options.merge(:use_hidden => discard[param])),
+ html_options))
date_or_time_select.insert(0,
case param
when :hour then (discard[:year] && discard[:day] ? "" : " — ")
@@ -682,7 +668,7 @@ module ActionView
else ""
end)
end
-
+
date_or_time_select
end
@@ -708,7 +694,7 @@ module ActionView
default[:sec] ||= default[:second]
time = Time.current
-
+
[:year, :month, :day, :hour, :min, :sec].each do |key|
default[key] ||= time.send(key)
end
diff --git a/actionpack/test/template/date_helper_test.rb b/actionpack/test/template/date_helper_test.rb
index 8b4e94c67f..d8c07e731b 100755
--- a/actionpack/test/template/date_helper_test.rb
+++ b/actionpack/test/template/date_helper_test.rb
@@ -17,7 +17,7 @@ class DateHelperTest < ActionView::TestCase
end
end
end
-
+
def assert_distance_of_time_in_words(from, to=nil)
to ||= from
@@ -86,13 +86,13 @@ class DateHelperTest < ActionView::TestCase
from = Time.mktime(2004, 6, 6, 21, 45, 0)
assert_distance_of_time_in_words(from)
end
-
+
def test_distance_in_words_with_time_zones
from = Time.mktime(2004, 6, 6, 21, 45, 0)
assert_distance_of_time_in_words(from.in_time_zone('Alaska'))
assert_distance_of_time_in_words(from.in_time_zone('Hawaii'))
end
-
+
def test_distance_in_words_with_different_time_zones
from = Time.mktime(2004, 6, 6, 21, 45, 0)
assert_distance_of_time_in_words(
@@ -100,13 +100,13 @@ class DateHelperTest < ActionView::TestCase
from.in_time_zone('Hawaii')
)
end
-
+
def test_distance_in_words_with_dates
start_date = Date.new 1975, 1, 31
end_date = Date.new 1977, 1, 31
assert_equal("over 2 years", distance_of_time_in_words(start_date, end_date))
end
-
+
def test_distance_in_words_with_integers
assert_equal "less than a minute", distance_of_time_in_words(59)
assert_equal "about 1 hour", distance_of_time_in_words(60*60)
@@ -757,6 +757,26 @@ class DateHelperTest < ActionView::TestCase
assert_dom_equal expected, select_date(Time.mktime(2003, 8, 16), {:start_year => 2003, :end_year => 2005, :prefix => "date[first]"}, :class => "selector")
end
+ def test_select_date_with_separator
+ expected = %(\n)
+ expected << %(2003 \n2004 \n2005 \n)
+ expected << " \n"
+
+ expected << " / "
+
+ expected << %(\n)
+ expected << %(January \nFebruary \nMarch \nApril \nMay \nJune \nJuly \nAugust \nSeptember \nOctober \nNovember \nDecember \n)
+ expected << " \n"
+
+ expected << " / "
+
+ expected << %(\n)
+ expected << %(1 \n2 \n3 \n4 \n5 \n6 \n7 \n8 \n9 \n10 \n11 \n12 \n13 \n14 \n15 \n16 \n17 \n18 \n19 \n20 \n21 \n22 \n23 \n24 \n25 \n26 \n27 \n28 \n29 \n30 \n31 \n)
+ expected << " \n"
+
+ assert_dom_equal expected, select_date(Time.mktime(2003, 8, 16), { :date_separator => " / ", :start_year => 2003, :end_year => 2005, :prefix => "date[first]"})
+ end
+
def test_select_datetime
expected = %(\n)
expected << %(2003 \n2004 \n2005 \n)
@@ -857,6 +877,38 @@ class DateHelperTest < ActionView::TestCase
assert_dom_equal expected, select_datetime(Time.mktime(2003, 8, 16, 8, 4, 18), {:start_year => 2003, :end_year => 2005, :prefix => "date[first]"}, :class => 'selector')
end
+ def test_select_datetime_with_all_separators
+ expected = %(\n)
+ expected << %(2003 \n2004 \n2005 \n)
+ expected << " \n"
+
+ expected << "/"
+
+ expected << %(\n)
+ expected << %(January \nFebruary \nMarch \nApril \nMay \nJune \nJuly \nAugust \nSeptember \nOctober \nNovember \nDecember \n)
+ expected << " \n"
+
+ expected << "/"
+
+ expected << %(\n)
+ expected << %(1 \n2 \n3 \n4 \n5 \n6 \n7 \n8 \n9 \n10 \n11 \n12 \n13 \n14 \n15 \n16 \n17 \n18 \n19 \n20 \n21 \n22 \n23 \n24 \n25 \n26 \n27 \n28 \n29 \n30 \n31 \n)
+ expected << " \n"
+
+ expected << "—"
+
+ expected << %(\n)
+ expected << %(00 \n01 \n02 \n03 \n04 \n05 \n06 \n07 \n08 \n09 \n10 \n11 \n12 \n13 \n14 \n15 \n16 \n17 \n18 \n19 \n20 \n21 \n22 \n23 \n)
+ expected << " \n"
+
+ expected << ":"
+
+ expected << %(\n)
+ expected << %(00 \n01 \n02 \n03 \n04 \n05 \n06 \n07 \n08 \n09 \n10 \n11 \n12 \n13 \n14 \n15 \n16 \n17 \n18 \n19 \n20 \n21 \n22 \n23 \n24 \n25 \n26 \n27 \n28 \n29 \n30 \n31 \n32 \n33 \n34 \n35 \n36 \n37 \n38 \n39 \n40 \n41 \n42 \n43 \n44 \n45 \n46 \n47 \n48 \n49 \n50 \n51 \n52 \n53 \n54 \n55 \n56 \n57 \n58 \n59 \n)
+ expected << " \n"
+
+ assert_dom_equal expected, select_datetime(Time.mktime(2003, 8, 16, 8, 4, 18), { :datetime_separator => "—", :date_separator => "/", :time_separator => ":", :start_year => 2003, :end_year => 2005, :prefix => "date[first]"}, :class => 'selector')
+ end
+
def test_select_time
expected = %(\n)
expected << %(00 \n01 \n02 \n03 \n04 \n05 \n06 \n07 \n08 \n09 \n10 \n11 \n12 \n13 \n14 \n15 \n16 \n17 \n18 \n19 \n20 \n21 \n22 \n23 \n)
@@ -933,7 +985,7 @@ class DateHelperTest < ActionView::TestCase
assert_dom_equal expected, select_time(Time.mktime(2003, 8, 16, 8, 4, 18), {}, :class => 'selector')
assert_dom_equal expected, select_time(Time.mktime(2003, 8, 16, 8, 4, 18), {:include_seconds => false}, :class => 'selector')
end
-
+
uses_mocha 'TestDatetimeAndTimeSelectUseTimeCurrentAsDefault' do
def test_select_datetime_uses_time_current_as_default
time = stub(:year => 2004, :month => 6, :day => 15, :hour => 16, :min => 35, :sec => 0)
@@ -942,7 +994,7 @@ class DateHelperTest < ActionView::TestCase
expects(:select_time).with(time, anything, anything).returns('')
select_datetime
end
-
+
def test_select_time_uses_time_current_as_default
time = stub(:year => 2004, :month => 6, :day => 15, :hour => 16, :min => 35, :sec => 0)
Time.expects(:current).returns time
@@ -950,7 +1002,7 @@ class DateHelperTest < ActionView::TestCase
expects(:select_minute).with(time, anything, anything).returns('')
select_time
end
-
+
def test_select_date_uses_date_current_as_default
date = stub(:year => 2004, :month => 6, :day => 15)
Date.expects(:current).returns date
@@ -1188,11 +1240,11 @@ class DateHelperTest < ActionView::TestCase
expected << %{ \n}
expected << %(\n)
- 0.upto(23) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(23) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
expected << " : "
expected << %(\n)
- 0.upto(59) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(59) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
assert_dom_equal expected, time_select("post", "written_on")
@@ -1203,11 +1255,11 @@ class DateHelperTest < ActionView::TestCase
@post.written_on = Time.local(2004, 6, 15, 15, 16, 35)
expected = %(\n)
- 0.upto(23) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(23) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
expected << " : "
expected << %(\n)
- 0.upto(59) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(59) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
assert_dom_equal expected, time_select("post", "written_on", :ignore_date => true)
@@ -1222,15 +1274,15 @@ class DateHelperTest < ActionView::TestCase
expected << %{ \n}
expected << %(\n)
- 0.upto(23) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(23) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
expected << " : "
expected << %(\n)
- 0.upto(59) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(59) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
expected << " : "
expected << %(\n)
- 0.upto(59) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(59) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
assert_dom_equal expected, time_select("post", "written_on", :include_seconds => true)
@@ -1245,11 +1297,11 @@ class DateHelperTest < ActionView::TestCase
expected << %{ \n}
expected << %(\n)
- 0.upto(23) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(23) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
expected << " : "
expected << %(\n)
- 0.upto(59) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(59) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
assert_dom_equal expected, time_select("post", "written_on", {}, :class => 'selector')
@@ -1268,11 +1320,11 @@ class DateHelperTest < ActionView::TestCase
expected << %{ \n}
expected << %(\n)
- 0.upto(23) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(23) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
expected << " : "
expected << %(\n)
- 0.upto(59) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(59) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
assert_dom_equal expected, output_buffer
@@ -1306,7 +1358,7 @@ class DateHelperTest < ActionView::TestCase
assert_dom_equal expected, datetime_select("post", "updated_at")
end
-
+
uses_mocha 'TestDatetimeSelectDefaultsToTimeZoneNowWhenConfigTimeZoneIsSet' do
def test_datetime_select_defaults_to_time_zone_now_when_config_time_zone_is_set
time = stub(:year => 2004, :month => 6, :day => 15, :hour => 16, :min => 35, :sec => 0)
@@ -1370,8 +1422,7 @@ class DateHelperTest < ActionView::TestCase
expected << " \n"
expected << %(\n)
- expected <<
-%(1 \n2 \n3 \n4 \n5 \n6 \n7 \n8 \n9 \n10 \n11 \n12 \n13 \n14 \n15 \n16 \n17 \n18 \n19 \n20 \n21 \n22 \n23 \n24 \n25 \n26 \n27 \n28 \n29 \n30 \n31 \n)
+ expected << %(1 \n2 \n3 \n4 \n5 \n6 \n7 \n8 \n9 \n10 \n11 \n12 \n13 \n14 \n15 \n16 \n17 \n18 \n19 \n20 \n21 \n22 \n23 \n24 \n25 \n26 \n27 \n28 \n29 \n30 \n31 \n)
expected << " \n"
assert_dom_equal expected, select_date(0, :end_year => Date.today.year+1, :prefix => "date[first]")
@@ -1388,8 +1439,7 @@ class DateHelperTest < ActionView::TestCase
expected << " \n"
expected << %(\n)
- expected <<
-%(1 \n2 \n3 \n4 \n5 \n6 \n7 \n8 \n9 \n10 \n11 \n12 \n13 \n14 \n15 \n16 \n17 \n18 \n19 \n20 \n21 \n22 \n23 \n24 \n25 \n26 \n27 \n28 \n29 \n30 \n31 \n)
+ expected << %(1 \n2 \n3 \n4 \n5 \n6 \n7 \n8 \n9 \n10 \n11 \n12 \n13 \n14 \n15 \n16 \n17 \n18 \n19 \n20 \n21 \n22 \n23 \n24 \n25 \n26 \n27 \n28 \n29 \n30 \n31 \n)
expected << " \n"
assert_dom_equal expected, select_date(0, :start_year => 2003, :prefix => "date[first]")
@@ -1405,8 +1455,7 @@ class DateHelperTest < ActionView::TestCase
expected << " \n"
expected << %(\n)
- expected <<
-%(1 \n2 \n3 \n4 \n5 \n6 \n7 \n8 \n9 \n10 \n11 \n12 \n13 \n14 \n15 \n16 \n17 \n18 \n19 \n20 \n21 \n22 \n23 \n24 \n25 \n26 \n27 \n28 \n29 \n30 \n31 \n)
+ expected << %(1 \n2 \n3 \n4 \n5 \n6 \n7 \n8 \n9 \n10 \n11 \n12 \n13 \n14 \n15 \n16 \n17 \n18 \n19 \n20 \n21 \n22 \n23 \n24 \n25 \n26 \n27 \n28 \n29 \n30 \n31 \n)
expected << " \n"
assert_dom_equal expected, select_date(0, :prefix => "date[first]")
@@ -1422,8 +1471,7 @@ class DateHelperTest < ActionView::TestCase
expected << " \n"
expected << %(\n)
- expected <<
-%(1 \n2 \n3 \n4 \n5 \n6 \n7 \n8 \n9 \n10 \n11 \n12 \n13 \n14 \n15 \n16 \n17 \n18 \n19 \n20 \n21 \n22 \n23 \n24 \n25 \n26 \n27 \n28 \n29 \n30 \n31 \n)
+ expected << %(1 \n2 \n3 \n4 \n5 \n6 \n7 \n8 \n9 \n10 \n11 \n12 \n13 \n14 \n15 \n16 \n17 \n18 \n19 \n20 \n21 \n22 \n23 \n24 \n25 \n26 \n27 \n28 \n29 \n30 \n31 \n)
expected << " \n"
assert_dom_equal expected, select_date(nil, :prefix => "date[first]")
@@ -1530,15 +1578,15 @@ class DateHelperTest < ActionView::TestCase
expected << " — "
expected << %{\n}
- 0.upto(23) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(23) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
expected << " : "
expected << %{\n}
- 0.upto(59) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(59) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
expected << " : "
expected << %{\n}
- 0.upto(59) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(59) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
assert_dom_equal expected, datetime_select("post", "updated_at", :include_seconds => true)
@@ -1559,11 +1607,11 @@ class DateHelperTest < ActionView::TestCase
expected << " — "
expected << %{\n}
- 0.upto(23) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(23) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
expected << " : "
expected << %{\n}
- 0.upto(59) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(59) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
assert_dom_equal expected, datetime_select("post", "updated_at", :discard_year => true)
@@ -1582,11 +1630,11 @@ class DateHelperTest < ActionView::TestCase
expected << " — "
expected << %{\n}
- 0.upto(23) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(23) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
expected << " : "
expected << %{\n}
- 0.upto(59) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(59) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
assert_dom_equal expected, datetime_select("post", "updated_at", :discard_month => true)
@@ -1601,11 +1649,11 @@ class DateHelperTest < ActionView::TestCase
expected << %{ \n}
expected << %{\n}
- 0.upto(23) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(23) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
expected << " : "
expected << %{\n}
- 0.upto(59) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(59) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
assert_dom_equal expected, datetime_select("post", "updated_at", :discard_year => true, :discard_month => true)
@@ -1628,11 +1676,11 @@ class DateHelperTest < ActionView::TestCase
expected << " — "
expected << %{\n}
- 0.upto(23) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(23) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
expected << " : "
expected << %{\n}
- 0.upto(59) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(59) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
assert_dom_equal expected, datetime_select("post", "updated_at", :order => [:minute, :day, :hour, :month, :year, :second])
@@ -1653,11 +1701,11 @@ class DateHelperTest < ActionView::TestCase
expected << " — "
expected << %{\n}
- 0.upto(23) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(23) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
expected << " : "
expected << %{\n}
- 0.upto(59) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(59) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
assert_dom_equal expected, datetime_select("post", "updated_at", :order => [:day, :month])
@@ -1680,11 +1728,11 @@ class DateHelperTest < ActionView::TestCase
expected << " — "
expected << %{\n}
- 0.upto(23) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(23) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
expected << " : "
expected << %{\n}
- 0.upto(59) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(59) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
assert_dom_equal expected, datetime_select("post", "updated_at", :default => Time.local(2006, 9, 19, 15, 16, 35))
@@ -1727,11 +1775,11 @@ class DateHelperTest < ActionView::TestCase
expected << " — "
expected << %{\n}
- 0.upto(23) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(23) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
expected << " : "
expected << %{\n}
- 0.upto(59) { |i| expected << %(#{leading_zero_on_single_digits(i)} \n) }
+ 0.upto(59) { |i| expected << %(#{sprintf("%02d", i)} \n) }
expected << " \n"
assert_dom_equal expected, datetime_select("post", "updated_at", :default => { :month => 10, :minute => 42, :hour => 9 })
@@ -1780,19 +1828,19 @@ class DateHelperTest < ActionView::TestCase
assert_equal 2, dummy_instance_tag.send!(:default_time_from_options, :hour => 2).hour
end
end
-
+
def test_instance_tag_default_time_from_options_handles_far_future_date
dummy_instance_tag = ActionView::Helpers::InstanceTag.new(1,2,3)
time = dummy_instance_tag.send!(:default_time_from_options, :year => 2050, :month => 2, :day => 10, :hour => 15, :min => 30, :sec => 45)
assert_equal 2050, time.year
end
end
-
+
protected
def with_env_tz(new_tz = 'US/Eastern')
old_tz, ENV['TZ'] = ENV['TZ'], new_tz
yield
ensure
old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ')
- end
+ end
end
--
cgit v1.2.3
From 0f43de644ea48c1ad11d4bc73307af066bb52870 Mon Sep 17 00:00:00 2001
From: Clemens Kofler
Date: Mon, 21 Jul 2008 13:05:27 -0500
Subject: Refactored NumberHelper API to accept arguments as an options hash
[#666 state:resolved]
Signed-off-by: Joshua Peek
---
.../lib/action_view/helpers/number_helper.rb | 98 +++++++++++++++-------
actionpack/test/template/number_helper_test.rb | 28 ++++++-
2 files changed, 93 insertions(+), 33 deletions(-)
diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb
index 6bb8263794..c4ba7ccc8e 100644
--- a/actionpack/lib/action_view/helpers/number_helper.rb
+++ b/actionpack/lib/action_view/helpers/number_helper.rb
@@ -22,7 +22,7 @@ module ActionView
# number_to_phone(1235551234, :country_code => 1) # => +1-123-555-1234
#
# number_to_phone(1235551234, :country_code => 1, :extension => 1343, :delimiter => ".")
- # => +1.123.555.1234 x 1343
+ # => +1.123.555.1234 x 1343
def number_to_phone(number, options = {})
number = number.to_s.strip unless number.nil?
options = options.stringify_keys
@@ -71,14 +71,14 @@ module ActionView
def number_to_currency(number, options = {})
options = options.symbolize_keys
defaults = I18n.translate(:'currency.format', :locale => options[:locale]) || {}
-
+
precision = options[:precision] || defaults[:precision]
unit = options[:unit] || defaults[:unit]
separator = options[:separator] || defaults[:separator]
delimiter = options[:delimiter] || defaults[:delimiter]
format = options[:format] || defaults[:format]
separator = '' if precision == 0
-
+
begin
parts = number_with_precision(number, precision).split('.')
format.gsub(/%n/, number_with_delimiter(parts[0], delimiter) + separator + parts[1].to_s).gsub(/%u/, unit)
@@ -118,49 +118,72 @@ module ActionView
end
end
- # Formats a +number+ with grouped thousands using +delimiter+ (e.g., 12,324). You
- # can customize the format using optional delimiter and separator parameters.
+ # Formats a +number+ with grouped thousands using +delimiter+ (e.g., 12,324). You can
+ # customize the format in the +options+ hash.
#
# ==== Options
- # * delimiter - Sets the thousands delimiter (defaults to ",").
- # * separator - Sets the separator between the units (defaults to ".").
+ # * :delimiter - Sets the thousands delimiter (defaults to ",").
+ # * :separator - Sets the separator between the units (defaults to ".").
#
# ==== Examples
- # number_with_delimiter(12345678) # => 12,345,678
- # number_with_delimiter(12345678.05) # => 12,345,678.05
- # number_with_delimiter(12345678, ".") # => 12.345.678
- #
- # number_with_delimiter(98765432.98, " ", ",")
+ # number_with_delimiter(12345678) # => 12,345,678
+ # number_with_delimiter(12345678.05) # => 12,345,678.05
+ # number_with_delimiter(12345678, :delimiter => ".") # => 12.345.678
+ # number_with_delimiter(12345678, :seperator => ",") # => 12,345,678
+ # number_with_delimiter(98765432.98, :delimiter => " ", :separator => ",")
# # => 98 765 432,98
- def number_with_delimiter(number, delimiter=",", separator=".")
+ #
+ # You can still use number_with_delimiter with the old API that accepts the
+ # +delimiter+ as its optional second and the +separator+ as its
+ # optional third parameter:
+ # number_with_delimiter(12345678, " ") # => 12 345.678
+ # number_with_delimiter(12345678.05, ".", ",") # => 12.345.678,05
+ def number_with_delimiter(number, *args)
+ options = args.extract_options!
+ unless args.empty?
+ options[:delimiter] = args[0] || ","
+ options[:separator] = args[1] || "."
+ end
+ options.reverse_merge!(:delimiter => ",", :separator => ".")
+
begin
parts = number.to_s.split('.')
- parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{delimiter}")
- parts.join separator
+ parts[0].gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{options[:delimiter]}")
+ parts.join options[:separator]
rescue
number
end
end
- # Formats a +number+ with the specified level of +precision+ (e.g., 112.32 has a precision of 2). The default
- # level of precision is 3.
+ # Formats a +number+ with the specified level of :precision (e.g., 112.32 has a precision of 2).
+ # The default level of precision is 3.
#
# ==== Examples
- # number_with_precision(111.2345) # => 111.235
- # number_with_precision(111.2345, 2) # => 111.23
- # number_with_precision(13, 5) # => 13.00000
- # number_with_precision(389.32314, 0) # => 389
- def number_with_precision(number, precision=3)
- "%01.#{precision}f" % ((Float(number) * (10 ** precision)).round.to_f / 10 ** precision)
+ # number_with_precision(111.2345) # => 111.235
+ # number_with_precision(111.2345, :precision => 2) # => 111.23
+ # number_with_precision(13, :precision => 5) # => 13.00000
+ # number_with_precision(389.32314, :precision => 0) # => 389
+ #
+ # You can still use number_with_precision with the old API that accepts the
+ # +precision+ as its optional second parameter:
+ # number_with_precision(number_with_precision(111.2345, 2) # => 111.23
+ def number_with_precision(number, *args)
+ options = args.extract_options!
+ unless args.empty?
+ options[:precision] = args[0] || 3
+ end
+ options.reverse_merge!(:precision => 3)
+ "%01.#{options[:precision]}f" %
+ ((Float(number) * (10 ** options[:precision])).round.to_f / 10 ** options[:precision])
rescue
number
end
# Formats the bytes in +size+ into a more understandable representation
- # (e.g., giving it 1500 yields 1.5 KB). This method is useful for
+ # (e.g., giving it 1500 yields 1.5 KB). This method is useful for
# reporting file sizes to users. This method returns nil if
# +size+ cannot be converted into a number. You can change the default
- # precision of 1 using the precision parameter +precision+.
+ # precision of 1 using the precision parameter :precision .
#
# ==== Examples
# number_to_human_size(123) # => 123 Bytes
@@ -169,17 +192,28 @@ module ActionView
# number_to_human_size(1234567) # => 1.2 MB
# number_to_human_size(1234567890) # => 1.1 GB
# number_to_human_size(1234567890123) # => 1.1 TB
+ # number_to_human_size(1234567, :precision => 2) # => 1.18 MB
+ # number_to_human_size(483989, :precision => 0) # => 473 KB
+ #
+ # You can still use number_to_human_size with the old API that accepts the
+ # +precision+ as its optional second parameter:
# number_to_human_size(1234567, 2) # => 1.18 MB
- # number_to_human_size(483989, 0) # => 4 MB
- def number_to_human_size(size, precision=1)
- size = Kernel.Float(size)
+ # number_to_human_size(483989, 0) # => 473 KB
+ def number_to_human_size(size, *args)
+ options = args.extract_options!
+ unless args.empty?
+ options[:precision] = args[0] || 1
+ end
+ options.reverse_merge!(:precision => 1)
+
+ size = Float(size)
case
when size.to_i == 1; "1 Byte"
when size < 1.kilobyte; "%d Bytes" % size
- when size < 1.megabyte; "%.#{precision}f KB" % (size / 1.0.kilobyte)
- when size < 1.gigabyte; "%.#{precision}f MB" % (size / 1.0.megabyte)
- when size < 1.terabyte; "%.#{precision}f GB" % (size / 1.0.gigabyte)
- else "%.#{precision}f TB" % (size / 1.0.terabyte)
+ when size < 1.megabyte; "%.#{options[:precision]}f KB" % (size / 1.0.kilobyte)
+ when size < 1.gigabyte; "%.#{options[:precision]}f MB" % (size / 1.0.megabyte)
+ when size < 1.terabyte; "%.#{options[:precision]}f GB" % (size / 1.0.gigabyte)
+ else "%.#{options[:precision]}f TB" % (size / 1.0.terabyte)
end.sub(/([0-9]\.\d*?)0+ /, '\1 ' ).sub(/\. /,' ')
rescue
nil
diff --git a/actionpack/test/template/number_helper_test.rb b/actionpack/test/template/number_helper_test.rb
index 4a8d09b544..bff349a754 100644
--- a/actionpack/test/template/number_helper_test.rb
+++ b/actionpack/test/template/number_helper_test.rb
@@ -54,9 +54,16 @@ class NumberHelperTest < ActionView::TestCase
assert_nil number_with_delimiter(nil)
end
+ def test_number_with_delimiter_with_options_hash
+ assert_equal '12 345 678', number_with_delimiter(12345678, :delimiter => ' ')
+ assert_equal '12,345,678-05', number_with_delimiter(12345678.05, :separator => '-')
+ assert_equal '12.345.678,05', number_with_delimiter(12345678.05, :separator => ',', :delimiter => '.')
+ assert_equal '12.345.678,05', number_with_delimiter(12345678.05, :delimiter => '.', :separator => ',')
+ end
+
def test_number_with_precision
assert_equal("111.235", number_with_precision(111.2346))
- assert_equal("31.83", number_with_precision(31.825, 2))
+ assert_equal("31.83", number_with_precision(31.825, 2))
assert_equal("111.23", number_with_precision(111.2346, 2))
assert_equal("111.00", number_with_precision(111, 2))
assert_equal("111.235", number_with_precision("111.2346"))
@@ -69,6 +76,17 @@ class NumberHelperTest < ActionView::TestCase
assert_nil number_with_precision(nil)
end
+ def test_number_with_precision_with_options_hash
+ assert_equal '111.235', number_with_precision(111.2346)
+ assert_equal '31.83', number_with_precision(31.825, :precision => 2)
+ assert_equal '111.23', number_with_precision(111.2346, :precision => 2)
+ assert_equal '111.00', number_with_precision(111, :precision => 2)
+ assert_equal '111.235', number_with_precision("111.2346")
+ assert_equal '31.83', number_with_precision("31.825", :precision => 2)
+ assert_equal '112', number_with_precision(111.50, :precision => 0)
+ assert_equal '1234567892', number_with_precision(1234567891.50, :precision => 0)
+ end
+
def test_number_to_human_size
assert_equal '0 Bytes', number_to_human_size(0)
assert_equal '1 Byte', number_to_human_size(1)
@@ -94,4 +112,12 @@ class NumberHelperTest < ActionView::TestCase
assert_nil number_to_human_size('x')
assert_nil number_to_human_size(nil)
end
+
+ def test_number_to_human_size_with_options_hash
+ assert_equal '1.18 MB', number_to_human_size(1234567, :precision => 2)
+ assert_equal '3 Bytes', number_to_human_size(3.14159265, :precision => 4)
+ assert_equal '1.01 KB', number_to_human_size(1.0123.kilobytes, :precision => 2)
+ assert_equal '1.01 KB', number_to_human_size(1.0100.kilobytes, :precision => 4)
+ assert_equal '10 KB', number_to_human_size(10.000.kilobytes, :precision => 4)
+ end
end
--
cgit v1.2.3
From 3bd34b6ffe017dd81fd26743aab052fc4324eb0f Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sat, 14 Jun 2008 16:24:23 -0500
Subject: Preload application classes. Uses same strategy as phusion passenger.
---
railties/lib/initializer.rb | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb
index b8b071d4c9..3be95de8d3 100644
--- a/railties/lib/initializer.rb
+++ b/railties/lib/initializer.rb
@@ -168,6 +168,9 @@ module Rails
# Observers are loaded after plugins in case Observers or observed models are modified by plugins.
load_observers
+ # load application classes
+ load_application_classes
+
# Flag initialized
Rails.initialized = true
end
@@ -330,6 +333,14 @@ Run `rake gems:install` to install the missing gems.
end
end
+ def load_application_classes
+ require_dependency 'application'
+
+ Dir.glob('app/{models,controllers,helpers}/*.rb').each do |file|
+ require_dependency file
+ end
+ end
+
# For Ruby 1.8, this initialization sets $KCODE to 'u' to enable the
# multibyte safe operations. Plugin authors supporting other encodings
# should override this behaviour and set the relevant +default_charset+
--
cgit v1.2.3
From 89ec72c2818a592323fe4ec3277638d379f1ac2a Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Mon, 21 Jul 2008 13:42:34 -0500
Subject: Added configurable eager load paths. Defaults to app/models,
app/controllers, and app/helpers
---
railties/CHANGELOG | 2 ++
railties/lib/initializer.rb | 25 +++++++++++++++++++++----
2 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/railties/CHANGELOG b/railties/CHANGELOG
index 9c5e5b59c6..5ff1867568 100644
--- a/railties/CHANGELOG
+++ b/railties/CHANGELOG
@@ -1,5 +1,7 @@
*Edge*
+* Added configurable eager load paths. Defaults to app/models, app/controllers, and app/helpers [Josh Peek]
+
* Introduce simple internationalization support. [Ruby i18n team]
* Make script/plugin install -r option work with git based plugins. #257. [Tim Pope Jakub Kuźma]. Example:
diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb
index 3be95de8d3..828d688475 100644
--- a/railties/lib/initializer.rb
+++ b/railties/lib/initializer.rb
@@ -333,11 +333,14 @@ Run `rake gems:install` to install the missing gems.
end
end
+ # Eager load application classes
def load_application_classes
- require_dependency 'application'
-
- Dir.glob('app/{models,controllers,helpers}/*.rb').each do |file|
- require_dependency file
+ if configuration.cache_classes
+ configuration.eager_load_paths.each do |load_path|
+ Dir.glob("#{load_path}/*.rb").each do |file|
+ require_dependency file
+ end
+ end
end
end
@@ -578,6 +581,11 @@ Run `rake gems:install` to install the missing gems.
# All elements of this array must also be in +load_paths+.
attr_accessor :load_once_paths
+ # 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+.
+ attr_accessor :eager_load_paths
+
# The log level to use for the default Rails logger. In production mode,
# this defaults to :info . In development mode, it defaults to
# :debug .
@@ -686,6 +694,7 @@ Run `rake gems:install` to install the missing gems.
self.frameworks = default_frameworks
self.load_paths = default_load_paths
self.load_once_paths = default_load_once_paths
+ self.eager_load_paths = default_eager_load_paths
self.log_path = default_log_path
self.log_level = default_log_level
self.view_path = default_view_path
@@ -826,6 +835,14 @@ Run `rake gems:install` to install the missing gems.
[]
end
+ def default_eager_load_paths
+ %w(
+ app/models
+ app/controllers
+ app/helpers
+ ).map { |dir| "#{root_path}/#{dir}" }.select { |dir| File.directory?(dir) }
+ end
+
def default_log_path
File.join(root_path, 'log', "#{environment}.log")
end
--
cgit v1.2.3
From c67713a2fe78d6f2db49b09771841f5022995703 Mon Sep 17 00:00:00 2001
From: Daniel Guettler
Date: Mon, 21 Jul 2008 15:21:13 -0400
Subject: Use klass.sti_name to make sure associations take
store_full_sti_class into account. [#671 state:resolved]
Signed-off-by: Pratik Naik
---
activerecord/lib/active_record/associations.rb | 4 ++--
.../cases/associations/has_many_associations_test.rb | 18 ++++++++++++++++++
activerecord/test/models/company.rb | 7 +++++++
3 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index fd9a443eb9..d916275ab9 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1884,7 +1884,7 @@ module ActiveRecord
jt_sti_extra = " AND %s.%s = %s" % [
connection.quote_table_name(aliased_join_table_name),
connection.quote_column_name(through_reflection.active_record.inheritance_column),
- through_reflection.klass.quote_value(through_reflection.klass.name.demodulize)]
+ through_reflection.klass.quote_value(through_reflection.klass.sti_name)]
end
when :belongs_to
first_key = primary_key
@@ -1952,7 +1952,7 @@ module ActiveRecord
join << %(AND %s.%s = %s ) % [
connection.quote_table_name(aliased_table_name),
connection.quote_column_name(klass.inheritance_column),
- klass.quote_value(klass.name.demodulize)] unless klass.descends_from_active_record?
+ klass.quote_value(klass.sti_name)] unless klass.descends_from_active_record?
[through_reflection, reflection].each do |ref|
join << "AND #{interpolate_sql(sanitize_sql(ref.options[:conditions]))} " if ref && ref.options[:conditions]
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index b9c7ec6377..f8b8b1f96d 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -999,4 +999,22 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert firm.clients.loaded?
end
+ def test_joins_with_namespaced_model_should_use_correct_type
+ old = ActiveRecord::Base.store_full_sti_class
+ ActiveRecord::Base.store_full_sti_class = true
+
+ firm = Namespaced::Firm.create({ :name => 'Some Company' })
+ firm.clients.create({ :name => 'Some Client' })
+
+ stats = Namespaced::Firm.find(firm.id, {
+ :select => "#{Namespaced::Firm.table_name}.*, COUNT(#{Namespaced::Client.table_name}.id) AS num_clients",
+ :joins => :clients,
+ :group => "#{Namespaced::Firm.table_name}.id"
+ })
+ assert_equal 1, stats.num_clients.to_i
+
+ ensure
+ ActiveRecord::Base.store_full_sti_class = old
+ end
+
end
diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb
index e6aa810146..cd435948a1 100755
--- a/activerecord/test/models/company.rb
+++ b/activerecord/test/models/company.rb
@@ -18,6 +18,13 @@ end
module Namespaced
class Company < ::Company
end
+
+ class Firm < ::Company
+ has_many :clients, :class_name => 'Namespaced::Client'
+ end
+
+ class Client < ::Company
+ end
end
class Firm < Company
--
cgit v1.2.3
From 92f944818eece9fe4bc62ffb39accdb71ebc32be Mon Sep 17 00:00:00 2001
From: Miles Georgi
Date: Sat, 19 Jul 2008 16:04:35 -0700
Subject: Make script/plugin work with svn+ssh urls. [#662 state:resolved]
Signed-off-by: Pratik Naik
---
railties/lib/commands/plugin.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/railties/lib/commands/plugin.rb b/railties/lib/commands/plugin.rb
index 0256090d16..980244a71b 100644
--- a/railties/lib/commands/plugin.rb
+++ b/railties/lib/commands/plugin.rb
@@ -907,7 +907,7 @@ class RecursiveHTTPFetcher
def ls
@urls_to_fetch.collect do |url|
- if url =~ /^svn:\/\/.*/
+ if url =~ /^svn(\+ssh)?:\/\/.*/
`svn ls #{url}`.split("\n").map {|entry| "/#{entry}"} rescue nil
else
open(url) do |stream|
--
cgit v1.2.3
From 8b858782fa693e89a47fc3dd5ae38d842ede6d04 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Mon, 21 Jul 2008 22:41:38 -0500
Subject: Ensure adapater specific code is loaded on
ActiveRecord::Base.establish_connection
---
.../connection_adapters/abstract/connection_specification.rb | 1 +
1 file changed, 1 insertion(+)
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb
index 2a8807fb78..07b122efd1 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb
@@ -211,6 +211,7 @@ module ActiveRecord
clear_active_connection_name
@active_connection_name = name
@@defined_connections[name] = spec
+ connection
when Symbol, String
if configuration = configurations[spec.to_s]
establish_connection(configuration)
--
cgit v1.2.3
From 8a87d8a6c2c6dfb423bcaf61c750010d80993b16 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Tue, 22 Jul 2008 10:26:44 -0500
Subject: Improved Memoizable test coverage and added support for multiple
arguments
---
.../active_support/core_ext/object/metaclass.rb | 5 +
activesupport/lib/active_support/memoizable.rb | 55 ++++---
activesupport/test/memoizable_test.rb | 166 ++++++++++++++++-----
3 files changed, 165 insertions(+), 61 deletions(-)
diff --git a/activesupport/lib/active_support/core_ext/object/metaclass.rb b/activesupport/lib/active_support/core_ext/object/metaclass.rb
index 169a76dfb7..93fb0ad594 100644
--- a/activesupport/lib/active_support/core_ext/object/metaclass.rb
+++ b/activesupport/lib/active_support/core_ext/object/metaclass.rb
@@ -5,4 +5,9 @@ class Object
self
end
end
+
+ # If class_eval is called on an object, add those methods to its metaclass
+ def class_eval(*args, &block)
+ metaclass.class_eval(*args, &block)
+ end
end
diff --git a/activesupport/lib/active_support/memoizable.rb b/activesupport/lib/active_support/memoizable.rb
index f7cd73d39c..21636b8af4 100644
--- a/activesupport/lib/active_support/memoizable.rb
+++ b/activesupport/lib/active_support/memoizable.rb
@@ -1,32 +1,43 @@
module ActiveSupport
- module Memoizable #:nodoc:
+ module Memoizable
+ module Freezable
+ def self.included(base)
+ base.class_eval do
+ unless base.method_defined?(:freeze_without_memoizable)
+ alias_method_chain :freeze, :memoizable
+ end
+ end
+ end
+
+ def freeze_with_memoizable
+ methods.each do |method|
+ if m = method.to_s.match(/^_unmemoized_(.*)/)
+ send(m[1])
+ end
+ end
+ freeze_without_memoizable
+ end
+ end
+
def memoize(*symbols)
symbols.each do |symbol|
- original_method = "unmemoized_#{symbol}"
- memoized_ivar = "@#{symbol}"
+ original_method = "_unmemoized_#{symbol}"
+ memoized_ivar = "@_memoized_#{symbol}"
- klass = respond_to?(:class_eval) ? self : self.metaclass
- raise "Already memoized #{symbol}" if klass.instance_methods.map(&:to_s).include?(original_method)
+ class_eval <<-EOS, __FILE__, __LINE__
+ include Freezable
- klass.class_eval <<-EOS, __FILE__, __LINE__
- unless instance_methods.map(&:to_s).include?("freeze_without_memoizable")
- alias_method :freeze_without_memoizable, :freeze
- def freeze
- methods.each do |method|
- if m = method.to_s.match(/^unmemoized_(.*)/)
- send(m[1])
- end
- end
- freeze_without_memoizable
- end
- end
+ raise "Already memoized #{symbol}" if method_defined?(:#{original_method})
+ alias #{original_method} #{symbol}
+
+ def #{symbol}(*args)
+ #{memoized_ivar} ||= {}
+ reload = args.pop if args.last == true || args.last == :reload
- alias_method :#{original_method}, :#{symbol}
- def #{symbol}(reload = false)
- if !reload && defined? #{memoized_ivar}
- #{memoized_ivar}
+ if !reload && #{memoized_ivar} && #{memoized_ivar}.has_key?(args)
+ #{memoized_ivar}[args]
else
- #{memoized_ivar} = #{original_method}.freeze
+ #{memoized_ivar}[args] = #{original_method}(*args).freeze
end
end
EOS
diff --git a/activesupport/test/memoizable_test.rb b/activesupport/test/memoizable_test.rb
index 79769631ad..cd84dcda53 100644
--- a/activesupport/test/memoizable_test.rb
+++ b/activesupport/test/memoizable_test.rb
@@ -5,86 +5,174 @@ uses_mocha 'Memoizable' do
class Person
extend ActiveSupport::Memoizable
- def name
- fetch_name_from_floppy
+ attr_reader :name_calls, :age_calls
+ def initialize
+ @name_calls = 0
+ @age_calls = 0
end
- memoize :name
+ def name
+ @name_calls += 1
+ "Josh"
+ end
def age
+ @age_calls += 1
nil
end
- def counter
- @counter ||= 0
- @counter += 1
+ memoize :name, :age
+ end
+
+ class Company
+ attr_reader :name_calls
+ def initialize
+ @name_calls = 0
end
- memoize :age, :counter
+ def name
+ @name_calls += 1
+ "37signals"
+ end
+ end
+
+ module Rates
+ extend ActiveSupport::Memoizable
- private
- def fetch_name_from_floppy
- "Josh"
+ attr_reader :sales_tax_calls
+ def sales_tax(price)
+ @sales_tax_calls ||= 0
+ @sales_tax_calls += 1
+ price * 0.1025
+ end
+ memoize :sales_tax
+ end
+
+ class Calculator
+ extend ActiveSupport::Memoizable
+ include Rates
+
+ attr_reader :fib_calls
+ def initialize
+ @fib_calls = 0
+ end
+
+ def fib(n)
+ @fib_calls += 1
+
+ if n == 0 || n == 1
+ n
+ else
+ fib(n - 1) + fib(n - 2)
end
+ end
+ memoize :fib
+
+ def counter
+ @count ||= 0
+ @count += 1
+ end
+ memoize :counter
end
def setup
@person = Person.new
+ @calculator = Calculator.new
end
def test_memoization
assert_equal "Josh", @person.name
+ assert_equal 1, @person.name_calls
- @person.expects(:fetch_name_from_floppy).never
- 2.times { assert_equal "Josh", @person.name }
+ 3.times { assert_equal "Josh", @person.name }
+ assert_equal 1, @person.name_calls
+ end
+
+ def test_memoization_with_nil_value
+ assert_equal nil, @person.age
+ assert_equal 1, @person.age_calls
+
+ 3.times { assert_equal nil, @person.age }
+ assert_equal 1, @person.age_calls
end
def test_reloadable
- counter = @person.counter
- assert_equal 1, @person.counter
- assert_equal 2, @person.counter(:reload)
+ counter = @calculator.counter
+ assert_equal 1, @calculator.counter
+ assert_equal 2, @calculator.counter(:reload)
+ assert_equal 2, @calculator.counter
+ assert_equal 3, @calculator.counter(true)
+ assert_equal 3, @calculator.counter
end
- def test_memoized_methods_are_frozen
- assert_equal true, @person.name.frozen?
+ def test_memoization_cache_is_different_for_each_instance
+ assert_equal 1, @calculator.counter
+ assert_equal 2, @calculator.counter(:reload)
+ assert_equal 1, Calculator.new.counter
+ end
+ def test_memoized_is_not_affected_by_freeze
@person.freeze
assert_equal "Josh", @person.name
- assert_equal true, @person.name.frozen?
end
- def test_memoization_frozen_with_nil_value
- @person.freeze
- assert_equal nil, @person.age
+ def test_memoization_with_args
+ assert_equal 55, @calculator.fib(10)
+ assert_equal 11, @calculator.fib_calls
end
- def test_double_memoization
- assert_raise(RuntimeError) { Person.memoize :name }
+ def test_reloadable_with_args
+ assert_equal 55, @calculator.fib(10)
+ assert_equal 11, @calculator.fib_calls
+ assert_equal 55, @calculator.fib(10, :reload)
+ assert_equal 12, @calculator.fib_calls
+ assert_equal 55, @calculator.fib(10, true)
+ assert_equal 13, @calculator.fib_calls
end
- class Company
- def name
- lookup_name
+ def test_object_memoization
+ [Company.new, Company.new, Company.new].each do |company|
+ company.extend ActiveSupport::Memoizable
+ company.memoize :name
+
+ assert_equal "37signals", company.name
+ assert_equal 1, company.name_calls
+ assert_equal "37signals", company.name
+ assert_equal 1, company.name_calls
end
+ end
- def lookup_name
- "37signals"
- end
+ def test_memoized_module_methods
+ assert_equal 1.025, @calculator.sales_tax(10)
+ assert_equal 1, @calculator.sales_tax_calls
+ assert_equal 1.025, @calculator.sales_tax(10)
+ assert_equal 1, @calculator.sales_tax_calls
+ assert_equal 2.5625, @calculator.sales_tax(25)
+ assert_equal 2, @calculator.sales_tax_calls
end
- def test_object_memoization
+ def test_object_memoized_module_methods
company = Company.new
- company.extend ActiveSupport::Memoizable
- company.memoize :name
+ company.extend(Rates)
+
+ assert_equal 1.025, company.sales_tax(10)
+ assert_equal 1, company.sales_tax_calls
+ assert_equal 1.025, company.sales_tax(10)
+ assert_equal 1, company.sales_tax_calls
+ assert_equal 2.5625, company.sales_tax(25)
+ assert_equal 2, company.sales_tax_calls
+ end
- assert_equal "37signals", company.name
- # Mocha doesn't play well with frozen objects
- company.metaclass.instance_eval { define_method(:lookup_name) { b00m } }
- assert_equal "37signals", company.name
+ def test_double_memoization
+ assert_raise(RuntimeError) { Person.memoize :name }
+ person = Person.new
+ person.extend ActiveSupport::Memoizable
+ assert_raise(RuntimeError) { person.memoize :name }
- assert_equal true, company.name.frozen?
- company.freeze
- assert_equal true, company.name.frozen?
+ company = Company.new
+ company.extend ActiveSupport::Memoizable
+ company.memoize :name
+ assert_raise(RuntimeError) { company.memoize :name }
end
end
end
--
cgit v1.2.3
From bc5896e708bf8070835bebe61de03b701fa5e6f7 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Tue, 22 Jul 2008 10:27:32 -0500
Subject: Memoize ActionView::Base pick_template and find_partial_path for
rendering duration
---
actionpack/lib/action_controller/base.rb | 2 ++
actionpack/lib/action_view/base.rb | 7 +++++--
actionpack/lib/action_view/partials.rb | 9 +++++----
actionpack/lib/action_view/template.rb | 2 +-
.../test/template/compiled_templates_test.rb | 23 ++++++++++++----------
5 files changed, 26 insertions(+), 17 deletions(-)
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index 50727c67c4..4dabff637b 100755
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -1261,6 +1261,8 @@ module ActionController #:nodoc:
def template_exempt_from_layout?(template_name = default_template_name)
template_name = @template.pick_template(template_name).to_s if @template
@@exempt_from_layout.any? { |ext| template_name =~ ext }
+ rescue ActionView::MissingTemplate
+ false
end
def default_template_name(action_name = self.action_name)
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index 619a4270f8..bdcb1dc246 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -323,8 +323,8 @@ module ActionView #:nodoc:
if self.class.warn_cache_misses && logger = ActionController::Base.logger
logger.debug "[PERFORMANCE] Rendering a template that was " +
"not found in view path. Templates outside the view path are " +
- "not cached and result in expensive disk operations. Move this " +
- "file into #{view_paths.join(':')} or add the folder to your " +
+ "not cached and result in expensive disk operations. Move this " +
+ "file into #{view_paths.join(':')} or add the folder to your " +
"view path list"
end
@@ -332,6 +332,9 @@ module ActionView #:nodoc:
end
end
+ extend ActiveSupport::Memoizable
+ memoize :pick_template
+
private
# Renders the template present at template_path . The hash in local_assigns
# is made available as local variables.
diff --git a/actionpack/lib/action_view/partials.rb b/actionpack/lib/action_view/partials.rb
index 5aa4c83009..eb74d4a4c7 100644
--- a/actionpack/lib/action_view/partials.rb
+++ b/actionpack/lib/action_view/partials.rb
@@ -102,6 +102,8 @@ module ActionView
#
# As you can see, the :locals hash is shared between both the partial and its layout.
module Partials
+ extend ActiveSupport::Memoizable
+
private
def render_partial(partial_path, object_assigns = nil, local_assigns = {}) #:nodoc:
local_assigns ||= {}
@@ -129,14 +131,12 @@ module ActionView
local_assigns = local_assigns ? local_assigns.clone : {}
spacer = partial_spacer_template ? render(:partial => partial_spacer_template) : ''
- _paths = {}
- _templates = {}
index = 0
collection.map do |object|
_partial_path ||= partial_path || ActionController::RecordIdentifier.partial_path(object, controller.class.controller_path)
- path = _paths[_partial_path] ||= find_partial_path(_partial_path)
- template = _templates[path] ||= pick_template(path)
+ path = find_partial_path(_partial_path)
+ template = pick_template(path)
local_assigns[template.counter_name] = index
result = template.render_partial(self, object, local_assigns, as)
index += 1
@@ -153,5 +153,6 @@ module ActionView
"_#{partial_path}"
end
end
+ memoize :find_partial_path
end
end
diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb
index 1f528dd900..3fcd9a2d01 100644
--- a/actionpack/lib/action_view/template.rb
+++ b/actionpack/lib/action_view/template.rb
@@ -75,7 +75,7 @@ module ActionView #:nodoc:
load_paths = Array(load_paths) + [nil]
load_paths.each do |load_path|
file = [load_path, path].compact.join('/')
- return load_path, file if File.exist?(file)
+ return load_path, file if File.exist?(file) && File.file?(file)
end
raise MissingTemplate.new(load_paths, path)
end
diff --git a/actionpack/test/template/compiled_templates_test.rb b/actionpack/test/template/compiled_templates_test.rb
index 4b34827f91..52996c7fcb 100644
--- a/actionpack/test/template/compiled_templates_test.rb
+++ b/actionpack/test/template/compiled_templates_test.rb
@@ -4,7 +4,6 @@ require 'controller/fake_models'
uses_mocha 'TestTemplateRecompilation' do
class CompiledTemplatesTest < Test::Unit::TestCase
def setup
- @view = ActionView::Base.new(ActionController::Base.view_paths, {})
@compiled_templates = ActionView::Base::CompiledTemplates
@compiled_templates.instance_methods.each do |m|
@compiled_templates.send(:remove_method, m) if m =~ /^_run_/
@@ -13,29 +12,33 @@ uses_mocha 'TestTemplateRecompilation' do
def test_template_gets_compiled
assert_equal 0, @compiled_templates.instance_methods.size
- assert_equal "Hello world!", @view.render("test/hello_world.erb")
+ assert_equal "Hello world!", render("test/hello_world.erb")
assert_equal 1, @compiled_templates.instance_methods.size
end
def test_template_gets_recompiled_when_using_different_keys_in_local_assigns
assert_equal 0, @compiled_templates.instance_methods.size
- assert_equal "Hello world!", @view.render("test/hello_world.erb")
- assert_equal "Hello world!", @view.render("test/hello_world.erb", {:foo => "bar"})
+ assert_equal "Hello world!", render("test/hello_world.erb")
+ assert_equal "Hello world!", render("test/hello_world.erb", {:foo => "bar"})
assert_equal 2, @compiled_templates.instance_methods.size
end
def test_compiled_template_will_not_be_recompiled_when_rendered_with_identical_local_assigns
assert_equal 0, @compiled_templates.instance_methods.size
- assert_equal "Hello world!", @view.render("test/hello_world.erb")
+ assert_equal "Hello world!", render("test/hello_world.erb")
ActionView::Template.any_instance.expects(:compile!).never
- assert_equal "Hello world!", @view.render("test/hello_world.erb")
+ assert_equal "Hello world!", render("test/hello_world.erb")
end
- def test_compiled_template_will_always_be_recompiled_when_rendered_if_template_is_outside_cache
+ def test_compiled_template_will_be_recompiled_when_rendered_if_template_is_outside_cache
assert_equal 0, @compiled_templates.instance_methods.size
- assert_equal "Hello world!", @view.render("#{FIXTURE_LOAD_PATH}/test/hello_world.erb")
- ActionView::Template.any_instance.expects(:compile!).times(3)
- 3.times { assert_equal "Hello world!", @view.render("#{FIXTURE_LOAD_PATH}/test/hello_world.erb") }
+ assert_equal "Hello world!", render("#{FIXTURE_LOAD_PATH}/test/hello_world.erb")
+ assert_equal 1, @compiled_templates.instance_methods.size
end
+
+ private
+ def render(*args)
+ ActionView::Base.new(ActionController::Base.view_paths, {}).render(*args)
+ end
end
end
--
cgit v1.2.3
From 2681685450631238511cfc3c2f0fa044c1f8033a Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Tue, 22 Jul 2008 11:12:16 -0500
Subject: Extract ActiveSupport::TypedArray class to ensure an array is all of
the same type [#673 state:resolved]
---
actionpack/lib/action_view/paths.rb | 31 +++------------
actionpack/test/controller/view_paths_test.rb | 10 +----
activesupport/lib/active_support.rb | 1 +
activesupport/lib/active_support/typed_array.rb | 31 +++++++++++++++
activesupport/test/typed_array_test.rb | 51 +++++++++++++++++++++++++
5 files changed, 91 insertions(+), 33 deletions(-)
create mode 100644 activesupport/lib/active_support/typed_array.rb
create mode 100644 activesupport/test/typed_array_test.rb
diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb
index 78548d4aa2..9cb50ab4f8 100644
--- a/actionpack/lib/action_view/paths.rb
+++ b/actionpack/lib/action_view/paths.rb
@@ -1,5 +1,5 @@
module ActionView #:nodoc:
- class PathSet < Array #:nodoc:
+ class PathSet < ActiveSupport::TypedArray #:nodoc:
def self.type_cast(obj)
if obj.is_a?(String)
if Base.warn_cache_misses && defined?(Rails) && Rails.initialized?
@@ -25,7 +25,7 @@ module ActionView #:nodoc:
end
attr_reader :path, :paths
- delegate :to_s, :to_str, :inspect, :to => :path
+ delegate :to_s, :to_str, :hash, :inspect, :to => :path
def initialize(path)
raise ArgumentError, "path already is a Path class" if path.is_a?(Path)
@@ -38,6 +38,10 @@ module ActionView #:nodoc:
to_str == path.to_str
end
+ def eql?(path)
+ to_str == path.to_str
+ end
+
def [](path)
@paths[path]
end
@@ -67,28 +71,10 @@ module ActionView #:nodoc:
end
end
- def initialize(*args)
- super(*args).map! { |obj| self.class.type_cast(obj) }
- end
-
def reload!
each { |path| path.reload! }
end
- def <<(obj)
- super(self.class.type_cast(obj))
- end
-
- def push(*objs)
- delete_paths!(objs)
- super(*objs.map { |obj| self.class.type_cast(obj) })
- end
-
- def unshift(*objs)
- delete_paths!(objs)
- super(*objs.map { |obj| self.class.type_cast(obj) })
- end
-
def [](template_path)
each do |path|
if template = path[template_path]
@@ -97,10 +83,5 @@ module ActionView #:nodoc:
end
nil
end
-
- private
- def delete_paths!(paths)
- paths.each { |p1| delete_if { |p2| p1.to_s == p2.to_s } }
- end
end
end
diff --git a/actionpack/test/controller/view_paths_test.rb b/actionpack/test/controller/view_paths_test.rb
index 85fa58a45b..b859a92cbd 100644
--- a/actionpack/test/controller/view_paths_test.rb
+++ b/actionpack/test/controller/view_paths_test.rb
@@ -54,10 +54,7 @@ class ViewLoadPathsTest < Test::Unit::TestCase
assert_equal [FIXTURE_LOAD_PATH, 'foo', 'bar', 'baz'], @controller.view_paths
@controller.append_view_path(FIXTURE_LOAD_PATH)
- assert_equal ['foo', 'bar', 'baz', FIXTURE_LOAD_PATH], @controller.view_paths
-
- @controller.append_view_path([FIXTURE_LOAD_PATH])
- assert_equal ['foo', 'bar', 'baz', FIXTURE_LOAD_PATH], @controller.view_paths
+ assert_equal [FIXTURE_LOAD_PATH, 'foo', 'bar', 'baz', FIXTURE_LOAD_PATH], @controller.view_paths
end
def test_controller_prepends_view_path_correctly
@@ -68,10 +65,7 @@ class ViewLoadPathsTest < Test::Unit::TestCase
assert_equal ['foo', 'bar', 'baz', FIXTURE_LOAD_PATH], @controller.view_paths
@controller.prepend_view_path(FIXTURE_LOAD_PATH)
- assert_equal [FIXTURE_LOAD_PATH, 'foo', 'bar', 'baz'], @controller.view_paths
-
- @controller.prepend_view_path([FIXTURE_LOAD_PATH])
- assert_equal [FIXTURE_LOAD_PATH, 'foo', 'bar', 'baz'], @controller.view_paths
+ assert_equal [FIXTURE_LOAD_PATH, 'foo', 'bar', 'baz', FIXTURE_LOAD_PATH], @controller.view_paths
end
def test_template_appends_view_path_correctly
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index 1df911a3f2..51067e910e 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -39,6 +39,7 @@ require 'active_support/cache'
require 'active_support/dependencies'
require 'active_support/deprecation'
+require 'active_support/typed_array'
require 'active_support/ordered_hash'
require 'active_support/ordered_options'
require 'active_support/option_merger'
diff --git a/activesupport/lib/active_support/typed_array.rb b/activesupport/lib/active_support/typed_array.rb
new file mode 100644
index 0000000000..1a4d8a8faf
--- /dev/null
+++ b/activesupport/lib/active_support/typed_array.rb
@@ -0,0 +1,31 @@
+module ActiveSupport
+ class TypedArray < Array
+ def self.type_cast(obj)
+ obj
+ end
+
+ def initialize(*args)
+ super(*args).map! { |obj| self.class.type_cast(obj) }
+ end
+
+ def <<(obj)
+ super(self.class.type_cast(obj))
+ end
+
+ def concat(array)
+ super(array.map! { |obj| self.class.type_cast(obj) })
+ end
+
+ def insert(index, obj)
+ super(index, self.class.type_cast(obj))
+ end
+
+ def push(*objs)
+ super(*objs.map { |obj| self.class.type_cast(obj) })
+ end
+
+ def unshift(*objs)
+ super(*objs.map { |obj| self.class.type_cast(obj) })
+ end
+ end
+end
diff --git a/activesupport/test/typed_array_test.rb b/activesupport/test/typed_array_test.rb
new file mode 100644
index 0000000000..023f3a1b84
--- /dev/null
+++ b/activesupport/test/typed_array_test.rb
@@ -0,0 +1,51 @@
+require 'abstract_unit'
+
+class TypedArrayTest < Test::Unit::TestCase
+ class StringArray < ActiveSupport::TypedArray
+ def self.type_cast(obj)
+ obj.to_s
+ end
+ end
+
+ def setup
+ @array = StringArray.new
+ end
+
+ def test_string_array_initialize
+ assert_equal ["1", "2", "3"], StringArray.new([1, "2", :"3"])
+ end
+
+ def test_string_array_append
+ @array << 1
+ @array << "2"
+ @array << :"3"
+ assert_equal ["1", "2", "3"], @array
+ end
+
+ def test_string_array_concat
+ @array.concat([1, "2"])
+ @array.concat([:"3"])
+ assert_equal ["1", "2", "3"], @array
+ end
+
+ def test_string_array_insert
+ @array.insert(0, 1)
+ @array.insert(1, "2")
+ @array.insert(2, :"3")
+ assert_equal ["1", "2", "3"], @array
+ end
+
+ def test_string_array_push
+ @array.push(1)
+ @array.push("2")
+ @array.push(:"3")
+ assert_equal ["1", "2", "3"], @array
+ end
+
+ def test_string_array_unshift
+ @array.unshift(:"3")
+ @array.unshift("2")
+ @array.unshift(1)
+ assert_equal ["1", "2", "3"], @array
+ end
+end
--
cgit v1.2.3
From 93e10f9911fb2a096681ee0a0bc82487a9a06c44 Mon Sep 17 00:00:00 2001
From: Jan De Poorter
Date: Wed, 23 Jul 2008 12:50:16 +0200
Subject: Ensure NamedScope#any? uses COUNT query wherever possible. [#680
state:resolved]
Signed-off-by: Pratik Naik
---
activerecord/lib/active_record/named_scope.rb | 10 +++++++++-
activerecord/test/cases/named_scope_test.rb | 22 ++++++++++++++++++++++
2 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb
index 080e3d0f5e..d5a1c5fe08 100644
--- a/activerecord/lib/active_record/named_scope.rb
+++ b/activerecord/lib/active_record/named_scope.rb
@@ -103,7 +103,7 @@ module ActiveRecord
attr_reader :proxy_scope, :proxy_options
[].methods.each do |m|
- unless m =~ /(^__|^nil\?|^send|^object_id$|class|extend|find|count|sum|average|maximum|minimum|paginate|first|last|empty?)/
+ unless m =~ /(^__|^nil\?|^send|^object_id$|class|extend|find|count|sum|average|maximum|minimum|paginate|first|last|empty?|any?)/
delegate m, :to => :proxy_found
end
end
@@ -140,6 +140,14 @@ module ActiveRecord
@found ? @found.empty? : count.zero?
end
+ def any?
+ if block_given?
+ proxy_found.any? { |*block_args| yield(*block_args) }
+ else
+ !empty?
+ end
+ end
+
protected
def proxy_found
@found || load_found
diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb
index 0c1eb23428..e21ffbbdba 100644
--- a/activerecord/test/cases/named_scope_test.rb
+++ b/activerecord/test/cases/named_scope_test.rb
@@ -184,6 +184,28 @@ class NamedScopeTest < ActiveRecord::TestCase
end
end
+ def test_any_should_not_load_results
+ topics = Topic.base
+ assert_queries(1) do
+ topics.expects(:empty?).returns(true)
+ assert !topics.any?
+ end
+ end
+
+ def test_any_should_call_proxy_found_if_using_a_block
+ topics = Topic.base
+ assert_queries(1) do
+ topics.expects(:empty?).never
+ topics.any? { true }
+ end
+ end
+
+ def test_any_should_not_fire_query_if_named_scope_loaded
+ topics = Topic.base
+ topics.collect # force load
+ assert_no_queries { assert topics.any? }
+ end
+
def test_should_build_with_proxy_options
topic = Topic.approved.build({})
assert topic.approved
--
cgit v1.2.3
From db1bac796e2d53fac4b51a3f560010b8f663fb54 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Wed, 23 Jul 2008 10:24:47 -0500
Subject: Just file?
---
actionpack/lib/action_view/template.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb
index 3fcd9a2d01..b281ff61f2 100644
--- a/actionpack/lib/action_view/template.rb
+++ b/actionpack/lib/action_view/template.rb
@@ -75,7 +75,7 @@ module ActionView #:nodoc:
load_paths = Array(load_paths) + [nil]
load_paths.each do |load_path|
file = [load_path, path].compact.join('/')
- return load_path, file if File.exist?(file) && File.file?(file)
+ return load_path, file if File.file?(file)
end
raise MissingTemplate.new(load_paths, path)
end
--
cgit v1.2.3
From 97a954bf1dd05e79a873bffc94fcf5420b807371 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Wed, 23 Jul 2008 10:41:28 -0500
Subject: Load view path cache after plugins and gems.
---
actionpack/lib/action_view/paths.rb | 18 +++++++++++++++---
railties/lib/initializer.rb | 13 ++++++++++---
2 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/actionpack/lib/action_view/paths.rb b/actionpack/lib/action_view/paths.rb
index 9cb50ab4f8..a37706faee 100644
--- a/actionpack/lib/action_view/paths.rb
+++ b/actionpack/lib/action_view/paths.rb
@@ -27,11 +27,10 @@ module ActionView #:nodoc:
attr_reader :path, :paths
delegate :to_s, :to_str, :hash, :inspect, :to => :path
- def initialize(path)
+ def initialize(path, load = true)
raise ArgumentError, "path already is a Path class" if path.is_a?(Path)
-
@path = path.freeze
- reload!
+ reload! if load
end
def ==(path)
@@ -46,6 +45,14 @@ module ActionView #:nodoc:
@paths[path]
end
+ def loaded?
+ @loaded ? true : false
+ end
+
+ def load
+ reload! unless loaded?
+ end
+
# Rebuild load path directory cache
def reload!
@paths = {}
@@ -59,6 +66,7 @@ module ActionView #:nodoc:
end
@paths.freeze
+ @loaded = true
end
private
@@ -71,6 +79,10 @@ module ActionView #:nodoc:
end
end
+ def load
+ each { |path| path.load }
+ end
+
def reload!
each { |path| path.reload! }
end
diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb
index 828d688475..97bb81a3c8 100644
--- a/railties/lib/initializer.rb
+++ b/railties/lib/initializer.rb
@@ -168,6 +168,9 @@ module Rails
# Observers are loaded after plugins in case Observers or observed models are modified by plugins.
load_observers
+ # Load view path cache
+ load_view_paths
+
# load application classes
load_application_classes
@@ -333,6 +336,12 @@ Run `rake gems:install` to install the missing gems.
end
end
+ def load_view_paths
+ ActionView::PathSet::Path.eager_load_templates! if configuration.cache_classes
+ ActionMailer::Base.template_root.load
+ ActionController::Base.view_paths.load
+ end
+
# Eager load application classes
def load_application_classes
if configuration.cache_classes
@@ -428,9 +437,7 @@ Run `rake gems:install` to install the missing gems.
# paths have already been set, it is not changed, otherwise it is
# set to use Configuration#view_path.
def initialize_framework_views
- ActionView::PathSet::Path.eager_load_templates! if configuration.cache_classes
- view_path = ActionView::PathSet::Path.new(configuration.view_path)
-
+ view_path = ActionView::PathSet::Path.new(configuration.view_path, false)
ActionMailer::Base.template_root ||= view_path if configuration.frameworks.include?(:action_mailer)
ActionController::Base.view_paths = view_path if configuration.frameworks.include?(:action_controller) && ActionController::Base.view_paths.empty?
end
--
cgit v1.2.3
From e0db925be04ab3e9c3db67dd0daa8caf3680dd21 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Wed, 23 Jul 2008 11:23:25 -0500
Subject: Revert 'bc5896e'
---
actionpack/lib/action_view/base.rb | 3 ---
actionpack/lib/action_view/partials.rb | 9 ++++-----
2 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index bdcb1dc246..c769013d42 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -332,9 +332,6 @@ module ActionView #:nodoc:
end
end
- extend ActiveSupport::Memoizable
- memoize :pick_template
-
private
# Renders the template present at template_path . The hash in local_assigns
# is made available as local variables.
diff --git a/actionpack/lib/action_view/partials.rb b/actionpack/lib/action_view/partials.rb
index eb74d4a4c7..5aa4c83009 100644
--- a/actionpack/lib/action_view/partials.rb
+++ b/actionpack/lib/action_view/partials.rb
@@ -102,8 +102,6 @@ module ActionView
#
# As you can see, the :locals hash is shared between both the partial and its layout.
module Partials
- extend ActiveSupport::Memoizable
-
private
def render_partial(partial_path, object_assigns = nil, local_assigns = {}) #:nodoc:
local_assigns ||= {}
@@ -131,12 +129,14 @@ module ActionView
local_assigns = local_assigns ? local_assigns.clone : {}
spacer = partial_spacer_template ? render(:partial => partial_spacer_template) : ''
+ _paths = {}
+ _templates = {}
index = 0
collection.map do |object|
_partial_path ||= partial_path || ActionController::RecordIdentifier.partial_path(object, controller.class.controller_path)
- path = find_partial_path(_partial_path)
- template = pick_template(path)
+ path = _paths[_partial_path] ||= find_partial_path(_partial_path)
+ template = _templates[path] ||= pick_template(path)
local_assigns[template.counter_name] = index
result = template.render_partial(self, object, local_assigns, as)
index += 1
@@ -153,6 +153,5 @@ module ActionView
"_#{partial_path}"
end
end
- memoize :find_partial_path
end
end
--
cgit v1.2.3
From 55adaa2efc08c892bf7be55d79ac571848068256 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Wed, 23 Jul 2008 13:47:30 -0500
Subject: Fixed bc5896e, and added test case for the caching bug it originally
introduced.
---
actionpack/lib/action_view/base.rb | 3 +++
actionpack/lib/action_view/partials.rb | 9 +++++----
actionpack/lib/action_view/renderable.rb | 2 +-
actionpack/test/template/compiled_templates_test.rb | 5 ++++-
4 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index c769013d42..bdcb1dc246 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -332,6 +332,9 @@ module ActionView #:nodoc:
end
end
+ extend ActiveSupport::Memoizable
+ memoize :pick_template
+
private
# Renders the template present at template_path . The hash in local_assigns
# is made available as local variables.
diff --git a/actionpack/lib/action_view/partials.rb b/actionpack/lib/action_view/partials.rb
index 5aa4c83009..eb74d4a4c7 100644
--- a/actionpack/lib/action_view/partials.rb
+++ b/actionpack/lib/action_view/partials.rb
@@ -102,6 +102,8 @@ module ActionView
#
# As you can see, the :locals hash is shared between both the partial and its layout.
module Partials
+ extend ActiveSupport::Memoizable
+
private
def render_partial(partial_path, object_assigns = nil, local_assigns = {}) #:nodoc:
local_assigns ||= {}
@@ -129,14 +131,12 @@ module ActionView
local_assigns = local_assigns ? local_assigns.clone : {}
spacer = partial_spacer_template ? render(:partial => partial_spacer_template) : ''
- _paths = {}
- _templates = {}
index = 0
collection.map do |object|
_partial_path ||= partial_path || ActionController::RecordIdentifier.partial_path(object, controller.class.controller_path)
- path = _paths[_partial_path] ||= find_partial_path(_partial_path)
- template = _templates[path] ||= pick_template(path)
+ path = find_partial_path(_partial_path)
+ template = pick_template(path)
local_assigns[template.counter_name] = index
result = template.render_partial(self, object, local_assigns, as)
index += 1
@@ -153,5 +153,6 @@ module ActionView
"_#{partial_path}"
end
end
+ memoize :find_partial_path
end
end
diff --git a/actionpack/lib/action_view/renderable.rb b/actionpack/lib/action_view/renderable.rb
index 2b825ac4e9..5fe1ca86f3 100644
--- a/actionpack/lib/action_view/renderable.rb
+++ b/actionpack/lib/action_view/renderable.rb
@@ -84,7 +84,7 @@ module ActionView
# The template will be compiled if the file has not been compiled yet, or
# if local_assigns has a new key, which isn't supported by the compiled code yet.
def recompile?(symbol)
- !(frozen? && Base::CompiledTemplates.method_defined?(symbol))
+ !(ActionView::PathSet::Path.eager_load_templates? && Base::CompiledTemplates.method_defined?(symbol))
end
end
end
diff --git a/actionpack/test/template/compiled_templates_test.rb b/actionpack/test/template/compiled_templates_test.rb
index 52996c7fcb..e005aa0f03 100644
--- a/actionpack/test/template/compiled_templates_test.rb
+++ b/actionpack/test/template/compiled_templates_test.rb
@@ -30,9 +30,12 @@ uses_mocha 'TestTemplateRecompilation' do
assert_equal "Hello world!", render("test/hello_world.erb")
end
- def test_compiled_template_will_be_recompiled_when_rendered_if_template_is_outside_cache
+ def test_compiled_template_will_always_be_recompiled_when_eager_loaded_templates_is_off
+ ActionView::PathSet::Path.expects(:eager_load_templates?).times(4).returns(false)
assert_equal 0, @compiled_templates.instance_methods.size
assert_equal "Hello world!", render("#{FIXTURE_LOAD_PATH}/test/hello_world.erb")
+ ActionView::Template.any_instance.expects(:compile!).times(3)
+ 3.times { assert_equal "Hello world!", render("#{FIXTURE_LOAD_PATH}/test/hello_world.erb") }
assert_equal 1, @compiled_templates.instance_methods.size
end
--
cgit v1.2.3
From 3fd9036fc554979e951422a79f0f77f061112bdc Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Thu, 24 Jul 2008 11:58:26 -0500
Subject: Added config.dependency_loading to enable or disable the dependency
loader after initialization
---
activesupport/lib/active_support/dependencies.rb | 78 ++++++++++++++++++------
activesupport/test/dependencies_test.rb | 12 ++++
railties/lib/initializer.rb | 27 +++++++-
3 files changed, 95 insertions(+), 22 deletions(-)
diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb
index e3d4f3d7eb..a3f5f799a2 100644
--- a/activesupport/lib/active_support/dependencies.rb
+++ b/activesupport/lib/active_support/dependencies.rb
@@ -51,17 +51,28 @@ module ActiveSupport #:nodoc:
module ModuleConstMissing #:nodoc:
def self.included(base) #:nodoc:
base.class_eval do
- # Rename the original handler so we can chain it to the new one
- alias_method :rails_original_const_missing, :const_missing
+ unless defined? const_missing_without_dependencies
+ alias_method_chain :const_missing, :dependencies
+ end
+ end
+ end
- # Use const_missing to autoload associations so we don't have to
- # require_association when using single-table inheritance.
- def const_missing(class_id)
- ActiveSupport::Dependencies.load_missing_constant self, class_id
+ def self.excluded(base) #:nodoc:
+ base.class_eval do
+ if defined? const_missing_without_dependencies
+ undef_method :const_missing
+ alias_method :const_missing, :const_missing_without_dependencies
+ undef_method :const_missing_without_dependencies
end
end
end
+ # Use const_missing to autoload associations so we don't have to
+ # require_association when using single-table inheritance.
+ def const_missing_with_dependencies(class_id)
+ ActiveSupport::Dependencies.load_missing_constant self, class_id
+ end
+
def unloadable(const_desc = self)
super(const_desc)
end
@@ -92,8 +103,38 @@ module ActiveSupport #:nodoc:
# Object includes this module
module Loadable #:nodoc:
- def load(file, *extras) #:nodoc:
- Dependencies.new_constants_in(Object) { super }
+ def self.included(base) #:nodoc:
+ base.class_eval do
+ unless defined? load_without_new_constant_marking
+ alias_method_chain :load, :new_constant_marking
+ end
+ end
+ end
+
+ def self.excluded(base) #:nodoc:
+ base.class_eval do
+ if defined? load_without_new_constant_marking
+ undef_method :load
+ alias_method :load, :load_without_new_constant_marking
+ undef_method :load_without_new_constant_marking
+ end
+ end
+ end
+
+ def require_or_load(file_name)
+ Dependencies.require_or_load(file_name)
+ end
+
+ def require_dependency(file_name)
+ Dependencies.depend_on(file_name)
+ end
+
+ def require_association(file_name)
+ Dependencies.associate_with(file_name)
+ end
+
+ def load_with_new_constant_marking(file, *extras) #:nodoc:
+ Dependencies.new_constants_in(Object) { load_without_new_constant_marking(file, *extras) }
rescue Exception => exception # errors from loading file
exception.blame_file! file
raise
@@ -145,19 +186,18 @@ module ActiveSupport #:nodoc:
end
end
- def inject!
- Object.instance_eval do
- define_method(:require_or_load) { |file_name| Dependencies.require_or_load(file_name) } unless Object.respond_to?(:require_or_load)
- define_method(:require_dependency) { |file_name| Dependencies.depend_on(file_name) } unless Object.respond_to?(:require_dependency)
- define_method(:require_association) { |file_name| Dependencies.associate_with(file_name) } unless Object.respond_to?(:require_association)
-
- alias_method :load_without_new_constant_marking, :load
- include Loadable
- end
-
+ def hook!
+ Object.instance_eval { include Loadable }
Module.instance_eval { include ModuleConstMissing }
Class.instance_eval { include ClassConstMissing }
Exception.instance_eval { include Blamable }
+ true
+ end
+
+ def unhook!
+ ModuleConstMissing.excluded(Module)
+ Loadable.excluded(Object)
+ true
end
def load?
@@ -560,4 +600,4 @@ module ActiveSupport #:nodoc:
end
end
-ActiveSupport::Dependencies.inject!
+ActiveSupport::Dependencies.hook!
diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb
index 038547a862..39c9c74c94 100644
--- a/activesupport/test/dependencies_test.rb
+++ b/activesupport/test/dependencies_test.rb
@@ -762,4 +762,16 @@ class DependenciesTest < Test::Unit::TestCase
ensure
ActiveSupport::Dependencies.load_once_paths = []
end
+
+ def test_hook_called_multiple_times
+ assert_nothing_raised { ActiveSupport::Dependencies.hook! }
+ end
+
+ def test_unhook
+ ActiveSupport::Dependencies.unhook!
+ assert !Module.new.respond_to?(:const_missing_without_dependencies)
+ assert !Module.new.respond_to?(:load_without_new_constant_marking)
+ ensure
+ ActiveSupport::Dependencies.hook!
+ end
end
diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb
index 97bb81a3c8..44863ab026 100644
--- a/railties/lib/initializer.rb
+++ b/railties/lib/initializer.rb
@@ -171,9 +171,12 @@ module Rails
# Load view path cache
load_view_paths
- # load application classes
+ # Load application classes
load_application_classes
+ # Disable dependency loading during request cycle
+ disable_dependency_loading
+
# Flag initialized
Rails.initialized = true
end
@@ -525,6 +528,12 @@ Run `rake gems:install` to install the missing gems.
Dispatcher.define_dispatcher_callbacks(configuration.cache_classes)
Dispatcher.new(RAILS_DEFAULT_LOGGER).send :run_callbacks, :prepare_dispatch
end
+
+ def disable_dependency_loading
+ if configuration.cache_classes && !configuration.dependency_loading
+ ActiveSupport::Dependencies.unhook!
+ end
+ end
end
# The Configuration class holds all the parameters for the Initializer and
@@ -659,6 +668,17 @@ Run `rake gems:install` to install the missing gems.
!!@reload_plugins
end
+ # Enables or disables dependency loading during the request cycle. Setting
+ # dependency_loading to true will allow new classes to be loaded
+ # during a request. Setting it to false will disable this behavior.
+ #
+ # Those who want to run in a threaded environment should disable this
+ # option and eager load or require all there classes on initialization.
+ #
+ # If cache_classes is disabled, dependency loaded will always be
+ # on.
+ attr_accessor :dependency_loading
+
# An array of gems that this rails application depends on. Rails will automatically load
# these gems during installation, and allow you to install any missing gems with:
#
@@ -707,6 +727,7 @@ Run `rake gems:install` to install the missing gems.
self.view_path = default_view_path
self.controller_paths = default_controller_paths
self.cache_classes = default_cache_classes
+ self.dependency_loading = default_dependency_loading
self.whiny_nils = default_whiny_nils
self.plugins = default_plugins
self.plugin_paths = default_plugin_paths
@@ -876,8 +897,8 @@ Run `rake gems:install` to install the missing gems.
paths
end
- def default_dependency_mechanism
- :load
+ def default_dependency_loading
+ true
end
def default_cache_classes
--
cgit v1.2.3
From a87462afcb6c642e59bfcd2e11e3351e2b718c38 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Thu, 24 Jul 2008 13:41:51 -0500
Subject: AbstractRequest.relative_url_root is no longer automatically
configured by a HTTP header. It can now be set in your configuration
environment with config.action_controller.relative_url_root
---
actionpack/CHANGELOG | 2 +
actionpack/lib/action_controller/base.rb | 4 +
actionpack/lib/action_controller/request.rb | 41 +++-----
.../lib/action_controller/routing/optimisations.rb | 2 +-
actionpack/lib/action_controller/url_rewriter.rb | 6 +-
.../lib/action_view/helpers/asset_tag_helper.rb | 6 +-
actionpack/test/controller/redirect_test.rb | 109 ++++++++++-----------
actionpack/test/controller/request_test.rb | 100 +++++--------------
actionpack/test/controller/routing_test.rb | 10 +-
actionpack/test/controller/url_rewriter_test.rb | 55 +++++------
actionpack/test/template/asset_tag_helper_test.rb | 45 ++++-----
11 files changed, 161 insertions(+), 219 deletions(-)
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index ebe4c047b8..03e011c75c 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,5 +1,7 @@
*Edge*
+* AbstractRequest.relative_url_root is no longer automatically configured by a HTTP header. It can now be set in your configuration environment with config.action_controller.relative_url_root [Josh Peek]
+
* Update Prototype to 1.6.0.2 #599 [Patrick Joyce]
* Conditional GET utility methods. [Jeremy Kemper]
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index 4dabff637b..bae7e8c12e 100755
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -354,6 +354,10 @@ module ActionController #:nodoc:
class_inheritable_accessor :allow_forgery_protection
self.allow_forgery_protection = true
+ # If you are deploying to a subdirectory, you will need to set
+ # config.action_controller.relative_url_root
+ class_inheritable_accessor :relative_url_root
+
# Holds the request object that's primarily used to get environment variables through access like
# request.env["REQUEST_URI"] .
attr_internal :request
diff --git a/actionpack/lib/action_controller/request.rb b/actionpack/lib/action_controller/request.rb
index c42f113d2c..c55788a531 100755
--- a/actionpack/lib/action_controller/request.rb
+++ b/actionpack/lib/action_controller/request.rb
@@ -3,13 +3,16 @@ require 'stringio'
require 'strscan'
module ActionController
- # HTTP methods which are accepted by default.
+ # HTTP methods which are accepted by default.
ACCEPTED_HTTP_METHODS = Set.new(%w( get head put post delete options ))
# CgiRequest and TestRequest provide concrete implementations.
class AbstractRequest
- cattr_accessor :relative_url_root
- remove_method :relative_url_root
+ def self.relative_url_root=(*args)
+ ActiveSupport::Deprecation.warn(
+ "ActionController::AbstractRequest.relative_url_root= has been renamed." +
+ "You can now set it with config.action_controller.relative_url_root=", caller)
+ end
# The hash of environment variables for this request,
# such as { 'RAILS_ENV' => 'production' }.
@@ -111,14 +114,14 @@ module ActionController
end
end
end
-
-
+
+
# Sets the format by string extension, which can be used to force custom formats that are not controlled by the extension.
# Example:
#
# class ApplicationController < ActionController::Base
# before_filter :adjust_format_for_iphone
- #
+ #
# private
# def adjust_format_for_iphone
# request.format = :iphone if request.env["HTTP_USER_AGENT"][/iPhone/]
@@ -303,26 +306,10 @@ EOM
path = (uri = request_uri) ? uri.split('?').first.to_s : ''
# Cut off the path to the installation directory if given
- path.sub!(%r/^#{relative_url_root}/, '')
- path || ''
- end
-
- # Returns the path minus the web server relative installation directory.
- # This can be set with the environment variable RAILS_RELATIVE_URL_ROOT.
- # It can be automatically extracted for Apache setups. If the server is not
- # Apache, this method returns an empty string.
- def relative_url_root
- @@relative_url_root ||= case
- when @env["RAILS_RELATIVE_URL_ROOT"]
- @env["RAILS_RELATIVE_URL_ROOT"]
- when server_software == 'apache'
- @env["SCRIPT_NAME"].to_s.sub(/\/dispatch\.(fcgi|rb|cgi)$/, '')
- else
- ''
- end
+ path.sub!(%r/^#{ActionController::Base.relative_url_root}/, '')
+ path || ''
end
-
# Read the request body. This is useful for web services that need to
# work with raw requests directly.
def raw_post
@@ -343,15 +330,15 @@ EOM
@symbolized_path_parameters = @parameters = nil
end
- # The same as path_parameters with explicitly symbolized keys
- def symbolized_path_parameters
+ # The same as path_parameters with explicitly symbolized keys
+ def symbolized_path_parameters
@symbolized_path_parameters ||= path_parameters.symbolize_keys
end
# Returns a hash with the parameters used to form the path of the request.
# Returned hash keys are strings. See symbolized_path_parameters for symbolized keys.
#
- # Example:
+ # Example:
#
# {'action' => 'my_action', 'controller' => 'my_controller'}
def path_parameters
diff --git a/actionpack/lib/action_controller/routing/optimisations.rb b/actionpack/lib/action_controller/routing/optimisations.rb
index cd4a423e6b..4b70ea13f2 100644
--- a/actionpack/lib/action_controller/routing/optimisations.rb
+++ b/actionpack/lib/action_controller/routing/optimisations.rb
@@ -76,7 +76,7 @@ module ActionController
elements << '#{request.host_with_port}'
end
- elements << '#{request.relative_url_root if request.relative_url_root}'
+ elements << '#{ActionController::Base.relative_url_root if ActionController::Base.relative_url_root}'
# The last entry in route.segments appears to *always* be a
# 'divider segment' for '/' but we have assertions to ensure that
diff --git a/actionpack/lib/action_controller/url_rewriter.rb b/actionpack/lib/action_controller/url_rewriter.rb
index 3a38f23396..d0bf6c0bd4 100644
--- a/actionpack/lib/action_controller/url_rewriter.rb
+++ b/actionpack/lib/action_controller/url_rewriter.rb
@@ -37,7 +37,7 @@ module ActionController
# * :port - Optionally specify the port to connect to.
# * :anchor - An anchor name to be appended to the path.
# * :skip_relative_url_root - If true, the url is not constructed using the
- # +relative_url_root+ set in ActionController::AbstractRequest.relative_url_root.
+ # +relative_url_root+ set in ActionController::Base.relative_url_root.
# * :trailing_slash - If true, adds a trailing slash, as in "/archive/2009/"
#
# Any other key (:controller , :action , etc.) given to
@@ -67,7 +67,7 @@ module ActionController
[:protocol, :host, :port, :skip_relative_url_root].each { |k| options.delete(k) }
end
trailing_slash = options.delete(:trailing_slash) if options.key?(:trailing_slash)
- url << ActionController::AbstractRequest.relative_url_root.to_s unless options[:skip_relative_url_root]
+ url << ActionController::Base.relative_url_root.to_s unless options[:skip_relative_url_root]
anchor = "##{CGI.escape options.delete(:anchor).to_param.to_s}" if options[:anchor]
generated = Routing::Routes.generate(options, {})
url << (trailing_slash ? generated.sub(/\?|\z/) { "/" + $& } : generated)
@@ -108,7 +108,7 @@ module ActionController
end
path = rewrite_path(options)
- rewritten_url << @request.relative_url_root.to_s unless options[:skip_relative_url_root]
+ rewritten_url << ActionController::Base.relative_url_root.to_s unless options[:skip_relative_url_root]
rewritten_url << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path)
rewritten_url << "##{options[:anchor]}" if options[:anchor]
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
index 8d0ee81684..769eada120 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb
@@ -476,7 +476,7 @@ module ActionView
if has_request
[ @controller.request.protocol,
ActionController::Base.asset_host.to_s,
- @controller.request.relative_url_root,
+ ActionController::Base.relative_url_root,
dir, source, ext, include_host ].join
else
[ ActionController::Base.asset_host.to_s,
@@ -492,8 +492,8 @@ module ActionView
else
source = "/#{dir}/#{source}" unless source[0] == ?/
if has_request
- unless source =~ %r{^#{@controller.request.relative_url_root}/}
- source = "#{@controller.request.relative_url_root}#{source}"
+ unless source =~ %r{^#{ActionController::Base.relative_url_root}/}
+ source = "#{ActionController::Base.relative_url_root}#{source}"
end
end
diff --git a/actionpack/test/controller/redirect_test.rb b/actionpack/test/controller/redirect_test.rb
index 28da5c6163..2f8bf7b6ee 100755
--- a/actionpack/test/controller/redirect_test.rb
+++ b/actionpack/test/controller/redirect_test.rb
@@ -9,11 +9,11 @@ class Workshop
def initialize(id, new_record)
@id, @new_record = id, new_record
end
-
+
def new_record?
@new_record
end
-
+
def to_s
id.to_s
end
@@ -24,32 +24,32 @@ class RedirectController < ActionController::Base
redirect_to :action => "hello_world"
end
- def redirect_with_status
+ def redirect_with_status
redirect_to({:action => "hello_world", :status => 301})
- end
+ end
def redirect_with_status_hash
redirect_to({:action => "hello_world"}, {:status => 301})
- end
+ end
- def url_redirect_with_status
+ def url_redirect_with_status
redirect_to("http://www.example.com", :status => :moved_permanently)
- end
-
- def url_redirect_with_status_hash
+ end
+
+ def url_redirect_with_status_hash
redirect_to("http://www.example.com", {:status => 301})
- end
+ end
- def relative_url_redirect_with_status
+ def relative_url_redirect_with_status
redirect_to("/things/stuff", :status => :found)
- end
-
+ end
+
def relative_url_redirect_with_status_hash
redirect_to("/things/stuff", {:status => 301})
- end
-
- def redirect_to_back_with_status
- redirect_to :back, :status => 307
+ end
+
+ def redirect_to_back_with_status
+ redirect_to :back, :status => 307
end
def host_redirect
@@ -90,9 +90,9 @@ class RedirectController < ActionController::Base
end
def rescue_errors(e) raise e end
-
+
def rescue_action(e) raise end
-
+
protected
def dashbord_url(id, message)
url_for :action => "dashboard", :params => { "id" => id, "message" => message }
@@ -118,48 +118,48 @@ class RedirectTest < Test::Unit::TestCase
assert_equal "http://test.host/redirect/hello_world", redirect_to_url
end
- def test_redirect_with_status
- get :redirect_with_status
- assert_response 301
- assert_equal "http://test.host/redirect/hello_world", redirect_to_url
- end
+ def test_redirect_with_status
+ get :redirect_with_status
+ assert_response 301
+ assert_equal "http://test.host/redirect/hello_world", redirect_to_url
+ end
- def test_redirect_with_status_hash
+ def test_redirect_with_status_hash
get :redirect_with_status_hash
- assert_response 301
- assert_equal "http://test.host/redirect/hello_world", redirect_to_url
+ assert_response 301
+ assert_equal "http://test.host/redirect/hello_world", redirect_to_url
+ end
+
+ def test_url_redirect_with_status
+ get :url_redirect_with_status
+ assert_response 301
+ assert_equal "http://www.example.com", redirect_to_url
end
-
- def test_url_redirect_with_status
- get :url_redirect_with_status
- assert_response 301
- assert_equal "http://www.example.com", redirect_to_url
- end
def test_url_redirect_with_status_hash
get :url_redirect_with_status_hash
- assert_response 301
- assert_equal "http://www.example.com", redirect_to_url
- end
+ assert_response 301
+ assert_equal "http://www.example.com", redirect_to_url
+ end
-
- def test_relative_url_redirect_with_status
- get :relative_url_redirect_with_status
+
+ def test_relative_url_redirect_with_status
+ get :relative_url_redirect_with_status
assert_response 302
- assert_equal "http://test.host/things/stuff", redirect_to_url
- end
-
+ assert_equal "http://test.host/things/stuff", redirect_to_url
+ end
+
def test_relative_url_redirect_with_status_hash
get :relative_url_redirect_with_status_hash
- assert_response 301
- assert_equal "http://test.host/things/stuff", redirect_to_url
- end
-
- def test_redirect_to_back_with_status
- @request.env["HTTP_REFERER"] = "http://www.example.com/coming/from"
- get :redirect_to_back_with_status
- assert_response 307
- assert_equal "http://www.example.com/coming/from", redirect_to_url
+ assert_response 301
+ assert_equal "http://test.host/things/stuff", redirect_to_url
+ end
+
+ def test_redirect_to_back_with_status
+ @request.env["HTTP_REFERER"] = "http://www.example.com/coming/from"
+ get :redirect_to_back_with_status
+ assert_response 307
+ assert_equal "http://www.example.com/coming/from", redirect_to_url
end
def test_simple_redirect_using_options
@@ -204,20 +204,20 @@ class RedirectTest < Test::Unit::TestCase
assert_response :redirect
assert_equal "http://www.example.com/coming/from", redirect_to_url
end
-
+
def test_redirect_to_back_with_no_referer
assert_raises(ActionController::RedirectBackError) {
@request.env["HTTP_REFERER"] = nil
get :redirect_to_back
}
end
-
+
def test_redirect_to_record
ActionController::Routing::Routes.draw do |map|
map.resources :workshops
map.connect ':controller/:action/:id'
end
-
+
get :redirect_to_existing_record
assert_equal "http://test.host/workshops/5", redirect_to_url
assert_redirected_to Workshop.new(5, false)
@@ -237,7 +237,6 @@ class RedirectTest < Test::Unit::TestCase
get :redirect_to_nil
end
end
-
end
module ModuleTest
diff --git a/actionpack/test/controller/request_test.rb b/actionpack/test/controller/request_test.rb
index 932c0e21a1..7db5264840 100644
--- a/actionpack/test/controller/request_test.rb
+++ b/actionpack/test/controller/request_test.rb
@@ -3,9 +3,14 @@ require 'action_controller/integration'
class RequestTest < Test::Unit::TestCase
def setup
+ ActionController::Base.relative_url_root = nil
@request = ActionController::TestRequest.new
end
+ def teardown
+ ActionController::Base.relative_url_root = nil
+ end
+
def test_remote_ip
assert_equal '0.0.0.0', @request.remote_ip
@@ -38,7 +43,7 @@ class RequestTest < Test::Unit::TestCase
@request.env['HTTP_X_FORWARDED_FOR'] = '10.0.0.1,3.4.5.6'
assert_equal '3.4.5.6', @request.remote_ip
-
+
@request.env['HTTP_X_FORWARDED_FOR'] = '10.0.0.1, 10.0.0.1, 3.4.5.6'
assert_equal '3.4.5.6', @request.remote_ip
@@ -120,155 +125,105 @@ class RequestTest < Test::Unit::TestCase
assert_equal ":8080", @request.port_string
end
- def test_relative_url_root
- @request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi"
- @request.env['SERVER_SOFTWARE'] = 'lighttpd/1.2.3'
- assert_equal '', @request.relative_url_root, "relative_url_root should be disabled on lighttpd"
-
- @request.env['SERVER_SOFTWARE'] = 'apache/1.2.3 some random text'
-
- @request.env['SCRIPT_NAME'] = nil
- assert_equal "", @request.relative_url_root
-
- @request.env['SCRIPT_NAME'] = "/dispatch.cgi"
- assert_equal "", @request.relative_url_root
-
- @request.env['SCRIPT_NAME'] = "/myapp.rb"
- assert_equal "", @request.relative_url_root
-
- @request.relative_url_root = nil
- @request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi"
- assert_equal "/hieraki", @request.relative_url_root
-
- @request.relative_url_root = nil
- @request.env['SCRIPT_NAME'] = "/collaboration/hieraki/dispatch.cgi"
- assert_equal "/collaboration/hieraki", @request.relative_url_root
-
- # apache/scgi case
- @request.relative_url_root = nil
- @request.env['SCRIPT_NAME'] = "/collaboration/hieraki"
- assert_equal "/collaboration/hieraki", @request.relative_url_root
-
- @request.relative_url_root = nil
- @request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi"
- @request.env['SERVER_SOFTWARE'] = 'lighttpd/1.2.3'
- @request.env['RAILS_RELATIVE_URL_ROOT'] = "/hieraki"
- assert_equal "/hieraki", @request.relative_url_root
-
- # @env overrides path guess
- @request.relative_url_root = nil
- @request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi"
- @request.env['SERVER_SOFTWARE'] = 'apache/1.2.3 some random text'
- @request.env['RAILS_RELATIVE_URL_ROOT'] = "/real_url"
- assert_equal "/real_url", @request.relative_url_root
- end
-
def test_request_uri
@request.env['SERVER_SOFTWARE'] = 'Apache 42.342.3432'
- @request.relative_url_root = nil
@request.set_REQUEST_URI "http://www.rubyonrails.org/path/of/some/uri?mapped=1"
assert_equal "/path/of/some/uri?mapped=1", @request.request_uri
assert_equal "/path/of/some/uri", @request.path
- @request.relative_url_root = nil
@request.set_REQUEST_URI "http://www.rubyonrails.org/path/of/some/uri"
assert_equal "/path/of/some/uri", @request.request_uri
assert_equal "/path/of/some/uri", @request.path
- @request.relative_url_root = nil
@request.set_REQUEST_URI "/path/of/some/uri"
assert_equal "/path/of/some/uri", @request.request_uri
assert_equal "/path/of/some/uri", @request.path
- @request.relative_url_root = nil
@request.set_REQUEST_URI "/"
assert_equal "/", @request.request_uri
assert_equal "/", @request.path
- @request.relative_url_root = nil
@request.set_REQUEST_URI "/?m=b"
assert_equal "/?m=b", @request.request_uri
assert_equal "/", @request.path
- @request.relative_url_root = nil
@request.set_REQUEST_URI "/"
@request.env['SCRIPT_NAME'] = "/dispatch.cgi"
assert_equal "/", @request.request_uri
assert_equal "/", @request.path
- @request.relative_url_root = nil
+ ActionController::Base.relative_url_root = "/hieraki"
@request.set_REQUEST_URI "/hieraki/"
@request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi"
assert_equal "/hieraki/", @request.request_uri
assert_equal "/", @request.path
+ ActionController::Base.relative_url_root = nil
- @request.relative_url_root = nil
+ ActionController::Base.relative_url_root = "/collaboration/hieraki"
@request.set_REQUEST_URI "/collaboration/hieraki/books/edit/2"
@request.env['SCRIPT_NAME'] = "/collaboration/hieraki/dispatch.cgi"
assert_equal "/collaboration/hieraki/books/edit/2", @request.request_uri
assert_equal "/books/edit/2", @request.path
+ ActionController::Base.relative_url_root = nil
# The following tests are for when REQUEST_URI is not supplied (as in IIS)
- @request.relative_url_root = nil
@request.set_REQUEST_URI nil
@request.env['PATH_INFO'] = "/path/of/some/uri?mapped=1"
@request.env['SCRIPT_NAME'] = nil #"/path/dispatch.rb"
assert_equal "/path/of/some/uri?mapped=1", @request.request_uri
assert_equal "/path/of/some/uri", @request.path
+ ActionController::Base.relative_url_root = '/path'
@request.set_REQUEST_URI nil
- @request.relative_url_root = nil
@request.env['PATH_INFO'] = "/path/of/some/uri?mapped=1"
@request.env['SCRIPT_NAME'] = "/path/dispatch.rb"
assert_equal "/path/of/some/uri?mapped=1", @request.request_uri
assert_equal "/of/some/uri", @request.path
+ ActionController::Base.relative_url_root = nil
@request.set_REQUEST_URI nil
- @request.relative_url_root = nil
@request.env['PATH_INFO'] = "/path/of/some/uri"
@request.env['SCRIPT_NAME'] = nil
assert_equal "/path/of/some/uri", @request.request_uri
assert_equal "/path/of/some/uri", @request.path
@request.set_REQUEST_URI nil
- @request.relative_url_root = nil
@request.env['PATH_INFO'] = "/"
assert_equal "/", @request.request_uri
assert_equal "/", @request.path
@request.set_REQUEST_URI nil
- @request.relative_url_root = nil
@request.env['PATH_INFO'] = "/?m=b"
assert_equal "/?m=b", @request.request_uri
assert_equal "/", @request.path
@request.set_REQUEST_URI nil
- @request.relative_url_root = nil
@request.env['PATH_INFO'] = "/"
@request.env['SCRIPT_NAME'] = "/dispatch.cgi"
assert_equal "/", @request.request_uri
assert_equal "/", @request.path
+ ActionController::Base.relative_url_root = '/hieraki'
@request.set_REQUEST_URI nil
- @request.relative_url_root = nil
@request.env['PATH_INFO'] = "/hieraki/"
@request.env['SCRIPT_NAME'] = "/hieraki/dispatch.cgi"
assert_equal "/hieraki/", @request.request_uri
assert_equal "/", @request.path
+ ActionController::Base.relative_url_root = nil
@request.set_REQUEST_URI '/hieraki/dispatch.cgi'
- @request.relative_url_root = '/hieraki'
+ ActionController::Base.relative_url_root = '/hieraki'
assert_equal "/dispatch.cgi", @request.path
- @request.relative_url_root = nil
+ ActionController::Base.relative_url_root = nil
@request.set_REQUEST_URI '/hieraki/dispatch.cgi'
- @request.relative_url_root = '/foo'
+ ActionController::Base.relative_url_root = '/foo'
assert_equal "/hieraki/dispatch.cgi", @request.path
- @request.relative_url_root = nil
+ ActionController::Base.relative_url_root = nil
# This test ensures that Rails uses REQUEST_URI over PATH_INFO
- @request.relative_url_root = nil
+ ActionController::Base.relative_url_root = nil
@request.env['REQUEST_URI'] = "/some/path"
@request.env['PATH_INFO'] = "/another/path"
@request.env['SCRIPT_NAME'] = "/dispatch.cgi"
@@ -276,13 +231,12 @@ class RequestTest < Test::Unit::TestCase
assert_equal "/some/path", @request.path
end
-
def test_host_with_default_port
@request.host = "rubyonrails.org"
@request.port = 80
assert_equal "rubyonrails.org", @request.host_with_port
end
-
+
def test_host_with_non_default_port
@request.host = "rubyonrails.org"
@request.port = 81
@@ -415,15 +369,15 @@ class RequestTest < Test::Unit::TestCase
@request.env["CONTENT_TYPE"] = "application/xml; charset=UTF-8"
assert_equal Mime::XML, @request.content_type
end
-
+
def test_user_agent
assert_not_nil @request.user_agent
end
-
+
def test_parameters
@request.instance_eval { @request_parameters = { "foo" => 1 } }
@request.instance_eval { @query_parameters = { "bar" => 2 } }
-
+
assert_equal({"foo" => 1, "bar" => 2}, @request.parameters)
assert_equal({"foo" => 1}, @request.request_parameters)
assert_equal({"bar" => 2}, @request.query_parameters)
@@ -774,19 +728,19 @@ class MultipartRequestParameterParsingTest < Test::Unit::TestCase
file = params['file']
foo = params['foo']
-
+
if RUBY_VERSION > '1.9'
assert_kind_of File, file
else
assert_kind_of Tempfile, file
end
-
+
assert_equal 'file.txt', file.original_filename
assert_equal "text/plain", file.content_type
-
+
assert_equal 'bar', foo
end
-
+
def test_large_text_file
params = process('large_text_file')
assert_equal %w(file foo), params.keys.sort
diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb
index 079189d7b3..84996fd6b1 100644
--- a/actionpack/test/controller/routing_test.rb
+++ b/actionpack/test/controller/routing_test.rb
@@ -731,15 +731,10 @@ uses_mocha 'LegacyRouteSet, Route, RouteSet and RouteLoading' do
def request
@request ||= MockRequest.new(:host => "named.route.test", :method => :get)
end
-
- def relative_url_root=(value)
- request.relative_url_root=value
- end
end
class MockRequest
- attr_accessor :path, :path_parameters, :host, :subdomains, :domain,
- :method, :relative_url_root
+ attr_accessor :path, :path_parameters, :host, :subdomains, :domain, :method
def initialize(values={})
values.each { |key, value| send("#{key}=", value) }
@@ -920,10 +915,11 @@ uses_mocha 'LegacyRouteSet, Route, RouteSet and RouteLoading' do
def test_basic_named_route_with_relative_url_root
rs.add_named_route :home, '', :controller => 'content', :action => 'list'
x = setup_for_named_route
- x.relative_url_root="/foo"
+ ActionController::Base.relative_url_root = "/foo"
assert_equal("http://named.route.test/foo/",
x.send(:home_url))
assert_equal "/foo/", x.send(:home_path)
+ ActionController::Base.relative_url_root = nil
end
def test_named_route_with_option
diff --git a/actionpack/test/controller/url_rewriter_test.rb b/actionpack/test/controller/url_rewriter_test.rb
index a9974db5d5..64e9a085ca 100644
--- a/actionpack/test/controller/url_rewriter_test.rb
+++ b/actionpack/test/controller/url_rewriter_test.rb
@@ -7,7 +7,7 @@ class UrlRewriterTests < Test::Unit::TestCase
@request = ActionController::TestRequest.new
@params = {}
@rewriter = ActionController::UrlRewriter.new(@request, @params)
- end
+ end
def test_port
assert_equal('http://test.host:1271/c/a/i',
@@ -24,7 +24,7 @@ class UrlRewriterTests < Test::Unit::TestCase
@rewriter.rewrite(:protocol => 'https://', :controller => 'c', :action => 'a', :id => 'i')
)
end
-
+
def test_user_name_and_password
assert_equal(
'http://david:secret@test.host/c/a/i',
@@ -38,12 +38,12 @@ class UrlRewriterTests < Test::Unit::TestCase
@rewriter.rewrite(:user => "openid.aol.com/nextangler", :password => "one two?", :controller => 'c', :action => 'a', :id => 'i')
)
end
-
- def test_anchor
- assert_equal(
- 'http://test.host/c/a/i#anchor',
- @rewriter.rewrite(:controller => 'c', :action => 'a', :id => 'i', :anchor => 'anchor')
- )
+
+ def test_anchor
+ assert_equal(
+ 'http://test.host/c/a/i#anchor',
+ @rewriter.rewrite(:controller => 'c', :action => 'a', :id => 'i', :anchor => 'anchor')
+ )
end
def test_overwrite_params
@@ -55,12 +55,12 @@ class UrlRewriterTests < Test::Unit::TestCase
u = @rewriter.rewrite(:only_path => false, :overwrite_params => {:action => 'hi'})
assert_match %r(/hi/hi/2$), u
end
-
+
def test_overwrite_removes_original
@params[:controller] = 'search'
@params[:action] = 'list'
@params[:list_page] = 1
-
+
assert_equal '/search/list?list_page=2', @rewriter.rewrite(:only_path => true, :overwrite_params => {"list_page" => 2})
u = @rewriter.rewrite(:only_path => false, :overwrite_params => {:list_page => 2})
assert_equal 'http://test.host/search/list?list_page=2', u
@@ -86,19 +86,19 @@ class UrlRewriterTests < Test::Unit::TestCase
end
class UrlWriterTests < Test::Unit::TestCase
-
+
class W
include ActionController::UrlWriter
end
-
+
def teardown
W.default_url_options.clear
end
-
+
def add_host!
W.default_url_options[:host] = 'www.basecamphq.com'
end
-
+
def test_exception_is_thrown_without_host
assert_raises RuntimeError do
W.new.url_for :controller => 'c', :action => 'a', :id => 'i'
@@ -110,35 +110,35 @@ class UrlWriterTests < Test::Unit::TestCase
W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :anchor => 'anchor')
)
end
-
+
def test_default_host
add_host!
assert_equal('http://www.basecamphq.com/c/a/i',
W.new.url_for(:controller => 'c', :action => 'a', :id => 'i')
)
end
-
+
def test_host_may_be_overridden
add_host!
assert_equal('http://37signals.basecamphq.com/c/a/i',
W.new.url_for(:host => '37signals.basecamphq.com', :controller => 'c', :action => 'a', :id => 'i')
)
end
-
+
def test_port
add_host!
assert_equal('http://www.basecamphq.com:3000/c/a/i',
W.new.url_for(:controller => 'c', :action => 'a', :id => 'i', :port => 3000)
)
end
-
+
def test_protocol
add_host!
assert_equal('https://www.basecamphq.com/c/a/i',
W.new.url_for(:controller => 'c', :action => 'a', :id => 'i', :protocol => 'https')
)
end
-
+
def test_protocol_with_and_without_separator
add_host!
assert_equal('https://www.basecamphq.com/c/a/i',
@@ -184,15 +184,15 @@ class UrlWriterTests < Test::Unit::TestCase
end
def test_relative_url_root_is_respected
- orig_relative_url_root = ActionController::AbstractRequest.relative_url_root
- ActionController::AbstractRequest.relative_url_root = '/subdir'
+ orig_relative_url_root = ActionController::Base.relative_url_root
+ ActionController::Base.relative_url_root = '/subdir'
add_host!
assert_equal('https://www.basecamphq.com/subdir/c/a/i',
W.new.url_for(:controller => 'c', :action => 'a', :id => 'i', :protocol => 'https')
)
ensure
- ActionController::AbstractRequest.relative_url_root = orig_relative_url_root
+ ActionController::Base.relative_url_root = orig_relative_url_root
end
def test_named_routes
@@ -217,8 +217,8 @@ class UrlWriterTests < Test::Unit::TestCase
end
def test_relative_url_root_is_respected_for_named_routes
- orig_relative_url_root = ActionController::AbstractRequest.relative_url_root
- ActionController::AbstractRequest.relative_url_root = '/subdir'
+ orig_relative_url_root = ActionController::Base.relative_url_root
+ ActionController::Base.relative_url_root = '/subdir'
ActionController::Routing::Routes.draw do |map|
map.home '/home/sweet/home/:user', :controller => 'home', :action => 'index'
@@ -231,7 +231,7 @@ class UrlWriterTests < Test::Unit::TestCase
controller.send(:home_url, :host => 'www.basecamphq.com', :user => 'again')
ensure
ActionController::Routing::Routes.load!
- ActionController::AbstractRequest.relative_url_root = orig_relative_url_root
+ ActionController::Base.relative_url_root = orig_relative_url_root
end
def test_only_path
@@ -239,14 +239,14 @@ class UrlWriterTests < Test::Unit::TestCase
map.home '/home/sweet/home/:user', :controller => 'home', :action => 'index'
map.connect ':controller/:action/:id'
end
-
+
# We need to create a new class in order to install the new named route.
kls = Class.new { include ActionController::UrlWriter }
controller = kls.new
assert controller.respond_to?(:home_url)
assert_equal '/brave/new/world',
controller.send(:url_for, :controller => 'brave', :action => 'new', :id => 'world', :only_path => true)
-
+
assert_equal("/home/sweet/home/alabama", controller.send(:home_url, :user => 'alabama', :host => 'unused', :only_path => true))
assert_equal("/home/sweet/home/alabama", controller.send(:home_path, 'alabama'))
ensure
@@ -306,5 +306,4 @@ class UrlWriterTests < Test::Unit::TestCase
def extract_params(url)
url.split('?', 2).last.split('&')
end
-
end
diff --git a/actionpack/test/template/asset_tag_helper_test.rb b/actionpack/test/template/asset_tag_helper_test.rb
index 0e7f9a94b7..8410e82c3c 100644
--- a/actionpack/test/template/asset_tag_helper_test.rb
+++ b/actionpack/test/template/asset_tag_helper_test.rb
@@ -30,7 +30,6 @@ class AssetTagHelperTest < ActionView::TestCase
end.new
@request = Class.new do
- def relative_url_root() "" end
def protocol() 'http://' end
def ssl?() false end
def host_with_port() 'localhost' end
@@ -118,7 +117,7 @@ class AssetTagHelperTest < ActionView::TestCase
%(image_path("xml")) => %(/images/xml),
%(image_path("xml.png")) => %(/images/xml.png),
%(image_path("dir/xml.png")) => %(/images/dir/xml.png),
- %(image_path("/dir/xml.png")) => %(/dir/xml.png)
+ %(image_path("/dir/xml.png")) => %(/dir/xml.png)
}
PathToImageToTag = {
@@ -173,7 +172,7 @@ class AssetTagHelperTest < ActionView::TestCase
ActionView::Helpers::AssetTagHelper::register_javascript_include_default 'lib1', '/elsewhere/blub/lib2'
assert_dom_equal %(\n\n\n\n\n\n\n), javascript_include_tag(:defaults)
end
-
+
def test_custom_javascript_expansions
ActionView::Helpers::AssetTagHelper::register_javascript_expansion :monkey => ["head", "body", "tail"]
assert_dom_equal %(\n\n\n\n), javascript_include_tag('first', :monkey, 'last')
@@ -216,7 +215,7 @@ class AssetTagHelperTest < ActionView::TestCase
def test_image_path
ImagePathToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end
-
+
def test_path_to_image_alias_for_image_path
PathToImageToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end
@@ -224,7 +223,7 @@ class AssetTagHelperTest < ActionView::TestCase
def test_image_tag
ImageLinkToTag.each { |method, tag| assert_dom_equal(tag, eval(method)) }
end
-
+
def test_timebased_asset_id
expected_time = File.stat(File.expand_path(File.dirname(__FILE__) + "/../fixtures/public/images/rails.png")).mtime.to_i.to_s
assert_equal %( ), image_tag("rails.png")
@@ -233,7 +232,7 @@ class AssetTagHelperTest < ActionView::TestCase
def test_should_skip_asset_id_on_complete_url
assert_equal %( ), image_tag("http://www.example.com/rails.png")
end
-
+
def test_should_use_preset_asset_id
ENV["RAILS_ASSET_ID"] = "4500"
assert_equal %( ), image_tag("rails.png")
@@ -255,14 +254,14 @@ class AssetTagHelperTest < ActionView::TestCase
ENV["RAILS_ASSET_ID"] = ""
ActionController::Base.asset_host = 'http://a0.example.com'
ActionController::Base.perform_caching = true
-
+
assert_dom_equal(
%(),
javascript_include_tag(:all, :cache => true)
)
assert File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js'))
-
+
assert_dom_equal(
%(),
javascript_include_tag(:all, :cache => "money")
@@ -344,7 +343,7 @@ class AssetTagHelperTest < ActionView::TestCase
ensure
FileUtils.rm_f(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'cache', 'money.js'))
end
-
+
def test_caching_javascript_include_tag_with_all_and_recursive_puts_defaults_at_the_start_of_the_file
ENV["RAILS_ASSET_ID"] = ""
ActionController::Base.asset_host = 'http://a0.example.com'
@@ -390,7 +389,7 @@ class AssetTagHelperTest < ActionView::TestCase
def test_caching_javascript_include_tag_when_caching_off
ENV["RAILS_ASSET_ID"] = ""
ActionController::Base.perform_caching = false
-
+
assert_dom_equal(
%(\n\n\n\n\n\n\n),
javascript_include_tag(:all, :cache => true)
@@ -402,7 +401,7 @@ class AssetTagHelperTest < ActionView::TestCase
)
assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::JAVASCRIPTS_DIR, 'all.js'))
-
+
assert_dom_equal(
%(\n\n\n\n\n\n\n),
javascript_include_tag(:all, :cache => "money")
@@ -420,7 +419,7 @@ class AssetTagHelperTest < ActionView::TestCase
ENV["RAILS_ASSET_ID"] = ""
ActionController::Base.asset_host = 'http://a0.example.com'
ActionController::Base.perform_caching = true
-
+
assert_dom_equal(
%( ),
stylesheet_link_tag(:all, :cache => true)
@@ -459,7 +458,7 @@ class AssetTagHelperTest < ActionView::TestCase
def test_caching_stylesheet_include_tag_when_caching_off
ENV["RAILS_ASSET_ID"] = ""
ActionController::Base.perform_caching = false
-
+
assert_dom_equal(
%( \n \n ),
stylesheet_link_tag(:all, :cache => true)
@@ -471,7 +470,7 @@ class AssetTagHelperTest < ActionView::TestCase
)
assert !File.exist?(File.join(ActionView::Helpers::AssetTagHelper::STYLESHEETS_DIR, 'all.css'))
-
+
assert_dom_equal(
%( \n \n ),
stylesheet_link_tag(:all, :cache => "money")
@@ -490,6 +489,8 @@ class AssetTagHelperNonVhostTest < ActionView::TestCase
tests ActionView::Helpers::AssetTagHelper
def setup
+ ActionController::Base.relative_url_root = "/collaboration/hieraki"
+
@controller = Class.new do
attr_accessor :request
@@ -497,22 +498,22 @@ class AssetTagHelperNonVhostTest < ActionView::TestCase
"http://www.example.com/collaboration/hieraki"
end
end.new
-
- @request = Class.new do
- def relative_url_root
- "/collaboration/hieraki"
- end
+ @request = Class.new do
def protocol
'gopher://'
end
end.new
-
+
@controller.request = @request
-
+
ActionView::Helpers::AssetTagHelper::reset_javascript_include_default
end
+ def teardown
+ ActionController::Base.relative_url_root = nil
+ end
+
def test_should_compute_proper_path
assert_dom_equal(%( ), auto_discovery_link_tag)
assert_dom_equal(%(/collaboration/hieraki/javascripts/xmlhr.js), javascript_path("xmlhr"))
@@ -521,7 +522,7 @@ class AssetTagHelperNonVhostTest < ActionView::TestCase
assert_dom_equal(%( ), image_tag("mouse.png", :mouseover => "/images/mouse_over.png"))
assert_dom_equal(%( ), image_tag("mouse2.png", :mouseover => image_path("mouse_over2.png")))
end
-
+
def test_should_ignore_relative_root_path_on_complete_url
assert_dom_equal(%(http://www.example.com/images/xml.png), image_path("http://www.example.com/images/xml.png"))
end
--
cgit v1.2.3
From 11fdcf88c2aea72ec84c5d4ab05986f5d35a9a81 Mon Sep 17 00:00:00 2001
From: Sam Granieri
Date: Thu, 24 Jul 2008 13:51:54 -0500
Subject: Check for ActionMailer and ActionController before attempting to
eager load their view paths Signed-off-by: Joshua Peek
---
railties/lib/initializer.rb | 4 ++--
railties/test/initializer_test.rb | 21 ++++++++++++++++++++-
2 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/railties/lib/initializer.rb b/railties/lib/initializer.rb
index 44863ab026..32411e8928 100644
--- a/railties/lib/initializer.rb
+++ b/railties/lib/initializer.rb
@@ -341,8 +341,8 @@ Run `rake gems:install` to install the missing gems.
def load_view_paths
ActionView::PathSet::Path.eager_load_templates! if configuration.cache_classes
- ActionMailer::Base.template_root.load
- ActionController::Base.view_paths.load
+ ActionMailer::Base.template_root.load if configuration.frameworks.include?(:action_mailer)
+ ActionController::Base.view_paths.load if configuration.frameworks.include?(:action_controller)
end
# Eager load application classes
diff --git a/railties/test/initializer_test.rb b/railties/test/initializer_test.rb
index dee7abe05f..07303a510e 100644
--- a/railties/test/initializer_test.rb
+++ b/railties/test/initializer_test.rb
@@ -136,8 +136,27 @@ uses_mocha 'framework paths' do
end
end
- protected
+ def test_action_mailer_load_paths_set_only_if_action_mailer_in_use
+ @config.frameworks = [:action_controller]
+ initializer = Rails::Initializer.new @config
+ initializer.send :require_frameworks
+
+ assert_nothing_raised NameError do
+ initializer.send :load_view_paths
+ end
+ end
+ def test_action_controller_load_paths_set_only_if_action_controller_in_use
+ @config.frameworks = []
+ initializer = Rails::Initializer.new @config
+ initializer.send :require_frameworks
+
+ assert_nothing_raised NameError do
+ initializer.send :load_view_paths
+ end
+ end
+
+ protected
def assert_framework_path(path)
assert @config.framework_paths.include?(path),
"<#{path.inspect}> not found among <#{@config.framework_paths.inspect}>"
--
cgit v1.2.3
From f48b9ab5c2741ddbdbc0a9f4cd06875a1e3c8b02 Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Thu, 24 Jul 2008 14:06:22 -0500
Subject: ActionController::Base.relative_url_root falls back to
ENV['RAILS_RELATIVE_URL_ROOT']
---
actionpack/lib/action_controller/base.rb | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index bae7e8c12e..5f4a38dac0 100755
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -356,7 +356,12 @@ module ActionController #:nodoc:
# If you are deploying to a subdirectory, you will need to set
# config.action_controller.relative_url_root
- class_inheritable_accessor :relative_url_root
+ # This defaults to ENV['RAILS_RELATIVE_URL_ROOT']
+ cattr_writer :relative_url_root
+
+ def self.relative_url_root
+ @@relative_url_root || ENV['RAILS_RELATIVE_URL_ROOT']
+ end
# Holds the request object that's primarily used to get environment variables through access like
# request.env["REQUEST_URI"] .
--
cgit v1.2.3
From e8fc894f66daa7909d1790f2cd145844d256d282 Mon Sep 17 00:00:00 2001
From: George Ogata
Date: Wed, 23 Jul 2008 06:38:26 +1000
Subject: Make observers define #after_find in the model only if needed.
[#676 state:resolved]
Signed-off-by: Michael Koziarski
---
activerecord/lib/active_record/observer.rb | 3 +++
activerecord/test/cases/lifecycle_test.rb | 32 ++++++++++++++++++++++++++++--
2 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/activerecord/lib/active_record/observer.rb b/activerecord/lib/active_record/observer.rb
index c96e5f9d51..b35e407cc1 100644
--- a/activerecord/lib/active_record/observer.rb
+++ b/activerecord/lib/active_record/observer.rb
@@ -189,6 +189,9 @@ module ActiveRecord
def add_observer!(klass)
klass.add_observer(self)
+ if respond_to?(:after_find) && !klass.method_defined?(:after_find)
+ klass.class_eval 'def after_find() end'
+ end
end
end
end
diff --git a/activerecord/test/cases/lifecycle_test.rb b/activerecord/test/cases/lifecycle_test.rb
index 3432abee31..ab005c6b00 100755
--- a/activerecord/test/cases/lifecycle_test.rb
+++ b/activerecord/test/cases/lifecycle_test.rb
@@ -143,12 +143,12 @@ class LifecycleTest < ActiveRecord::TestCase
assert_equal developer.name, multi_observer.record.name
end
- def test_after_find_cannot_be_observed_when_its_not_defined_on_the_model
+ def test_after_find_can_be_observed_when_its_not_defined_on_the_model
observer = MinimalisticObserver.instance
assert_equal Minimalistic, MinimalisticObserver.observed_class
minimalistic = Minimalistic.find(1)
- assert_nil observer.minimalistic
+ assert_equal minimalistic, observer.minimalistic
end
def test_after_find_can_be_observed_when_its_defined_on_the_model
@@ -159,6 +159,34 @@ class LifecycleTest < ActiveRecord::TestCase
assert_equal topic, observer.topic
end
+ def test_after_find_is_not_created_if_its_not_used
+ # use a fresh class so an observer can't have defined an
+ # after_find on it
+ model_class = Class.new(ActiveRecord::Base)
+ observer_class = Class.new(ActiveRecord::Observer)
+ observer_class.observe(model_class)
+
+ observer = observer_class.instance
+
+ assert !model_class.method_defined?(:after_find)
+ end
+
+ def test_after_find_is_not_clobbered_if_it_already_exists
+ # use a fresh observer class so we can instantiate it (Observer is
+ # a Singleton)
+ model_class = Class.new(ActiveRecord::Base) do
+ def after_find; end
+ end
+ original_method = model_class.instance_method(:after_find)
+ observer_class = Class.new(ActiveRecord::Observer) do
+ def after_find; end
+ end
+ observer_class.observe(model_class)
+
+ observer = observer_class.instance
+ assert_equal original_method, model_class.instance_method(:after_find)
+ end
+
def test_invalid_observer
assert_raise(ArgumentError) { Topic.observers = Object.new; Topic.instantiate_observers }
end
--
cgit v1.2.3
From 490178c93008c6fca20e3e2d6302a28d86aab94d Mon Sep 17 00:00:00 2001
From: Joshua Peek
Date: Sun, 27 Jul 2008 16:06:51 -0500
Subject: Revert "Ensure adapater specific code is loaded on
ActiveRecord::Base.establish_connection"
This reverts commit 8b858782fa693e89a47fc3dd5ae38d842ede6d04.
---
.../connection_adapters/abstract/connection_specification.rb | 1 -
1 file changed, 1 deletion(-)
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb
index 07b122efd1..2a8807fb78 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb
@@ -211,7 +211,6 @@ module ActiveRecord
clear_active_connection_name
@active_connection_name = name
@@defined_connections[name] = spec
- connection
when Symbol, String
if configuration = configurations[spec.to_s]
establish_connection(configuration)
--
cgit v1.2.3
From f7abf0c9db61621b3f27061debd7983075cdca61 Mon Sep 17 00:00:00 2001
From: Clemens Kofler
Date: Sun, 27 Jul 2008 16:34:20 -0500
Subject: error_message_on takes an options hash instead of ordered parameters
[#704 state:resolved] Signed-off-by: Joshua Peek
---
.../action_view/helpers/active_record_helper.rb | 46 ++++++++++++++-------
actionpack/lib/action_view/helpers/form_helper.rb | 4 +-
.../test/template/active_record_helper_test.rb | 48 +++++++++++-----------
3 files changed, 58 insertions(+), 40 deletions(-)
diff --git a/actionpack/lib/action_view/helpers/active_record_helper.rb b/actionpack/lib/action_view/helpers/active_record_helper.rb
index 959d8a8563..ff70ce9aae 100644
--- a/actionpack/lib/action_view/helpers/active_record_helper.rb
+++ b/actionpack/lib/action_view/helpers/active_record_helper.rb
@@ -25,7 +25,7 @@ module ActionView
# Returns an entire form with all needed input tags for a specified Active Record object. For example, if @post
# has attributes named +title+ of type +VARCHAR+ and +body+ of type +TEXT+ then
#
- # form("post")
+ # form("post")
#
# would yield a form like the following (modulus formatting):
#
@@ -90,23 +90,41 @@ module ActionView
end
# Returns a string containing the error message attached to the +method+ on the +object+ if one exists.
- # This error message is wrapped in a DIV tag, which can be extended to include a +prepend_text+ and/or +append_text+
- # (to properly explain the error), and a +css_class+ to style it accordingly. +object+ should either be the name of an instance variable or
- # the actual object. As an example, let's say you have a model @post that has an error message on the +title+ attribute:
+ # This error message is wrapped in a DIV tag, which can be extended to include a :prepend_text
+ # and/or :append_text (to properly explain the error), and a :css_class to style it
+ # accordingly. +object+ should either be the name of an instance variable or the actual object. The method can be
+ # passed in either as a string or a symbol.
+ # As an example, let's say you have a model @post that has an error message on the +title+ attribute:
#
# <%= error_message_on "post", "title" %>
# # => can't be empty
#
- # <%= error_message_on @post, "title" %>
+ # <%= error_message_on @post, :title %>
# # => can't be empty
#
- # <%= error_message_on "post", "title", "Title simply ", " (or it won't work).", "inputError" %>
- # # => Title simply can't be empty (or it won't work).
- def error_message_on(object, method, prepend_text = "", append_text = "", css_class = "formError")
+ # <%= error_message_on "post", "title",
+ # :prepend_text => "Title simply ",
+ # :append_text => " (or it won't work).",
+ # :css_class => "inputError" %>
+ def error_message_on(object, method, *args)
+ options = args.extract_options!
+ unless args.empty?
+ ActiveSupport::Deprecation.warn('error_message_on takes an option hash instead of separate' +
+ 'prepend_text, append_text, and css_class arguments', caller)
+
+ options[:prepend_text] = args[0] || ''
+ options[:append_text] = args[1] || ''
+ options[:css_class] = args[2] || 'formError'
+ end
+ options.reverse_merge!(:prepend_text => '', :append_text => '', :css_class => 'formError')
+
if (obj = (object.respond_to?(:errors) ? object : instance_variable_get("@#{object}"))) &&
(errors = obj.errors.on(method))
- content_tag("div", "#{prepend_text}#{errors.is_a?(Array) ? errors.first : errors}#{append_text}", :class => css_class)
- else
+ content_tag("div",
+ "#{options[:prepend_text]}#{errors.is_a?(Array) ? errors.first : errors}#{options[:append_text]}",
+ :class => options[:css_class]
+ )
+ else
''
end
end
@@ -133,7 +151,7 @@ module ActionView
#
# To specify the display for one object, you simply provide its name as a parameter.
# For example, for the @user model:
- #
+ #
# error_messages_for 'user'
#
# To specify more than one object, you simply list them; optionally, you can add an extra :object_name parameter, which
@@ -157,7 +175,7 @@ module ActionView
else
objects = params.collect {|object_name| instance_variable_get("@#{object_name}") }.compact
end
-
+
count = objects.inject(0) {|sum, object| sum + object.errors.count }
unless count.zero?
html = {}
@@ -174,7 +192,7 @@ module ActionView
I18n.with_options :locale => options[:locale], :scope => [:active_record, :error] do |locale|
header_message = if options.include?(:header_message)
options[:header_message]
- else
+ else
object_name = options[:object_name].to_s.gsub('_', ' ')
object_name = I18n.t(object_name, :default => object_name)
locale.t :header_message, :count => count, :object_name => object_name
@@ -193,7 +211,7 @@ module ActionView
''
end
end
-
+
private
def all_input_tags(record, record_name, options)
input_block = options[:input_block] || default_input_block
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index ada6fa2ea8..7bb82ba5bb 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -782,8 +782,8 @@ module ActionView
@template.radio_button(@object_name, method, tag_value, objectify_options(options))
end
- def error_message_on(method, prepend_text = "", append_text = "", css_class = "formError")
- @template.error_message_on(@object, method, prepend_text, append_text, css_class)
+ def error_message_on(method, *args)
+ @template.error_message_on(@object, method, *args)
end
def error_messages(options = {})
diff --git a/actionpack/test/template/active_record_helper_test.rb b/actionpack/test/template/active_record_helper_test.rb
index dfc30e651a..e46f95d18b 100644
--- a/actionpack/test/template/active_record_helper_test.rb
+++ b/actionpack/test/template/active_record_helper_test.rb
@@ -10,17 +10,17 @@ class ActiveRecordHelperTest < ActionView::TestCase
alias_method :body_before_type_cast, :body unless respond_to?(:body_before_type_cast)
alias_method :author_name_before_type_cast, :author_name unless respond_to?(:author_name_before_type_cast)
end
-
+
User = Struct.new("User", :email)
User.class_eval do
alias_method :email_before_type_cast, :email unless respond_to?(:email_before_type_cast)
end
-
+
Column = Struct.new("Column", :type, :name, :human_name)
end
def setup_post
- @post = Post.new
+ @post = Post.new
def @post.errors
Class.new {
def on(field)
@@ -33,12 +33,12 @@ class ActiveRecordHelperTest < ActionView::TestCase
false
end
end
- def empty?() false end
- def count() 1 end
+ def empty?() false end
+ def count() 1 end
def full_messages() [ "Author name can't be empty" ] end
}.new
end
-
+
def @post.new_record?() true end
def @post.to_param() nil end
@@ -58,16 +58,16 @@ class ActiveRecordHelperTest < ActionView::TestCase
end
def setup_user
- @user = User.new
+ @user = User.new
def @user.errors
Class.new {
def on(field) field == "email" end
- def empty?() false end
- def count() 1 end
+ def empty?() false end
+ def count() 1 end
def full_messages() [ "User email can't be empty" ] end
}.new
end
-
+
def @user.new_record?() true end
def @user.to_param() nil end
@@ -81,7 +81,7 @@ class ActiveRecordHelperTest < ActionView::TestCase
@user.email = ""
end
-
+
def protect_against_forgery?
@protect_against_forgery ? true : false
end
@@ -92,7 +92,7 @@ class ActiveRecordHelperTest < ActionView::TestCase
setup_user
@response = ActionController::TestResponse.new
-
+
@controller = Object.new
def @controller.url_for(options)
options = options.symbolize_keys
@@ -111,7 +111,7 @@ class ActiveRecordHelperTest < ActionView::TestCase
assert_dom_equal(
%(
),
text_area("post", "body")
- )
+ )
end
def test_text_field_with_errors
@@ -140,7 +140,7 @@ class ActiveRecordHelperTest < ActionView::TestCase
form("post")
)
end
-
+
def test_form_with_protect_against_forgery
@protect_against_forgery = true
@request_forgery_protection_token = 'authenticity_token'
@@ -150,7 +150,7 @@ class ActiveRecordHelperTest < ActionView::TestCase
form("post")
)
end
-
+
def test_form_with_method_option
assert_dom_equal(
%(
),
@@ -211,9 +211,9 @@ class ActiveRecordHelperTest < ActionView::TestCase
other_post = @post
assert_dom_equal "can't be empty
", error_message_on(other_post, :author_name)
end
-
- def test_error_message_on_should_use_options
- assert_dom_equal "beforecan't be emptyafter
", error_message_on(:post, :author_name, "before", "after", "differentError")
+
+ def test_error_message_on_with_options_hash
+ assert_dom_equal "beforecan't be emptyafter
", error_message_on(:post, :author_name, :css_class => 'differentError', :prepend_text => 'before', :append_text => 'after')
end
def test_error_messages_for_many_objects
@@ -224,10 +224,10 @@ class ActiveRecordHelperTest < ActionView::TestCase
# add the default to put post back in the title
assert_dom_equal %(2 errors prohibited this post from being saved There were problems with the following fields:
User email can't be empty Author name can't be empty ), error_messages_for("user", "post", :object_name => "post")
-
+
# symbols work as well
assert_dom_equal %(2 errors prohibited this post from being saved There were problems with the following fields:
User email can't be empty Author name can't be empty ), error_messages_for(:user, :post, :object_name => :post)
-
+
# any default works too
assert_dom_equal %(2 errors prohibited this monkey from being saved There were problems with the following fields:
User email can't be empty Author name can't be empty ), error_messages_for(:user, :post, :object_name => "monkey")
@@ -242,7 +242,7 @@ class ActiveRecordHelperTest < ActionView::TestCase
message = "Please fix the following fields and resubmit:"
assert_dom_equal %(#{header_message} #{message}
User email can't be empty Author name can't be empty ), error_messages_for(:user, :post, :header_message => header_message, :message => message)
end
-
+
def test_error_messages_for_non_instance_variable
actual_user = @user
actual_post = @post
@@ -251,14 +251,14 @@ class ActiveRecordHelperTest < ActionView::TestCase
#explicitly set object
assert_dom_equal %(1 error prohibited this post from being saved There were problems with the following fields:
Author name can't be empty ), error_messages_for("post", :object => actual_post)
-
+
#multiple objects
assert_dom_equal %(2 errors prohibited this user from being saved There were problems with the following fields:
User email can't be empty Author name can't be empty ), error_messages_for("user", "post", :object => [actual_user, actual_post])
-
+
#nil object
assert_equal '', error_messages_for('user', :object => nil)
end
-
+
def test_form_with_string_multipart
assert_dom_equal(
%(Title
\nBody
Back to the hill and over it again!
),
--
cgit v1.2.3
From 10d9fe4bf3110c1d5de0c6b509fe0cbb9d5eda1d Mon Sep 17 00:00:00 2001
From: Clemens Kofler
Date: Sun, 27 Jul 2008 16:49:19 -0500
Subject: Refactored TextHelper#truncate, highlight, excerpt, word_wrap and
auto_link to accept options hash [#705 state:resolved] Signed-off-by: Joshua
Peek
---
.../action_view/helpers/active_record_helper.rb | 2 +-
actionpack/lib/action_view/helpers/text_helper.rb | 206 +++++++++++++++------
actionpack/test/template/text_helper_test.rb | 51 ++++-
3 files changed, 191 insertions(+), 68 deletions(-)
diff --git a/actionpack/lib/action_view/helpers/active_record_helper.rb b/actionpack/lib/action_view/helpers/active_record_helper.rb
index ff70ce9aae..fce03ff605 100644
--- a/actionpack/lib/action_view/helpers/active_record_helper.rb
+++ b/actionpack/lib/action_view/helpers/active_record_helper.rb
@@ -109,7 +109,7 @@ module ActionView
def error_message_on(object, method, *args)
options = args.extract_options!
unless args.empty?
- ActiveSupport::Deprecation.warn('error_message_on takes an option hash instead of separate' +
+ ActiveSupport::Deprecation.warn('error_message_on takes an option hash instead of separate ' +
'prepend_text, append_text, and css_class arguments', caller)
options[:prepend_text] = args[0] || ''
diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb
index 9342b38680..3c9f7230c3 100644
--- a/actionpack/lib/action_view/helpers/text_helper.rb
+++ b/actionpack/lib/action_view/helpers/text_helper.rb
@@ -34,40 +34,69 @@ module ActionView
end
if RUBY_VERSION < '1.9'
- # If +text+ is longer than +length+, +text+ will be truncated to the length of
- # +length+ (defaults to 30) and the last characters will be replaced with the +truncate_string+
- # (defaults to "...").
+ # Truncates a given +text+ after a given :length if +text+ is longer than :length
+ # (defaults to 30). The last characters will be replaced with the :omission (defaults to "...").
#
# ==== Examples
- # truncate("Once upon a time in a world far far away", 14)
- # # => Once upon a...
#
# truncate("Once upon a time in a world far far away")
# # => Once upon a time in a world f...
#
- # truncate("And they found that many people were sleeping better.", 25, "(clipped)")
+ # truncate("Once upon a time in a world far far away", :length => 14)
+ # # => Once upon a...
+ #
+ # truncate("And they found that many people were sleeping better.", :length => 25, "(clipped)")
# # => And they found that many (clipped)
#
+ # truncate("And they found that many people were sleeping better.", :omission => "... (continued)", :length => 15)
+ # # => And they found... (continued)
+ #
+ # You can still use truncate with the old API that accepts the
+ # +length+ as its optional second and the +ellipsis+ as its
+ # optional third parameter:
+ # truncate("Once upon a time in a world far far away", 14)
+ # # => Once upon a time in a world f...
+ #
# truncate("And they found that many people were sleeping better.", 15, "... (continued)")
# # => And they found... (continued)
- def truncate(text, length = 30, truncate_string = "...")
+ def truncate(text, *args)
+ options = args.extract_options!
+ unless args.empty?
+ ActiveSupport::Deprecation.warn('truncate takes an option hash instead of separate ' +
+ 'length and omission arguments', caller)
+
+ options[:length] = args[0] || 30
+ options[:omission] = args[1] || "..."
+ end
+ options.reverse_merge!(:length => 30, :omission => "...")
+
if text
- l = length - truncate_string.chars.length
+ l = options[:length] - options[:omission].chars.length
chars = text.chars
- (chars.length > length ? chars[0...l] + truncate_string : text).to_s
+ (chars.length > options[:length] ? chars[0...l] + options[:omission] : text).to_s
end
end
else
- def truncate(text, length = 30, truncate_string = "...") #:nodoc:
+ def truncate(text, *args) #:nodoc:
+ options = args.extract_options!
+ unless args.empty?
+ ActiveSupport::Deprecation.warn('truncate takes an option hash instead of separate ' +
+ 'length and omission arguments', caller)
+
+ options[:length] = args[0] || 30
+ options[:omission] = args[1] || "..."
+ end
+ options.reverse_merge!(:length => 30, :omission => "...")
+
if text
- l = length - truncate_string.length
- (text.length > length ? text[0...l] + truncate_string : text).to_s
+ l = options[:length].to_i - options[:omission].length
+ (text.length > options[:length].to_i ? text[0...l] + options[:omission] : text).to_s
end
end
end
# Highlights one or more +phrases+ everywhere in +text+ by inserting it into
- # a +highlighter+ string. The highlighter can be specialized by passing +highlighter+
+ # a :highlighter string. The highlighter can be specialized by passing :highlighter
# as a single-quoted string with \1 where the phrase is to be inserted (defaults to
# '\1 ')
#
@@ -78,52 +107,75 @@ module ActionView
# highlight('You searched for: ruby, rails, dhh', 'actionpack')
# # => You searched for: ruby, rails, dhh
#
- # highlight('You searched for: rails', ['for', 'rails'], '\1 ')
+ # highlight('You searched for: rails', ['for', 'rails'], :highlighter => '\1 ')
# # => You searched for : rails
#
- # highlight('You searched for: rails', 'rails', "\1 ")
- # # => You searched for: \1')
+ # highlight('You searched for: rails', 'rails', :highlighter => ' \1 ')
+ # # => You searched for: rails
+ #
+ # You can still use highlight with the old API that accepts the
+ # +highlighter+ as its optional third parameter:
+ # highlight('You searched for: rails', 'rails', '\1 ') # => You searched for: rails
+ def highlight(text, phrases, *args)
+ options = args.extract_options!
+ unless args.empty?
+ options[:highlighter] = args[0] || '\1 '
+ end
+ options.reverse_merge!(:highlighter => '\1 ')
+
if text.blank? || phrases.blank?
text
else
match = Array(phrases).map { |p| Regexp.escape(p) }.join('|')
- text.gsub(/(#{match})/i, highlighter)
+ text.gsub(/(#{match})/i, options[:highlighter])
end
end
if RUBY_VERSION < '1.9'
# Extracts an excerpt from +text+ that matches the first instance of +phrase+.
- # The +radius+ expands the excerpt on each side of the first occurrence of +phrase+ by the number of characters
- # defined in +radius+ (which defaults to 100). If the excerpt radius overflows the beginning or end of the +text+,
- # then the +excerpt_string+ will be prepended/appended accordingly. The resulting string will be stripped in any case.
- # If the +phrase+ isn't found, nil is returned.
+ # The :radius option expands the excerpt on each side of the first occurrence of +phrase+ by the number of characters
+ # defined in :radius (which defaults to 100). If the excerpt radius overflows the beginning or end of the +text+,
+ # then the :omission option (which defaults to "...") will be prepended/appended accordingly. The resulting string
+ # will be stripped in any case. If the +phrase+ isn't found, nil is returned.
#
# ==== Examples
- # excerpt('This is an example', 'an', 5)
- # # => "...s is an exam..."
+ # excerpt('This is an example', 'an', :radius => 5)
+ # # => ...s is an exam...
#
- # excerpt('This is an example', 'is', 5)
- # # => "This is a..."
+ # excerpt('This is an example', 'is', :radius => 5)
+ # # => This is a...
#
# excerpt('This is an example', 'is')
- # # => "This is an example"
+ # # => This is an example
#
- # excerpt('This next thing is an example', 'ex', 2)
- # # => "...next..."
+ # excerpt('This next thing is an example', 'ex', :radius => 2)
+ # # => ...next...
#
- # excerpt('This is also an example', 'an', 8, ' ')
- # # => " is also an example"
- def excerpt(text, phrase, radius = 100, excerpt_string = "...")
+ # excerpt('This is also an example', 'an', :radius => 8, :omission => ' ')
+ # # => is also an example
+ #
+ # You can still use excerpt with the old API that accepts the
+ # +radius+ as its optional third and the +ellipsis+ as its
+ # optional forth parameter:
+ # excerpt('This is an example', 'an', 5) # => ...s is an exam...
+ # excerpt('This is also an example', 'an', 8, ' ') # => is also an example
+ def excerpt(text, phrase, *args)
+ options = args.extract_options!
+ unless args.empty?
+ options[:radius] = args[0] || 100
+ options[:omission] = args[1] || "..."
+ end
+ options.reverse_merge!(:radius => 100, :omission => "...")
+
if text && phrase
phrase = Regexp.escape(phrase)
if found_pos = text.chars =~ /(#{phrase})/i
- start_pos = [ found_pos - radius, 0 ].max
- end_pos = [ [ found_pos + phrase.chars.length + radius - 1, 0].max, text.chars.length ].min
+ start_pos = [ found_pos - options[:radius], 0 ].max
+ end_pos = [ [ found_pos + phrase.chars.length + options[:radius] - 1, 0].max, text.chars.length ].min
- prefix = start_pos > 0 ? excerpt_string : ""
- postfix = end_pos < text.chars.length - 1 ? excerpt_string : ""
+ prefix = start_pos > 0 ? options[:omission] : ""
+ postfix = end_pos < text.chars.length - 1 ? options[:omission] : ""
prefix + text.chars[start_pos..end_pos].strip + postfix
else
@@ -132,16 +184,23 @@ module ActionView
end
end
else
- def excerpt(text, phrase, radius = 100, excerpt_string = "...") #:nodoc:
+ def excerpt(text, phrase, *args) #:nodoc:
+ options = args.extract_options!
+ unless args.empty?
+ options[:radius] = args[0] || 100
+ options[:omission] = args[1] || "..."
+ end
+ options.reverse_merge!(:radius => 100, :omission => "...")
+
if text && phrase
phrase = Regexp.escape(phrase)
if found_pos = text =~ /(#{phrase})/i
- start_pos = [ found_pos - radius, 0 ].max
- end_pos = [ [ found_pos + phrase.length + radius - 1, 0].max, text.length ].min
+ start_pos = [ found_pos - options[:radius], 0 ].max
+ end_pos = [ [ found_pos + phrase.length + options[:radius] - 1, 0].max, text.length ].min
- prefix = start_pos > 0 ? excerpt_string : ""
- postfix = end_pos < text.length - 1 ? excerpt_string : ""
+ prefix = start_pos > 0 ? options[:omission] : ""
+ postfix = end_pos < text.length - 1 ? options[:omission] : ""
prefix + text[start_pos..end_pos].strip + postfix
else
@@ -176,20 +235,31 @@ module ActionView
# (which is 80 by default).
#
# ==== Examples
- # word_wrap('Once upon a time', 4)
- # # => Once\nupon\na\ntime
- #
- # word_wrap('Once upon a time', 8)
- # # => Once upon\na time
#
# word_wrap('Once upon a time')
# # => Once upon a time
#
- # word_wrap('Once upon a time', 1)
+ # word_wrap('Once upon a time, in a kingdom called Far Far Away, a king fell ill, and finding a successor to the throne turned out to be more trouble than anyone could have imagined...')
+ # # => Once upon a time, in a kingdom called Far Far Away, a king fell ill, and finding\n a successor to the throne turned out to be more trouble than anyone could have\n imagined...
+ #
+ # word_wrap('Once upon a time', :line_width => 8)
+ # # => Once upon\na time
+ #
+ # word_wrap('Once upon a time', :line_width => 1)
# # => Once\nupon\na\ntime
- def word_wrap(text, line_width = 80)
+ #
+ # You can still use word_wrap with the old API that accepts the
+ # +line_width+ as its optional second parameter:
+ # word_wrap('Once upon a time', 8) # => Once upon\na time
+ def word_wrap(text, *args)
+ options = args.extract_options!
+ unless args.blank?
+ options[:line_width] = args[0] || 80
+ end
+ options.reverse_merge!(:line_width => 80)
+
text.split("\n").collect do |line|
- line.length > line_width ? line.gsub(/(.{1,#{line_width}})(\s+|$)/, "\\1\n").strip : line
+ line.length > options[:line_width] ? line.gsub(/(.{1,#{options[:line_width]}})(\s+|$)/, "\\1\n").strip : line
end * "\n"
end
@@ -336,12 +406,32 @@ module ActionView
# # => "Welcome to my new blog at http://www.m... .
# Please e-mail me at me@email.com ."
#
- def auto_link(text, link = :all, href_options = {}, &block)
+ #
+ # You can still use auto_link with the old API that accepts the
+ # +link+ as its optional second parameter and the +html_options+ hash
+ # as its optional third parameter:
+ # post_body = "Welcome to my new blog at http://www.myblog.com/. Please e-mail me at me@email.com."
+ # auto_link(post_body, :urls) # => Once upon\na time
+ # # => "Welcome to my new blog at http://www.myblog.com .
+ # Please e-mail me at me@email.com."
+ #
+ # auto_link(post_body, :all, :target => "_blank") # => Once upon\na time
+ # # => "Welcome to my new blog at http://www.myblog.com .
+ # Please e-mail me at me@email.com ."
+ def auto_link(text, *args, &block)#link = :all, href_options = {}, &block)
return '' if text.blank?
- case link
- when :all then auto_link_email_addresses(auto_link_urls(text, href_options, &block), &block)
- when :email_addresses then auto_link_email_addresses(text, &block)
- when :urls then auto_link_urls(text, href_options, &block)
+
+ options = args.size == 2 ? {} : args.extract_options! # this is necessary because the old auto_link API has a Hash as its last parameter
+ unless args.empty?
+ options[:link] = args[0] || :all
+ options[:html] = args[1] || {}
+ end
+ options.reverse_merge!(:link => :all, :html => {})
+
+ case options[:link].to_sym
+ when :all then auto_link_email_addresses(auto_link_urls(text, options[:html], &block), &block)
+ when :email_addresses then auto_link_email_addresses(text, &block)
+ when :urls then auto_link_urls(text, options[:html], &block)
end
end
@@ -468,7 +558,7 @@ module ActionView
[-\w]+ # subdomain or domain
(?:\.[-\w]+)* # remaining subdomains or domain
(?::\d+)? # port
- (?:/(?:(?:[~\w\+@%=\(\)-]|(?:[,.;:'][^\s$])))*)* # path
+ (?:/(?:(?:[~\w\+@%=\(\)-]|(?:[,.;:'][^\s$]))+)?)* # path
(?:\?[\w\+@%&=.;-]+)? # query string
(?:\#[\w\-]*)? # trailing anchor
)
@@ -477,8 +567,8 @@ module ActionView
# Turns all urls into clickable links. If a block is given, each url
# is yielded and the result is used as the link text.
- def auto_link_urls(text, href_options = {})
- extra_options = tag_options(href_options.stringify_keys) || ""
+ def auto_link_urls(text, html_options = {})
+ extra_options = tag_options(html_options.stringify_keys) || ""
text.gsub(AUTO_LINK_RE) do
all, a, b, c, d = $&, $1, $2, $3, $4
if a =~ / 12)
+ assert_equal "Hello Wor...", truncate("Hello World!!", :length => 12)
end
def test_truncate_should_use_default_length_of_30
@@ -44,23 +44,29 @@ class TextHelperTest < ActionView::TestCase
assert_equal str[0...27] + "...", truncate(str)
end
+ def test_truncate_with_options_hash
+ assert_equal "This is a string that wil[...]", truncate("This is a string that will go longer then the default truncate length of 30", :omission => "[...]")
+ assert_equal "Hello W...", truncate("Hello World!", :length => 10)
+ assert_equal "Hello[...]", truncate("Hello World!", :omission => "[...]", :length => 10)
+ end
+
if RUBY_VERSION < '1.9.0'
def test_truncate_multibyte
with_kcode 'none' do
- assert_equal "\354\225\210\353\205\225\355...", truncate("\354\225\210\353\205\225\355\225\230\354\204\270\354\232\224", 10)
+ assert_equal "\354\225\210\353\205\225\355...", truncate("\354\225\210\353\205\225\355\225\230\354\204\270\354\232\224", :length => 10)
end
with_kcode 'u' do
assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...",
- truncate("\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244", 10)
+ truncate("\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244", :length => 10)
end
end
else
def test_truncate_multibyte
assert_equal "\354\225\210\353\205\225\355...",
- truncate("\354\225\210\353\205\225\355\225\230\354\204\270\354\232\224", 10)
+ truncate("\354\225\210\353\205\225\355\225\230\354\204\270\354\232\224", :length => 10)
assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...".force_encoding('UTF-8'),
- truncate("\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".force_encoding('UTF-8'), 10)
+ truncate("\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 \354\225\204\353\235\274\353\246\254\354\230\244".force_encoding('UTF-8'), :length => 10)
end
end
@@ -88,7 +94,7 @@ class TextHelperTest < ActionView::TestCase
assert_equal ' ', highlight(' ', 'blank text is returned verbatim')
end
- def test_highlighter_with_regexp
+ def test_highlight_with_regexp
assert_equal(
"This is a beautiful! morning",
highlight("This is a beautiful! morning", "beautiful!")
@@ -105,10 +111,17 @@ class TextHelperTest < ActionView::TestCase
)
end
- def test_highlighting_multiple_phrases_in_one_pass
+ def test_highlight_with_multiple_phrases_in_one_pass
assert_equal %(wow em ), highlight('wow em', %w(wow em), '\1 ')
end
+ def test_highlight_with_options_hash
+ assert_equal(
+ "This is a beautiful morning, but also a beautiful day",
+ highlight("This is a beautiful morning, but also a beautiful day", "beautiful", :highlighter => '\1 ')
+ )
+ end
+
def test_excerpt
assert_equal("...is a beautiful morn...", excerpt("This is a beautiful morning", "beautiful", 5))
assert_equal("This is a...", excerpt("This is a beautiful morning", "this", 5))
@@ -138,6 +151,16 @@ class TextHelperTest < ActionView::TestCase
assert_equal('...is a beautiful? mor...', excerpt('This is a beautiful? morning', 'beautiful', 5))
end
+ def test_excerpt_with_options_hash
+ assert_equal("...is a beautiful morn...", excerpt("This is a beautiful morning", "beautiful", :radius => 5))
+ assert_equal("[...]is a beautiful morn[...]", excerpt("This is a beautiful morning", "beautiful", :omission => "[...]",:radius => 5))
+ assert_equal(
+ "This is the ultimate supercalifragilisticexpialidoceous very looooooooooooooooooong looooooooooooong beautiful morning with amazing sunshine and awesome tempera[...]",
+ excerpt("This is the ultimate supercalifragilisticexpialidoceous very looooooooooooooooooong looooooooooooong beautiful morning with amazing sunshine and awesome temperatures. So what are you gonna do about it?", "very",
+ :omission => "[...]")
+ )
+ end
+
if RUBY_VERSION < '1.9'
def test_excerpt_with_utf8
with_kcode('u') do
@@ -162,6 +185,10 @@ class TextHelperTest < ActionView::TestCase
assert_equal("my very very\nvery long\nstring\n\nwith another\nline", word_wrap("my very very very long string\n\nwith another line", 15))
end
+ def test_word_wrap_with_options_hash
+ assert_equal("my very very\nvery long\nstring", word_wrap("my very very very long string", :line_width => 15))
+ end
+
def test_pluralization
assert_equal("1 count", pluralize(1, "count"))
assert_equal("2 counts", pluralize(2, "count"))
@@ -285,7 +312,13 @@ class TextHelperTest < ActionView::TestCase
url = "http://api.rubyonrails.com/Foo.html"
email = "fantabulous@shiznadel.ic"
- assert_equal %(#{url[0...7]}... #{email[0...7]}...
), auto_link("#{url} #{email}
") { |url| truncate(url, 10) }
+ assert_equal %(#{url[0...7]}... #{email[0...7]}...
), auto_link("#{url} #{email}
") { |url| truncate(url, :length => 10) }
+ end
+
+ def test_auto_link_with_options_hash
+ assert_equal 'Welcome to my new blog at . Please e-mail me at me@email.com .',
+ auto_link("Welcome to my new blog at http://www.myblog.com/. Please e-mail me at me@email.com.",
+ :link => :all, :html => { :class => "menu", :target => "_blank" })
end
def test_cycle_class
--
cgit v1.2.3