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 ++++++++++++++++++++++ 6 files changed, 191 insertions(+), 88 deletions(-) create mode 100644 actionpack/lib/action_view/lang/en-US.rb (limited to 'actionpack/lib') 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:" + } + } +} -- 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 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 actionpack/lib/action_view/helpers/i18n_helper.rb (limited to 'actionpack/lib') 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 -- 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 --- actionpack/lib/action_view/helpers/form_options_helper.rb | 2 +- actionpack/lib/action_view/lang/en-US.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'actionpack/lib') 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", -- 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 +- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'actionpack/lib') 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", -- 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 ++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 94 deletions(-) delete mode 100644 actionpack/lib/action_view/lang/en-US.rb create mode 100644 actionpack/lib/action_view/locale/en-US.rb (limited to 'actionpack/lib') 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:" + } + } +} -- 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 ---------- 3 files changed, 87 insertions(+), 71 deletions(-) create mode 100644 actionpack/lib/action_view/helpers/form_country_helper.rb (limited to 'actionpack/lib') 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"], -- 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 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'actionpack/lib') 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] -- 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 --- actionpack/lib/action_view/helpers/number_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') 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) -- 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 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 actionpack/lib/action_view/helpers/i18n_helper.rb (limited to 'actionpack/lib') 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 -- 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(-) (limited to 'actionpack/lib') 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 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 --------------------- 1 file changed, 21 deletions(-) (limited to 'actionpack/lib') 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', -- 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 --- actionpack/lib/action_view/helpers/date_helper.rb | 5 +++-- actionpack/lib/action_view/helpers/number_helper.rb | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'actionpack/lib') 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] -- 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 --- actionpack/lib/action_view/helpers/translation_helper.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 actionpack/lib/action_view/helpers/translation_helper.rb (limited to 'actionpack/lib') 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 -- 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 +++--- 3 files changed, 6 insertions(+), 7 deletions(-) (limited to 'actionpack/lib') 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 -- 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 + 1 file changed, 1 insertion(+) (limited to 'actionpack/lib') 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) -- 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 ++++ 1 file changed, 4 insertions(+) (limited to 'actionpack/lib') 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 -- 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'actionpack/lib') 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) -- 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 ++-- 5 files changed, 12 insertions(+), 20 deletions(-) (limited to 'actionpack/lib') 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 -- 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(-) (limited to 'actionpack/lib') 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(-) (limited to 'actionpack/lib') 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 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 --- actionpack/lib/action_view/helpers/form_options_helper.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'actionpack/lib') 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 -- 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(-) (limited to 'actionpack/lib') 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(-) (limited to 'actionpack/lib') 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 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(-) (limited to 'actionpack/lib') 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 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(-) (limited to 'actionpack/lib') 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(-) (limited to 'actionpack/lib') 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 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(-) (limited to 'actionpack/lib') 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(-) (limited to 'actionpack/lib') 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 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(-) (limited to 'actionpack/lib') 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 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'actionpack/lib') 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) -- 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(-) (limited to 'actionpack/lib') 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 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(-) (limited to 'actionpack/lib') 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 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 --- .../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 - 7 files changed, 191 insertions(+), 218 deletions(-) (limited to 'actionpack/lib') 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: Refresh - # 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 :html => { :action => + # form_remote_tag :html => { :action => # url_for(:controller => "some", :action => "place") } # # The Hash passed to the :html key is equivalent to the options (2nd) # argument in the FormTagHelper.form_tag method. # - # By default the fall-through action is the same as the one specified in + # By default the fall-through action is the same as the one specified in # the :url (and the default method is :post). # # form_remote_tag also takes a block, like form_tag: # # 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 }) %>"> # # @@ -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 # - # mail_to "me@domain.com", "My email", :encode => "hex" + # mail_to "me@domain.com", "My email", :encode => "hex" # # => My email # - # mail_to "me@domain.com", nil, :replace_at => "_at_", :replace_dot => "_dot_", :class => "email" + # mail_to "me@domain.com", nil, :replace_at => "_at_", :replace_dot => "_dot_", :class => "email" # # => # # mail_to "me@domain.com", "My email", :cc => "ccaddress@domain.com", - # :subject => "This is an example email" + # :subject => "This is an example email" # # => My email def mail_to(email_address, name = nil, html_options = {}) html_options = html_options.stringify_keys -- 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] --- .../action_view/helpers/javascripts/prototype.js | 304 ++++++++++----------- 1 file changed, 150 insertions(+), 154 deletions(-) (limited to 'actionpack/lib') 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) { -- 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 +++++++++++++++++------ 1 file changed, 23 insertions(+), 7 deletions(-) (limited to 'actionpack/lib') 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 -- 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 --- actionpack/lib/action_view/paths.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'actionpack/lib') 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(-) (limited to 'actionpack/lib') 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 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 +++++++++++----------- 1 file changed, 142 insertions(+), 156 deletions(-) (limited to 'actionpack/lib') 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 -- 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 +++++++++++++++------- 1 file changed, 66 insertions(+), 32 deletions(-) (limited to 'actionpack/lib') 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 -- 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 +- 4 files changed, 13 insertions(+), 7 deletions(-) (limited to 'actionpack/lib') 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 -- 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 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) (limited to 'actionpack/lib') 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 -- 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(-) (limited to 'actionpack/lib') 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 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'actionpack/lib') 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 -- 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(-) (limited to 'actionpack/lib') 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 +- 3 files changed, 9 insertions(+), 5 deletions(-) (limited to 'actionpack/lib') 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 -- 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/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 ++-- 5 files changed, 25 insertions(+), 34 deletions(-) (limited to 'actionpack/lib') 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 -- 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(-) (limited to 'actionpack/lib') 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 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 +- 2 files changed, 34 insertions(+), 16 deletions(-) (limited to 'actionpack/lib') 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 = {}) -- 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 +++++++++++++++------ 2 files changed, 149 insertions(+), 59 deletions(-) (limited to 'actionpack/lib') 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 =~ /