diff options
Diffstat (limited to 'actionpack')
-rw-r--r-- | actionpack/CHANGELOG.md | 5 | ||||
-rw-r--r-- | actionpack/lib/action_controller/metal/hide_actions.rb | 10 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/http/filter_parameters.rb | 29 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/http/headers.rb | 43 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/http/parameter_filter.rb | 90 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/http/request.rb | 8 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/date_helper.rb | 9 | ||||
-rw-r--r-- | actionpack/test/dispatch/header_test.rb | 20 | ||||
-rw-r--r-- | actionpack/test/template/date_helper_i18n_test.rb | 29 | ||||
-rw-r--r-- | actionpack/test/template/date_helper_test.rb | 16 |
10 files changed, 170 insertions, 89 deletions
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 0af79e83cb..48ba1518e0 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,5 +1,10 @@ ## Rails 4.0.0 (unreleased) ## +* `date_select` helper accepts `with_css_classes: true` to add css classes similar with type + of generated select tags. + + *Pavel Nikitin* + * Only non-js/css under app/assets path will be included in default config.assets.precompile. *Josh Peek* diff --git a/actionpack/lib/action_controller/metal/hide_actions.rb b/actionpack/lib/action_controller/metal/hide_actions.rb index 420b22cf56..2aa6b7adaf 100644 --- a/actionpack/lib/action_controller/metal/hide_actions.rb +++ b/actionpack/lib/action_controller/metal/hide_actions.rb @@ -26,20 +26,14 @@ module ActionController self.hidden_actions = hidden_actions.dup.merge(args.map(&:to_s)).freeze end - def inherited(klass) - klass.class_eval { @visible_actions = {} } - super - end - def visible_action?(action_name) - return @visible_actions[action_name] if @visible_actions.key?(action_name) - @visible_actions[action_name] = !hidden_actions.include?(action_name) + action_methods.include?(action_name) end # Overrides AbstractController::Base#action_methods to remove any methods # that are listed as hidden methods. def action_methods - @action_methods ||= Set.new(super.reject { |name| hidden_actions.include?(name) }) + @action_methods ||= Set.new(super.reject { |name| hidden_actions.include?(name) }).freeze end end end diff --git a/actionpack/lib/action_dispatch/http/filter_parameters.rb b/actionpack/lib/action_dispatch/http/filter_parameters.rb index 47cf41cfa3..4a7df6b657 100644 --- a/actionpack/lib/action_dispatch/http/filter_parameters.rb +++ b/actionpack/lib/action_dispatch/http/filter_parameters.rb @@ -1,3 +1,4 @@ +require 'mutex_m' require 'active_support/core_ext/hash/keys' require 'active_support/core_ext/object/duplicable' @@ -20,9 +21,18 @@ module ActionDispatch # end # => reverses the value to all keys matching /secret/i module FilterParameters - extend ActiveSupport::Concern + @@parameter_filter_for = {}.extend(Mutex_m) - @@parameter_filter_for = {} + ENV_MATCH = [/RAW_POST_DATA/, "rack.request.form_vars"] # :nodoc: + NULL_PARAM_FILTER = ParameterFilter.new # :nodoc: + NULL_ENV_FILTER = ParameterFilter.new ENV_MATCH # :nodoc: + + def initialize(env) + super + @filtered_parameters = nil + @filtered_env = nil + @filtered_path = nil + end # Return a hash of parameters with all sensitive data replaced. def filtered_parameters @@ -42,15 +52,24 @@ module ActionDispatch protected def parameter_filter - parameter_filter_for(@env["action_dispatch.parameter_filter"]) + parameter_filter_for @env.fetch("action_dispatch.parameter_filter") { + return NULL_PARAM_FILTER + } end def env_filter - parameter_filter_for(Array(@env["action_dispatch.parameter_filter"]) + [/RAW_POST_DATA/, "rack.request.form_vars"]) + user_key = @env.fetch("action_dispatch.parameter_filter") { + return NULL_ENV_FILTER + } + parameter_filter_for(Array(user_key) + ENV_MATCH) end def parameter_filter_for(filters) - @@parameter_filter_for[filters] ||= ParameterFilter.new(filters) + @@parameter_filter_for.synchronize do + # Do we *actually* need this cache? Constructing ParameterFilters + # doesn't seem too expensive. + @@parameter_filter_for[filters] ||= ParameterFilter.new(filters) + end end KV_RE = '[^&;=]+' diff --git a/actionpack/lib/action_dispatch/http/headers.rb b/actionpack/lib/action_dispatch/http/headers.rb index a3bb25f75a..dc04d4577b 100644 --- a/actionpack/lib/action_dispatch/http/headers.rb +++ b/actionpack/lib/action_dispatch/http/headers.rb @@ -1,32 +1,39 @@ module ActionDispatch module Http - class Headers < ::Hash - @@env_cache = Hash.new { |h,k| h[k] = "HTTP_#{k.upcase.gsub(/-/, '_')}" } + class Headers + include Enumerable - def initialize(*args) - - if args.size == 1 && args[0].is_a?(Hash) - super() - update(args[0]) - else - super - end + def initialize(env = {}) + @headers = env end def [](header_name) - super env_name(header_name) + @headers[env_name(header_name)] + end + + def []=(k,v); @headers[k] = v; end + def key?(k); @headers.key? k; end + alias :include? :key? + + def fetch(header_name, *args, &block) + @headers.fetch env_name(header_name), *args, &block end - def fetch(header_name, default=nil, &block) - super env_name(header_name), default, &block + def each(&block) + @headers.each(&block) end private - # Converts a HTTP header name to an environment variable name if it is - # not contained within the headers hash. - def env_name(header_name) - include?(header_name) ? header_name : @@env_cache[header_name] - end + + # Converts a HTTP header name to an environment variable name if it is + # not contained within the headers hash. + def env_name(header_name) + @headers.include?(header_name) ? header_name : cgi_name(header_name) + end + + def cgi_name(k) + "HTTP_#{k.upcase.gsub(/-/, '_')}" + end end end end diff --git a/actionpack/lib/action_dispatch/http/parameter_filter.rb b/actionpack/lib/action_dispatch/http/parameter_filter.rb index 490b46c990..b655a54865 100644 --- a/actionpack/lib/action_dispatch/http/parameter_filter.rb +++ b/actionpack/lib/action_dispatch/http/parameter_filter.rb @@ -1,74 +1,72 @@ module ActionDispatch module Http class ParameterFilter + FILTERED = '[FILTERED]'.freeze # :nodoc: - def initialize(filters) + def initialize(filters = []) @filters = filters end def filter(params) - if enabled? - compiled_filter.call(params) - else - params.dup - end + compiled_filter.call(params) end private - def enabled? - @filters.present? + def compiled_filter + @compiled_filter ||= CompiledFilter.compile(@filters) end - FILTERED = '[FILTERED]'.freeze + class CompiledFilter # :nodoc: + def self.compile(filters) + return lambda { |params| params.dup } if filters.empty? - def compiled_filter - @compiled_filter ||= begin - regexps, blocks = compile_filter + strings, regexps, blocks = [], [], [] - lambda do |original_params| - filtered_params = {} + filters.each do |item| + case item + when Proc + blocks << item + when Regexp + regexps << item + else + strings << item.to_s + end + end - original_params.each do |key, value| - if regexps.find { |r| key =~ r } - value = FILTERED - elsif value.is_a?(Hash) - value = filter(value) - elsif value.is_a?(Array) - value = value.map { |v| v.is_a?(Hash) ? filter(v) : v } - elsif blocks.present? - key = key.dup - value = value.dup if value.duplicable? - blocks.each { |b| b.call(key, value) } - end + regexps << Regexp.new(strings.join('|'), true) unless strings.empty? + new regexps, blocks + end - filtered_params[key] = value - end + attr_reader :regexps, :blocks - filtered_params - end + def initialize(regexps, blocks) + @regexps = regexps + @blocks = blocks end - end - def compile_filter - strings, regexps, blocks = [], [], [] + def call(original_params) + filtered_params = {} + + original_params.each do |key, value| + if regexps.any? { |r| key =~ r } + value = FILTERED + elsif value.is_a?(Hash) + value = call(value) + elsif value.is_a?(Array) + value = value.map { |v| v.is_a?(Hash) ? call(v) : v } + elsif blocks.any? + key = key.dup + value = value.dup if value.duplicable? + blocks.each { |b| b.call(key, value) } + end - @filters.each do |item| - case item - when NilClass - when Proc - blocks << item - when Regexp - regexps << item - else - strings << item.to_s + filtered_params[key] = value end - end - regexps << Regexp.new(strings.join('|'), true) unless strings.empty? - [regexps, blocks] + filtered_params + end end - end end end diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index b8ebeb408f..fc8825d6d9 100644 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -70,7 +70,13 @@ module ActionDispatch RFC5789 = %w(PATCH) HTTP_METHODS = RFC2616 + RFC2518 + RFC3253 + RFC3648 + RFC3744 + RFC5323 + RFC5789 - HTTP_METHOD_LOOKUP = Hash.new { |h, m| h[m] = m.underscore.to_sym if HTTP_METHODS.include?(m) } + + HTTP_METHOD_LOOKUP = {} + + # Populate the HTTP method lookup cache + HTTP_METHODS.each { |method| + HTTP_METHOD_LOOKUP[method] = method.underscore.to_sym + } # Returns the HTTP \method that the application should see. # In the case where the \method was overridden by a middleware diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb index 387dfeab17..f43d20c6ed 100644 --- a/actionpack/lib/action_view/helpers/date_helper.rb +++ b/actionpack/lib/action_view/helpers/date_helper.rb @@ -73,13 +73,17 @@ module ActionView options[:include_seconds] ||= !!include_seconds_or_options end + options = { + scope: :'datetime.distance_in_words' + }.merge!(options) + 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) from_time, to_time = to_time, from_time if from_time > to_time distance_in_minutes = ((to_time - from_time)/60.0).round distance_in_seconds = (to_time - from_time).round - I18n.with_options :locale => options[:locale], :scope => :'datetime.distance_in_words' do |locale| + I18n.with_options :locale => options[:locale], :scope => options[:scope] do |locale| case distance_in_minutes when 0..1 return distance_in_minutes == 0 ? @@ -196,6 +200,8 @@ module ActionView # for <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>, <tt>:hour</tt>, <tt>:minute</tt> and <tt>:second</tt>. # Setting this option prepends a select option with a generic prompt (Day, Month, Year, Hour, Minute, Seconds) # or the given prompt string. + # * <tt>:with_css_classes</tt> - Set to true if you want assign different styles for 'select' tags. This option + # automatically set classes 'year', 'month', 'day', 'hour', 'minute' and 'second' for your 'select' tags. # # If anything is passed in the +html_options+ hash it will be applied to every select tag in the set. # @@ -937,6 +943,7 @@ module ActionView :name => input_name_from_type(type) }.merge!(@html_options) select_options[:disabled] = 'disabled' if @options[:disabled] + select_options[:class] = type if @options[:with_css_classes] select_html = "\n" select_html << content_tag(:option, '', :value => '') + "\n" if @options[:include_blank] diff --git a/actionpack/test/dispatch/header_test.rb b/actionpack/test/dispatch/header_test.rb index bc7cad8db5..42432510c3 100644 --- a/actionpack/test/dispatch/header_test.rb +++ b/actionpack/test/dispatch/header_test.rb @@ -7,6 +7,26 @@ class HeaderTest < ActiveSupport::TestCase ) end + def test_each + headers = [] + @headers.each { |pair| headers << pair } + assert_equal [["HTTP_CONTENT_TYPE", "text/plain"]], headers + end + + def test_setter + @headers['foo'] = "bar" + assert_equal "bar", @headers['foo'] + end + + def test_key? + assert @headers.key?('HTTP_CONTENT_TYPE') + assert @headers.include?('HTTP_CONTENT_TYPE') + end + + def test_fetch_with_block + assert_equal 'omg', @headers.fetch('notthere') { 'omg' } + end + test "content type" do assert_equal "text/plain", @headers["Content-Type"] assert_equal "text/plain", @headers["content-type"] diff --git a/actionpack/test/template/date_helper_i18n_test.rb b/actionpack/test/template/date_helper_i18n_test.rb index 63066d40cd..495a9d3f9d 100644 --- a/actionpack/test/template/date_helper_i18n_test.rb +++ b/actionpack/test/template/date_helper_i18n_test.rb @@ -36,16 +36,13 @@ class DateHelperDistanceOfTimeInWordsI18nTests < ActiveSupport::TestCase end end - def assert_distance_of_time_in_words_translates_key(passed, expected) - diff, passed_options = *passed - key, count = *expected - to = @from + diff - - options = {:locale => 'en', :scope => :'datetime.distance_in_words'} - options[:count] = count if count - - I18n.expects(:t).with(key, options) - distance_of_time_in_words(@from, to, passed_options.merge(:locale => 'en')) + def test_distance_of_time_in_words_calls_i18n_with_custom_scope + { + [30.days, { scope: :'datetime.distance_in_words_ago' }] => [:'about_x_months', 1], + [60.days, { scope: :'datetime.distance_in_words_ago' }] => [:'x_months', 2], + }.each do |passed, expected| + assert_distance_of_time_in_words_translates_key(passed, expected, scope: :'datetime.distance_in_words_ago') + end end def test_time_ago_in_words_passes_locale @@ -74,6 +71,18 @@ class DateHelperDistanceOfTimeInWordsI18nTests < ActiveSupport::TestCase assert_equal expected, I18n.t(key, :count => count, :scope => 'datetime.distance_in_words') end end + + def assert_distance_of_time_in_words_translates_key(passed, expected, expected_options = {}) + diff, passed_options = *passed + key, count = *expected + to = @from + diff + + options = { locale: 'en', scope: :'datetime.distance_in_words' }.merge!(expected_options) + options[:count] = count if count + + I18n.expects(:t).with(key, options) + distance_of_time_in_words(@from, to, passed_options.merge(locale: 'en')) + end end class DateHelperSelectTagsI18nTests < ActiveSupport::TestCase diff --git a/actionpack/test/template/date_helper_test.rb b/actionpack/test/template/date_helper_test.rb index a4da7cd4b0..8bd8eff3c0 100644 --- a/actionpack/test/template/date_helper_test.rb +++ b/actionpack/test/template/date_helper_test.rb @@ -1007,6 +1007,22 @@ class DateHelperTest < ActionView::TestCase assert_dom_equal expected, select_date(Time.mktime(2003, 8, 16), { :date_separator => " / ", :prefix => "date[first]", :use_hidden => true }) end + def test_select_date_with_css_classes_option + expected = %(<select id="date_first_year" name="date[first][year]" class="year">\n) + expected << %(<option value="2003" selected="selected">2003</option>\n<option value="2004">2004</option>\n<option value="2005">2005</option>\n) + expected << "</select>\n" + + expected << %(<select id="date_first_month" name="date[first][month]" class="month">\n) + expected << %(<option value="1">January</option>\n<option value="2">February</option>\n<option value="3">March</option>\n<option value="4">April</option>\n<option value="5">May</option>\n<option value="6">June</option>\n<option value="7">July</option>\n<option value="8" selected="selected">August</option>\n<option value="9">September</option>\n<option value="10">October</option>\n<option value="11">November</option>\n<option value="12">December</option>\n) + expected << "</select>\n" + + expected << %(<select id="date_first_day" name="date[first][day]" class="day">\n) + expected << %(<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="4">4</option>\n<option value="5">5</option>\n<option value="6">6</option>\n<option value="7">7</option>\n<option value="8">8</option>\n<option value="9">9</option>\n<option value="10">10</option>\n<option value="11">11</option>\n<option value="12">12</option>\n<option value="13">13</option>\n<option value="14">14</option>\n<option value="15">15</option>\n<option value="16" selected="selected">16</option>\n<option value="17">17</option>\n<option value="18">18</option>\n<option value="19">19</option>\n<option value="20">20</option>\n<option value="21">21</option>\n<option value="22">22</option>\n<option value="23">23</option>\n<option value="24">24</option>\n<option value="25">25</option>\n<option value="26">26</option>\n<option value="27">27</option>\n<option value="28">28</option>\n<option value="29">29</option>\n<option value="30">30</option>\n<option value="31">31</option>\n) + expected << "</select>\n" + + assert_dom_equal expected, select_date(Time.mktime(2003, 8, 16), {:start_year => 2003, :end_year => 2005, :prefix => "date[first]", :with_css_classes => true}) + end + def test_select_datetime expected = %(<select id="date_first_year" name="date[first][year]">\n) expected << %(<option value="2003" selected="selected">2003</option>\n<option value="2004">2004</option>\n<option value="2005">2005</option>\n) |