aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Lopez <seniorlopez@gmail.com>2010-08-02 13:30:08 -0700
committerBrian Lopez <seniorlopez@gmail.com>2010-08-02 13:30:08 -0700
commit954de9940b8f212cafdb9f5e97abc83d27b3e4ff (patch)
tree2cc9e60c1967cc217d55dcb187c4bcfc24c44cd5
parent2353e826b0446917eb655b60c47533f5a9c2a07f (diff)
parent88b5f938cf7d3eb26ad204451a4dbb9c2cf4f571 (diff)
downloadrails-954de9940b8f212cafdb9f5e97abc83d27b3e4ff.tar.gz
rails-954de9940b8f212cafdb9f5e97abc83d27b3e4ff.tar.bz2
rails-954de9940b8f212cafdb9f5e97abc83d27b3e4ff.zip
Merge branch 'master' into mysql2
* master: Bring returning back to ease migration. Remove duplicated logic. Eager loading an association should not change the count of children fix loading of different elements in array then int and string [#5036 state:resolved] Tidy up previous commit. test and fix collection_singular_ids= with string primary keys [#5125 state:resolved] Handle edge cases in the previous patch. Improved how AppGenerator generates the application name. It now detects the current app name whenever possible. This means that renaming the residing directory will not effect the app name generated by AppGenerator. ActiveModel::Errors json serialization to work as Rails 3b4 [#5254 state:resolved] Add missing require in ActiveSupport::HashWithIndifferentAccess [#5189 state:resolved] Add an internal (private API) after_touch callback. [#5271 state:resolved] added failing touch propagation test Makes rails destroy scaffold don't duplicate routes.draw do |map| |map| when using the deprecated syntax Failing test to check for route file corruption if legacy map parameter is used. [#5263 state:open] Corrected the rake test:units and test:functionals description [#5251 state:committed] Use AS::OrderedHash when trusting in the order of the hash Fix label form helper to use I18n and html options, without the need of 'nil' text param:
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb7
-rw-r--r--actionpack/test/controller/test_test.rb5
-rw-r--r--actionpack/test/template/form_helper_test.rb11
-rw-r--r--activemodel/lib/active_model/errors.rb4
-rw-r--r--activemodel/test/cases/serializeration/json_serialization_test.rb16
-rw-r--r--activemodel/test/cases/validations_test.rb8
-rw-r--r--activerecord/lib/active_record/associations.rb19
-rw-r--r--activerecord/lib/active_record/callbacks.rb8
-rw-r--r--activerecord/lib/active_record/persistence.rb13
-rw-r--r--activerecord/lib/active_record/reflection.rb26
-rw-r--r--activerecord/lib/active_record/timestamp.rb13
-rw-r--r--activerecord/test/cases/associations/has_many_through_associations_test.rb40
-rw-r--r--activerecord/test/cases/associations_test.rb13
-rw-r--r--activerecord/test/cases/timestamp_test.rb19
-rw-r--r--activerecord/test/fixtures/subscriptions.yml2
-rw-r--r--activerecord/test/models/book.rb3
-rw-r--r--activerecord/test/models/electron.rb3
-rw-r--r--activerecord/test/models/liquid.rb5
-rw-r--r--activerecord/test/models/molecule.rb4
-rw-r--r--activerecord/test/schema/schema.rb15
-rw-r--r--activeresource/lib/active_resource/base.rb6
-rw-r--r--activeresource/test/cases/base/load_test.rb12
-rw-r--r--activesupport/lib/active_support/core_ext/object.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/object/returning.rb43
-rw-r--r--activesupport/lib/active_support/hash_with_indifferent_access.rb1
-rw-r--r--railties/lib/rails/generators/actions.rb2
-rw-r--r--railties/lib/rails/generators/rails/app/app_generator.rb7
-rw-r--r--railties/lib/rails/test_unit/testing.rake2
-rw-r--r--railties/test/generators/app_generator_test.rb24
-rw-r--r--railties/test/generators/scaffold_generator_test.rb15
30 files changed, 291 insertions, 56 deletions
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index f8e60faa2a..ebe055bebd 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -215,7 +215,7 @@ module ActionView
# ...
# <% end %>
#
- # If your resource has associations defined, for example, you want to add comments
+ # If your resource has associations defined, for example, you want to add comments
# to the post given that the routes are set correctly:
#
# <%= form_for([@document, @comment]) do |f| %>
@@ -583,8 +583,9 @@ module ActionView
# 'Accept <a href="/terms">Terms</a>.'
# end
def label(object_name, method, content_or_options = nil, options = nil, &block)
- if block_given?
- options = content_or_options if content_or_options.is_a?(Hash)
+ content_is_options = content_or_options.is_a?(Hash)
+ if content_is_options || block_given?
+ options = content_or_options if content_is_options
text = nil
else
text = content_or_options
diff --git a/actionpack/test/controller/test_test.rb b/actionpack/test/controller/test_test.rb
index 950ad9266f..13c9d9ee38 100644
--- a/actionpack/test/controller/test_test.rb
+++ b/actionpack/test/controller/test_test.rb
@@ -1,5 +1,6 @@
require 'abstract_unit'
require 'controller/fake_controllers'
+require 'active_support/ordered_hash'
class TestTest < ActionController::TestCase
class TestController < ActionController::Base
@@ -137,14 +138,14 @@ XML
end
def test_raw_post_handling
- params = {:page => {:name => 'page name'}, 'some key' => 123}
+ params = ActiveSupport::OrderedHash[:page, {:name => 'page name'}, 'some key', 123]
post :render_raw_post, params.dup
assert_equal params.to_query, @response.body
end
def test_body_stream
- params = { :page => { :name => 'page name' }, 'some key' => 123 }
+ params = ActiveSupport::OrderedHash[:page, { :name => 'page name' }, 'some key', 123]
post :render_body, params.dup
diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb
index f248a38ae9..9086a23345 100644
--- a/actionpack/test/template/form_helper_test.rb
+++ b/actionpack/test/template/form_helper_test.rb
@@ -120,6 +120,13 @@ class FormHelperTest < ActionView::TestCase
I18n.locale = old_locale
end
+ def test_label_with_locales_and_options
+ old_locale, I18n.locale = I18n.locale, :label
+ assert_dom_equal('<label for="post_body" class="post_body">Write entire text here</label>', label(:post, :body, :class => 'post_body'))
+ ensure
+ I18n.locale = old_locale
+ end
+
def test_label_with_for_attribute_as_symbol
assert_dom_equal('<label for="my_for">Title</label>', label(:post, :title, nil, :for => "my_for"))
end
@@ -620,7 +627,7 @@ class FormHelperTest < ActionView::TestCase
def test_form_for_with_symbol_object_name
form_for(@post, :as => "other_name", :html => { :id => 'create-post' }) do |f|
- concat f.label(:title)
+ concat f.label(:title, :class => 'post_title')
concat f.text_field(:title)
concat f.text_area(:body)
concat f.check_box(:secret)
@@ -628,7 +635,7 @@ class FormHelperTest < ActionView::TestCase
end
expected = whole_form("/posts/123", "create-post", "other_name_edit", :method => "put") do
- "<label for='other_name_title'>Title</label>" +
+ "<label for='other_name_title' class='post_title'>Title</label>" +
"<input name='other_name[title]' size='30' id='other_name_title' value='Hello World' type='text' />" +
"<textarea name='other_name[body]' id='other_name_body' rows='20' cols='40'>Back to the hill and over it again!</textarea>" +
"<input name='other_name[secret]' value='0' type='hidden' />" +
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index bf93126d27..f39678db83 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -169,9 +169,9 @@ module ActiveModel
to_a.to_xml options.reverse_merge(:root => "errors", :skip_types => true)
end
- # Returns an array as JSON representation for this object.
+ # Returns an ActiveSupport::OrderedHash that can be used as the JSON representation for this object.
def as_json(options=nil)
- to_a
+ self
end
# Adds +message+ to the error messages on +attribute+, which will be returned on a call to
diff --git a/activemodel/test/cases/serializeration/json_serialization_test.rb b/activemodel/test/cases/serializeration/json_serialization_test.rb
index 04b50e5bb8..1ac991a8f1 100644
--- a/activemodel/test/cases/serializeration/json_serialization_test.rb
+++ b/activemodel/test/cases/serializeration/json_serialization_test.rb
@@ -89,7 +89,7 @@ class JsonSerializationTest < ActiveModel::TestCase
assert_match %r{"preferences":\{"shows":"anime"\}}, json
end
- test "methds are called on object" do
+ test "methods are called on object" do
# Define methods on fixture.
def @contact.label; "Has cheezburger"; end
def @contact.favorite_quote; "Constraints are liberating"; end
@@ -102,4 +102,18 @@ class JsonSerializationTest < ActiveModel::TestCase
assert_match %r{"label":"Has cheezburger"}, methods_json
assert_match %r{"favorite_quote":"Constraints are liberating"}, methods_json
end
+
+ test "should return OrderedHash for errors" do
+ car = Automobile.new
+
+ # run the validation
+ car.valid?
+
+ hash = ActiveSupport::OrderedHash.new
+ hash[:make] = "can't be blank"
+ hash[:model] = "is too short (minimum is 2 characters)"
+ assert_equal hash.to_json, car.errors.to_json
+ end
+
+
end
diff --git a/activemodel/test/cases/validations_test.rb b/activemodel/test/cases/validations_test.rb
index e94d8ce88c..8d6bdeb6a5 100644
--- a/activemodel/test/cases/validations_test.rb
+++ b/activemodel/test/cases/validations_test.rb
@@ -170,9 +170,11 @@ class ValidationsTest < ActiveModel::TestCase
assert_match %r{<errors>}, xml
assert_match %r{<error>Title can't be blank</error>}, xml
assert_match %r{<error>Content can't be blank</error>}, xml
-
- json = t.errors.to_json
- assert_equal t.errors.to_a.to_json, json
+
+ hash = ActiveSupport::OrderedHash.new
+ hash[:title] = "can't be blank"
+ hash[:content] = "can't be blank"
+ assert_equal t.errors.to_json, hash.to_json
end
def test_validation_order
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index f540aa7f25..fdc203e298 100644
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1437,9 +1437,11 @@ module ActiveRecord
association.replace(new_value)
association
end
-
+
redefine_method("#{reflection.name.to_s.singularize}_ids=") do |new_value|
- ids = (new_value || []).reject { |nid| nid.blank? }.map(&:to_i)
+ pk_column = reflection.primary_key_column
+ ids = (new_value || []).reject { |nid| nid.blank? }
+ ids.map!{ |i| pk_column.type_cast(i) }
send("#{reflection.name}=", reflection.klass.find(ids).index_by(&:id).values_at(*ids))
end
end
@@ -1498,6 +1500,7 @@ module ActiveRecord
end
end
after_save(method_name)
+ after_touch(method_name)
after_destroy(method_name)
end
@@ -1802,9 +1805,7 @@ module ActiveRecord
case associations
when Symbol, String
reflection = base.reflections[associations]
- if reflection && reflection.collection?
- records.each { |record| record.send(reflection.name).target.uniq! }
- end
+ remove_uniq_by_reflection(reflection, records)
when Array
associations.each do |association|
remove_duplicate_results!(base, records, association)
@@ -1812,6 +1813,7 @@ module ActiveRecord
when Hash
associations.keys.each do |name|
reflection = base.reflections[name]
+ remove_uniq_by_reflection(reflection, records)
parent_records = []
records.each do |record|
@@ -1830,6 +1832,7 @@ module ActiveRecord
end
protected
+
def build(associations, parent = nil, join_class = Arel::InnerJoin)
parent ||= @joins.last
case associations
@@ -1852,6 +1855,12 @@ module ActiveRecord
end
end
+ def remove_uniq_by_reflection(reflection, records)
+ if reflection && reflection.collection?
+ records.each { |record| record.send(reflection.name).target.uniq! }
+ end
+ end
+
def build_join_association(reflection, parent)
JoinAssociation.new(reflection, self, parent)
end
diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb
index 637dac450b..82c45a41b0 100644
--- a/activerecord/lib/active_record/callbacks.rb
+++ b/activerecord/lib/active_record/callbacks.rb
@@ -228,7 +228,7 @@ module ActiveRecord
extend ActiveSupport::Concern
CALLBACKS = [
- :after_initialize, :after_find, :before_validation, :after_validation,
+ :after_initialize, :after_find, :after_touch, :before_validation, :after_validation,
:before_save, :around_save, :after_save, :before_create, :around_create,
:after_create, :before_update, :around_update, :after_update,
:before_destroy, :around_destroy, :after_destroy
@@ -238,7 +238,7 @@ module ActiveRecord
extend ActiveModel::Callbacks
include ActiveModel::Validations::Callbacks
- define_model_callbacks :initialize, :find, :only => :after
+ define_model_callbacks :initialize, :find, :touch, :only => :after
define_model_callbacks :save, :create, :update, :destroy
end
@@ -256,6 +256,10 @@ module ActiveRecord
_run_destroy_callbacks { super }
end
+ def touch(*) #:nodoc:
+ _run_touch_callbacks { super }
+ end
+
def deprecated_callback_method(symbol) #:nodoc:
if respond_to?(symbol, true)
ActiveSupport::Deprecation.warn("Overwriting #{symbol} in your models has been deprecated, please use Base##{symbol} :method_name instead")
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index 38b91652ee..cbc2220e96 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -218,6 +218,19 @@ module ActiveRecord
self
end
+ # Saves the record with the updated_at/on attributes set to the current time.
+ # Please note that no validation is performed and no callbacks are executed.
+ # If an attribute name is passed, that attribute is updated along with
+ # updated_at/on attributes.
+ #
+ # Examples:
+ #
+ # product.touch # updates updated_at/on
+ # product.touch(:designed_at) # updates the designed_at attribute and updated_at/on
+ def touch(attribute = nil)
+ update_attribute(attribute, current_time_from_proper_timezone)
+ end
+
private
def create_or_update
raise ReadOnlyRecord if readonly?
diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb
index 03a932f642..7f47a812eb 100644
--- a/activerecord/lib/active_record/reflection.rb
+++ b/activerecord/lib/active_record/reflection.rb
@@ -91,25 +91,19 @@ module ActiveRecord
#
# <tt>composed_of :balance, :class_name => 'Money'</tt> returns <tt>:balance</tt>
# <tt>has_many :clients</tt> returns <tt>:clients</tt>
- def name
- @name
- end
+ attr_reader :name
# Returns the macro type.
#
# <tt>composed_of :balance, :class_name => 'Money'</tt> returns <tt>:composed_of</tt>
# <tt>has_many :clients</tt> returns <tt>:has_many</tt>
- def macro
- @macro
- end
+ attr_reader :macro
# Returns the hash of options used for the macro.
#
# <tt>composed_of :balance, :class_name => 'Money'</tt> returns <tt>{ :class_name => "Money" }</tt>
# <tt>has_many :clients</tt> returns +{}+
- def options
- @options
- end
+ attr_reader :options
# Returns the class for the macro.
#
@@ -137,11 +131,6 @@ module ActiveRecord
@sanitized_conditions ||= klass.send(:sanitize_sql, options[:conditions]) if options[:conditions]
end
- # Returns +true+ if +self+ is a +belongs_to+ reflection.
- def belongs_to?
- macro == :belongs_to
- end
-
private
def derive_class_name
name.to_s.camelize
@@ -213,6 +202,10 @@ module ActiveRecord
@primary_key_name ||= options[:foreign_key] || derive_primary_key_name
end
+ def primary_key_column
+ @primary_key_column ||= klass.columns.find { |c| c.name == klass.primary_key }
+ end
+
def association_foreign_key
@association_foreign_key ||= @options[:association_foreign_key] || class_name.foreign_key
end
@@ -307,6 +300,11 @@ module ActiveRecord
dependent_conditions
end
+ # Returns +true+ if +self+ is a +belongs_to+ reflection.
+ def belongs_to?
+ macro == :belongs_to
+ end
+
private
def derive_class_name
class_name = name.to_s.camelize
diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb
index 92f7a7753d..32b3f03f13 100644
--- a/activerecord/lib/active_record/timestamp.rb
+++ b/activerecord/lib/active_record/timestamp.rb
@@ -31,19 +31,6 @@ module ActiveRecord
class_inheritable_accessor :record_timestamps, :instance_writer => false
self.record_timestamps = true
end
-
- # Saves the record with the updated_at/on attributes set to the current time.
- # Please note that no validation is performed and no callbacks are executed.
- # If an attribute name is passed, that attribute is updated along with
- # updated_at/on attributes.
- #
- # Examples:
- #
- # product.touch # updates updated_at/on
- # product.touch(:designed_at) # updates the designed_at attribute and updated_at/on
- def touch(attribute = nil)
- update_attribute(attribute, current_time_from_proper_timezone)
- end
private
diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb
index e4dd810732..0eaadac5ae 100644
--- a/activerecord/test/cases/associations/has_many_through_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb
@@ -14,9 +14,14 @@ require 'models/toy'
require 'models/contract'
require 'models/company'
require 'models/developer'
+require 'models/subscriber'
+require 'models/book'
+require 'models/subscription'
class HasManyThroughAssociationsTest < ActiveRecord::TestCase
- fixtures :posts, :readers, :people, :comments, :authors, :owners, :pets, :toys, :jobs, :references, :companies
+ fixtures :posts, :readers, :people, :comments, :authors,
+ :owners, :pets, :toys, :jobs, :references, :companies,
+ :subscribers, :books, :subscriptions, :developers
# Dummies to force column loads so query counts are clean.
def setup
@@ -383,4 +388,37 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
lambda { authors(:david).very_special_comments.delete(authors(:david).very_special_comments.first) },
].each {|block| assert_raise(ActiveRecord::HasManyThroughCantAssociateThroughHasOneOrManyReflection, &block) }
end
+
+ def test_collection_singular_ids_getter_with_string_primary_keys
+ book = books(:awdr)
+ assert_equal 2, book.subscriber_ids.size
+ assert_equal [subscribers(:first).nick, subscribers(:second).nick].sort, book.subscriber_ids.sort
+ end
+
+ def test_collection_singular_ids_setter
+ company = companies(:rails_core)
+ dev = Developer.find(:first)
+
+ company.developer_ids = [dev.id]
+ assert_equal [dev], company.developers
+ end
+
+ def test_collection_singular_ids_setter_with_string_primary_keys
+ assert_nothing_raised do
+ book = books(:awdr)
+ book.subscriber_ids = [subscribers(:second).nick]
+ assert_equal [subscribers(:second)], book.subscribers(true)
+
+ book.subscriber_ids = []
+ assert_equal [], book.subscribers(true)
+ end
+
+ end
+
+ def test_collection_singular_ids_setter_raises_exception_when_invalid_ids_set
+ company = companies(:rails_core)
+ ids = [Developer.find(:first).id, -9999]
+ assert_raises(ActiveRecord::RecordNotFound) {company.developer_ids= ids}
+ end
+
end
diff --git a/activerecord/test/cases/associations_test.rb b/activerecord/test/cases/associations_test.rb
index a1c794c084..d328ca630b 100644
--- a/activerecord/test/cases/associations_test.rb
+++ b/activerecord/test/cases/associations_test.rb
@@ -14,11 +14,24 @@ require 'models/reader'
require 'models/parrot'
require 'models/ship_part'
require 'models/ship'
+require 'models/liquid'
+require 'models/molecule'
+require 'models/electron'
class AssociationsTest < ActiveRecord::TestCase
fixtures :accounts, :companies, :developers, :projects, :developers_projects,
:computers, :people, :readers
+ def test_eager_loading_should_not_change_count_of_children
+ liquid = Liquid.create(:name => 'salty')
+ molecule = liquid.molecules.create(:name => 'molecule_1')
+ molecule.electrons.create(:name => 'electron_1')
+ molecule.electrons.create(:name => 'electron_2')
+
+ liquids = Liquid.includes(:molecules => :electrons).where('molecules.id is not null')
+ assert_equal 1, liquids[0].molecules.length
+ end
+
def test_loading_the_association_target_should_keep_child_records_marked_for_destruction
ship = Ship.create!(:name => "The good ship Dollypop")
part = ship.parts.create!(:name => "Mast")
diff --git a/activerecord/test/cases/timestamp_test.rb b/activerecord/test/cases/timestamp_test.rb
index f765540808..06ab7aa9c7 100644
--- a/activerecord/test/cases/timestamp_test.rb
+++ b/activerecord/test/cases/timestamp_test.rb
@@ -2,9 +2,10 @@ require 'cases/helper'
require 'models/developer'
require 'models/owner'
require 'models/pet'
+require 'models/toy'
class TimestampTest < ActiveRecord::TestCase
- fixtures :developers, :owners, :pets
+ fixtures :developers, :owners, :pets, :toys
def setup
@developer = Developer.first
@@ -82,4 +83,20 @@ class TimestampTest < ActiveRecord::TestCase
ensure
Pet.belongs_to :owner, :touch => true
end
+
+ def test_touching_a_record_touches_parent_record_and_grandparent_record
+ Toy.belongs_to :pet, :touch => true
+ Pet.belongs_to :owner, :touch => true
+
+ toy = Toy.first
+ pet = toy.pet
+ owner = pet.owner
+
+ owner.update_attribute(:updated_at, (time = 3.days.ago))
+ toy.touch
+
+ assert_not_equal time, owner.updated_at
+ ensure
+ Toy.belongs_to :pet
+ end
end
diff --git a/activerecord/test/fixtures/subscriptions.yml b/activerecord/test/fixtures/subscriptions.yml
index 371bfd3422..5a93c12193 100644
--- a/activerecord/test/fixtures/subscriptions.yml
+++ b/activerecord/test/fixtures/subscriptions.yml
@@ -9,4 +9,4 @@ webster_rfr:
alterself_awdr:
id: 3
subscriber_id: alterself
- book_id: 3 \ No newline at end of file
+ book_id: 1
diff --git a/activerecord/test/models/book.rb b/activerecord/test/models/book.rb
index cfd07abddc..1e030b4f59 100644
--- a/activerecord/test/models/book.rb
+++ b/activerecord/test/models/book.rb
@@ -1,4 +1,7 @@
class Book < ActiveRecord::Base
has_many :citations, :foreign_key => 'book1_id'
has_many :references, :through => :citations, :source => :reference_of, :uniq => true
+
+ has_many :subscriptions
+ has_many :subscribers, :through => :subscriptions
end
diff --git a/activerecord/test/models/electron.rb b/activerecord/test/models/electron.rb
new file mode 100644
index 0000000000..35af9f679b
--- /dev/null
+++ b/activerecord/test/models/electron.rb
@@ -0,0 +1,3 @@
+class Electron < ActiveRecord::Base
+ belongs_to :molecule
+end
diff --git a/activerecord/test/models/liquid.rb b/activerecord/test/models/liquid.rb
new file mode 100644
index 0000000000..b96c054f6c
--- /dev/null
+++ b/activerecord/test/models/liquid.rb
@@ -0,0 +1,5 @@
+class Liquid < ActiveRecord::Base
+ set_table_name :liquid
+ has_many :molecules, :uniq => true
+end
+
diff --git a/activerecord/test/models/molecule.rb b/activerecord/test/models/molecule.rb
new file mode 100644
index 0000000000..69325b8d29
--- /dev/null
+++ b/activerecord/test/models/molecule.rb
@@ -0,0 +1,4 @@
+class Molecule < ActiveRecord::Base
+ belongs_to :liquid
+ has_many :electrons
+end
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index f3fd37cd61..fc3810f82b 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -398,6 +398,7 @@ ActiveRecord::Schema.define do
create_table :pets, :primary_key => :pet_id ,:force => true do |t|
t.string :name
t.integer :owner_id, :integer
+ t.timestamps
end
create_table :pirates, :force => true do |t|
@@ -530,6 +531,7 @@ ActiveRecord::Schema.define do
create_table :toys, :primary_key => :toy_id ,:force => true do |t|
t.string :name
t.integer :pet_id, :integer
+ t.timestamps
end
create_table :traffic_lights, :force => true do |t|
@@ -616,6 +618,19 @@ ActiveRecord::Schema.define do
t.datetime :updated_at
end
+ create_table :liquid, :force => true do |t|
+ t.string :name
+ end
+ create_table :molecules, :force => true do |t|
+ t.integer :liquid_id
+ t.string :name
+ end
+ create_table :electrons, :force => true do |t|
+ t.integer :molecule_id
+ t.string :name
+ end
+
+
except 'SQLite' do
# fk_test_has_fk should be before fk_test_has_pk
create_table :fk_test_has_fk, :force => true do |t|
diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb
index 72ad2f5872..62420725ad 100644
--- a/activeresource/lib/active_resource/base.rb
+++ b/activeresource/lib/active_resource/base.rb
@@ -1222,10 +1222,10 @@ module ActiveResource
when Array
resource = find_or_create_resource_for_collection(key)
value.map do |attrs|
- if attrs.is_a?(String) || attrs.is_a?(Numeric)
- attrs.duplicable? ? attrs.dup : attrs
- else
+ if attrs.is_a?(Hash)
resource.new(attrs)
+ else
+ attrs.duplicable? ? attrs.dup : attrs
end
end
when Hash
diff --git a/activeresource/test/cases/base/load_test.rb b/activeresource/test/cases/base/load_test.rb
index 7745a9439b..228dc36d9b 100644
--- a/activeresource/test/cases/base/load_test.rb
+++ b/activeresource/test/cases/base/load_test.rb
@@ -47,6 +47,8 @@ class BaseLoadTest < Test::Unit::TestCase
{ :id => 1, :name => 'Willamette' },
{ :id => 2, :name => 'Columbia', :rafted_by => @matz }],
:postal_codes => [ 97018, 1234567890 ],
+ :dates => [ Time.now ],
+ :votes => [ true, false, true ],
:places => [ "Columbia City", "Unknown" ]}}}
@person = Person.new
@@ -149,6 +151,16 @@ class BaseLoadTest < Test::Unit::TestCase
assert_kind_of Array, places
assert_kind_of String, places.first
assert_equal @deep[:street][:state][:places].first, places.first
+
+ dates = state.dates
+ assert_kind_of Array, dates
+ assert_kind_of Time, dates.first
+ assert_equal @deep[:street][:state][:dates].first, dates.first
+
+ votes = state.votes
+ assert_kind_of Array, votes
+ assert_kind_of TrueClass, votes.first
+ assert_equal @deep[:street][:state][:votes].first, votes.first
end
def test_nested_collections_within_the_same_namespace
diff --git a/activesupport/lib/active_support/core_ext/object.rb b/activesupport/lib/active_support/core_ext/object.rb
index 790a26f5c1..d671da6711 100644
--- a/activesupport/lib/active_support/core_ext/object.rb
+++ b/activesupport/lib/active_support/core_ext/object.rb
@@ -2,6 +2,7 @@ require 'active_support/core_ext/object/acts_like'
require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/object/duplicable'
require 'active_support/core_ext/object/try'
+require 'active_support/core_ext/object/returning'
require 'active_support/core_ext/object/conversions'
require 'active_support/core_ext/object/instance_variables'
diff --git a/activesupport/lib/active_support/core_ext/object/returning.rb b/activesupport/lib/active_support/core_ext/object/returning.rb
new file mode 100644
index 0000000000..07250b2a27
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/object/returning.rb
@@ -0,0 +1,43 @@
+class Object
+ # Returns +value+ after yielding +value+ to the block. This simplifies the
+ # process of constructing an object, performing work on the object, and then
+ # returning the object from a method. It is a Ruby-ized realization of the K
+ # combinator, courtesy of Mikael Brockman.
+ #
+ # ==== Examples
+ #
+ # # Without returning
+ # def foo
+ # values = []
+ # values << "bar"
+ # values << "baz"
+ # return values
+ # end
+ #
+ # foo # => ['bar', 'baz']
+ #
+ # # returning with a local variable
+ # def foo
+ # returning values = [] do
+ # values << 'bar'
+ # values << 'baz'
+ # end
+ # end
+ #
+ # foo # => ['bar', 'baz']
+ #
+ # # returning with a block argument
+ # def foo
+ # returning [] do |values|
+ # values << 'bar'
+ # values << 'baz'
+ # end
+ # end
+ #
+ # foo # => ['bar', 'baz']
+ def returning(value)
+ ActiveSupport::Deprecation.warn('Object#returning has been deprecated in favor of Object#tap.', caller)
+ yield(value)
+ value
+ end
+end \ No newline at end of file
diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb
index f64f0f44cc..eec5d4cf47 100644
--- a/activesupport/lib/active_support/hash_with_indifferent_access.rb
+++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb
@@ -1,3 +1,4 @@
+require 'active_support/core_ext/hash/indifferent_access'
require 'active_support/core_ext/hash/keys'
# This class has dubious semantics and we only have it so that
diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb
index 2280cc1507..668ef48892 100644
--- a/railties/lib/rails/generators/actions.rb
+++ b/railties/lib/rails/generators/actions.rb
@@ -275,7 +275,7 @@ module Rails
#
def route(routing_code)
log :route, routing_code
- sentinel = /\.routes\.draw do(\s*\|map\|)?\s*$/
+ sentinel = /\.routes\.draw do(?:\s*\|map\|)?\s*$/
in_root do
inject_into_file 'config/routes.rb', "\n #{routing_code}\n", { :after => sentinel, :verbose => false }
diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb
index 96c49a81bb..a90f109844 100644
--- a/railties/lib/rails/generators/rails/app/app_generator.rb
+++ b/railties/lib/rails/generators/rails/app/app_generator.rb
@@ -356,8 +356,13 @@ module Rails
@app_name ||= File.basename(destination_root)
end
+ def defined_app_const_base
+ Rails.respond_to?(:application) && defined?(Rails::Application) &&
+ Rails.application.is_a?(Rails::Application) && Rails.application.class.name.sub(/::Application$/, "")
+ end
+
def app_const_base
- @app_const_base ||= app_name.gsub(/\W/, '_').squeeze('_').camelize
+ @app_const_base ||= defined_app_const_base || app_name.gsub(/\W/, '_').squeeze('_').camelize
end
def app_const
diff --git a/railties/lib/rails/test_unit/testing.rake b/railties/lib/rails/test_unit/testing.rake
index ecd513c2c8..38c14fcd6b 100644
--- a/railties/lib/rails/test_unit/testing.rake
+++ b/railties/lib/rails/test_unit/testing.rake
@@ -70,7 +70,7 @@ module Kernel
end
end
-desc 'Runs test:unit, test:functional, test:integration together (also available: test:benchmark, test:profile, test:plugins)'
+desc 'Runs test:units, test:functionals, test:integration together (also available: test:benchmark, test:profile, test:plugins)'
task :test do
errors = %w(test:units test:functionals test:integration).collect do |task|
begin
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index 1e0b3bf4c7..21725a380c 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -106,6 +106,30 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_file "things-43/config/application.rb", /^module Things43$/
end
+ def test_application_name_is_detected_if_it_exists_and_app_folder_renamed
+ app_root = File.join(destination_root, "myapp")
+ app_moved_root = File.join(destination_root, "myapp_moved")
+
+ run_generator [app_root]
+
+ Rails.application.config.root = app_moved_root
+ Rails.application.class.stubs(:name).returns("Myapp")
+ Rails.application.stubs(:instance_of?).returns(Rails::Application)
+
+ FileUtils.mv(app_root, app_moved_root)
+
+ # forces the shell to automatically overwrite all files
+ Thor::Base.shell.send(:attr_accessor, :always_force)
+ shell = Thor::Base.shell.new
+ shell.send(:always_force=, true)
+
+ generator = Rails::Generators::AppGenerator.new ["rails"], { :with_dispatchers => true },
+ :destination_root => app_moved_root, :shell => shell
+ generator.send(:app_const)
+ silence(:stdout){ generator.send(:create_config_files) }
+ assert_file "myapp_moved/config/environment.rb", /Myapp::Application\.initialize!/
+ end
+
def test_application_names_are_not_singularized
run_generator [File.join(destination_root, "hats")]
assert_file "hats/config/environment.rb", /Hats::Application\.initialize!/
diff --git a/railties/test/generators/scaffold_generator_test.rb b/railties/test/generators/scaffold_generator_test.rb
index ea469cb3c8..f12445ae35 100644
--- a/railties/test/generators/scaffold_generator_test.rb
+++ b/railties/test/generators/scaffold_generator_test.rb
@@ -216,4 +216,19 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
# Stylesheets (should not be removed)
assert_file "public/stylesheets/scaffold.css"
end
+
+ def test_scaffold_generator_on_revoke_does_not_mutilate_legacy_map_parameter
+ run_generator
+
+ # Add a |map| parameter to the routes block manually
+ route_path = File.expand_path("config/routes.rb", destination_root)
+ content = File.read(route_path).gsub(/\.routes\.draw do/) do |match|
+ "#{match} |map|"
+ end
+ File.open(route_path, "wb") { |file| file.write(content) }
+
+ run_generator ["product_line"], :behavior => :revoke
+
+ assert_file "config/routes.rb", /\.routes\.draw do\s*\|map\|\s*$/
+ end
end