diff options
author | José Valim <jose.valim@gmail.com> | 2010-01-23 22:53:26 +0100 |
---|---|---|
committer | José Valim <jose.valim@gmail.com> | 2010-01-23 22:53:26 +0100 |
commit | f915f9e33903ee474920e24ad12a1625f2ef1c52 (patch) | |
tree | 5b6d41e8a809aeaadbc2c0be59603f5f58b16231 | |
parent | b17e358e3df34c03019e357f693611618092e1d6 (diff) | |
parent | 8ff2fb6f3aa6140f5a8bd018d5919a8a1e707cda (diff) | |
download | rails-f915f9e33903ee474920e24ad12a1625f2ef1c52.tar.gz rails-f915f9e33903ee474920e24ad12a1625f2ef1c52.tar.bz2 rails-f915f9e33903ee474920e24ad12a1625f2ef1c52.zip |
Merge branch 'master' into app
Conflicts:
railties/lib/rails/application.rb
55 files changed, 303 insertions, 890 deletions
diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb index 826e82c8c6..a168b1b4c5 100644 --- a/actionpack/lib/abstract_controller/rendering.rb +++ b/actionpack/lib/abstract_controller/rendering.rb @@ -98,18 +98,9 @@ module AbstractController _view_paths end - # Normalize options, by converting render "foo" to render :template => "foo" - # and render "/foo" to render :file => "/foo". - def _normalize_options(action=nil, options={}) - case action - when Hash - options, action = action, nil - when String - key = (action.index("/") == 0 ? :file : :template) - options.merge!(key => action) - end - - options + # The prefix used in render "foo" shortcuts. + def _prefix + controller_path end # Return a string representation of a Rack-compatible response body. @@ -126,6 +117,28 @@ module AbstractController private + # Normalize options, by converting render "foo" to render :template => "prefix/foo" + # and render "/foo" to render :file => "/foo". + def _normalize_options(action=nil, options={}) + case action + when Hash + options, action = action, nil + when String, Symbol + action = action.to_s + case action.index("/") + when NilClass + options[:_prefix] = _prefix + options[:_template_name] = action + when 0 + options[:file] = action + else + options[:template] = action + end + end + + options + end + # Take in a set of options and determine the template to render # # ==== Options diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index a66aafd80e..f46231d72b 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -81,28 +81,5 @@ module ActionController filter << block if block filter end - - def _normalize_options(action=nil, options={}, &blk) - case action - when NilClass - when Hash, String - options = super - when Symbol - options.merge! :action => action - else - options.merge! :partial => action - end - - if options.key?(:action) && options[:action].to_s.index("/") - options[:template] = options.delete(:action) - end - - if options[:status] - options[:status] = Rack::Utils.status_code(options[:status]) - end - - options[:update] = blk if block_given? - options - end end end diff --git a/actionpack/lib/action_controller/metal/rendering.rb b/actionpack/lib/action_controller/metal/rendering.rb index 475ed54167..72e2bbd00e 100644 --- a/actionpack/lib/action_controller/metal/rendering.rb +++ b/actionpack/lib/action_controller/metal/rendering.rb @@ -25,18 +25,6 @@ module ActionController end private - def _prefix - controller_path - end - - def _determine_template(options) - if (options.keys & [:partial, :file, :template, :text, :inline]).empty? - options[:_template_name] ||= options[:action] - options[:_prefix] = _prefix - end - - super - end def _render_partial(options) options[:partial] = action_name if options[:partial] == true @@ -54,5 +42,29 @@ module ActionController self.content_type = content_type if content_type self.headers["Location"] = url_for(location) if location end + + def _normalize_options(action=nil, options={}, &blk) + case action + when NilClass + when Hash + options = super(action.delete(:action), action) + when String, Symbol + options = super + else + options.merge! :partial => action + end + + if (options.keys & [:partial, :file, :template, :text, :inline]).empty? + options[:_template_name] ||= options[:action] + options[:_prefix] = _prefix + end + + if options[:status] + options[:status] = Rack::Utils.status_code(options[:status]) + end + + options[:update] = blk if block_given? + options + end end end diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb index 4970c768e8..c4b0455c2a 100644 --- a/actionpack/lib/action_view/base.rb +++ b/actionpack/lib/action_view/base.rb @@ -181,7 +181,6 @@ module ActionView #:nodoc: extend ActiveSupport::Memoizable attr_accessor :base_path, :assigns, :template_extension, :formats - attr_accessor :controller attr_internal :captures def reset_formats(formats) @@ -277,13 +276,13 @@ module ActionView #:nodoc: @config = nil @formats = formats @assigns = assigns_for_first_render.each { |key, value| instance_variable_set("@#{key}", value) } - @controller = controller + @_controller = controller @helpers = self.class.helpers || Module.new @_content_for = Hash.new {|h,k| h[k] = ActionView::SafeBuffer.new } self.view_paths = view_paths end - attr_internal :template + attr_internal :controller, :template attr_reader :view_paths def view_paths=(paths) @@ -298,12 +297,11 @@ module ActionView #:nodoc: # Evaluates the local assigns and controller ivars, pushes them to the view. def _evaluate_assigns_and_ivars #:nodoc: - if @controller - variables = @controller.instance_variable_names - variables -= @controller.protected_instance_variables if @controller.respond_to?(:protected_instance_variables) - variables.each { |name| instance_variable_set(name, @controller.instance_variable_get(name)) } + if controller + variables = controller.instance_variable_names + variables -= controller.protected_instance_variables if controller.respond_to?(:protected_instance_variables) + variables.each { |name| instance_variable_set(name, controller.instance_variable_get(name)) } end end - end end diff --git a/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/actionpack/lib/action_view/helpers/asset_tag_helper.rb index 15b70ecff5..83357dd76f 100644 --- a/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -634,8 +634,8 @@ module ActionView # Prefix with <tt>/dir/</tt> if lacking a leading +/+. Account for relative URL # roots. Rewrite the asset path for cache-busting asset ids. Include # asset host, if configured, with the correct request protocol. - def compute_public_path(source, dir, ext = nil, include_host = true) - has_request = @controller.respond_to?(:request) + def compute_public_path(source, dir, ext = nil, include_host = true) + has_request = controller.respond_to?(:request) source_ext = File.extname(source)[1..-1] if ext && !is_uri?(source) && (source_ext.blank? || (ext != source_ext && File.exist?(File.join(config.assets_dir, dir, "#{source}.#{ext}")))) @@ -658,7 +658,7 @@ module ActionView host = compute_asset_host(source) if has_request && !host.blank? && !is_uri?(host) - host = "#{@controller.request.protocol}#{host}" + host = "#{controller.request.protocol}#{host}" end "#{host}#{source}" @@ -681,7 +681,7 @@ module ActionView if host.is_a?(Proc) || host.respond_to?(:call) case host.is_a?(Proc) ? host.arity : host.method(:call).arity when 2 - request = @controller.respond_to?(:request) && @controller.request + request = controller.respond_to?(:request) && controller.request host.call(source, request) else host.call(source) diff --git a/actionpack/lib/action_view/helpers/cache_helper.rb b/actionpack/lib/action_view/helpers/cache_helper.rb index 64d1ad2715..d5cc14b29a 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 # <i>Topics listed alphabetically</i> # <% end %> def cache(name = {}, options = nil, &block) - @controller.fragment_for(output_buffer, name, options, &block) + controller.fragment_for(output_buffer, name, options, &block) end end end diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb index 14628c5404..511386fede 100644 --- a/actionpack/lib/action_view/helpers/url_helper.rb +++ b/actionpack/lib/action_view/helpers/url_helper.rb @@ -13,7 +13,7 @@ module ActionView # Need to map default url options to controller one. def default_url_options(*args) #:nodoc: - @controller.send(:default_url_options, *args) + controller.send(:default_url_options, *args) end # Returns the URL for the set of +options+ provided. This takes the @@ -89,10 +89,10 @@ module ActionView when Hash options = { :only_path => options[:host].nil? }.update(options.symbolize_keys) escape = options.key?(:escape) ? options.delete(:escape) : false - @controller.send(:url_for, options) + controller.send(:url_for, options) when :back escape = false - @controller.request.env["HTTP_REFERER"] || 'javascript:history.back()' + controller.request.env["HTTP_REFERER"] || 'javascript:history.back()' else escape = false polymorphic_path(options) @@ -546,10 +546,10 @@ module ActionView # # => false def current_page?(options) url_string = CGI.unescapeHTML(url_for(options)) - request = @controller.request - # We ignore any extra parameters in the request_uri if the + request = controller.request + # We ignore any extra parameters in the request_uri if the # submitted url doesn't have any either. This lets the function - # work with things like ?order=asc + # work with things like ?order=asc if url_string.index("?") request_uri = request.request_uri else diff --git a/actionpack/lib/action_view/render/rendering.rb b/actionpack/lib/action_view/render/rendering.rb index ec278ca783..7c33f1334a 100644 --- a/actionpack/lib/action_view/render/rendering.rb +++ b/actionpack/lib/action_view/render/rendering.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/object/try' + module ActionView module Rendering # Returns the result of a render that's dictated by the options hash. The primary options are: diff --git a/actionpack/test/abstract/render_test.rb b/actionpack/test/abstract/render_test.rb index 4bec44c9ae..ffd430fa86 100644 --- a/actionpack/test/abstract/render_test.rb +++ b/actionpack/test/abstract/render_test.rb @@ -6,9 +6,16 @@ module AbstractController class ControllerRenderer < AbstractController::Base include AbstractController::Rendering + def _prefix + "renderer" + end + self.view_paths = [ActionView::FixtureResolver.new( "default.erb" => "With Default", "template.erb" => "With Template", + "renderer/string.erb" => "With String", + "renderer/symbol.erb" => "With Symbol", + "string/with_path.erb" => "With String With Path", "some/file.erb" => "With File", "template_name.erb" => "With Template Name" )] @@ -33,8 +40,16 @@ module AbstractController render end - def shortcut - render "template" + def string + render "string" + end + + def string_with_path + render "string/with_path" + end + + def symbol + render :symbol end def template_name @@ -77,9 +92,19 @@ module AbstractController assert_equal "With Default", @controller.response_body end - def test_render_template_through_shortcut - @controller.process(:shortcut) - assert_equal "With Template", @controller.response_body + def test_render_string + @controller.process(:string) + assert_equal "With String", @controller.response_body + end + + def test_render_symbol + @controller.process(:symbol) + assert_equal "With Symbol", @controller.response_body + end + + def test_render_string_with_path + @controller.process(:string_with_path) + assert_equal "With String With Path", @controller.response_body end def test_render_template_name diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb index 58673ab7bd..cc0accf90e 100644 --- a/activerecord/lib/active_record.rb +++ b/activerecord/lib/active_record.rb @@ -45,7 +45,6 @@ module ActiveRecord autoload :AssociationPreload autoload :Associations autoload :AttributeMethods - autoload :Attributes autoload :AutosaveAssociation autoload :Relation @@ -77,7 +76,6 @@ module ActiveRecord autoload :StateMachine autoload :Timestamp autoload :Transactions - autoload :Types autoload :Validations end @@ -95,28 +93,6 @@ module ActiveRecord end end - module Attributes - extend ActiveSupport::Autoload - - eager_autoload do - autoload :Aliasing - autoload :Store - autoload :Typecasting - end - end - - module Type - extend ActiveSupport::Autoload - - eager_autoload do - autoload :Number, 'active_record/types/number' - autoload :Object, 'active_record/types/object' - autoload :Serialize, 'active_record/types/serialize' - autoload :TimeWithZone, 'active_record/types/time_with_zone' - autoload :Unknown, 'active_record/types/unknown' - end - end - module Locking extend ActiveSupport::Autoload diff --git a/activerecord/lib/active_record/attribute_methods/before_type_cast.rb b/activerecord/lib/active_record/attribute_methods/before_type_cast.rb index 74921241f7..a4e144f233 100644 --- a/activerecord/lib/active_record/attribute_methods/before_type_cast.rb +++ b/activerecord/lib/active_record/attribute_methods/before_type_cast.rb @@ -8,18 +8,25 @@ module ActiveRecord end def read_attribute_before_type_cast(attr_name) - _attributes.without_typecast[attr_name] + @attributes[attr_name] end # Returns a hash of attributes before typecasting and deserialization. def attributes_before_type_cast - _attributes.without_typecast + self.attribute_names.inject({}) do |attrs, name| + attrs[name] = read_attribute_before_type_cast(name) + attrs + end end private # Handle *_before_type_cast for method_missing. def attribute_before_type_cast(attribute_name) - read_attribute_before_type_cast(attribute_name) + if attribute_name == 'id' + read_attribute_before_type_cast(self.class.primary_key) + else + read_attribute_before_type_cast(attribute_name) + end end end end diff --git a/activerecord/lib/active_record/attribute_methods/query.rb b/activerecord/lib/active_record/attribute_methods/query.rb index 0154ee35f8..a949d80120 100644 --- a/activerecord/lib/active_record/attribute_methods/query.rb +++ b/activerecord/lib/active_record/attribute_methods/query.rb @@ -8,7 +8,23 @@ module ActiveRecord end def query_attribute(attr_name) - _attributes.has?(attr_name) + unless value = read_attribute(attr_name) + false + else + column = self.class.columns_hash[attr_name] + if column.nil? + if Numeric === value || value !~ /[^0-9]/ + !value.to_i.zero? + else + return false if ActiveRecord::ConnectionAdapters::Column::FALSE_VALUES.include?(value) + !value.blank? + end + elsif column.number? + !value.zero? + else + !value.blank? + end + end end private @@ -19,5 +35,3 @@ module ActiveRecord end end end - - diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb index 97caec7744..3da3d9d8cc 100644 --- a/activerecord/lib/active_record/attribute_methods/read.rb +++ b/activerecord/lib/active_record/attribute_methods/read.rb @@ -37,7 +37,11 @@ module ActiveRecord protected def define_method_attribute(attr_name) - define_read_method(attr_name.to_sym, attr_name, columns_hash[attr_name]) + if self.serialized_attributes[attr_name] + define_read_method_for_serialized_attribute(attr_name) + else + define_read_method(attr_name.to_sym, attr_name, columns_hash[attr_name]) + end if attr_name == primary_key && attr_name != "id" define_read_method(:id, attr_name, columns_hash[attr_name]) @@ -45,12 +49,18 @@ module ActiveRecord end private + # Define read method for serialized attribute. + def define_read_method_for_serialized_attribute(attr_name) + generated_attribute_methods.module_eval("def #{attr_name}; unserialize_attribute('#{attr_name}'); end", __FILE__, __LINE__) + end # Define an attribute reader method. Cope with nil column. def define_read_method(symbol, attr_name, column) - access_code = "_attributes['#{attr_name}']" + cast_code = column.type_cast_code('v') if column + access_code = cast_code ? "(v=@attributes['#{attr_name}']) && #{cast_code}" : "@attributes['#{attr_name}']" + unless attr_name.to_s == self.primary_key.to_s - access_code = access_code.insert(0, "missing_attribute('#{attr_name}', caller) unless _attributes.key?('#{attr_name}'); ") + access_code = access_code.insert(0, "missing_attribute('#{attr_name}', caller) unless @attributes.has_key?('#{attr_name}'); ") end if cache_attribute?(attr_name) @@ -63,7 +73,38 @@ module ActiveRecord # Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example, # "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)). def read_attribute(attr_name) - _attributes[attr_name] + attr_name = attr_name.to_s + attr_name = self.class.primary_key if attr_name == 'id' + if !(value = @attributes[attr_name]).nil? + if column = column_for_attribute(attr_name) + if unserializable_attribute?(attr_name, column) + unserialize_attribute(attr_name) + else + column.type_cast(value) + end + else + value + end + else + nil + end + end + + # Returns true if the attribute is of a text column and marked for serialization. + def unserializable_attribute?(attr_name, column) + column.text? && self.class.serialized_attributes[attr_name] + end + + # Returns the unserialized object of the attribute. + def unserialize_attribute(attr_name) + unserialized_object = object_from_yaml(@attributes[attr_name]) + + if unserialized_object.is_a?(self.class.serialized_attributes[attr_name]) || unserialized_object.nil? + @attributes.frozen? ? unserialized_object : @attributes[attr_name] = unserialized_object + else + raise SerializationTypeMismatch, + "#{attr_name} was supposed to be a #{self.class.serialized_attributes[attr_name]}, but was a #{unserialized_object.class.to_s}" + end end private diff --git a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb index 4ac0c7f608..a8e3e28a7a 100644 --- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb +++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb @@ -12,20 +12,48 @@ module ActiveRecord end module ClassMethods - - def cache_attribute?(attr_name) - time_zone_aware?(attr_name) || super - end - protected + # Defined for all +datetime+ and +timestamp+ attributes when +time_zone_aware_attributes+ are enabled. + # This enhanced read method automatically converts the UTC time stored in the database to the time zone stored in Time.zone. + def define_method_attribute(attr_name) + if create_time_zone_conversion_attribute?(attr_name, columns_hash[attr_name]) + method_body = <<-EOV + def #{attr_name}(reload = false) + cached = @attributes_cache['#{attr_name}'] + return cached if cached && !reload + time = read_attribute('#{attr_name}') + @attributes_cache['#{attr_name}'] = time.acts_like?(:time) ? time.in_time_zone : time + end + EOV + generated_attribute_methods.module_eval(method_body, __FILE__, __LINE__) + else + super + end + end - def time_zone_aware?(attr_name) - column = columns_hash[attr_name] - time_zone_aware_attributes && - !skip_time_zone_conversion_for_attributes.include?(attr_name.to_sym) && - [:datetime, :timestamp].include?(column.type) + # Defined for all +datetime+ and +timestamp+ attributes when +time_zone_aware_attributes+ are enabled. + # This enhanced write method will automatically convert the time passed to it to the zone stored in Time.zone. + def define_method_attribute=(attr_name) + if create_time_zone_conversion_attribute?(attr_name, columns_hash[attr_name]) + method_body = <<-EOV + def #{attr_name}=(time) + unless time.acts_like?(:time) + time = time.is_a?(String) ? Time.zone.parse(time) : time.to_time rescue time + end + time = time.in_time_zone rescue nil if time + write_attribute(:#{attr_name}, time) + end + EOV + generated_attribute_methods.module_eval(method_body, __FILE__, __LINE__) + else + super + end end + private + def create_time_zone_conversion_attribute?(name, column) + time_zone_aware_attributes && !skip_time_zone_conversion_for_attributes.include?(name.to_sym) && [:datetime, :timestamp].include?(column.type) + end end end end diff --git a/activerecord/lib/active_record/attribute_methods/write.rb b/activerecord/lib/active_record/attribute_methods/write.rb index 37eadbe0a9..e31acac050 100644 --- a/activerecord/lib/active_record/attribute_methods/write.rb +++ b/activerecord/lib/active_record/attribute_methods/write.rb @@ -17,9 +17,14 @@ module ActiveRecord # Updates the attribute identified by <tt>attr_name</tt> with the specified +value+. Empty strings for fixnum and float # columns are turned into +nil+. def write_attribute(attr_name, value) - attr_name = _attributes.unalias(attr_name) + attr_name = attr_name.to_s + attr_name = self.class.primary_key if attr_name == 'id' @attributes_cache.delete(attr_name) - _attributes[attr_name] = value + if (column = column_for_attribute(attr_name)) && column.number? + @attributes[attr_name] = convert_number_column_value(value) + else + @attributes[attr_name] = value + end end private diff --git a/activerecord/lib/active_record/attributes.rb b/activerecord/lib/active_record/attributes.rb deleted file mode 100644 index e4d9e89821..0000000000 --- a/activerecord/lib/active_record/attributes.rb +++ /dev/null @@ -1,37 +0,0 @@ -module ActiveRecord - module Attributes - - # Returns true if the given attribute is in the attributes hash - def has_attribute?(attr_name) - _attributes.key?(attr_name) - end - - # Returns an array of names for the attributes available on this object sorted alphabetically. - def attribute_names - _attributes.keys.sort! - end - - # Returns a hash of all the attributes with their names as keys and the values of the attributes as values. - def attributes - attributes = _attributes.dup - attributes.typecast! unless _attributes.frozen? - attributes.to_h - end - - protected - - # Not to be confused with the public #attributes method, which returns a typecasted Hash. - def _attributes - @attributes - end - - def initialize_attribute_store(merge_attributes = nil) - @attributes = ActiveRecord::Attributes::Store.new - @attributes.merge!(merge_attributes) if merge_attributes - @attributes.types.merge!(self.class.attribute_types) - @attributes.aliases.merge!('id' => self.class.primary_key) unless 'id' == self.class.primary_key - @attributes - end - - end -end diff --git a/activerecord/lib/active_record/attributes/aliasing.rb b/activerecord/lib/active_record/attributes/aliasing.rb deleted file mode 100644 index db77739d1f..0000000000 --- a/activerecord/lib/active_record/attributes/aliasing.rb +++ /dev/null @@ -1,42 +0,0 @@ -module ActiveRecord - module Attributes - module Aliasing - # Allows access to keys using aliased names. - # - # Example: - # class Attributes < Hash - # include Aliasing - # end - # - # attributes = Attributes.new - # attributes.aliases['id'] = 'fancy_primary_key' - # attributes['fancy_primary_key'] = 2020 - # - # attributes['id'] - # => 2020 - # - # Additionally, symbols are always aliases of strings: - # attributes[:fancy_primary_key] - # => 2020 - # - def [](key) - super(unalias(key)) - end - - def []=(key, value) - super(unalias(key), value) - end - - def aliases - @aliases ||= {} - end - - def unalias(key) - key = key.to_s - aliases[key] || key - end - - end - end -end - diff --git a/activerecord/lib/active_record/attributes/store.rb b/activerecord/lib/active_record/attributes/store.rb deleted file mode 100644 index 61109f4acc..0000000000 --- a/activerecord/lib/active_record/attributes/store.rb +++ /dev/null @@ -1,15 +0,0 @@ -module ActiveRecord - module Attributes - class Store < Hash - include ActiveRecord::Attributes::Typecasting - include ActiveRecord::Attributes::Aliasing - - # Attributes not mapped to a column are handled using Type::Unknown, - # which enables boolean typecasting for unmapped keys. - def types - @types ||= Hash.new(Type::Unknown.new) - end - - end - end -end diff --git a/activerecord/lib/active_record/attributes/typecasting.rb b/activerecord/lib/active_record/attributes/typecasting.rb deleted file mode 100644 index 56c32f9895..0000000000 --- a/activerecord/lib/active_record/attributes/typecasting.rb +++ /dev/null @@ -1,117 +0,0 @@ -module ActiveRecord - module Attributes - module Typecasting - # Typecasts values during access based on their key mapping to a Type. - # - # Example: - # class Attributes < Hash - # include Typecasting - # end - # - # attributes = Attributes.new - # attributes.types['comments_count'] = Type::Integer - # attributes['comments_count'] = '5' - # - # attributes['comments_count'] - # => 5 - # - # To support keys not mapped to a typecaster, add a default to types. - # attributes.types.default = Type::Unknown - # attributes['age'] = '25' - # attributes['age'] - # => '25' - # - # A valid type supports #cast, #precast, #boolean, and #appendable? methods. - # - def [](key) - value = super(key) - typecast_read(key, value) - end - - def []=(key, value) - super(key, typecast_write(key, value)) - end - - def to_h - hash = {} - hash.merge!(self) - hash - end - - def dup # :nodoc: - copy = super - copy.types = types.dup - copy - end - - # Provides a duplicate with typecasting disabled. - # - # Example: - # attributes = Attributes.new - # attributes.types['comments_count'] = Type::Integer - # attributes['comments_count'] = '5' - # - # attributes.without_typecast['comments_count'] - # => '5' - # - def without_typecast - dup.without_typecast! - end - - def without_typecast! - types.clear - self - end - - def typecast! - keys.each { |key| self[key] = self[key] } - self - end - - # Check if key has a value that typecasts to true. - # - # attributes = Attributes.new - # attributes.types['comments_count'] = Type::Integer - # - # attributes['comments_count'] = 0 - # attributes.has?('comments_count') - # => false - # - # attributes['comments_count'] = 1 - # attributes.has?('comments_count') - # => true - # - def has?(key) - value = self[key] - boolean_typecast(key, value) - end - - def types - @types ||= {} - end - - protected - - def types=(other_types) - @types = other_types - end - - def boolean_typecast(key, value) - value ? types[key].boolean(value) : false - end - - def typecast_read(key, value) - type = types[key] - value = type.cast(value) - self[key] = value if type.appendable? && !frozen? - - value - end - - def typecast_write(key, value) - types[key].precast(value) - end - - end - end -end diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index bc1b0bde31..12feef4849 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -1200,7 +1200,7 @@ module ActiveRecord #:nodoc: def instantiate(record) object = find_sti_class(record[inheritance_column]).allocate - object.send(:initialize_attribute_store, record) + object.instance_variable_set(:'@attributes', record) object.instance_variable_set(:'@attributes_cache', {}) object.send(:_run_find_callbacks) @@ -1236,7 +1236,7 @@ module ActiveRecord #:nodoc: end def construct_finder_arel(options = {}, scope = nil) - relation = unscoped.apply_finder_options(options) + relation = options.is_a?(Hash) ? unscoped.apply_finder_options(options) : unscoped.merge(options) relation = scope.merge(relation) if scope relation end @@ -1450,7 +1450,8 @@ module ActiveRecord #:nodoc: end def scoped_methods #:nodoc: - Thread.current[:"#{self}_scoped_methods"] ||= self.default_scoping.dup + key = :"#{self}_scoped_methods" + Thread.current[key] = Thread.current[key].presence || self.default_scoping.dup end def current_scoped_methods #:nodoc: @@ -1663,7 +1664,7 @@ module ActiveRecord #:nodoc: # In both instances, valid attribute keys are determined by the column names of the associated table -- # hence you can't have attributes that aren't part of the table columns. def initialize(attributes = nil) - initialize_attribute_store(attributes_from_column_definition) + @attributes = attributes_from_column_definition @attributes_cache = {} @new_record = true ensure_proper_type @@ -1694,7 +1695,7 @@ module ActiveRecord #:nodoc: callback(:after_initialize) if respond_to_without_attributes?(:after_initialize) cloned_attributes = other.clone_attributes(:read_attribute_before_type_cast) cloned_attributes.delete(self.class.primary_key) - initialize_attribute_store(cloned_attributes) + @attributes = cloned_attributes clear_aggregation_cache @attributes_cache = {} @new_record = true @@ -1924,11 +1925,21 @@ module ActiveRecord #:nodoc: def reload(options = nil) clear_aggregation_cache clear_association_cache - _attributes.update(self.class.find(self.id, options).instance_variable_get('@attributes')) + @attributes.update(self.class.find(self.id, options).instance_variable_get('@attributes')) @attributes_cache = {} self end + # Returns true if the given attribute is in the attributes hash + def has_attribute?(attr_name) + @attributes.has_key?(attr_name.to_s) + end + + # Returns an array of names for the attributes available on this object sorted alphabetically. + def attribute_names + @attributes.keys.sort + end + # Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example, # "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)). # (Alias for the protected read_attribute method). @@ -2262,7 +2273,7 @@ module ActiveRecord #:nodoc: end def instantiate_time_object(name, values) - if self.class.send(:time_zone_aware?, name) + if self.class.send(:create_time_zone_conversion_attribute?, name, column_for_attribute(name)) Time.zone.local(*values) else Time.time_with_datetime_fallback(@@default_timezone, *values) @@ -2345,6 +2356,22 @@ module ActiveRecord #:nodoc: comma_pair_list(quote_columns(quoter, hash)) end + def convert_number_column_value(value) + if value == false + 0 + elsif value == true + 1 + elsif value.is_a?(String) && value.blank? + nil + else + value + end + end + + def object_from_yaml(string) + return string unless string.is_a?(String) && string =~ /^---/ + YAML::load(string) rescue string + end end Base.class_eval do @@ -2359,7 +2386,6 @@ module ActiveRecord #:nodoc: include AttributeMethods::PrimaryKey include AttributeMethods::TimeZoneConversion include AttributeMethods::Dirty - include Attributes, Types include Callbacks, ActiveModel::Observing, Timestamp include Associations, AssociationPreload, NamedScope include ActiveModel::Conversion diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 04b85119cb..1a96cdad17 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -32,7 +32,7 @@ module ActiveRecord end def respond_to?(method, include_private = false) - return true if arel.respond_to?(method, include_private) || Array.method_defined?(method) + return true if arel.respond_to?(method, include_private) || Array.method_defined?(method) || @klass.respond_to?(method, include_private) if match = DynamicFinderMatch.match(method) return true if @klass.send(:all_attributes_exists?, match.attribute_names) @@ -301,6 +301,8 @@ module ActiveRecord def method_missing(method, *args, &block) if Array.method_defined?(method) to_a.send(method, *args, &block) + elsif @klass.respond_to?(method) + @klass.send(:with_scope, self) { @klass.send(method, *args, &block) } elsif arel.respond_to?(method) arel.send(method, *args, &block) elsif match = DynamicFinderMatch.match(method) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index ce3e4e8eed..8954f2d12b 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -8,11 +8,10 @@ module ActiveRecord class_eval <<-CEVAL def #{query_method}(*args) - spawn.tap do |new_relation| - new_relation.#{query_method}_values ||= [] - value = Array.wrap(args.flatten).reject {|x| x.blank? } - new_relation.#{query_method}_values += value if value.present? - end + new_relation = spawn + value = Array.wrap(args.flatten).reject {|x| x.blank? } + new_relation.#{query_method}_values += value if value.present? + new_relation end CEVAL end @@ -20,11 +19,10 @@ module ActiveRecord [:where, :having].each do |query_method| class_eval <<-CEVAL def #{query_method}(*args) - spawn.tap do |new_relation| - new_relation.#{query_method}_values ||= [] - value = build_where(*args) - new_relation.#{query_method}_values += [*value] if value.present? - end + new_relation = spawn + value = build_where(*args) + new_relation.#{query_method}_values += [*value] if value.present? + new_relation end CEVAL end @@ -34,9 +32,9 @@ module ActiveRecord class_eval <<-CEVAL def #{query_method}(value = true) - spawn.tap do |new_relation| - new_relation.#{query_method}_value = value - end + new_relation = spawn + new_relation.#{query_method}_value = value + new_relation end CEVAL end diff --git a/activerecord/lib/active_record/types.rb b/activerecord/lib/active_record/types.rb deleted file mode 100644 index 74f569352b..0000000000 --- a/activerecord/lib/active_record/types.rb +++ /dev/null @@ -1,38 +0,0 @@ -module ActiveRecord - module Types - extend ActiveSupport::Concern - - module ClassMethods - - def attribute_types - attribute_types = {} - columns.each do |column| - options = {} - options[:time_zone_aware] = time_zone_aware?(column.name) - options[:serialize] = serialized_attributes[column.name] - - attribute_types[column.name] = to_type(column, options) - end - attribute_types - end - - private - - def to_type(column, options = {}) - type_class = if options[:time_zone_aware] - Type::TimeWithZone - elsif options[:serialize] - Type::Serialize - elsif [ :integer, :float, :decimal ].include?(column.type) - Type::Number - else - Type::Object - end - - type_class.new(column, options) - end - - end - - end -end diff --git a/activerecord/lib/active_record/types/number.rb b/activerecord/lib/active_record/types/number.rb deleted file mode 100644 index cfbe877575..0000000000 --- a/activerecord/lib/active_record/types/number.rb +++ /dev/null @@ -1,30 +0,0 @@ -module ActiveRecord - module Type - class Number < Object - - def boolean(value) - value = cast(value) - !(value.nil? || value.zero?) - end - - def precast(value) - convert_number_column_value(value) - end - - private - - def convert_number_column_value(value) - if value == false - 0 - elsif value == true - 1 - elsif value.is_a?(String) && value.blank? - nil - else - value - end - end - - end - end -end
\ No newline at end of file diff --git a/activerecord/lib/active_record/types/object.rb b/activerecord/lib/active_record/types/object.rb deleted file mode 100644 index ec3f861abd..0000000000 --- a/activerecord/lib/active_record/types/object.rb +++ /dev/null @@ -1,37 +0,0 @@ -module ActiveRecord - module Type - module Casting - - def cast(value) - typecaster.type_cast(value) - end - - def precast(value) - value - end - - def boolean(value) - cast(value).present? - end - - # Attributes::Typecasting stores appendable? types (e.g. serialized Arrays) when typecasting reads. - def appendable? - false - end - - end - - class Object - include Casting - - attr_reader :name, :options - attr_reader :typecaster - - def initialize(typecaster = nil, options = {}) - @typecaster, @options = typecaster, options - end - - end - - end -end
\ No newline at end of file diff --git a/activerecord/lib/active_record/types/serialize.rb b/activerecord/lib/active_record/types/serialize.rb deleted file mode 100644 index 7b6af1981f..0000000000 --- a/activerecord/lib/active_record/types/serialize.rb +++ /dev/null @@ -1,33 +0,0 @@ -module ActiveRecord - module Type - class Serialize < Object - - def cast(value) - unserialize(value) - end - - def appendable? - true - end - - protected - - def unserialize(value) - unserialized_object = object_from_yaml(value) - - if unserialized_object.is_a?(@options[:serialize]) || unserialized_object.nil? - unserialized_object - else - raise SerializationTypeMismatch, - "#{name} was supposed to be a #{@options[:serialize]}, but was a #{unserialized_object.class.to_s}" - end - end - - def object_from_yaml(string) - return string unless string.is_a?(String) && string =~ /^---/ - YAML::load(string) rescue string - end - - end - end -end
\ No newline at end of file diff --git a/activerecord/lib/active_record/types/time_with_zone.rb b/activerecord/lib/active_record/types/time_with_zone.rb deleted file mode 100644 index 3a8b9292f9..0000000000 --- a/activerecord/lib/active_record/types/time_with_zone.rb +++ /dev/null @@ -1,20 +0,0 @@ -module ActiveRecord - module Type - class TimeWithZone < Object - - def cast(time) - time = super(time) - time.acts_like?(:time) ? time.in_time_zone : time - end - - def precast(time) - unless time.acts_like?(:time) - time = time.is_a?(String) ? ::Time.zone.parse(time) : time.to_time rescue time - end - time = time.in_time_zone rescue nil if time - super(time) - end - - end - end -end diff --git a/activerecord/lib/active_record/types/unknown.rb b/activerecord/lib/active_record/types/unknown.rb deleted file mode 100644 index f832c7b304..0000000000 --- a/activerecord/lib/active_record/types/unknown.rb +++ /dev/null @@ -1,37 +0,0 @@ -module ActiveRecord - module Type - # Useful for handling attributes not mapped to types. Performs some boolean typecasting, - # but otherwise leaves the value untouched. - class Unknown - - def cast(value) - value - end - - def precast(value) - value - end - - # Attempts typecasting to handle numeric, false and blank values. - def boolean(value) - empty = (numeric?(value) && value.to_i.zero?) || false?(value) || value.blank? - !empty - end - - def appendable? - false - end - - protected - - def false?(value) - ActiveRecord::ConnectionAdapters::Column::FALSE_VALUES.include?(value) - end - - def numeric?(value) - Numeric === value || value !~ /[^0-9]/ - end - - end - end -end
\ No newline at end of file diff --git a/activerecord/test/cases/attributes/aliasing_test.rb b/activerecord/test/cases/attributes/aliasing_test.rb deleted file mode 100644 index 7ee25779f1..0000000000 --- a/activerecord/test/cases/attributes/aliasing_test.rb +++ /dev/null @@ -1,20 +0,0 @@ -require "cases/helper" - -class AliasingTest < ActiveRecord::TestCase - - class AliasingAttributes < Hash - include ActiveRecord::Attributes::Aliasing - end - - test "attribute access with aliasing" do - attributes = AliasingAttributes.new - attributes[:name] = 'Batman' - attributes.aliases['nickname'] = 'name' - - assert_equal 'Batman', attributes[:name], "Symbols should point to Strings" - assert_equal 'Batman', attributes['name'] - assert_equal 'Batman', attributes['nickname'] - assert_equal 'Batman', attributes[:nickname] - end - -end diff --git a/activerecord/test/cases/attributes/typecasting_test.rb b/activerecord/test/cases/attributes/typecasting_test.rb deleted file mode 100644 index 8a3b551375..0000000000 --- a/activerecord/test/cases/attributes/typecasting_test.rb +++ /dev/null @@ -1,120 +0,0 @@ -require "cases/helper" - -class TypecastingTest < ActiveRecord::TestCase - - class TypecastingAttributes < Hash - include ActiveRecord::Attributes::Typecasting - end - - module MockType - class Object - - def cast(value) - value - end - - def precast(value) - value - end - - def boolean(value) - !value.blank? - end - - def appendable? - false - end - - end - - class Integer < Object - - def cast(value) - value.to_i - end - - def precast(value) - value ? value : 0 - end - - def boolean(value) - !Float(value).zero? - end - - end - - class Serialize < Object - - def cast(value) - YAML::load(value) rescue value - end - - def precast(value) - value - end - - def appendable? - true - end - - end - end - - def setup - @attributes = TypecastingAttributes.new - @attributes.types.default = MockType::Object.new - @attributes.types['comments_count'] = MockType::Integer.new - end - - test "typecast on read" do - attributes = @attributes.merge('comments_count' => '5') - assert_equal 5, attributes['comments_count'] - end - - test "typecast on write" do - @attributes['comments_count'] = false - - assert_equal 0, @attributes.to_h['comments_count'] - end - - test "serialized objects" do - attributes = @attributes.merge('tags' => [ 'peanut butter' ].to_yaml) - attributes.types['tags'] = MockType::Serialize.new - attributes['tags'] << 'jelly' - - assert_equal [ 'peanut butter', 'jelly' ], attributes['tags'] - end - - test "without typecasting" do - @attributes.merge!('comments_count' => '5') - attributes = @attributes.without_typecast - - assert_equal '5', attributes['comments_count'] - assert_equal 5, @attributes['comments_count'], "Original attributes should typecast" - end - - - test "typecast all attributes" do - attributes = @attributes.merge('title' => 'I love sandwiches', 'comments_count' => '5') - attributes.typecast! - - assert_equal({ 'title' => 'I love sandwiches', 'comments_count' => 5 }, attributes) - end - - test "query for has? value" do - attributes = @attributes.merge('comments_count' => '1') - - assert_equal true, attributes.has?('comments_count') - attributes['comments_count'] = '0' - assert_equal false, attributes.has?('comments_count') - end - - test "attributes to Hash" do - attributes_hash = { 'title' => 'I love sandwiches', 'comments_count' => '5' } - attributes = @attributes.merge(attributes_hash) - - assert_equal Hash, attributes.to_h.class - assert_equal attributes_hash, attributes.to_h - end - -end diff --git a/activerecord/test/cases/method_scoping_test.rb b/activerecord/test/cases/method_scoping_test.rb index fbd1adf088..1081aa40a9 100644 --- a/activerecord/test/cases/method_scoping_test.rb +++ b/activerecord/test/cases/method_scoping_test.rb @@ -588,7 +588,7 @@ class HasAndBelongsToManyScopingTest< ActiveRecord::TestCase end class DefaultScopingTest < ActiveRecord::TestCase - fixtures :developers + fixtures :developers, :posts def test_default_scope expected = Developer.find(:all, :order => 'salary DESC').collect { |dev| dev.salary } @@ -657,6 +657,12 @@ class DefaultScopingTest < ActiveRecord::TestCase received = DeveloperOrderedBySalary.find(:all, :order => 'salary').collect { |dev| dev.salary } assert_equal expected, received end + + def test_default_scope_using_relation + posts = PostWithComment.scoped + assert_equal 2, posts.count + assert_equal posts(:thinking), posts.first + end end =begin diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb index 2c34ab787d..894d96346e 100644 --- a/activerecord/test/cases/named_scope_test.rb +++ b/activerecord/test/cases/named_scope_test.rb @@ -380,6 +380,15 @@ class NamedScopeTest < ActiveRecord::TestCase assert_deprecated('named_scope has been deprecated') { Topic.named_scope :deprecated_named_scope } end + def test_named_scopes_on_relations + # Topic.replied + approved_topics = Topic.scoped.approved.order('id DESC') + assert_equal topics(:fourth), approved_topics.first + + replied_approved_topics = approved_topics.replied + assert_equal topics(:third), replied_approved_topics.first + end + def test_index_on_named_scope approved = Topic.approved.order('id ASC') assert_equal topics(:second), approved[0] diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index d34c9b4895..1e345399f5 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -164,6 +164,11 @@ class RelationTest < ActiveRecord::TestCase end end + def test_respond_to_class_methods_and_named_scopes + assert DeveloperOrderedBySalary.scoped.respond_to?(:all_ordered_by_name) + assert Topic.scoped.respond_to?(:by_lifo) + end + def test_find_with_readonly_option Developer.scoped.each { |d| assert !d.readonly? } Developer.scoped.readonly.each { |d| assert d.readonly? } diff --git a/activerecord/test/cases/types/number_test.rb b/activerecord/test/cases/types/number_test.rb deleted file mode 100644 index ee7216a0f1..0000000000 --- a/activerecord/test/cases/types/number_test.rb +++ /dev/null @@ -1,30 +0,0 @@ -require "cases/helper" - -class NumberTest < ActiveRecord::TestCase - - def setup - @column = ActiveRecord::ConnectionAdapters::Column.new('comments_count', 0, 'integer') - @number = ActiveRecord::Type::Number.new(@column) - end - - test "typecast" do - assert_equal 1, @number.cast(1) - assert_equal 1, @number.cast('1') - assert_equal 0, @number.cast('') - - assert_equal 0, @number.precast(false) - assert_equal 1, @number.precast(true) - assert_equal nil, @number.precast('') - assert_equal 0, @number.precast(0) - end - - test "cast as boolean" do - assert_equal true, @number.boolean('1') - assert_equal true, @number.boolean(1) - - assert_equal false, @number.boolean(0) - assert_equal false, @number.boolean('0') - assert_equal false, @number.boolean(nil) - end - -end diff --git a/activerecord/test/cases/types/object_test.rb b/activerecord/test/cases/types/object_test.rb deleted file mode 100644 index f2667a9b00..0000000000 --- a/activerecord/test/cases/types/object_test.rb +++ /dev/null @@ -1,24 +0,0 @@ -require "cases/helper" - -class ObjectTest < ActiveRecord::TestCase - - def setup - @column = ActiveRecord::ConnectionAdapters::Column.new('name', '', 'date') - @object = ActiveRecord::Type::Object.new(@column) - end - - test "typecast with column" do - date = Date.new(2009, 7, 10) - assert_equal date, @object.cast('10-07-2009') - assert_equal nil, @object.cast('') - - assert_equal date, @object.precast(date) - end - - test "cast as boolean" do - assert_equal false, @object.boolean(nil) - assert_equal false, @object.boolean('false') - assert_equal true, @object.boolean('10-07-2009') - end - -end diff --git a/activerecord/test/cases/types/serialize_test.rb b/activerecord/test/cases/types/serialize_test.rb deleted file mode 100644 index e9423a5b9d..0000000000 --- a/activerecord/test/cases/types/serialize_test.rb +++ /dev/null @@ -1,20 +0,0 @@ -require "cases/helper" - -class SerializeTest < ActiveRecord::TestCase - - test "typecast" do - serializer = ActiveRecord::Type::Serialize.new(column = nil, :serialize => Array) - - assert_equal [], serializer.cast([].to_yaml) - assert_equal ['1'], serializer.cast(['1'].to_yaml) - assert_equal nil, serializer.cast(nil.to_yaml) - end - - test "cast as boolean" do - serializer = ActiveRecord::Type::Serialize.new(column = nil, :serialize => Array) - - assert_equal true, serializer.boolean(['1'].to_yaml) - assert_equal false, serializer.boolean([].to_yaml) - end - -end
\ No newline at end of file diff --git a/activerecord/test/cases/types/time_with_zone_test.rb b/activerecord/test/cases/types/time_with_zone_test.rb deleted file mode 100644 index b3de79a6c8..0000000000 --- a/activerecord/test/cases/types/time_with_zone_test.rb +++ /dev/null @@ -1,42 +0,0 @@ -require "cases/helper" - -class TimeWithZoneTest < ActiveRecord::TestCase - - def setup - @column = ActiveRecord::ConnectionAdapters::Column.new('created_at', 0, 'datetime') - @time_with_zone = ActiveRecord::Type::TimeWithZone.new(@column) - end - - test "typecast" do - Time.use_zone("Pacific Time (US & Canada)") do - time_string = "2009-10-07 21:29:10" - time = Time.zone.parse(time_string) - - # assert_equal time, @time_with_zone.cast(time_string) - assert_equal nil, @time_with_zone.cast('') - assert_equal nil, @time_with_zone.cast(nil) - - assert_equal time, @time_with_zone.precast(time) - assert_equal time, @time_with_zone.precast(time_string) - assert_equal time, @time_with_zone.precast(time.to_time) - # assert_equal "#{time.to_date.to_s} 00:00:00 -0700", @time_with_zone.precast(time.to_date).to_s - end - end - - test "cast as boolean" do - Time.use_zone('Central Time (US & Canada)') do - time = Time.zone.now - - assert_equal true, @time_with_zone.boolean(time) - assert_equal true, @time_with_zone.boolean(time.to_date) - assert_equal true, @time_with_zone.boolean(time.to_time) - - assert_equal true, @time_with_zone.boolean(time.to_s) - assert_equal true, @time_with_zone.boolean(time.to_date.to_s) - assert_equal true, @time_with_zone.boolean(time.to_time.to_s) - - assert_equal false, @time_with_zone.boolean('') - end - end - -end diff --git a/activerecord/test/cases/types/unknown_test.rb b/activerecord/test/cases/types/unknown_test.rb deleted file mode 100644 index 230d67b2fb..0000000000 --- a/activerecord/test/cases/types/unknown_test.rb +++ /dev/null @@ -1,29 +0,0 @@ -require "cases/helper" - -class UnknownTest < ActiveRecord::TestCase - - test "typecast attributes does't modify values" do - unkown = ActiveRecord::Type::Unknown.new - person = { 'name' => '0' } - - assert_equal person['name'], unkown.cast(person['name']) - assert_equal person['name'], unkown.precast(person['name']) - end - - test "cast as boolean" do - person = { 'id' => 0, 'name' => ' ', 'admin' => 'false', 'votes' => '0' } - unkown = ActiveRecord::Type::Unknown.new - - assert_equal false, unkown.boolean(person['votes']) - assert_equal false, unkown.boolean(person['admin']) - assert_equal false, unkown.boolean(person['name']) - assert_equal false, unkown.boolean(person['id']) - - person = { 'id' => 5, 'name' => 'Eric', 'admin' => 'true', 'votes' => '25' } - assert_equal true, unkown.boolean(person['votes']) - assert_equal true, unkown.boolean(person['admin']) - assert_equal true, unkown.boolean(person['name']) - assert_equal true, unkown.boolean(person['id']) - end - -end
\ No newline at end of file diff --git a/activerecord/test/cases/types_test.rb b/activerecord/test/cases/types_test.rb deleted file mode 100644 index 403a9a6e02..0000000000 --- a/activerecord/test/cases/types_test.rb +++ /dev/null @@ -1,32 +0,0 @@ -require "cases/helper" -require 'models/topic' - -class TypesTest < ActiveRecord::TestCase - - test "attribute types from columns" do - begin - ActiveRecord::Base.time_zone_aware_attributes = true - attribute_type_classes = {} - Topic.attribute_types.each { |key, type| attribute_type_classes[key] = type.class } - - expected = { "id" => ActiveRecord::Type::Number, - "replies_count" => ActiveRecord::Type::Number, - "parent_id" => ActiveRecord::Type::Number, - "content" => ActiveRecord::Type::Serialize, - "written_on" => ActiveRecord::Type::TimeWithZone, - "title" => ActiveRecord::Type::Object, - "author_name" => ActiveRecord::Type::Object, - "approved" => ActiveRecord::Type::Object, - "parent_title" => ActiveRecord::Type::Object, - "bonus_time" => ActiveRecord::Type::Object, - "type" => ActiveRecord::Type::Object, - "last_read" => ActiveRecord::Type::Object, - "author_email_address" => ActiveRecord::Type::Object } - - assert_equal expected, attribute_type_classes - ensure - ActiveRecord::Base.time_zone_aware_attributes = false - end - end - -end diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb index f48b35486c..704313649a 100644 --- a/activerecord/test/models/post.rb +++ b/activerecord/test/models/post.rb @@ -100,3 +100,8 @@ end class SubStiPost < StiPost self.table_name = Post.table_name end + +class PostWithComment < ActiveRecord::Base + self.table_name = 'posts' + default_scope where("posts.comments_count > 0").order("posts.comments_count ASC") +end diff --git a/railties/lib/generators/rails/app/templates/config.ru b/railties/lib/generators/rails/app/templates/config.ru index 2ab821e38d..fcfbc6b07a 100644 --- a/railties/lib/generators/rails/app/templates/config.ru +++ b/railties/lib/generators/rails/app/templates/config.ru @@ -1,4 +1,4 @@ # This file is used by Rack-based servers to start the application. require ::File.expand_path('../config/environment', __FILE__) -run <%= app_const %>.instance +run <%= app_const %> diff --git a/railties/lib/generators/rails/app/templates/config/databases/ibm_db.yml b/railties/lib/generators/rails/app/templates/config/databases/ibm_db.yml index a9716ddb44..2cecb5c879 100644 --- a/railties/lib/generators/rails/app/templates/config/databases/ibm_db.yml +++ b/railties/lib/generators/rails/app/templates/config/databases/ibm_db.yml @@ -59,4 +59,4 @@ production: #account: my_account #app_user: my_app_user #application: my_application - #workstation: my_workstation
\ No newline at end of file + #workstation: my_workstation diff --git a/railties/lib/generators/rails/app/templates/config/environments/development.rb.tt b/railties/lib/generators/rails/app/templates/config/environments/development.rb.tt index b10103b436..177ce44d41 100644 --- a/railties/lib/generators/rails/app/templates/config/environments/development.rb.tt +++ b/railties/lib/generators/rails/app/templates/config/environments/development.rb.tt @@ -16,4 +16,4 @@ # Don't care if the mailer can't send config.action_mailer.raise_delivery_errors = false -end
\ No newline at end of file +end diff --git a/railties/lib/generators/rails/app/templates/config/environments/production.rb.tt b/railties/lib/generators/rails/app/templates/config/environments/production.rb.tt index 543a40108c..ee071df63b 100644 --- a/railties/lib/generators/rails/app/templates/config/environments/production.rb.tt +++ b/railties/lib/generators/rails/app/templates/config/environments/production.rb.tt @@ -30,4 +30,4 @@ # Enable threaded mode # config.threadsafe! -end
\ No newline at end of file +end diff --git a/railties/lib/generators/rails/app/templates/config/environments/test.rb.tt b/railties/lib/generators/rails/app/templates/config/environments/test.rb.tt index 428fa35633..f6c38f3c0d 100644 --- a/railties/lib/generators/rails/app/templates/config/environments/test.rb.tt +++ b/railties/lib/generators/rails/app/templates/config/environments/test.rb.tt @@ -26,4 +26,4 @@ # This is necessary if your schema can't be completely dumped by the schema dumper, # like if you have constraints or database-specific column types # config.active_record.schema_format = :sql -end
\ No newline at end of file +end diff --git a/railties/lib/generators/rails/app/templates/config/initializers/backtrace_silencers.rb b/railties/lib/generators/rails/app/templates/config/initializers/backtrace_silencers.rb index 839d4cde19..59385cdf37 100644 --- a/railties/lib/generators/rails/app/templates/config/initializers/backtrace_silencers.rb +++ b/railties/lib/generators/rails/app/templates/config/initializers/backtrace_silencers.rb @@ -4,4 +4,4 @@ # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. -# Rails.backtrace_cleaner.remove_silencers!
\ No newline at end of file +# Rails.backtrace_cleaner.remove_silencers! diff --git a/railties/lib/generators/rails/app/templates/config/locales/en.yml b/railties/lib/generators/rails/app/templates/config/locales/en.yml index f265c068d8..a747bfa698 100644 --- a/railties/lib/generators/rails/app/templates/config/locales/en.yml +++ b/railties/lib/generators/rails/app/templates/config/locales/en.yml @@ -2,4 +2,4 @@ # See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points. en: - hello: "Hello world"
\ No newline at end of file + hello: "Hello world" diff --git a/railties/lib/generators/rails/app/templates/db/seeds.rb b/railties/lib/generators/rails/app/templates/db/seeds.rb index bc8695e6f0..664d8c74c8 100644 --- a/railties/lib/generators/rails/app/templates/db/seeds.rb +++ b/railties/lib/generators/rails/app/templates/db/seeds.rb @@ -2,6 +2,6 @@ # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). # # Examples: -# +# # cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }]) # Mayor.create(:name => 'Daley', :city => cities.first) diff --git a/railties/lib/generators/rails/app/templates/script/console.tt b/railties/lib/generators/rails/app/templates/script/console.tt index daba8ba2f1..915c5b8294 100755 --- a/railties/lib/generators/rails/app/templates/script/console.tt +++ b/railties/lib/generators/rails/app/templates/script/console.tt @@ -2,4 +2,4 @@ require File.expand_path('../../config/boot', __FILE__) require 'rails/commands/console' require File.expand_path('../../config/application', __FILE__) -Rails::Console.start(<%= app_const %>.instance) +Rails::Console.start(<%= app_const %>) diff --git a/railties/lib/generators/rails/app/templates/script/dbconsole.tt b/railties/lib/generators/rails/app/templates/script/dbconsole.tt index a7f114a97f..a92f6f2844 100755 --- a/railties/lib/generators/rails/app/templates/script/dbconsole.tt +++ b/railties/lib/generators/rails/app/templates/script/dbconsole.tt @@ -2,4 +2,4 @@ require File.expand_path('../../config/boot', __FILE__) require 'rails/commands/dbconsole' require File.expand_path('../../config/application', __FILE__) -Rails::DBConsole.start(<%= app_const %>.instance) +Rails::DBConsole.start(<%= app_const %>) diff --git a/railties/lib/generators/rails/metal/templates/metal.rb b/railties/lib/generators/rails/metal/templates/metal.rb index e94982b69a..2f5d4e7593 100644 --- a/railties/lib/generators/rails/metal/templates/metal.rb +++ b/railties/lib/generators/rails/metal/templates/metal.rb @@ -1,12 +1,12 @@ # Allow the metal piece to run in isolation -require(File.dirname(__FILE__) + "/../../config/environment") unless defined?(Rails) +require File.expand_path('../../../config/environment', __FILE__) class <%= class_name %> def self.call(env) if env["PATH_INFO"] =~ /^\/<%= file_name %>/ [200, {"Content-Type" => "text/html"}, ["Hello, World!"]] else - [404, {"Content-Type" => "text/html"}, ["Not Found"]] + [404, {"Content-Type" => "text/html", "X-Cascade" => "pass"}, ["Not Found"]] end end end diff --git a/railties/lib/generators/rails/plugin/templates/Rakefile.tt b/railties/lib/generators/rails/plugin/templates/Rakefile.tt index 23c2245a41..e94c0bfc77 100644 --- a/railties/lib/generators/rails/plugin/templates/Rakefile.tt +++ b/railties/lib/generators/rails/plugin/templates/Rakefile.tt @@ -1,22 +1,10 @@ -require 'rake' require 'rake/testtask' -require 'rake/rdoctask' desc 'Default: run unit tests.' task :default => :test desc 'Test the <%= file_name %> plugin.' Rake::TestTask.new(:test) do |t| - t.libs << 'lib' t.libs << 'test' t.pattern = 'test/**/*_test.rb' end - -desc 'Generate documentation for the <%= file_name %> plugin.' -Rake::RDocTask.new(:rdoc) do |rdoc| - rdoc.rdoc_dir = 'rdoc' - rdoc.title = '<%= class_name %>' - rdoc.options << '--line-numbers' << '--inline-source' - rdoc.rdoc_files.include('README') - rdoc.rdoc_files.include('lib/**/*.rb') -end diff --git a/railties/lib/generators/rails/stylesheets/templates/scaffold.css b/railties/lib/generators/rails/stylesheets/templates/scaffold.css index d9fa2cf2dc..de6669ad9e 100644 --- a/railties/lib/generators/rails/stylesheets/templates/scaffold.css +++ b/railties/lib/generators/rails/stylesheets/templates/scaffold.css @@ -59,4 +59,3 @@ div.field, div.actions { font-size: 12px; list-style: square; } - diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb index 8c4247e840..31696598ce 100644 --- a/railties/test/application/middleware_test.rb +++ b/railties/test/application/middleware_test.rb @@ -76,7 +76,7 @@ module ApplicationTests end def middleware - AppTemplate::Application.instance.middleware.active.map(&:klass).map(&:name) + AppTemplate::Application.middleware.active.map(&:klass).map(&:name) end end end diff --git a/railties/test/generators/plugin_generator_test.rb b/railties/test/generators/plugin_generator_test.rb index 4bfe210efb..0a79e2cfb8 100644 --- a/railties/test/generators/plugin_generator_test.rb +++ b/railties/test/generators/plugin_generator_test.rb @@ -17,11 +17,11 @@ class PluginGeneratorTest < Rails::Generators::TestCase vendor/plugins/plugin_fu/uninstall.rb vendor/plugins/plugin_fu/lib vendor/plugins/plugin_fu/lib/plugin_fu.rb + vendor/plugins/plugin_fu/Rakefile ).each{ |path| assert_file path } %w( vendor/plugins/plugin_fu/README - vendor/plugins/plugin_fu/Rakefile ).each{ |path| assert_file path, /PluginFu/ } %w( |