Merge branch 'master' of https://github.com/aushack/metasploit-framework into aushack-master
commit
e12cce775e
2
Gemfile
2
Gemfile
|
@ -1,5 +1,5 @@
|
||||||
source 'http://rubygems.org'
|
source 'http://rubygems.org'
|
||||||
gem 'rails', '3.2.4'
|
gem 'rails', '3.2.2'
|
||||||
gem 'metasploit_data_models', '0.0.2', :git => "git://github.com/rapid7/metasploit_data_models.git"
|
gem 'metasploit_data_models', '0.0.2', :git => "git://github.com/rapid7/metasploit_data_models.git"
|
||||||
gem 'pg', '>=0.13'
|
gem 'pg', '>=0.13'
|
||||||
gem 'msgpack'
|
gem 'msgpack'
|
||||||
|
|
|
@ -1,43 +1,3 @@
|
||||||
## Rails 3.2.4 (May 31, 2012) ##
|
|
||||||
|
|
||||||
* Perf fix: Don't load the records when doing assoc.delete_all.
|
|
||||||
GH #6289. *Jon Leighton*
|
|
||||||
|
|
||||||
* Association preloading shouldn't be affected by the current scoping.
|
|
||||||
This could cause infinite recursion and potentially other problems.
|
|
||||||
See GH #5667. *Jon Leighton*
|
|
||||||
|
|
||||||
* Datetime attributes are forced to be changed. GH #3965
|
|
||||||
|
|
||||||
* Fix attribute casting. GH #5549
|
|
||||||
|
|
||||||
* Fix #5667. Preloading should ignore scoping.
|
|
||||||
|
|
||||||
* Predicate builder should not recurse for determining where columns.
|
|
||||||
Thanks to Ben Murphy for reporting this! CVE-2012-2661
|
|
||||||
|
|
||||||
## Rails 3.2.3 (March 30, 2012) ##
|
|
||||||
|
|
||||||
* Added find_or_create_by_{attribute}! dynamic method. *Andrew White*
|
|
||||||
|
|
||||||
* Whitelist all attribute assignment by default. Change the default for newly generated applications to whitelist all attribute assignment. Also update the generated model classes so users are reminded of the importance of attr_accessible. *NZKoz*
|
|
||||||
|
|
||||||
* Update ActiveRecord::AttributeMethods#attribute_present? to return false for empty strings. *Jacobkg*
|
|
||||||
|
|
||||||
* Fix associations when using per class databases. *larskanis*
|
|
||||||
|
|
||||||
* Revert setting NOT NULL constraints in add_timestamps *fxn*
|
|
||||||
|
|
||||||
* Fix mysql to use proper text types. Fixes #3931. *kennyj*
|
|
||||||
|
|
||||||
* Fix #5069 - Protect foreign key from mass assignment through association builder. *byroot*
|
|
||||||
|
|
||||||
|
|
||||||
## Rails 3.2.2 (March 1, 2012) ##
|
|
||||||
|
|
||||||
* No changes.
|
|
||||||
|
|
||||||
|
|
||||||
## Rails 3.2.1 (January 26, 2012) ##
|
## Rails 3.2.1 (January 26, 2012) ##
|
||||||
|
|
||||||
* The threshold for auto EXPLAIN is ignored if there's no logger. *fxn*
|
* The threshold for auto EXPLAIN is ignored if there's no logger. *fxn*
|
||||||
|
@ -232,8 +192,7 @@
|
||||||
|
|
||||||
*Brian Durand*
|
*Brian Durand*
|
||||||
|
|
||||||
|
## Rails 3.1.3 (unreleased) ##
|
||||||
## Rails 3.1.3 (November 20, 2011) ##
|
|
||||||
|
|
||||||
* Perf fix: If we're deleting all records in an association, don't add a IN(..) clause
|
* Perf fix: If we're deleting all records in an association, don't add a IN(..) clause
|
||||||
to the query. *GH 3672*
|
to the query. *GH 3672*
|
||||||
|
@ -246,8 +205,7 @@
|
||||||
|
|
||||||
*Christos Zisopoulos and Kenny J*
|
*Christos Zisopoulos and Kenny J*
|
||||||
|
|
||||||
|
## Rails 3.1.2 (unreleased) ##
|
||||||
## Rails 3.1.2 (November 18, 2011) ##
|
|
||||||
|
|
||||||
* Fix bug with PostgreSQLAdapter#indexes. When the search path has multiple schemas, spaces
|
* Fix bug with PostgreSQLAdapter#indexes. When the search path has multiple schemas, spaces
|
||||||
were not being stripped from the schema names after the first.
|
were not being stripped from the schema names after the first.
|
||||||
|
@ -294,7 +252,6 @@
|
||||||
|
|
||||||
*Kenny J*
|
*Kenny J*
|
||||||
|
|
||||||
|
|
||||||
## Rails 3.1.1 (October 7, 2011) ##
|
## Rails 3.1.1 (October 7, 2011) ##
|
||||||
|
|
||||||
* Add deprecation for the preload_associations method. Fixes #3022.
|
* Add deprecation for the preload_associations method. Fixes #3022.
|
|
@ -203,7 +203,7 @@ The latest version of Active Record can be installed with RubyGems:
|
||||||
|
|
||||||
Source code can be downloaded as part of the Rails project on GitHub
|
Source code can be downloaded as part of the Rails project on GitHub
|
||||||
|
|
||||||
* https://github.com/rails/rails/tree/3-2-stable/activerecord
|
* https://github.com/rails/rails/tree/master/activerecord
|
||||||
|
|
||||||
|
|
||||||
== License
|
== License
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
|
@ -46,7 +46,7 @@ module ActiveRecord
|
||||||
#
|
#
|
||||||
# def <=>(other_money)
|
# def <=>(other_money)
|
||||||
# if currency == other_money.currency
|
# if currency == other_money.currency
|
||||||
# amount <=> other_money.amount
|
# amount <=> amount
|
||||||
# else
|
# else
|
||||||
# amount <=> other_money.exchange_to(currency).amount
|
# amount <=> other_money.exchange_to(currency).amount
|
||||||
# end
|
# end
|
|
@ -1513,8 +1513,8 @@ module ActiveRecord
|
||||||
# * <tt>Developer#projects.size</tt>
|
# * <tt>Developer#projects.size</tt>
|
||||||
# * <tt>Developer#projects.find(id)</tt>
|
# * <tt>Developer#projects.find(id)</tt>
|
||||||
# * <tt>Developer#projects.exists?(...)</tt>
|
# * <tt>Developer#projects.exists?(...)</tt>
|
||||||
# * <tt>Developer#projects.build</tt> (similar to <tt>Project.new("developer_id" => id)</tt>)
|
# * <tt>Developer#projects.build</tt> (similar to <tt>Project.new("project_id" => id)</tt>)
|
||||||
# * <tt>Developer#projects.create</tt> (similar to <tt>c = Project.new("developer_id" => id); c.save; c</tt>)
|
# * <tt>Developer#projects.create</tt> (similar to <tt>c = Project.new("project_id" => id); c.save; c</tt>)
|
||||||
# The declaration may include an options hash to specialize the behavior of the association.
|
# The declaration may include an options hash to specialize the behavior of the association.
|
||||||
#
|
#
|
||||||
# === Options
|
# === Options
|
|
@ -5,13 +5,12 @@ module ActiveRecord
|
||||||
# Keeps track of table aliases for ActiveRecord::Associations::ClassMethods::JoinDependency and
|
# Keeps track of table aliases for ActiveRecord::Associations::ClassMethods::JoinDependency and
|
||||||
# ActiveRecord::Associations::ThroughAssociationScope
|
# ActiveRecord::Associations::ThroughAssociationScope
|
||||||
class AliasTracker # :nodoc:
|
class AliasTracker # :nodoc:
|
||||||
attr_reader :aliases, :table_joins, :connection
|
attr_reader :aliases, :table_joins
|
||||||
|
|
||||||
# table_joins is an array of arel joins which might conflict with the aliases we assign here
|
# table_joins is an array of arel joins which might conflict with the aliases we assign here
|
||||||
def initialize(connection = ActiveRecord::Model.connection, table_joins = [])
|
def initialize(table_joins = [])
|
||||||
@aliases = Hash.new { |h,k| h[k] = initial_count_for(k) }
|
@aliases = Hash.new { |h,k| h[k] = initial_count_for(k) }
|
||||||
@table_joins = table_joins
|
@table_joins = table_joins
|
||||||
@connection = connection
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def aliased_table_for(table_name, aliased_name = nil)
|
def aliased_table_for(table_name, aliased_name = nil)
|
||||||
|
@ -71,6 +70,10 @@ module ActiveRecord
|
||||||
def truncate(name)
|
def truncate(name)
|
||||||
name.slice(0, connection.table_alias_length - 2)
|
name.slice(0, connection.table_alias_length - 2)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def connection
|
||||||
|
ActiveRecord::Base.connection
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -231,8 +231,7 @@ module ActiveRecord
|
||||||
|
|
||||||
def build_record(attributes, options)
|
def build_record(attributes, options)
|
||||||
reflection.build_association(attributes, options) do |record|
|
reflection.build_association(attributes, options) do |record|
|
||||||
attributes = create_scope.except(*(record.changed - [reflection.foreign_key]))
|
record.assign_attributes(create_scope.except(*record.changed), :without_protection => true)
|
||||||
record.assign_attributes(attributes, :without_protection => true)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -10,7 +10,7 @@ module ActiveRecord
|
||||||
|
|
||||||
def initialize(association)
|
def initialize(association)
|
||||||
@association = association
|
@association = association
|
||||||
@alias_tracker = AliasTracker.new klass.connection
|
@alias_tracker = AliasTracker.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def scope
|
def scope
|
||||||
|
@ -75,7 +75,7 @@ module ActiveRecord
|
||||||
|
|
||||||
conditions.each do |condition|
|
conditions.each do |condition|
|
||||||
if options[:through] && condition.is_a?(Hash)
|
if options[:through] && condition.is_a?(Hash)
|
||||||
condition = disambiguate_condition(table, condition)
|
condition = { table.name => condition }
|
||||||
end
|
end
|
||||||
|
|
||||||
scope = scope.where(interpolate(condition))
|
scope = scope.where(interpolate(condition))
|
||||||
|
@ -114,21 +114,6 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def disambiguate_condition(table, condition)
|
|
||||||
if condition.is_a?(Hash)
|
|
||||||
Hash[
|
|
||||||
condition.map do |k, v|
|
|
||||||
if v.is_a?(Hash)
|
|
||||||
[k, v]
|
|
||||||
else
|
|
||||||
[table.table_alias || table.name, { k => v }]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
]
|
|
||||||
else
|
|
||||||
condition
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -154,7 +154,7 @@ module ActiveRecord
|
||||||
#
|
#
|
||||||
# See delete for more info.
|
# See delete for more info.
|
||||||
def delete_all
|
def delete_all
|
||||||
delete(:all).tap do
|
delete(load_target).tap do
|
||||||
reset
|
reset
|
||||||
loaded!
|
loaded!
|
||||||
end
|
end
|
||||||
|
@ -226,17 +226,7 @@ module ActiveRecord
|
||||||
# are actually removed from the database, that depends precisely on
|
# are actually removed from the database, that depends precisely on
|
||||||
# +delete_records+. They are in any case removed from the collection.
|
# +delete_records+. They are in any case removed from the collection.
|
||||||
def delete(*records)
|
def delete(*records)
|
||||||
dependent = options[:dependent]
|
delete_or_destroy(records, options[:dependent])
|
||||||
|
|
||||||
if records.first == :all
|
|
||||||
if loaded? || dependent == :destroy
|
|
||||||
delete_or_destroy(load_target, dependent)
|
|
||||||
else
|
|
||||||
delete_records(:all, dependent)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
delete_or_destroy(records, dependent)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Destroy +records+ and remove them from this association calling
|
# Destroy +records+ and remove them from this association calling
|
||||||
|
@ -491,8 +481,6 @@ module ActiveRecord
|
||||||
raise RecordNotSaved, "Failed to replace #{reflection.name} because one or more of the " \
|
raise RecordNotSaved, "Failed to replace #{reflection.name} because one or more of the " \
|
||||||
"new records could not be saved."
|
"new records could not be saved."
|
||||||
end
|
end
|
||||||
|
|
||||||
target
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def concat_records(records)
|
def concat_records(records)
|
|
@ -44,20 +44,13 @@ module ActiveRecord
|
||||||
|
|
||||||
def delete_records(records, method)
|
def delete_records(records, method)
|
||||||
if sql = options[:delete_sql]
|
if sql = options[:delete_sql]
|
||||||
records = load_target if records == :all
|
|
||||||
records.each { |record| owner.connection.delete(interpolate(sql, record)) }
|
records.each { |record| owner.connection.delete(interpolate(sql, record)) }
|
||||||
else
|
else
|
||||||
relation = join_table
|
relation = join_table
|
||||||
condition = relation[reflection.foreign_key].eq(owner.id)
|
stmt = relation.where(relation[reflection.foreign_key].eq(owner.id).
|
||||||
|
and(relation[reflection.association_foreign_key].in(records.map { |x| x.id }.compact))
|
||||||
unless records == :all
|
).compile_delete
|
||||||
condition = condition.and(
|
owner.connection.delete stmt
|
||||||
relation[reflection.association_foreign_key].
|
|
||||||
in(records.map { |x| x.id }.compact)
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
owner.connection.delete(relation.where(condition).compile_delete)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -89,12 +89,8 @@ module ActiveRecord
|
||||||
records.each { |r| r.destroy }
|
records.each { |r| r.destroy }
|
||||||
update_counter(-records.length) unless inverse_updates_counter_cache?
|
update_counter(-records.length) unless inverse_updates_counter_cache?
|
||||||
else
|
else
|
||||||
if records == :all
|
keys = records.map { |r| r[reflection.association_primary_key] }
|
||||||
scope = scoped
|
scope = scoped.where(reflection.association_primary_key => keys)
|
||||||
else
|
|
||||||
keys = records.map { |r| r[reflection.association_primary_key] }
|
|
||||||
scope = scoped.where(reflection.association_primary_key => keys)
|
|
||||||
end
|
|
||||||
|
|
||||||
if method == :delete_all
|
if method == :delete_all
|
||||||
update_counter(-scope.delete_all)
|
update_counter(-scope.delete_all)
|
|
@ -73,9 +73,7 @@ module ActiveRecord
|
||||||
# association
|
# association
|
||||||
def build_through_record(record)
|
def build_through_record(record)
|
||||||
@through_records[record.object_id] ||= begin
|
@through_records[record.object_id] ||= begin
|
||||||
ensure_mutable
|
through_record = through_association.build(construct_join_attributes(record))
|
||||||
|
|
||||||
through_record = through_association.build
|
|
||||||
through_record.send("#{source_reflection.name}=", record)
|
through_record.send("#{source_reflection.name}=", record)
|
||||||
through_record
|
through_record
|
||||||
end
|
end
|
||||||
|
@ -126,10 +124,6 @@ module ActiveRecord
|
||||||
def delete_records(records, method)
|
def delete_records(records, method)
|
||||||
ensure_not_nested
|
ensure_not_nested
|
||||||
|
|
||||||
# This is unoptimised; it will load all the target records
|
|
||||||
# even when we just want to delete everything.
|
|
||||||
records = load_target if records == :all
|
|
||||||
|
|
||||||
scope = through_association.scoped.where(construct_join_attributes(*records))
|
scope = through_association.scoped.where(construct_join_attributes(*records))
|
||||||
|
|
||||||
case method
|
case method
|
|
@ -13,7 +13,7 @@ module ActiveRecord
|
||||||
@join_parts = [JoinBase.new(base)]
|
@join_parts = [JoinBase.new(base)]
|
||||||
@associations = {}
|
@associations = {}
|
||||||
@reflections = []
|
@reflections = []
|
||||||
@alias_tracker = AliasTracker.new(base.connection, joins)
|
@alias_tracker = AliasTracker.new(joins)
|
||||||
@alias_tracker.aliased_name_for(base.table_name) # Updates the count for base.table_name to 1
|
@alias_tracker.aliased_name_for(base.table_name) # Updates the count for base.table_name to 1
|
||||||
build(associations)
|
build(associations)
|
||||||
end
|
end
|
|
@ -77,7 +77,7 @@ module ActiveRecord
|
||||||
# Some databases impose a limit on the number of ids in a list (in Oracle it's 1000)
|
# Some databases impose a limit on the number of ids in a list (in Oracle it's 1000)
|
||||||
# Make several smaller queries if necessary or make one query if the adapter supports it
|
# Make several smaller queries if necessary or make one query if the adapter supports it
|
||||||
sliced = owner_keys.each_slice(model.connection.in_clause_length || owner_keys.size)
|
sliced = owner_keys.each_slice(model.connection.in_clause_length || owner_keys.size)
|
||||||
records = sliced.map { |slice| records_for(slice).to_a }.flatten
|
records = sliced.map { |slice| records_for(slice) }.flatten
|
||||||
end
|
end
|
||||||
|
|
||||||
# Each record may have multiple owners, and vice-versa
|
# Each record may have multiple owners, and vice-versa
|
||||||
|
@ -93,8 +93,7 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_scope
|
def build_scope
|
||||||
scope = klass.unscoped
|
scope = klass.scoped
|
||||||
scope.default_scoped = true
|
|
||||||
|
|
||||||
scope = scope.where(process_conditions(options[:conditions]))
|
scope = scope.where(process_conditions(options[:conditions]))
|
||||||
scope = scope.where(process_conditions(preload_options[:conditions]))
|
scope = scope.where(process_conditions(preload_options[:conditions]))
|
|
@ -37,7 +37,9 @@ module ActiveRecord
|
||||||
# situation it is more natural for the user to just create or modify their join records
|
# situation it is more natural for the user to just create or modify their join records
|
||||||
# directly as required.
|
# directly as required.
|
||||||
def construct_join_attributes(*records)
|
def construct_join_attributes(*records)
|
||||||
ensure_mutable
|
if source_reflection.macro != :belongs_to
|
||||||
|
raise HasManyThroughCantAssociateThroughHasOneOrManyReflection.new(owner, reflection)
|
||||||
|
end
|
||||||
|
|
||||||
join_attributes = {
|
join_attributes = {
|
||||||
source_reflection.foreign_key =>
|
source_reflection.foreign_key =>
|
||||||
|
@ -71,12 +73,6 @@ module ActiveRecord
|
||||||
!owner[through_reflection.foreign_key].nil?
|
!owner[through_reflection.foreign_key].nil?
|
||||||
end
|
end
|
||||||
|
|
||||||
def ensure_mutable
|
|
||||||
if source_reflection.macro != :belongs_to
|
|
||||||
raise HasManyThroughCantAssociateThroughHasOneOrManyReflection.new(owner, reflection)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def ensure_not_nested
|
def ensure_not_nested
|
||||||
if reflection.nested?
|
if reflection.nested?
|
||||||
raise HasManyThroughNestedAssociationsAreReadonly.new(owner, reflection)
|
raise HasManyThroughNestedAssociationsAreReadonly.new(owner, reflection)
|
|
@ -64,7 +64,6 @@ module ActiveRecord
|
||||||
return if attribute_methods_generated?
|
return if attribute_methods_generated?
|
||||||
superclass.define_attribute_methods unless self == base_class
|
superclass.define_attribute_methods unless self == base_class
|
||||||
super(column_names)
|
super(column_names)
|
||||||
column_names.each { |name| define_external_attribute_method(name) }
|
|
||||||
@attribute_methods_generated = true
|
@attribute_methods_generated = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -213,7 +212,7 @@ module ActiveRecord
|
||||||
# nil nor empty? (the latter only applies to objects that respond to empty?, most notably Strings).
|
# nil nor empty? (the latter only applies to objects that respond to empty?, most notably Strings).
|
||||||
def attribute_present?(attribute)
|
def attribute_present?(attribute)
|
||||||
value = read_attribute(attribute)
|
value = read_attribute(attribute)
|
||||||
!value.nil? && !(value.respond_to?(:empty?) && value.empty?)
|
!value.nil? || (value.respond_to?(:empty?) && !value.empty?)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns the column object for the named attribute.
|
# Returns the column object for the named attribute.
|
|
@ -67,9 +67,19 @@ module ActiveRecord
|
||||||
# we first define with the __temp__ identifier, and then use alias method to
|
# we first define with the __temp__ identifier, and then use alias method to
|
||||||
# rename it to what we want.
|
# rename it to what we want.
|
||||||
def define_method_attribute(attr_name)
|
def define_method_attribute(attr_name)
|
||||||
|
cast_code = attribute_cast_code(attr_name)
|
||||||
|
|
||||||
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
||||||
def __temp__
|
def __temp__
|
||||||
#{internal_attribute_access_code(attr_name, attribute_cast_code(attr_name))}
|
#{internal_attribute_access_code(attr_name, cast_code)}
|
||||||
|
end
|
||||||
|
alias_method '#{attr_name}', :__temp__
|
||||||
|
undef_method :__temp__
|
||||||
|
STR
|
||||||
|
|
||||||
|
generated_external_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
||||||
|
def __temp__(v, attributes, attributes_cache, attr_name)
|
||||||
|
#{external_attribute_access_code(attr_name, cast_code)}
|
||||||
end
|
end
|
||||||
alias_method '#{attr_name}', :__temp__
|
alias_method '#{attr_name}', :__temp__
|
||||||
undef_method :__temp__
|
undef_method :__temp__
|
||||||
|
@ -77,17 +87,6 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def define_external_attribute_method(attr_name)
|
|
||||||
generated_external_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
|
|
||||||
def __temp__(v, attributes, attributes_cache, attr_name)
|
|
||||||
#{external_attribute_access_code(attr_name, attribute_cast_code(attr_name))}
|
|
||||||
end
|
|
||||||
alias_method '#{attr_name}', :__temp__
|
|
||||||
undef_method :__temp__
|
|
||||||
STR
|
|
||||||
end
|
|
||||||
|
|
||||||
def cacheable_column?(column)
|
def cacheable_column?(column)
|
||||||
attribute_types_cached_by_default.include?(column.type)
|
attribute_types_cached_by_default.include?(column.type)
|
||||||
end
|
end
|
|
@ -43,7 +43,6 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
time = time.in_time_zone rescue nil if time
|
time = time.in_time_zone rescue nil if time
|
||||||
write_attribute(:#{attr_name}, original_time)
|
write_attribute(:#{attr_name}, original_time)
|
||||||
#{attr_name}_will_change!
|
|
||||||
@attributes_cache["#{attr_name}"] = time
|
@attributes_cache["#{attr_name}"] = time
|
||||||
end
|
end
|
||||||
EOV
|
EOV
|
|
@ -208,9 +208,6 @@ module ActiveRecord #:nodoc:
|
||||||
# # Now 'Bob' exist and is an 'admin'
|
# # Now 'Bob' exist and is an 'admin'
|
||||||
# User.find_or_create_by_name('Bob', :age => 40) { |u| u.admin = true }
|
# User.find_or_create_by_name('Bob', :age => 40) { |u| u.admin = true }
|
||||||
#
|
#
|
||||||
# Adding an exclamation point (!) on to the end of <tt>find_or_create_by_</tt> will
|
|
||||||
# raise an <tt>ActiveRecord::RecordInvalid</tt> error if the new record is invalid.
|
|
||||||
#
|
|
||||||
# Use the <tt>find_or_initialize_by_</tt> finder if you want to return a new record without
|
# Use the <tt>find_or_initialize_by_</tt> finder if you want to return a new record without
|
||||||
# saving it first. Protected attributes won't be set unless they are given in a block.
|
# saving it first. Protected attributes won't be set unless they are given in a block.
|
||||||
#
|
#
|
||||||
|
@ -442,7 +439,7 @@ module ActiveRecord #:nodoc:
|
||||||
if self == ActiveRecord::Base
|
if self == ActiveRecord::Base
|
||||||
ActiveRecord::Base
|
ActiveRecord::Base
|
||||||
else
|
else
|
||||||
connection_handler.retrieve_connection_pool(self) ? self : superclass.arel_engine
|
connection_handler.connection_pools[name] ? self : superclass.arel_engine
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -92,18 +92,13 @@ module ActiveRecord
|
||||||
# #connection can be called any number of times; the connection is
|
# #connection can be called any number of times; the connection is
|
||||||
# held in a hash keyed by the thread id.
|
# held in a hash keyed by the thread id.
|
||||||
def connection
|
def connection
|
||||||
synchronize do
|
@reserved_connections[current_connection_id] ||= checkout
|
||||||
@reserved_connections[current_connection_id] ||= checkout
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Is there an open connection that is being used for the current thread?
|
# Check to see if there is an active connection in this connection
|
||||||
|
# pool.
|
||||||
def active_connection?
|
def active_connection?
|
||||||
synchronize do
|
active_connections.any?
|
||||||
@reserved_connections.fetch(current_connection_id) {
|
|
||||||
return false
|
|
||||||
}.in_use?
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Signal that the thread is finished with the current connection.
|
# Signal that the thread is finished with the current connection.
|
||||||
|
@ -230,9 +225,8 @@ connection. For example: ActiveRecord::Base.connection.close
|
||||||
# - ConnectionTimeoutError: no connection can be obtained from the pool
|
# - ConnectionTimeoutError: no connection can be obtained from the pool
|
||||||
# within the timeout period.
|
# within the timeout period.
|
||||||
def checkout
|
def checkout
|
||||||
|
# Checkout an available connection
|
||||||
synchronize do
|
synchronize do
|
||||||
waited_time = 0
|
|
||||||
|
|
||||||
loop do
|
loop do
|
||||||
conn = @connections.find { |c| c.lease }
|
conn = @connections.find { |c| c.lease }
|
||||||
|
|
||||||
|
@ -248,25 +242,17 @@ connection. For example: ActiveRecord::Base.connection.close
|
||||||
return conn
|
return conn
|
||||||
end
|
end
|
||||||
|
|
||||||
if waited_time >= @timeout
|
@queue.wait(@timeout)
|
||||||
raise ConnectionTimeoutError, "could not obtain a database connection#{" within #{@timeout} seconds" if @timeout} (waited #{waited_time} seconds). The max pool size is currently #{@size}; consider increasing it."
|
|
||||||
end
|
|
||||||
|
|
||||||
# Sometimes our wait can end because a connection is available,
|
if(active_connections.size < @connections.size)
|
||||||
# but another thread can snatch it up first. If timeout hasn't
|
next
|
||||||
# passed but no connection is avail, looks like that happened --
|
else
|
||||||
# loop and wait again, for the time remaining on our timeout.
|
|
||||||
before_wait = Time.now
|
|
||||||
@queue.wait( [@timeout - waited_time, 0].max )
|
|
||||||
waited_time += (Time.now - before_wait)
|
|
||||||
|
|
||||||
# Will go away in Rails 4, when we don't clean up
|
|
||||||
# after leaked connections automatically anymore. Right now, clean
|
|
||||||
# up after we've returned from a 'wait' if it looks like it's
|
|
||||||
# needed, then loop and try again.
|
|
||||||
if(active_connections.size >= @connections.size)
|
|
||||||
clear_stale_cached_connections!
|
clear_stale_cached_connections!
|
||||||
|
if @size == active_connections.size
|
||||||
|
raise ConnectionTimeoutError, "could not obtain a database connection#{" within #{@timeout} seconds" if @timeout}. The max pool size is currently #{@size}; consider increasing it."
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -282,29 +268,11 @@ connection. For example: ActiveRecord::Base.connection.close
|
||||||
conn.expire
|
conn.expire
|
||||||
@queue.signal
|
@queue.signal
|
||||||
end
|
end
|
||||||
|
|
||||||
release conn
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def release(conn)
|
|
||||||
synchronize do
|
|
||||||
thread_id = nil
|
|
||||||
|
|
||||||
if @reserved_connections[current_connection_id] == conn
|
|
||||||
thread_id = current_connection_id
|
|
||||||
else
|
|
||||||
thread_id = @reserved_connections.keys.find { |k|
|
|
||||||
@reserved_connections[k] == conn
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
@reserved_connections.delete thread_id if thread_id
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def new_connection
|
def new_connection
|
||||||
ActiveRecord::Base.send(spec.adapter_method, spec.config)
|
ActiveRecord::Base.send(spec.adapter_method, spec.config)
|
||||||
end
|
end
|
||||||
|
@ -376,7 +344,9 @@ connection. For example: ActiveRecord::Base.connection.close
|
||||||
connection_pools.values.any? { |pool| pool.active_connection? }
|
connection_pools.values.any? { |pool| pool.active_connection? }
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns any connections in use by the current thread back to the pool.
|
# Returns any connections in use by the current thread back to the pool,
|
||||||
|
# and also returns connections to the pool cached by threads that are no
|
||||||
|
# longer alive.
|
||||||
def clear_active_connections!
|
def clear_active_connections!
|
||||||
@connection_pools.each_value {|pool| pool.release_connection }
|
@connection_pools.each_value {|pool| pool.release_connection }
|
||||||
end
|
end
|
|
@ -160,7 +160,7 @@ module ActiveRecord
|
||||||
yield td if block_given?
|
yield td if block_given?
|
||||||
|
|
||||||
if options[:force] && table_exists?(table_name)
|
if options[:force] && table_exists?(table_name)
|
||||||
drop_table(table_name, options)
|
drop_table(table_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
create_sql = "CREATE#{' TEMPORARY' if options[:temporary]} TABLE "
|
create_sql = "CREATE#{' TEMPORARY' if options[:temporary]} TABLE "
|
||||||
|
@ -252,7 +252,7 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
# Drops a table from the database.
|
# Drops a table from the database.
|
||||||
def drop_table(table_name, options = {})
|
def drop_table(table_name)
|
||||||
execute "DROP TABLE #{quote_table_name(table_name)}"
|
execute "DROP TABLE #{quote_table_name(table_name)}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -269,15 +269,7 @@ module ActiveRecord
|
||||||
# remove_column(:suppliers, :qualification)
|
# remove_column(:suppliers, :qualification)
|
||||||
# remove_columns(:suppliers, :qualification, :experience)
|
# remove_columns(:suppliers, :qualification, :experience)
|
||||||
def remove_column(table_name, *column_names)
|
def remove_column(table_name, *column_names)
|
||||||
if column_names.flatten!
|
columns_for_remove(table_name, *column_names).each {|column_name| execute "ALTER TABLE #{quote_table_name(table_name)} DROP #{column_name}" }
|
||||||
message = 'Passing array to remove_columns is deprecated, please use ' +
|
|
||||||
'multiple arguments, like: `remove_columns(:posts, :foo, :bar)`'
|
|
||||||
ActiveSupport::Deprecation.warn message, caller
|
|
||||||
end
|
|
||||||
|
|
||||||
columns_for_remove(table_name, *column_names).each do |column_name|
|
|
||||||
execute "ALTER TABLE #{quote_table_name(table_name)} DROP #{column_name}"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
alias :remove_columns :remove_column
|
alias :remove_columns :remove_column
|
||||||
|
|
||||||
|
@ -516,8 +508,8 @@ module ActiveRecord
|
||||||
# ===== Examples
|
# ===== Examples
|
||||||
# add_timestamps(:suppliers)
|
# add_timestamps(:suppliers)
|
||||||
def add_timestamps(table_name)
|
def add_timestamps(table_name)
|
||||||
add_column table_name, :created_at, :datetime
|
add_column table_name, :created_at, :datetime, :null => false
|
||||||
add_column table_name, :updated_at, :datetime
|
add_column table_name, :updated_at, :datetime, :null => false
|
||||||
end
|
end
|
||||||
|
|
||||||
# Removes the timestamp columns (created_at and updated_at) from the table definition.
|
# Removes the timestamp columns (created_at and updated_at) from the table definition.
|
|
@ -54,7 +54,7 @@ module ActiveRecord
|
||||||
define_callbacks :checkout, :checkin
|
define_callbacks :checkout, :checkin
|
||||||
|
|
||||||
attr_accessor :visitor, :pool
|
attr_accessor :visitor, :pool
|
||||||
attr_reader :schema_cache, :last_use, :in_use, :logger
|
attr_reader :schema_cache, :last_use, :in_use
|
||||||
alias :in_use? :in_use
|
alias :in_use? :in_use
|
||||||
|
|
||||||
def initialize(connection, logger = nil, pool = nil) #:nodoc:
|
def initialize(connection, logger = nil, pool = nil) #:nodoc:
|
|
@ -484,26 +484,15 @@ module ActiveRecord
|
||||||
|
|
||||||
# Maps logical Rails types to MySQL-specific data types.
|
# Maps logical Rails types to MySQL-specific data types.
|
||||||
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
|
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
|
||||||
case type.to_s
|
return super unless type.to_s == 'integer'
|
||||||
when 'integer'
|
|
||||||
case limit
|
case limit
|
||||||
when 1; 'tinyint'
|
when 1; 'tinyint'
|
||||||
when 2; 'smallint'
|
when 2; 'smallint'
|
||||||
when 3; 'mediumint'
|
when 3; 'mediumint'
|
||||||
when nil, 4, 11; 'int(11)' # compatibility with MySQL default
|
when nil, 4, 11; 'int(11)' # compatibility with MySQL default
|
||||||
when 5..8; 'bigint'
|
when 5..8; 'bigint'
|
||||||
else raise(ActiveRecordError, "No integer type has byte size #{limit}")
|
else raise(ActiveRecordError, "No integer type has byte size #{limit}")
|
||||||
end
|
|
||||||
when 'text'
|
|
||||||
case limit
|
|
||||||
when 0..0xff; 'tinytext'
|
|
||||||
when nil, 0x100..0xffff; 'text'
|
|
||||||
when 0x10000..0xffffff; 'mediumtext'
|
|
||||||
when 0x1000000..0xffffffff; 'longtext'
|
|
||||||
else raise(ActiveRecordError, "No text type has character length #{limit}")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
super
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -525,7 +514,7 @@ module ActiveRecord
|
||||||
def pk_and_sequence_for(table)
|
def pk_and_sequence_for(table)
|
||||||
execute_and_free("SHOW CREATE TABLE #{quote_table_name(table)}", 'SCHEMA') do |result|
|
execute_and_free("SHOW CREATE TABLE #{quote_table_name(table)}", 'SCHEMA') do |result|
|
||||||
create_table = each_hash(result).first[:"Create Table"]
|
create_table = each_hash(result).first[:"Create Table"]
|
||||||
if create_table.to_s =~ /PRIMARY KEY\s+(?:USING\s+\w+\s+)?\((.+)\)/
|
if create_table.to_s =~ /PRIMARY KEY\s+\((.+)\)/
|
||||||
keys = $1.split(",").map { |key| key.gsub(/[`"]/, "") }
|
keys = $1.split(",").map { |key| key.gsub(/[`"]/, "") }
|
||||||
keys.length == 1 ? [keys.first, nil] : nil
|
keys.length == 1 ? [keys.first, nil] : nil
|
||||||
else
|
else
|
|
@ -264,7 +264,7 @@ module ActiveRecord
|
||||||
|
|
||||||
# increase timeout so mysql server doesn't disconnect us
|
# increase timeout so mysql server doesn't disconnect us
|
||||||
wait_timeout = @config[:wait_timeout]
|
wait_timeout = @config[:wait_timeout]
|
||||||
wait_timeout = 2147483 unless wait_timeout.is_a?(Fixnum)
|
wait_timeout = 2592000 unless wait_timeout.is_a?(Fixnum)
|
||||||
variable_assignments << "@@wait_timeout = #{wait_timeout}"
|
variable_assignments << "@@wait_timeout = #{wait_timeout}"
|
||||||
|
|
||||||
execute("SET #{variable_assignments.join(', ')}", :skip_logging)
|
execute("SET #{variable_assignments.join(', ')}", :skip_logging)
|
|
@ -885,7 +885,7 @@ module ActiveRecord
|
||||||
# This should be not be called manually but set in database.yml.
|
# This should be not be called manually but set in database.yml.
|
||||||
def schema_search_path=(schema_csv)
|
def schema_search_path=(schema_csv)
|
||||||
if schema_csv
|
if schema_csv
|
||||||
execute("SET search_path TO #{schema_csv}", 'SCHEMA')
|
execute "SET search_path TO #{schema_csv}"
|
||||||
@schema_search_path = schema_csv
|
@schema_search_path = schema_csv
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1067,25 +1067,14 @@ module ActiveRecord
|
||||||
|
|
||||||
# Maps logical Rails types to PostgreSQL-specific data types.
|
# Maps logical Rails types to PostgreSQL-specific data types.
|
||||||
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
|
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
|
||||||
case type.to_s
|
return super unless type.to_s == 'integer'
|
||||||
when 'binary'
|
return 'integer' unless limit
|
||||||
# PostgreSQL doesn't support limits on binary (bytea) columns.
|
|
||||||
# The hard limit is 1Gb, because of a 32-bit size field, and TOAST.
|
case limit
|
||||||
case limit
|
when 1, 2; 'smallint'
|
||||||
when nil, 0..0x3fffffff; super(type)
|
when 3, 4; 'integer'
|
||||||
else raise(ActiveRecordError, "No binary type has byte size #{limit}.")
|
when 5..8; 'bigint'
|
||||||
end
|
else raise(ActiveRecordError, "No integer type has byte size #{limit}. Use a numeric with precision 0 instead.")
|
||||||
when 'integer'
|
|
||||||
return 'integer' unless limit
|
|
||||||
|
|
||||||
case limit
|
|
||||||
when 1, 2; 'smallint'
|
|
||||||
when 3, 4; 'integer'
|
|
||||||
when 5..8; 'bigint'
|
|
||||||
else raise(ActiveRecordError, "No integer type has byte size #{limit}. Use a numeric with precision 0 instead.")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
super
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -204,7 +204,7 @@ module ActiveRecord
|
||||||
|
|
||||||
value = super
|
value = super
|
||||||
if column.type == :string && value.encoding == Encoding::ASCII_8BIT
|
if column.type == :string && value.encoding == Encoding::ASCII_8BIT
|
||||||
logger.error "Binary data inserted for `string` type on column `#{column.name}`" if logger
|
@logger.error "Binary data inserted for `string` type on column `#{column.name}`"
|
||||||
value.encode! 'utf-8'
|
value.encode! 'utf-8'
|
||||||
end
|
end
|
||||||
value
|
value
|
||||||
|
@ -407,14 +407,7 @@ module ActiveRecord
|
||||||
|
|
||||||
def remove_column(table_name, *column_names) #:nodoc:
|
def remove_column(table_name, *column_names) #:nodoc:
|
||||||
raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_names.empty?
|
raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_names.empty?
|
||||||
|
column_names.flatten.each do |column_name|
|
||||||
if column_names.flatten!
|
|
||||||
message = 'Passing array to remove_columns is deprecated, please use ' +
|
|
||||||
'multiple arguments, like: `remove_columns(:posts, :foo, :bar)`'
|
|
||||||
ActiveSupport::Deprecation.warn message, caller
|
|
||||||
end
|
|
||||||
|
|
||||||
column_names.each do |column_name|
|
|
||||||
alter_table(table_name) do |definition|
|
alter_table(table_name) do |definition|
|
||||||
definition.columns.delete(definition[column_name])
|
definition.columns.delete(definition[column_name])
|
||||||
end
|
end
|
|
@ -18,10 +18,6 @@ module ActiveRecord
|
||||||
when /^find_by_([_a-zA-Z]\w*)\!$/
|
when /^find_by_([_a-zA-Z]\w*)\!$/
|
||||||
bang = true
|
bang = true
|
||||||
names = $1
|
names = $1
|
||||||
when /^find_or_create_by_([_a-zA-Z]\w*)\!$/
|
|
||||||
bang = true
|
|
||||||
instantiator = :create
|
|
||||||
names = $1
|
|
||||||
when /^find_or_(initialize|create)_by_([_a-zA-Z]\w*)$/
|
when /^find_or_(initialize|create)_by_([_a-zA-Z]\w*)$/
|
||||||
instantiator = $1 == 'initialize' ? :new : :create
|
instantiator = $1 == 'initialize' ? :new : :create
|
||||||
names = $2
|
names = $2
|
||||||
|
@ -56,13 +52,5 @@ module ActiveRecord
|
||||||
def bang?
|
def bang?
|
||||||
@bang
|
@bang
|
||||||
end
|
end
|
||||||
|
|
||||||
def save_record?
|
|
||||||
@instantiator == :create
|
|
||||||
end
|
|
||||||
|
|
||||||
def save_method
|
|
||||||
bang? ? :save! : :save
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -419,15 +419,11 @@ module ActiveRecord
|
||||||
cache_for_connection(connection).update(fixtures_map)
|
cache_for_connection(connection).update(fixtures_map)
|
||||||
end
|
end
|
||||||
|
|
||||||
#--
|
def self.instantiate_fixtures(object, fixture_name, fixtures, load_instances = true)
|
||||||
# TODO:NOTE: in the next version, the __with_new_arity suffix and
|
|
||||||
# the method with the old arity will be removed.
|
|
||||||
#++
|
|
||||||
def self.instantiate_fixtures__with_new_arity(object, fixture_set, load_instances = true) # :nodoc:
|
|
||||||
if load_instances
|
if load_instances
|
||||||
fixture_set.each do |fixture_name, fixture|
|
fixtures.each do |name, fixture|
|
||||||
begin
|
begin
|
||||||
object.instance_variable_set "@#{fixture_name}", fixture.find
|
object.instance_variable_set "@#{name}", fixture.find
|
||||||
rescue FixtureClassNotFound
|
rescue FixtureClassNotFound
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
@ -435,24 +431,9 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# The use with parameters <tt>(object, fixture_set_name, fixture_set, load_instances = true)</tt> is deprecated, +fixture_set_name+ parameter is not used.
|
|
||||||
# Use as:
|
|
||||||
#
|
|
||||||
# instantiate_fixtures(object, fixture_set, load_instances = true)
|
|
||||||
def self.instantiate_fixtures(object, fixture_set, load_instances = true, rails_3_2_compatibility_argument = true)
|
|
||||||
unless load_instances == true || load_instances == false
|
|
||||||
ActiveSupport::Deprecation.warn(
|
|
||||||
"ActiveRecord::Fixtures.instantiate_fixtures with parameters (object, fixture_set_name, fixture_set, load_instances = true) is deprecated and shall be removed from future releases. Use it with parameters (object, fixture_set, load_instances = true) instead (skip fixture_set_name).",
|
|
||||||
caller)
|
|
||||||
fixture_set = load_instances
|
|
||||||
load_instances = rails_3_2_compatibility_argument
|
|
||||||
end
|
|
||||||
instantiate_fixtures__with_new_arity(object, fixture_set, load_instances)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.instantiate_all_loaded_fixtures(object, load_instances = true)
|
def self.instantiate_all_loaded_fixtures(object, load_instances = true)
|
||||||
all_loaded_fixtures.each_value do |fixture_set|
|
all_loaded_fixtures.each do |table_name, fixtures|
|
||||||
ActiveRecord::Fixtures.instantiate_fixtures(object, fixture_set, load_instances)
|
ActiveRecord::Fixtures.instantiate_fixtures(object, table_name, fixtures, load_instances)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -678,6 +659,9 @@ module ActiveRecord
|
||||||
"#{@fixture_path}.yml"
|
"#{@fixture_path}.yml"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def yaml_fixtures_key(path)
|
||||||
|
::File.basename(@fixture_path).split(".").first
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Fixture #:nodoc:
|
class Fixture #:nodoc:
|
||||||
|
@ -909,8 +893,8 @@ module ActiveRecord
|
||||||
ActiveRecord::Fixtures.instantiate_all_loaded_fixtures(self, load_instances?)
|
ActiveRecord::Fixtures.instantiate_all_loaded_fixtures(self, load_instances?)
|
||||||
else
|
else
|
||||||
raise RuntimeError, 'Load fixtures before instantiating them.' if @loaded_fixtures.nil?
|
raise RuntimeError, 'Load fixtures before instantiating them.' if @loaded_fixtures.nil?
|
||||||
@loaded_fixtures.each_value do |fixture_set|
|
@loaded_fixtures.each do |fixture_name, fixtures|
|
||||||
ActiveRecord::Fixtures.instantiate_fixtures(self, fixture_set, load_instances?)
|
ActiveRecord::Fixtures.instantiate_fixtures(self, fixture_name, fixtures, load_instances?)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue