aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib')
-rw-r--r--activerecord/lib/active_record/base.rb33
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb9
-rw-r--r--activerecord/lib/active_record/locking/optimistic.rb2
-rw-r--r--activerecord/lib/active_record/named_scope.rb19
-rw-r--r--activerecord/lib/active_record/persistence.rb4
-rw-r--r--activerecord/lib/active_record/relation.rb5
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb2
-rw-r--r--activerecord/lib/active_record/relation/spawn_methods.rb2
8 files changed, 57 insertions, 19 deletions
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index e970445082..fd52038647 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -709,6 +709,12 @@ module ActiveRecord #:nodoc:
connection_pool.columns_hash[table_name]
end
+ # Returns a hash where the keys are column names and the values are
+ # default values when instantiating the AR object for this table.
+ def column_defaults
+ connection_pool.column_defaults[table_name]
+ end
+
# Returns an array of column names as strings.
def column_names
@column_names ||= columns.map { |column| column.name }
@@ -1204,11 +1210,11 @@ MSG
end
def current_scope #:nodoc:
- Thread.current[:"#{self}_current_scope"]
+ Thread.current["#{self}_current_scope"]
end
def current_scope=(scope) #:nodoc:
- Thread.current[:"#{self}_current_scope"] = scope
+ Thread.current["#{self}_current_scope"] = scope
end
# Use this macro in your model to set a default scope for all operations on
@@ -1527,6 +1533,7 @@ MSG
@marked_for_destruction = false
@previously_changed = {}
@changed_attributes = {}
+ @relation = nil
ensure_proper_type
set_serialized_attributes
@@ -1535,9 +1542,8 @@ MSG
assign_attributes(attributes, options) if attributes
- result = yield self if block_given?
+ yield self if block_given?
run_callbacks :initialize
- result
end
# Populate +coder+ with attributes about this record that should be
@@ -1568,6 +1574,7 @@ MSG
# post.title # => 'hello world'
def init_with(coder)
@attributes = coder['attributes']
+ @relation = nil
set_serialized_attributes
@@ -1894,9 +1901,10 @@ MSG
private
def set_serialized_attributes
- (@attributes.keys & self.class.serialized_attributes.keys).each do |key|
- coder = self.class.serialized_attributes[key]
- @attributes[key] = coder.load @attributes[key]
+ sattrs = self.class.serialized_attributes
+
+ sattrs.each do |key, coder|
+ @attributes[key] = coder.load @attributes[key] if @attributes.key?(key)
end
end
@@ -1906,8 +1914,9 @@ MSG
# do Reply.new without having to set <tt>Reply[Reply.inheritance_column] = "Reply"</tt> yourself.
# No such attribute would be set for objects of the Message class in that example.
def ensure_proper_type
- unless self.class.descends_from_active_record?
- write_attribute(self.class.inheritance_column, self.class.sti_name)
+ klass = self.class
+ if klass.finder_needs_type_condition?
+ write_attribute(klass.inheritance_column, klass.sti_name)
end
end
@@ -2081,8 +2090,10 @@ MSG
end
def populate_with_current_scope_attributes
- self.class.scoped.scope_for_create.each do |att,value|
- respond_to?("#{att}=") && send("#{att}=", value)
+ return unless self.class.scope_attributes?
+
+ self.class.scope_attributes.each do |att,value|
+ send("#{att}=", value) if respond_to?("#{att}=")
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
index 090f6bc6fe..ddfdb05297 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
@@ -60,6 +60,7 @@ module ActiveRecord
attr_accessor :automatic_reconnect
attr_reader :spec, :connections
attr_reader :columns, :columns_hash, :primary_keys, :tables
+ attr_reader :column_defaults
# Creates a new ConnectionPool object. +spec+ is a ConnectionSpecification
# object which describes database connection information (e.g. adapter,
@@ -106,6 +107,12 @@ module ActiveRecord
}]
end
+ @column_defaults = Hash.new do |h, table_name|
+ h[table_name] = Hash[columns[table_name].map { |col|
+ [col.name, col.default]
+ }]
+ end
+
@primary_keys = Hash.new do |h, table_name|
h[table_name] = with_connection do |conn|
table_exists?(table_name) ? conn.primary_key(table_name) : 'id'
@@ -133,6 +140,7 @@ module ActiveRecord
def clear_cache!
@columns.clear
@columns_hash.clear
+ @column_defaults.clear
@tables.clear
end
@@ -140,6 +148,7 @@ module ActiveRecord
def clear_table_cache!(table_name)
@columns.delete table_name
@columns_hash.delete table_name
+ @column_defaults.delete table_name
@primary_keys.delete table_name
end
diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb
index 3afa257a76..6cfce6e573 100644
--- a/activerecord/lib/active_record/locking/optimistic.rb
+++ b/activerecord/lib/active_record/locking/optimistic.rb
@@ -73,7 +73,7 @@ module ActiveRecord
# <tt>locking_enabled?</tt> at this point as
# <tt>@attributes</tt> may not have been initialized yet.
- if lock_optimistically && result.include?(self.class.locking_column)
+ if result.key?(self.class.locking_column) && lock_optimistically
result[self.class.locking_column] ||= 0
end
diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb
index 14db7a6cd6..0313abe456 100644
--- a/activerecord/lib/active_record/named_scope.rb
+++ b/activerecord/lib/active_record/named_scope.rb
@@ -40,6 +40,25 @@ module ActiveRecord
end
end
+ ##
+ # Collects attributes from scopes that should be applied when creating
+ # an AR instance for the particular class this is called on.
+ def scope_attributes # :nodoc:
+ if current_scope
+ current_scope.scope_for_create
+ else
+ scope = relation.clone
+ scope.default_scoped = true
+ scope.scope_for_create
+ end
+ end
+
+ ##
+ # Are there default attributes associated with this scope?
+ def scope_attributes? # :nodoc:
+ current_scope || default_scopes.any?
+ end
+
# Adds a class method for retrieving and querying objects. A \scope represents a narrowing of a database query,
# such as <tt>where(:color => :red).select('shirts.*').includes(:washing_instructions)</tt>.
#
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index 367a1be4d9..f425118f59 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -319,9 +319,7 @@ module ActiveRecord
# that a new instance, or one populated from a passed-in Hash, still has all the attributes
# that instances loaded from the database would.
def attributes_from_column_definition
- Hash[self.class.columns.map do |column|
- [column.name, column.default]
- end]
+ self.class.column_defaults.dup
end
end
end
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index 317af8a15d..9cd146b857 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -6,7 +6,7 @@ module ActiveRecord
JoinOperation = Struct.new(:relation, :join_class, :on)
ASSOCIATION_METHODS = [:includes, :eager_load, :preload]
MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having, :bind]
- SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :create_with, :from, :reorder, :reverse_order]
+ SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :from, :reorder, :reverse_order]
include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches
@@ -29,6 +29,7 @@ module ActiveRecord
SINGLE_VALUE_METHODS.each {|v| instance_variable_set(:"@#{v}_value", nil)}
(ASSOCIATION_METHODS + MULTI_VALUE_METHODS).each {|v| instance_variable_set(:"@#{v}_values", [])}
@extensions = []
+ @create_with_value = {}
end
def insert(values)
@@ -403,7 +404,7 @@ module ActiveRecord
end
def scope_for_create
- @scope_for_create ||= where_values_hash.merge(@create_with_value || {})
+ @scope_for_create ||= where_values_hash.merge(create_with_value)
end
def eager_loading?
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 7fbbefeea2..d17861f407 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -137,7 +137,7 @@ module ActiveRecord
def create_with(value)
relation = clone
- relation.create_with_value = value && (@create_with_value || {}).merge(value)
+ relation.create_with_value = value ? create_with_value.merge(value) : {}
relation
end
diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb
index 69706b5ead..ba882beca9 100644
--- a/activerecord/lib/active_record/relation/spawn_methods.rb
+++ b/activerecord/lib/active_record/relation/spawn_methods.rb
@@ -55,7 +55,7 @@ module ActiveRecord
merged_relation.lock_value = r.lock_value unless merged_relation.lock_value
- merged_relation = merged_relation.create_with(r.create_with_value) if r.create_with_value
+ merged_relation = merged_relation.create_with(r.create_with_value) unless r.create_with_value.empty?
# Apply scope extension modules
merged_relation.send :apply_modules, r.extensions