Permalink
Browse files

Merge branch 'master' of github.com:rails/rails

  • Loading branch information...
2 parents 028911a + 1ac5cf4 commit a49c3b03650b3193cc9440a3b219ab7f19326297 @jeremy jeremy committed Oct 19, 2009
Showing with 988 additions and 1,432 deletions.
  1. +23 −21 actionmailer/test/url_test.rb
  2. +103 −190 actionpack/test/controller/routing_test.rb
  3. +5 −5 actionpack/test/controller/url_rewriter_test.rb
  4. +16 −0 activerecord/lib/active_record.rb
  5. +3 −10 activerecord/lib/active_record/attribute_methods/before_type_cast.rb
  6. +3 −17 activerecord/lib/active_record/attribute_methods/query.rb
  7. +4 −45 activerecord/lib/active_record/attribute_methods/read.rb
  8. +10 −38 activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
  9. +2 −7 activerecord/lib/active_record/attribute_methods/write.rb
  10. +37 −0 activerecord/lib/active_record/attributes.rb
  11. +42 −0 activerecord/lib/active_record/attributes/aliasing.rb
  12. +15 −0 activerecord/lib/active_record/attributes/store.rb
  13. +117 −0 activerecord/lib/active_record/attributes/typecasting.rb
  14. +7 −31 activerecord/lib/active_record/base.rb
  15. +38 −0 activerecord/lib/active_record/types.rb
  16. +30 −0 activerecord/lib/active_record/types/number.rb
  17. +37 −0 activerecord/lib/active_record/types/object.rb
  18. +33 −0 activerecord/lib/active_record/types/serialize.rb
  19. +20 −0 activerecord/lib/active_record/types/time_with_zone.rb
  20. +37 −0 activerecord/lib/active_record/types/unknown.rb
  21. +20 −0 activerecord/test/cases/attributes/aliasing_test.rb
  22. +120 −0 activerecord/test/cases/attributes/typecasting_test.rb
  23. +30 −0 activerecord/test/cases/types/number_test.rb
  24. +24 −0 activerecord/test/cases/types/object_test.rb
  25. +20 −0 activerecord/test/cases/types/serialize_test.rb
  26. +42 −0 activerecord/test/cases/types/time_with_zone_test.rb
  27. +29 −0 activerecord/test/cases/types/unknown_test.rb
  28. +32 −0 activerecord/test/cases/types_test.rb
  29. +5 −76 railties/lib/rails/application.rb
  30. +0 −4 railties/lib/rails/backtrace_cleaner.rb
  31. +1 −20 railties/lib/rails/configuration.rb
  32. +9 −1 railties/lib/rails/deprecation.rb
  33. +0 −21 railties/lib/rails/gem_builder.rb
  34. +0 −311 railties/lib/rails/gem_dependency.rb
  35. +0 −2 railties/lib/rails/generators.rb
  36. +1 −1 railties/lib/rails/generators/rails/app/app_generator.rb
  37. +14 −3 railties/lib/rails/generators/rails/app/templates/Gemfile
  38. +1 −1 railties/lib/rails/generators/rails/app/templates/Rakefile
  39. +1 −8 railties/lib/rails/generators/rails/app/templates/config/application.rb
  40. +16 −136 railties/lib/rails/generators/rails/app/templates/config/boot.rb
  41. +1 −5 railties/lib/rails/generators/rails/app/templates/config/environment.rb
  42. +0 −1 railties/lib/rails/initializer.rb
  43. +1 −1 railties/lib/rails/plugin/locator.rb
  44. +0 −1 railties/lib/rails/tasks.rb
  45. +0 −5 railties/lib/rails/tasks/framework.rake
  46. +0 −78 railties/lib/rails/tasks/gems.rake
  47. +2 −3 railties/lib/rails/tasks/statistics.rake
  48. +0 −140 railties/lib/rails/vendor_gem_source_index.rb
  49. +0 −1 railties/test/application/configuration_test.rb
  50. +1 −0 railties/test/application/generators_test.rb
  51. +1 −0 railties/test/application/initializer_test.rb
  52. +1 −1 railties/test/application/notifications_test.rb
  53. +1 −0 railties/test/application/plugins_test.rb
  54. +1 −7 railties/test/backtrace_cleaner_test.rb
  55. +0 −220 railties/test/gem_dependency_test.rb
  56. +1 −1 railties/test/generators/actions_test.rb
  57. +2 −2 railties/test/generators/app_generator_test.rb
  58. +5 −4 railties/test/generators_test.rb
  59. +1 −0 railties/test/initializer/check_ruby_version_test.rb
  60. +1 −0 railties/test/initializer/initialize_i18n_test.rb
  61. +1 −0 railties/test/initializer/path_test.rb
  62. +13 −10 railties/test/isolation/abstract_unit.rb
  63. +8 −4 railties/test/rails_info_controller_test.rb
@@ -1,9 +1,9 @@
require 'abstract_unit'
class TestMailer < ActionMailer::Base
-
+
default_url_options[:host] = 'www.basecamphq.com'
-
+
def signed_up_with_url(recipient)
@recipients = recipient
@subject = "[Signed up] Welcome #{recipient}"
@@ -52,25 +52,27 @@ def teardown
end
def test_signed_up_with_url
- ActionController::Routing::Routes.draw do |map|
- map.connect ':controller/:action/:id'
- map.welcome 'welcome', :controller=>"foo", :action=>"bar"
- end
+ ActionController::Routing.use_controllers! ['welcome'] do
+ ActionController::Routing::Routes.draw do |map|
+ map.connect ':controller/:action/:id'
+ map.welcome 'welcome', :controller=>"foo", :action=>"bar"
+ end
- expected = new_mail
- expected.to = @recipient
- expected.subject = "[Signed up] Welcome #{@recipient}"
- expected.body = "Hello there, \n\nMr. #{@recipient}. Please see our greeting at http://example.com/welcome/greeting http://www.basecamphq.com/welcome\n\n<img alt=\"Somelogo\" src=\"/images/somelogo.png\" />"
- expected.from = "system@loudthinking.com"
- expected.date = Time.local(2004, 12, 12)
-
- created = nil
- assert_nothing_raised { created = TestMailer.create_signed_up_with_url(@recipient) }
- assert_not_nil created
- assert_equal expected.encoded, created.encoded
-
- assert_nothing_raised { TestMailer.deliver_signed_up_with_url(@recipient) }
- assert_not_nil ActionMailer::Base.deliveries.first
- assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded
+ expected = new_mail
+ expected.to = @recipient
+ expected.subject = "[Signed up] Welcome #{@recipient}"
+ expected.body = "Hello there, \n\nMr. #{@recipient}. Please see our greeting at http://example.com/welcome/greeting http://www.basecamphq.com/welcome\n\n<img alt=\"Somelogo\" src=\"/images/somelogo.png\" />"
+ expected.from = "system@loudthinking.com"
+ expected.date = Time.local(2004, 12, 12)
+
+ created = nil
+ assert_nothing_raised { created = TestMailer.create_signed_up_with_url(@recipient) }
+ assert_not_nil created
+ assert_equal expected.encoded, created.encoded
+
+ assert_nothing_raised { TestMailer.deliver_signed_up_with_url(@recipient) }
+ assert_not_nil ActionMailer::Base.deliveries.first
+ assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded
+ end
end
end

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -321,8 +321,8 @@ def test_hash_recursive_and_array_parameters
params = extract_params(url)
assert_equal params[0], { 'query[hobby]' => 'piercing' }.to_query
assert_equal params[1], { 'query[person][name]' => 'Bob' }.to_query
- assert_equal params[2], { 'query[person][position][]' => 'prof' }.to_query
- assert_equal params[3], { 'query[person][position][]' => 'art director' }.to_query
+ assert_equal params[2], { 'query[person][position][]' => 'art director' }.to_query
+ assert_equal params[3], { 'query[person][position][]' => 'prof' }.to_query
end
def test_path_generation_for_symbol_parameter_keys
@@ -359,10 +359,10 @@ def test_formatted_url_methods_are_deprecated
controller = kls.new
params = {:id => 1, :format => :xml}
assert_deprecated do
- assert_equal("/posts/1.xml", controller.send(:formatted_post_path, params))
+ assert_equal("/posts/1.xml", controller.send(:formatted_post_path, params))
end
assert_deprecated do
- assert_equal("/posts/1.xml", controller.send(:formatted_post_path, 1, :xml))
+ assert_equal("/posts/1.xml", controller.send(:formatted_post_path, 1, :xml))
end
end
end
@@ -382,6 +382,6 @@ def test_multiple_includes_maintain_distinct_options
private
def extract_params(url)
- url.split('?', 2).last.split('&')
+ url.split('?', 2).last.split('&').sort
end
end
@@ -51,6 +51,7 @@ def self.load_all!
autoload :AssociationPreload, 'active_record/association_preload'
autoload :Associations, 'active_record/associations'
autoload :AttributeMethods, 'active_record/attribute_methods'
+ autoload :Attributes, 'active_record/attributes'
autoload :AutosaveAssociation, 'active_record/autosave_association'
autoload :Relation, 'active_record/relation'
autoload :Base, 'active_record/base'
@@ -74,6 +75,7 @@ def self.load_all!
autoload :TestCase, 'active_record/test_case'
autoload :Timestamp, 'active_record/timestamp'
autoload :Transactions, 'active_record/transactions'
+ autoload :Types, 'active_record/types'
autoload :Validator, 'active_record/validator'
autoload :Validations, 'active_record/validations'
@@ -87,6 +89,20 @@ module AttributeMethods
autoload :Write, 'active_record/attribute_methods/write'
end
+ module Attributes
+ autoload :Aliasing, 'active_record/attributes/aliasing'
+ autoload :Store, 'active_record/attributes/store'
+ autoload :Typecasting, 'active_record/attributes/typecasting'
+ end
+
+ module Type
+ 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
+
module Locking
autoload :Optimistic, 'active_record/locking/optimistic'
autoload :Pessimistic, 'active_record/locking/pessimistic'
@@ -8,25 +8,18 @@ module BeforeTypeCast
end
def read_attribute_before_type_cast(attr_name)
- @attributes[attr_name]
+ _attributes.without_typecast[attr_name]
end
# Returns a hash of attributes before typecasting and deserialization.
def attributes_before_type_cast
- self.attribute_names.inject({}) do |attrs, name|
- attrs[name] = read_attribute_before_type_cast(name)
- attrs
- end
+ _attributes.without_typecast
end
private
# Handle *_before_type_cast for method_missing.
def 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
+ read_attribute_before_type_cast(attribute_name)
end
end
end
@@ -8,23 +8,7 @@ module Query
end
def query_attribute(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
+ _attributes.has?(attr_name)
end
private
@@ -35,3 +19,5 @@ def attribute?(attribute_name)
end
end
end
+
+
@@ -37,30 +37,20 @@ def cache_attribute?(attr_name)
protected
def define_method_attribute(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
+ define_read_method(attr_name.to_sym, attr_name, columns_hash[attr_name])
if attr_name == primary_key && attr_name != "id"
define_read_method(:id, attr_name, columns_hash[attr_name])
end
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)
- cast_code = column.type_cast_code('v') if column
- access_code = cast_code ? "(v=@attributes['#{attr_name}']) && #{cast_code}" : "@attributes['#{attr_name}']"
-
+ access_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.has_key?('#{attr_name}'); ")
+ access_code = access_code.insert(0, "missing_attribute('#{attr_name}', caller) unless _attributes.key?('#{attr_name}'); ")
end
if cache_attribute?(attr_name)
@@ -73,38 +63,7 @@ def define_read_method(symbol, attr_name, column)
# 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)
- 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
+ _attributes[attr_name]
end
private
@@ -12,48 +12,20 @@ module TimeZoneConversion
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
- # 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
+ 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)
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
@@ -17,14 +17,9 @@ def define_method_attribute=(attr_name)
# 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 = attr_name.to_s
- attr_name = self.class.primary_key if attr_name == 'id'
+ attr_name = _attributes.unalias(attr_name)
@attributes_cache.delete(attr_name)
- if (column = column_for_attribute(attr_name)) && column.number?
- @attributes[attr_name] = convert_number_column_value(value)
- else
- @attributes[attr_name] = value
- end
+ _attributes[attr_name] = value
end
private
@@ -0,0 +1,37 @@
+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
Oops, something went wrong.

0 comments on commit a49c3b0

Please sign in to comment.