aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/lib/action_controller/metal/params_wrapper.rb2
-rw-r--r--actionpack/test/activerecord/controller_runtime_test.rb15
-rw-r--r--actionpack/test/controller/params_wrapper_test.rb15
-rw-r--r--activerecord/lib/active_record/associations/collection_association.rb42
-rw-r--r--activerecord/lib/active_record/railties/controller_runtime.rb10
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb10
-rw-r--r--activerecord/test/models/bulb.rb4
-rw-r--r--activerecord/test/schema/schema.rb1
-rw-r--r--railties/guides/source/configuring.textile41
9 files changed, 100 insertions, 40 deletions
diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb
index 9b27bb8b91..b18be60201 100644
--- a/actionpack/lib/action_controller/metal/params_wrapper.rb
+++ b/actionpack/lib/action_controller/metal/params_wrapper.rb
@@ -163,7 +163,7 @@ module ActionController
unless options[:only] || options[:except]
model ||= _default_wrap_model
- if model.respond_to?(:column_names)
+ if !(model.respond_to?(:abstract_class?) && model.abstract_class?) && model.respond_to?(:column_names)
options[:only] = model.column_names
end
end
diff --git a/actionpack/test/activerecord/controller_runtime_test.rb b/actionpack/test/activerecord/controller_runtime_test.rb
index 7931da3741..b87b9f9c47 100644
--- a/actionpack/test/activerecord/controller_runtime_test.rb
+++ b/actionpack/test/activerecord/controller_runtime_test.rb
@@ -11,6 +11,10 @@ class ControllerRuntimeLogSubscriberTest < ActionController::TestCase
def show
render :inline => "<%= Project.all %>"
end
+
+ def zero
+ render :inline => "Zero DB runtime"
+ end
end
include ActiveSupport::LogSubscriber::TestHelper
@@ -37,6 +41,15 @@ class ControllerRuntimeLogSubscriberTest < ActionController::TestCase
wait
assert_equal 2, @logger.logged(:info).size
- assert_match(/\(Views: [\d.]+ms | ActiveRecord: [\d.]+ms\)/, @logger.logged(:info)[1])
+ assert_match(/\(Views: [\d.]+ms \| ActiveRecord: [\d.]+ms\)/, @logger.logged(:info)[1])
+ end
+
+ def test_runtime_reset_before_requests
+ ActiveRecord::LogSubscriber.runtime += 12345
+ get :zero
+ wait
+
+ assert_equal 2, @logger.logged(:info).size
+ assert_match(/\(Views: [\d.]+ms \| ActiveRecord: 0.0ms\)/, @logger.logged(:info)[1])
end
end
diff --git a/actionpack/test/controller/params_wrapper_test.rb b/actionpack/test/controller/params_wrapper_test.rb
index 85464fc780..bed4a6a553 100644
--- a/actionpack/test/controller/params_wrapper_test.rb
+++ b/actionpack/test/controller/params_wrapper_test.rb
@@ -133,6 +133,7 @@ class ParamsWrapperTest < ActionController::TestCase
end
def test_derived_wrapped_keys_from_matching_model
+ User.expects(:respond_to?).with(:abstract_class?).returns(false)
User.expects(:respond_to?).with(:column_names).returns(true)
User.expects(:column_names).returns(["username"])
@@ -145,6 +146,7 @@ class ParamsWrapperTest < ActionController::TestCase
def test_derived_wrapped_keys_from_specified_model
with_default_wrapper_options do
+ Person.expects(:respond_to?).with(:abstract_class?).returns(false)
Person.expects(:respond_to?).with(:column_names).returns(true)
Person.expects(:column_names).returns(["username"])
@@ -156,6 +158,17 @@ class ParamsWrapperTest < ActionController::TestCase
end
end
+ def test_not_wrapping_abstract_model
+ User.expects(:respond_to?).with(:abstract_class?).returns(true)
+ User.expects(:abstract_class?).returns(true)
+
+ with_default_wrapper_options do
+ @request.env['CONTENT_TYPE'] = 'application/json'
+ post :parse, { 'username' => 'sikachu', 'title' => 'Developer' }
+ assert_parameters({ 'username' => 'sikachu', 'title' => 'Developer', 'user' => { 'username' => 'sikachu', 'title' => 'Developer' }})
+ end
+ end
+
private
def with_default_wrapper_options(&block)
@controller.class._wrapper_options = {:format => [:json]}
@@ -246,4 +259,4 @@ class NamespacedParamsWrapperTest < ActionController::TestCase
def assert_parameters(expected)
assert_equal expected, Admin::Users::UsersController.last_parameters
end
-end \ No newline at end of file
+end
diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb
index 4429c655a2..525ac65722 100644
--- a/activerecord/lib/active_record/associations/collection_association.rb
+++ b/activerecord/lib/active_record/associations/collection_association.rb
@@ -387,25 +387,35 @@ module ActiveRecord
records
end
- def merge_target_lists(loaded, existing)
- return loaded if existing.empty?
- return existing if loaded.empty?
-
- loaded.map do |f|
- i = existing.index(f)
- if i
- existing.delete_at(i).tap do |t|
- keys = ["id"] + t.changes.keys + (f.attribute_names - t.attribute_names)
- # FIXME: this call to attributes causes many NoMethodErrors
- attributes = f.attributes
- (attributes.keys - keys).each do |k|
- t.send("#{k}=", attributes[k])
- end
+ # We have some records loaded from the database (persisted) and some that are
+ # in-memory (memory). The same record may be represented in the persisted array
+ # and in the memory array.
+ #
+ # So the task of this method is to merge them according to the following rules:
+ #
+ # * The final array must not have duplicates
+ # * The order of the persisted array is to be preserved
+ # * Any changes made to attributes on objects in the memory array are to be preserved
+ # * Otherwise, attributes should have the value found in the database
+ def merge_target_lists(persisted, memory)
+ return persisted if memory.empty?
+ return memory if persisted.empty?
+
+ persisted.map! do |record|
+ mem_record = memory.delete(record)
+
+ if mem_record
+ (record.attribute_names - mem_record.changes.keys).each do |name|
+ mem_record[name] = record[name]
end
+
+ mem_record
else
- f
+ record
end
- end + existing
+ end
+
+ persisted + memory
end
# Do the relevant stuff to insert the given record into the association collection.
diff --git a/activerecord/lib/active_record/railties/controller_runtime.rb b/activerecord/lib/active_record/railties/controller_runtime.rb
index bc6ca936c0..9e3b3429e4 100644
--- a/activerecord/lib/active_record/railties/controller_runtime.rb
+++ b/activerecord/lib/active_record/railties/controller_runtime.rb
@@ -2,13 +2,21 @@ require 'active_support/core_ext/module/attr_internal'
module ActiveRecord
module Railties
- module ControllerRuntime
+ module ControllerRuntime #:nodoc:
extend ActiveSupport::Concern
protected
attr_internal :db_runtime
+ def process_action(action, *args)
+ # We also need to reset the runtime before each action
+ # because of queries in middleware or in cases we are streaming
+ # and it won't be cleaned up by the method below.
+ ActiveRecord::LogSubscriber.reset_runtime
+ super
+ end
+
def cleanup_view_runtime
if ActiveRecord::Base.connected?
db_rt_before_render = ActiveRecord::LogSubscriber.reset_runtime
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index b149f5912f..0e33fa9c8e 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -1445,4 +1445,14 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_not_equal target.object_id, ary.object_id
end
+
+ def test_merging_with_custom_attribute_writer
+ bulb = Bulb.new(:color => "red")
+ assert_equal "RED!", bulb.color
+
+ car = Car.create!
+ car.bulbs << bulb
+
+ assert_equal "RED!", car.bulbs.to_a.first.color
+ end
end
diff --git a/activerecord/test/models/bulb.rb b/activerecord/test/models/bulb.rb
index 643dcefed3..7d90963720 100644
--- a/activerecord/test/models/bulb.rb
+++ b/activerecord/test/models/bulb.rb
@@ -11,4 +11,8 @@ class Bulb < ActiveRecord::Base
@scope_after_initialize = self.class.scoped
end
+ def color=(color)
+ self[:color] = color.upcase + "!"
+ end
+
end
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index c8a98f121d..d56cdd57b2 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -90,6 +90,7 @@ ActiveRecord::Schema.define do
t.integer :car_id
t.string :name
t.boolean :frickinawesome
+ t.string :color
end
create_table "CamelCase", :force => true do |t|
diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile
index d7069b31fc..2958d1b053 100644
--- a/railties/guides/source/configuring.textile
+++ b/railties/guides/source/configuring.textile
@@ -9,37 +9,38 @@ endprologue.
h3. Locations for Initialization Code
-Rails offers (at least) four good spots to place initialization code:
+Rails offers four standard spots to place initialization code:
-* application.rb
-* Environment-specific Configuration Files
+* +config/application.rb+
+* Environment-specific configuration files
* Initializers
-* After-Initializers
+* After-initializers
h3. Running Code Before Rails
-To run some code before Rails itself is loaded, simply put it above the call to
-+require 'rails/all'+ in your +application.rb+.
+In the rare event that your application needs to run some code before Rails itself is loaded, put it above the call to +require 'rails/all'+ in your +config/application.rb+.
h3. Configuring Rails Components
-In general, the work of configuring Rails means configuring the components of Rails, as well as configuring Rails itself. The +application.rb+ and environment-specific configuration files (such as +config/environments/production.rb+) allow you to specify the various settings that you want to pass down to all of the components. For example, the default Rails 3.0 +application.rb+ file includes this setting:
+In general, the work of configuring Rails means configuring the components of Rails, as well as configuring Rails itself. The configuration file +config/application.rb+ and environment-specific configuration files (such as +config/environments/production.rb+) allow you to specify the various settings that you want to pass down to all of the components.
+
+For example, the default +config/application.rb+ file includes this setting:
<ruby>
- config.filter_parameters += [:password]
+config.filter_parameters += [:password]
</ruby>
-This is a setting for Rails itself. If you want to pass settings to individual Rails components, you can do so via the same +config+ object:
+This is a setting for Rails itself. If you want to pass settings to individual Rails components, you can do so via the same +config+ object in +config/application.rb+:
<ruby>
- config.active_record.timestamped_migrations = false
+config.active_record.observers = [:hotel_observer, :review_observer]
</ruby>
Rails will use that particular setting to configure Active Record.
h4. Rails General Configuration
-* +config.after_initialize+ takes a block which will be ran _after_ Rails has finished initializing. Useful for configuring values set up by other initializers:
+* +config.after_initialize+ takes a block which will be ran _after_ Rails has finished initializing the application. That includes the initialization of the framework itself, plugins, engines, and all the application's initializers in +config/initializers+. Useful for configuring values set up by other initializers:
<ruby>
config.after_initialize do
@@ -47,25 +48,25 @@ config.after_initialize do
end
</ruby>
-* +config.allow_concurrency+ should be set to +true+ to allow concurrent (threadsafe) action processing. Set to +false+ by default. You probably don't want to call this one directly, though, because a series of other adjustments need to be made for threadsafe mode to work properly. Can also be enabled with +threadsafe!+.
+* +config.allow_concurrency+ should be true to allow concurrent (threadsafe) action processing. False by default. You probably don't want to call this one directly, though, because a series of other adjustments need to be made for threadsafe mode to work properly. Can also be enabled with +threadsafe!+.
-* +config.asset_host+ sets the host for the assets. Useful when CDNs are used for hosting assets rather than the application server itself. Shorter version of +config.action_controller.asset_host+.
+* +config.asset_host+ sets the host for the assets. Useful when CDNs are used for hosting assets, or when you want to work around the concurrency constraints builtin in browsers using different domain aliases. Shorter version of +config.action_controller.asset_host+.
-* +config.asset_path+ takes a block which configures where assets can be found. Shorter version of +config.action_controller.asset_path+.
+* +config.asset_path+ can take a callable, a string, or be +nil+. Default is +nil+. If set, this configuration parameter let's you decorate asset paths. For example, the normal path for +blog.js+ would be +/javascripts/blog.js+, let that absolute path be +path+. If +config.asset_path+ is a callable, Rails calls it when generating asset paths passing +path+ as argument. If +config.asset_path+ is a string, it is expected to be a +sprintf+ format string with a +%s+ where +path+ will get inserted. In either case, Rails outputs the decorated path. *This option is ignored if the asset pipeline is enabled, which is by default*. Shorter version of +config.action_controller.asset_path+.
<ruby>
- config.asset_path = proc { |asset_path| "assets/#{asset_path}" }
+config.asset_path = proc { |path| "/blog/public#{path}" }
</ruby>
-* +config.autoload_once_paths+ accepts an array of paths from which Rails will automatically load from only once. All elements of this array must also be in +autoload_paths+.
+* +config.autoload_once_paths+ accepts an array of paths from which Rails will autoload constants that won't be wiped per request. Relevant if +config.cache_classes+ is false, which is the case in development mode by default. Otherwise, all autoloading happens only once. All elements of this array must also be in +autoload_paths+. Default is an empty array.
-* +config.autoload_paths+ accepts an array of additional paths to prepend to the load path. By default, all app, lib, vendor and mock paths are included in this list.
+* +config.autoload_paths+ accepts an array of paths from which Rails will autoload constants. By default that's the abolute paths of +app/mailers+, +app/assets+, +app/controllers+, +app/models+, and +app/helpers+. Please use <tt>+=</tt> to extend the default list.
-* +config.cache_classes+ controls whether or not application classes should be reloaded on each request. Defaults to _true_ in development, _false_ in test and production. Can also be enabled with +threadsafe!+.
+* +config.cache_classes+ controls whether or not application classes and modules should be reloaded on each request. Defaults to true in development mode, and false in test and production modes. Can also be enabled with +threadsafe!+.
-* +config.action_view.cache_template_loading+ controls whether or not templates should be reloaded on each request. Defaults to whatever is set for config.cache_classes.
+* +config.action_view.cache_template_loading+ controls whether or not templates should be reloaded on each request. Defaults to whatever is set for +config.cache_classes+.
-* +config.cache_store+ configures which cache store to use for Rails caching. Options include +:memory_store+, +:file_store+, +:mem_cache_store+ or the name of your own custom class. Defaults to +:file_store+.
+* +config.cache_store+ configures which cache store to use for Rails caching. Options include one of the symbols +:memory_store+, +:file_store+, +:mem_cache_store+, or an object that implements the cache API. Defaults to +:file_store+ if the directory +tmp/cache+ exists, and to +:memory_store+ otherwise.
* +config.colorize_logging+ specifies whether or not to use ANSI color codes when logging information. Defaults to _true_.