diff options
Diffstat (limited to 'actionpack/lib/action_controller/support')
5 files changed, 303 insertions, 0 deletions
diff --git a/actionpack/lib/action_controller/support/class_attribute_accessors.rb b/actionpack/lib/action_controller/support/class_attribute_accessors.rb new file mode 100644 index 0000000000..786dcf98cb --- /dev/null +++ b/actionpack/lib/action_controller/support/class_attribute_accessors.rb @@ -0,0 +1,57 @@ +# Extends the class object with class and instance accessors for class attributes, +# just like the native attr* accessors for instance attributes. +class Class # :nodoc: + def cattr_reader(*syms) + syms.each do |sym| + class_eval <<-EOS + if ! defined? @@#{sym.id2name} + @@#{sym.id2name} = nil + end + + def self.#{sym.id2name} + @@#{sym} + end + + def #{sym.id2name} + @@#{sym} + end + + def call_#{sym.id2name} + case @@#{sym.id2name} + when Symbol then send(@@#{sym}) + when Proc then @@#{sym}.call(self) + when String then @@#{sym} + else nil + end + end + EOS + end + end + + def cattr_writer(*syms) + syms.each do |sym| + class_eval <<-EOS + if ! defined? @@#{sym.id2name} + @@#{sym.id2name} = nil + end + + def self.#{sym.id2name}=(obj) + @@#{sym.id2name} = obj + end + + def self.set_#{sym.id2name}(obj) + @@#{sym.id2name} = obj + end + + def #{sym.id2name}=(obj) + @@#{sym} = obj + end + EOS + end + end + + def cattr_accessor(*syms) + cattr_reader(*syms) + cattr_writer(*syms) + end +end
\ No newline at end of file diff --git a/actionpack/lib/action_controller/support/class_inheritable_attributes.rb b/actionpack/lib/action_controller/support/class_inheritable_attributes.rb new file mode 100644 index 0000000000..7f061fdf1b --- /dev/null +++ b/actionpack/lib/action_controller/support/class_inheritable_attributes.rb @@ -0,0 +1,37 @@ +# Allows attributes to be shared within an inheritance hierarchy, but where each descendant gets a copy of +# their parents' attributes, instead of just a pointer to the same. This means that the child can add elements +# to, for example, an array without those additions being shared with either their parent, siblings, or +# children, which is unlike the regular class-level attributes that are shared across the entire hierarchy. +module ClassInheritableAttributes # :nodoc: + def self.append_features(base) + super + base.extend(ClassMethods) + end + + module ClassMethods # :nodoc: + @@classes ||= {} + + def inheritable_attributes + @@classes[self] ||= {} + end + + def write_inheritable_attribute(key, value) + inheritable_attributes[key] = value + end + + def write_inheritable_array(key, elements) + write_inheritable_attribute(key, []) if read_inheritable_attribute(key).nil? + write_inheritable_attribute(key, read_inheritable_attribute(key) + elements) + end + + def read_inheritable_attribute(key) + inheritable_attributes[key] + end + + private + def inherited(child) + @@classes[child] = inheritable_attributes.dup + end + + end +end diff --git a/actionpack/lib/action_controller/support/clean_logger.rb b/actionpack/lib/action_controller/support/clean_logger.rb new file mode 100644 index 0000000000..1a36562892 --- /dev/null +++ b/actionpack/lib/action_controller/support/clean_logger.rb @@ -0,0 +1,10 @@ +require 'logger' + +class Logger #:nodoc: + private + remove_const "Format" + Format = "%s\n" + def format_message(severity, timestamp, msg, progname) + Format % [msg] + end +end
\ No newline at end of file diff --git a/actionpack/lib/action_controller/support/cookie_performance_fix.rb b/actionpack/lib/action_controller/support/cookie_performance_fix.rb new file mode 100644 index 0000000000..225cea1905 --- /dev/null +++ b/actionpack/lib/action_controller/support/cookie_performance_fix.rb @@ -0,0 +1,121 @@ +CGI.module_eval { remove_const "Cookie" } + +class CGI #:nodoc: + # This is a cookie class that fixes the performance problems with the default one that ships with 1.8.1 and below. + # It replaces the inheritance on SimpleDelegator with DelegateClass(Array) following the suggestion from Matz on + # http://groups.google.com/groups?th=e3a4e68ba042f842&seekm=c3sioe%241qvm%241%40news.cybercity.dk#link14 + class Cookie < DelegateClass(Array) + # Create a new CGI::Cookie object. + # + # The contents of the cookie can be specified as a +name+ and one + # or more +value+ arguments. Alternatively, the contents can + # be specified as a single hash argument. The possible keywords of + # this hash are as follows: + # + # name:: the name of the cookie. Required. + # value:: the cookie's value or list of values. + # path:: the path for which this cookie applies. Defaults to the + # base directory of the CGI script. + # domain:: the domain for which this cookie applies. + # expires:: the time at which this cookie expires, as a +Time+ object. + # secure:: whether this cookie is a secure cookie or not (default to + # false). Secure cookies are only transmitted to HTTPS + # servers. + # + # These keywords correspond to attributes of the cookie object. + def initialize(name = "", *value) + options = if name.kind_of?(String) + { "name" => name, "value" => value } + else + name + end + unless options.has_key?("name") + raise ArgumentError, "`name' required" + end + + @name = options["name"] + @value = Array(options["value"]) + # simple support for IE + if options["path"] + @path = options["path"] + else + %r|^(.*/)|.match(ENV["SCRIPT_NAME"]) + @path = ($1 or "") + end + @domain = options["domain"] + @expires = options["expires"] + @secure = options["secure"] == true ? true : false + + super(@value) + end + + def __setobj__(obj) + @_dc_obj = obj + end + + attr_accessor("name", "value", "path", "domain", "expires") + attr_reader("secure") + + # Set whether the Cookie is a secure cookie or not. + # + # +val+ must be a boolean. + def secure=(val) + @secure = val if val == true or val == false + @secure + end + + # Convert the Cookie to its string representation. + def to_s + buf = "" + buf += @name + '=' + + if @value.kind_of?(String) + buf += CGI::escape(@value) + else + buf += @value.collect{|v| CGI::escape(v) }.join("&") + end + + if @domain + buf += '; domain=' + @domain + end + + if @path + buf += '; path=' + @path + end + + if @expires + buf += '; expires=' + CGI::rfc1123_date(@expires) + end + + if @secure == true + buf += '; secure' + end + + buf + end + + # Parse a raw cookie string into a hash of cookie-name=>Cookie + # pairs. + # + # cookies = CGI::Cookie::parse("raw_cookie_string") + # # { "name1" => cookie1, "name2" => cookie2, ... } + # + def self.parse(raw_cookie) + cookies = Hash.new([]) + return cookies unless raw_cookie + + raw_cookie.split(/; /).each do |pairs| + name, values = pairs.split('=',2) + next unless name and values + name = CGI::unescape(name) + values ||= "" + values = values.split('&').collect{|v| CGI::unescape(v) } + unless cookies.has_key?(name) + cookies[name] = new({ "name" => name, "value" => values }) + end + end + + cookies + end + end # class Cookie +end
\ No newline at end of file diff --git a/actionpack/lib/action_controller/support/inflector.rb b/actionpack/lib/action_controller/support/inflector.rb new file mode 100644 index 0000000000..05ff4fede9 --- /dev/null +++ b/actionpack/lib/action_controller/support/inflector.rb @@ -0,0 +1,78 @@ +# The Inflector transforms words from singular to plural, class names to table names, modulized class names to ones without, +# and class names to foreign keys. +module Inflector + extend self + + def pluralize(word) + result = word.dup + plural_rules.each do |(rule, replacement)| + break if result.gsub!(rule, replacement) + end + return result + end + + def singularize(word) + result = word.dup + singular_rules.each do |(rule, replacement)| + break if result.gsub!(rule, replacement) + end + return result + end + + def camelize(lower_case_and_underscored_word) + lower_case_and_underscored_word.gsub(/(^|_)(.)/){$2.upcase} + end + + def underscore(camel_cased_word) + camel_cased_word.gsub(/([A-Z]+)([A-Z])/,'\1_\2').gsub(/([a-z])([A-Z])/,'\1_\2').downcase + end + + def demodulize(class_name_in_module) + class_name_in_module.gsub(/^.*::/, '') + end + + def tableize(class_name) + pluralize(underscore(class_name)) + end + + def classify(table_name) + camelize(singularize(table_name)) + end + + def foreign_key(class_name, separate_class_name_and_id_with_underscore = true) + Inflector.underscore(Inflector.demodulize(class_name)) + + (separate_class_name_and_id_with_underscore ? "_id" : "id") + end + + private + def plural_rules #:doc: + [ + [/(x|ch|ss)$/, '\1es'], # search, switch, fix, box, process, address + [/([^aeiouy]|qu)y$/, '\1ies'], # query, ability, agency + [/(?:([^f])fe|([lr])f)$/, '\1\2ves'], # half, safe, wife + [/sis$/, 'ses'], # basis, diagnosis + [/([ti])um$/, '\1a'], # datum, medium + [/person$/, 'people'], # person, salesperson + [/man$/, 'men'], # man, woman, spokesman + [/child$/, 'children'], # child + [/s$/, 's'], # no change (compatibility) + [/$/, 's'] + ] + end + + def singular_rules #:doc: + [ + [/(x|ch|ss)es$/, '\1'], + [/([^aeiouy]|qu)ies$/, '\1y'], + [/([lr])ves$/, '\1f'], + [/([^f])ves$/, '\1fe'], + [/(analy|ba|diagno|parenthe|progno|synop|the)ses$/, '\1sis'], + [/([ti])a$/, '\1um'], + [/people$/, 'person'], + [/men$/, 'man'], + [/status$/, 'status'], + [/children$/, 'child'], + [/s$/, ''] + ] + end +end
\ No newline at end of file |