activerecord 2.0.2 → 2.0.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- data/CHANGELOG +25 -0
- data/README +0 -0
- data/Rakefile +5 -3
- data/lib/active_record.rb +0 -0
- data/lib/active_record/associations.rb +232 -193
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +14 -14
- data/lib/active_record/associations/has_many_association.rb +2 -2
- data/lib/active_record/associations/has_many_through_association.rb +25 -6
- data/lib/active_record/attribute_methods.rb +4 -3
- data/lib/active_record/base.rb +75 -41
- data/lib/active_record/calculations.rb +2 -1
- data/lib/active_record/callbacks.rb +0 -0
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +8 -6
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +12 -11
- data/lib/active_record/connection_adapters/abstract_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +3 -3
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +13 -6
- data/lib/active_record/fixtures.rb +29 -31
- data/lib/active_record/migration.rb +4 -5
- data/lib/active_record/observer.rb +1 -1
- data/lib/active_record/transactions.rb +3 -5
- data/lib/active_record/validations.rb +5 -3
- data/lib/active_record/version.rb +1 -1
- data/test/abstract_unit.rb +0 -0
- data/test/active_schema_test_mysql.rb +5 -2
- data/test/adapter_test.rb +1 -0
- data/test/all.sh +0 -0
- data/test/associations/callbacks_test.rb +1 -1
- data/test/associations/eager_test.rb +5 -0
- data/test/associations/join_model_test.rb +11 -3
- data/test/associations_test.rb +36 -6
- data/test/attribute_methods_test.rb +0 -0
- data/test/base_test.rb +92 -10
- data/test/calculations_test.rb +9 -1
- data/test/debug.log +358 -0
- data/test/deprecated_finder_test.rb +0 -0
- data/test/fixtures/author.rb +1 -1
- data/test/fixtures/company.rb +0 -0
- data/test/fixtures/fixture_database.sqlite3 +0 -0
- data/test/fixtures/fixture_database_2.sqlite3 +0 -0
- data/test/fixtures/reply.rb +0 -0
- data/test/fixtures/topic.rb +0 -0
- data/test/fixtures_test.rb +20 -12
- data/test/inheritance_test.rb +0 -0
- data/test/lifecycle_test.rb +0 -0
- data/test/migration_test.rb +46 -0
- data/test/query_cache_test.rb +22 -2
- data/test/readonly_test.rb +0 -0
- data/test/unconnected_test.rb +0 -0
- data/test/validations_test.rb +50 -38
- metadata +8 -4
@@ -14,7 +14,7 @@ module ActiveRecord
|
|
14
14
|
def create(attributes = {})
|
15
15
|
create_record(attributes) { |record| insert_record(record) }
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
def create!(attributes = {})
|
19
19
|
create_record(attributes) { |record| insert_record(record, true) }
|
20
20
|
end
|
@@ -33,10 +33,10 @@ module ActiveRecord
|
|
33
33
|
|
34
34
|
if ids.size == 1
|
35
35
|
id = ids.first.to_i
|
36
|
-
record = load_target.detect { |
|
36
|
+
record = load_target.detect { |r| id == r.id }
|
37
37
|
expects_array ? [record] : record
|
38
38
|
else
|
39
|
-
load_target.select { |
|
39
|
+
load_target.select { |r| ids.include?(r.id) }
|
40
40
|
end
|
41
41
|
else
|
42
42
|
conditions = "#{@finder_sql}"
|
@@ -80,30 +80,30 @@ module ActiveRecord
|
|
80
80
|
end
|
81
81
|
|
82
82
|
if @reflection.options[:insert_sql]
|
83
|
-
@owner.connection.
|
83
|
+
@owner.connection.insert(interpolate_sql(@reflection.options[:insert_sql], record))
|
84
84
|
else
|
85
85
|
columns = @owner.connection.columns(@reflection.options[:join_table], "#{@reflection.options[:join_table]} Columns")
|
86
86
|
|
87
|
-
attributes = columns.inject({}) do |
|
87
|
+
attributes = columns.inject({}) do |attrs, column|
|
88
88
|
case column.name
|
89
89
|
when @reflection.primary_key_name
|
90
|
-
|
90
|
+
attrs[column.name] = @owner.quoted_id
|
91
91
|
when @reflection.association_foreign_key
|
92
|
-
|
92
|
+
attrs[column.name] = record.quoted_id
|
93
93
|
else
|
94
|
-
if record.
|
94
|
+
if record.has_attribute?(column.name)
|
95
95
|
value = @owner.send(:quote_value, record[column.name], column)
|
96
|
-
|
96
|
+
attrs[column.name] = value unless value.nil?
|
97
97
|
end
|
98
98
|
end
|
99
|
-
|
99
|
+
attrs
|
100
100
|
end
|
101
101
|
|
102
102
|
sql =
|
103
103
|
"INSERT INTO #{@reflection.options[:join_table]} (#{@owner.send(:quoted_column_names, attributes).join(', ')}) " +
|
104
104
|
"VALUES (#{attributes.values.join(', ')})"
|
105
105
|
|
106
|
-
@owner.connection.
|
106
|
+
@owner.connection.insert(sql)
|
107
107
|
end
|
108
108
|
|
109
109
|
return true
|
@@ -111,11 +111,11 @@ module ActiveRecord
|
|
111
111
|
|
112
112
|
def delete_records(records)
|
113
113
|
if sql = @reflection.options[:delete_sql]
|
114
|
-
records.each { |record| @owner.connection.
|
114
|
+
records.each { |record| @owner.connection.delete(interpolate_sql(sql, record)) }
|
115
115
|
else
|
116
116
|
ids = quoted_record_ids(records)
|
117
|
-
sql = "DELETE FROM #{@reflection.options[:join_table]} WHERE #{@reflection.primary_key_name} = #{@owner.quoted_id} AND #{@reflection.association_foreign_key} IN (#{ids})"
|
118
|
-
@owner.connection.
|
117
|
+
sql = "DELETE FROM #{@owner.connection.quote_table_name @reflection.options[:join_table]} WHERE #{@reflection.primary_key_name} = #{@owner.quoted_id} AND #{@reflection.association_foreign_key} IN (#{ids})"
|
118
|
+
@owner.connection.delete(sql)
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
@@ -41,10 +41,10 @@ module ActiveRecord
|
|
41
41
|
|
42
42
|
if ids.size == 1
|
43
43
|
id = ids.first
|
44
|
-
record = load_target.detect { |
|
44
|
+
record = load_target.detect { |r| id == r.id }
|
45
45
|
expects_array ? [ record ] : record
|
46
46
|
else
|
47
|
-
load_target.select { |
|
47
|
+
load_target.select { |r| ids.include?(r.id) }
|
48
48
|
end
|
49
49
|
else
|
50
50
|
conditions = "#{@finder_sql}"
|
@@ -262,12 +262,31 @@ module ActiveRecord
|
|
262
262
|
end
|
263
263
|
|
264
264
|
def conditions
|
265
|
-
@conditions
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
265
|
+
@conditions = build_conditions unless defined?(@conditions)
|
266
|
+
@conditions
|
267
|
+
end
|
268
|
+
|
269
|
+
def build_conditions
|
270
|
+
association_conditions = @reflection.options[:conditions]
|
271
|
+
through_conditions = @reflection.through_reflection.options[:conditions]
|
272
|
+
source_conditions = @reflection.source_reflection.options[:conditions]
|
273
|
+
uses_sti = !@reflection.through_reflection.klass.descends_from_active_record?
|
274
|
+
|
275
|
+
if association_conditions || through_conditions || source_conditions || uses_sti
|
276
|
+
all = []
|
277
|
+
|
278
|
+
[association_conditions, through_conditions, source_conditions].each do |conditions|
|
279
|
+
all << interpolate_sql(sanitize_sql(conditions)) if conditions
|
280
|
+
end
|
281
|
+
|
282
|
+
all << build_sti_condition if uses_sti
|
283
|
+
|
284
|
+
all.map { |sql| "(#{sql})" } * ' AND '
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def build_sti_condition
|
289
|
+
"#{@reflection.through_reflection.table_name}.#{@reflection.through_reflection.klass.inheritance_column} = #{@reflection.klass.quote_value(@reflection.through_reflection.klass.name.demodulize)}"
|
271
290
|
end
|
272
291
|
|
273
292
|
alias_method :sql_conditions, :conditions
|
@@ -5,7 +5,7 @@ module ActiveRecord
|
|
5
5
|
|
6
6
|
def self.included(base)
|
7
7
|
base.extend ClassMethods
|
8
|
-
base.attribute_method_suffix
|
8
|
+
base.attribute_method_suffix(*DEFAULT_SUFFIXES)
|
9
9
|
base.cattr_accessor :attribute_types_cached_by_default, :instance_writer => false
|
10
10
|
base.attribute_types_cached_by_default = ATTRIBUTE_TYPES_CACHED_BY_DEFAULT
|
11
11
|
end
|
@@ -82,9 +82,10 @@ module ActiveRecord
|
|
82
82
|
# Check to see if the method is defined in the model or any of its subclasses that also derive from ActiveRecord.
|
83
83
|
# Raise DangerousAttributeError if the method is defined by ActiveRecord though.
|
84
84
|
def instance_method_already_implemented?(method_name)
|
85
|
+
method_name = method_name.to_s
|
85
86
|
return true if method_name =~ /^id(=$|\?$|$)/
|
86
|
-
@_defined_class_methods ||=
|
87
|
-
@@_defined_activerecord_methods ||=
|
87
|
+
@_defined_class_methods ||= ancestors.first(ancestors.index(ActiveRecord::Base)).sum([]) { |m| m.public_instance_methods(false) | m.private_instance_methods(false) | m.protected_instance_methods(false) }.map(&:to_s).to_set
|
88
|
+
@@_defined_activerecord_methods ||= (ActiveRecord::Base.public_instance_methods(false) | ActiveRecord::Base.private_instance_methods(false) | ActiveRecord::Base.protected_instance_methods(false)).map(&:to_s).to_set
|
88
89
|
raise DangerousAttributeError, "#{method_name} is defined by ActiveRecord" if @@_defined_activerecord_methods.include?(method_name)
|
89
90
|
@_defined_class_methods.include?(method_name)
|
90
91
|
end
|
data/lib/active_record/base.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'base64'
|
2
1
|
require 'yaml'
|
3
2
|
require 'set'
|
4
3
|
|
@@ -549,8 +548,14 @@ module ActiveRecord #:nodoc:
|
|
549
548
|
# Person.exists?(:name => "David")
|
550
549
|
# Person.exists?(['name LIKE ?', "%#{query}%"])
|
551
550
|
def exists?(id_or_conditions)
|
552
|
-
|
553
|
-
|
551
|
+
connection.select_all(
|
552
|
+
construct_finder_sql(
|
553
|
+
:select => "#{quoted_table_name}.#{primary_key}",
|
554
|
+
:conditions => expand_id_conditions(id_or_conditions),
|
555
|
+
:limit => 1
|
556
|
+
),
|
557
|
+
"#{name} Exists"
|
558
|
+
).size > 0
|
554
559
|
end
|
555
560
|
|
556
561
|
# Creates an object (or multiple objects) and saves it to the database, if validations pass.
|
@@ -593,7 +598,7 @@ module ActiveRecord #:nodoc:
|
|
593
598
|
def update(id, attributes)
|
594
599
|
if id.is_a?(Array)
|
595
600
|
idx = -1
|
596
|
-
id.collect { |
|
601
|
+
id.collect { |one_id| idx += 1; update(one_id, attributes[idx]) }
|
597
602
|
else
|
598
603
|
object = find(id)
|
599
604
|
object.update_attributes(attributes)
|
@@ -643,7 +648,11 @@ module ActiveRecord #:nodoc:
|
|
643
648
|
# todos = [1,2,3]
|
644
649
|
# Todo.destroy(todos)
|
645
650
|
def destroy(id)
|
646
|
-
id.is_a?(Array)
|
651
|
+
if id.is_a?(Array)
|
652
|
+
id.map { |one_id| destroy(one_id) }
|
653
|
+
else
|
654
|
+
find(id).destroy
|
655
|
+
end
|
647
656
|
end
|
648
657
|
|
649
658
|
# Updates all records with details given if they match a set of conditions supplied, limits and order can
|
@@ -671,8 +680,8 @@ module ActiveRecord #:nodoc:
|
|
671
680
|
sql = "UPDATE #{table_name} SET #{sanitize_sql_for_assignment(updates)} "
|
672
681
|
scope = scope(:find)
|
673
682
|
add_conditions!(sql, conditions, scope)
|
674
|
-
add_order!(sql, options[:order],
|
675
|
-
add_limit!(sql, options,
|
683
|
+
add_order!(sql, options[:order], nil)
|
684
|
+
add_limit!(sql, options, nil)
|
676
685
|
connection.update(sql, "#{name} Update")
|
677
686
|
end
|
678
687
|
|
@@ -957,14 +966,19 @@ module ActiveRecord #:nodoc:
|
|
957
966
|
end
|
958
967
|
|
959
968
|
def reset_primary_key #:nodoc:
|
969
|
+
key = get_primary_key(base_class.name)
|
970
|
+
set_primary_key(key)
|
971
|
+
key
|
972
|
+
end
|
973
|
+
|
974
|
+
def get_primary_key(base_name) #:nodoc:
|
960
975
|
key = 'id'
|
961
976
|
case primary_key_prefix_type
|
962
977
|
when :table_name
|
963
|
-
key = Inflector.foreign_key(
|
978
|
+
key = Inflector.foreign_key(base_name, false)
|
964
979
|
when :table_name_with_underscore
|
965
|
-
key = Inflector.foreign_key(
|
980
|
+
key = Inflector.foreign_key(base_name)
|
966
981
|
end
|
967
|
-
set_primary_key(key)
|
968
982
|
key
|
969
983
|
end
|
970
984
|
|
@@ -1076,9 +1090,9 @@ module ActiveRecord #:nodoc:
|
|
1076
1090
|
|
1077
1091
|
# Returns an array of column objects for the table associated with this class.
|
1078
1092
|
def columns
|
1079
|
-
unless @columns
|
1093
|
+
unless defined?(@columns) && @columns
|
1080
1094
|
@columns = connection.columns(table_name, "#{name} Columns")
|
1081
|
-
@columns.each {|column| column.primary = column.name == primary_key}
|
1095
|
+
@columns.each { |column| column.primary = column.name == primary_key }
|
1082
1096
|
end
|
1083
1097
|
@columns
|
1084
1098
|
end
|
@@ -1176,13 +1190,13 @@ module ActiveRecord #:nodoc:
|
|
1176
1190
|
# project.milestones << Milestone.find(:all)
|
1177
1191
|
# end
|
1178
1192
|
#
|
1179
|
-
# The benchmark is only recorded if the current level of the logger
|
1180
|
-
# easy to include benchmarking statements in production software that will remain inexpensive because
|
1181
|
-
# will only be conducted if the log level is low enough.
|
1193
|
+
# The benchmark is only recorded if the current level of the logger is less than or equal to the <tt>log_level</tt>,
|
1194
|
+
# which makes it easy to include benchmarking statements in production software that will remain inexpensive because
|
1195
|
+
# the benchmark will only be conducted if the log level is low enough.
|
1182
1196
|
#
|
1183
1197
|
# The logging of the multiple statements is turned off unless <tt>use_silence</tt> is set to false.
|
1184
1198
|
def benchmark(title, log_level = Logger::DEBUG, use_silence = true)
|
1185
|
-
if logger && logger.level
|
1199
|
+
if logger && logger.level <= log_level
|
1186
1200
|
result = nil
|
1187
1201
|
seconds = Benchmark.realtime { result = use_silence ? silence { yield } : yield }
|
1188
1202
|
logger.add(log_level, "#{title} (#{'%.5f' % seconds})")
|
@@ -1218,7 +1232,7 @@ module ActiveRecord #:nodoc:
|
|
1218
1232
|
# Returns whether this class is a base AR class. If A is a base class and
|
1219
1233
|
# B descends from A, then B.base_class will return B.
|
1220
1234
|
def abstract_class?
|
1221
|
-
abstract_class == true
|
1235
|
+
defined?(@abstract_class) && @abstract_class == true
|
1222
1236
|
end
|
1223
1237
|
|
1224
1238
|
private
|
@@ -1429,7 +1443,7 @@ module ActiveRecord #:nodoc:
|
|
1429
1443
|
case join
|
1430
1444
|
when Symbol, Hash, Array
|
1431
1445
|
join_dependency = ActiveRecord::Associations::ClassMethods::InnerJoinDependency.new(self, join, nil)
|
1432
|
-
sql << " #{join_dependency.join_associations.collect{|
|
1446
|
+
sql << " #{join_dependency.join_associations.collect { |assoc| assoc.association_join }.join} "
|
1433
1447
|
else
|
1434
1448
|
sql << " #{join} "
|
1435
1449
|
end
|
@@ -1484,7 +1498,7 @@ module ActiveRecord #:nodoc:
|
|
1484
1498
|
|
1485
1499
|
self.class_eval %{
|
1486
1500
|
def self.#{method_id}(*args)
|
1487
|
-
options = args.
|
1501
|
+
options = args.extract_options!
|
1488
1502
|
attributes = construct_attributes_from_arguments([:#{attribute_names.join(',:')}], args)
|
1489
1503
|
finder_options = { :conditions => attributes }
|
1490
1504
|
validate_find_options(options)
|
@@ -1863,10 +1877,13 @@ module ActiveRecord #:nodoc:
|
|
1863
1877
|
end
|
1864
1878
|
|
1865
1879
|
def expand_range_bind_variables(bind_vars) #:nodoc:
|
1866
|
-
bind_vars.
|
1867
|
-
|
1880
|
+
bind_vars.sum do |var|
|
1881
|
+
if var.is_a?(Range)
|
1882
|
+
[var.first, var.last]
|
1883
|
+
else
|
1884
|
+
[var]
|
1885
|
+
end
|
1868
1886
|
end
|
1869
|
-
bind_vars
|
1870
1887
|
end
|
1871
1888
|
|
1872
1889
|
def quote_bound_value(value) #:nodoc:
|
@@ -1963,7 +1980,7 @@ module ActiveRecord #:nodoc:
|
|
1963
1980
|
|
1964
1981
|
# Returns true if this object hasn't been saved yet -- that is, a record for the object doesn't exist yet.
|
1965
1982
|
def new_record?
|
1966
|
-
@new_record
|
1983
|
+
defined?(@new_record) && @new_record
|
1967
1984
|
end
|
1968
1985
|
|
1969
1986
|
# * No record exists: Creates a new record with values matching those of the object attributes.
|
@@ -2040,28 +2057,28 @@ module ActiveRecord #:nodoc:
|
|
2040
2057
|
save!
|
2041
2058
|
end
|
2042
2059
|
|
2043
|
-
# Initializes the +attribute+ to zero if nil and adds one. Only makes sense for number-based attributes. Returns self.
|
2044
|
-
def increment(attribute)
|
2060
|
+
# Initializes the +attribute+ to zero if nil and adds the value passed as +by+ (default is one). Only makes sense for number-based attributes. Returns self.
|
2061
|
+
def increment(attribute, by = 1)
|
2045
2062
|
self[attribute] ||= 0
|
2046
|
-
self[attribute] +=
|
2063
|
+
self[attribute] += by
|
2047
2064
|
self
|
2048
2065
|
end
|
2049
2066
|
|
2050
2067
|
# Increments the +attribute+ and saves the record.
|
2051
|
-
def increment!(attribute)
|
2052
|
-
increment(attribute).update_attribute(attribute, self[attribute])
|
2068
|
+
def increment!(attribute, by = 1)
|
2069
|
+
increment(attribute, by).update_attribute(attribute, self[attribute])
|
2053
2070
|
end
|
2054
2071
|
|
2055
|
-
# Initializes the +attribute+ to zero if nil and subtracts one. Only makes sense for number-based attributes. Returns self.
|
2056
|
-
def decrement(attribute)
|
2072
|
+
# Initializes the +attribute+ to zero if nil and subtracts the value passed as +by+ (default is one). Only makes sense for number-based attributes. Returns self.
|
2073
|
+
def decrement(attribute, by = 1)
|
2057
2074
|
self[attribute] ||= 0
|
2058
|
-
self[attribute] -=
|
2075
|
+
self[attribute] -= by
|
2059
2076
|
self
|
2060
2077
|
end
|
2061
2078
|
|
2062
2079
|
# Decrements the +attribute+ and saves the record.
|
2063
|
-
def decrement!(attribute)
|
2064
|
-
decrement(attribute).update_attribute(attribute, self[attribute])
|
2080
|
+
def decrement!(attribute, by = 1)
|
2081
|
+
decrement(attribute, by).update_attribute(attribute, self[attribute])
|
2065
2082
|
end
|
2066
2083
|
|
2067
2084
|
# Turns an +attribute+ that's currently true into false and vice versa. Returns self.
|
@@ -2128,6 +2145,7 @@ module ActiveRecord #:nodoc:
|
|
2128
2145
|
if options.nil?
|
2129
2146
|
attributes
|
2130
2147
|
else
|
2148
|
+
ActiveSupport::Deprecation.warn "Passing options to Base#attributes is deprecated and will be removed in Rails 2.1. Please use Hash#slice or Hash#except instead"
|
2131
2149
|
if except = options[:except]
|
2132
2150
|
except = Array(except).collect { |attribute| attribute.to_s }
|
2133
2151
|
except.each { |attribute_name| attributes.delete(attribute_name) }
|
@@ -2214,7 +2232,7 @@ module ActiveRecord #:nodoc:
|
|
2214
2232
|
# Returns +true+ if the record is read only. Records loaded through joins with piggy-back
|
2215
2233
|
# attributes will be marked as read only since they cannot be saved.
|
2216
2234
|
def readonly?
|
2217
|
-
@readonly == true
|
2235
|
+
defined?(@readonly) && @readonly == true
|
2218
2236
|
end
|
2219
2237
|
|
2220
2238
|
# Marks this record as read only.
|
@@ -2335,11 +2353,11 @@ module ActiveRecord #:nodoc:
|
|
2335
2353
|
# Returns a copy of the attributes hash where all the values have been safely quoted for use in
|
2336
2354
|
# an SQL statement.
|
2337
2355
|
def attributes_with_quotes(include_primary_key = true, include_readonly_attributes = true)
|
2338
|
-
quoted = attributes.inject({}) do |
|
2356
|
+
quoted = attributes.inject({}) do |result, (name, value)|
|
2339
2357
|
if column = column_for_attribute(name)
|
2340
|
-
|
2358
|
+
result[name] = quote_value(value, column) unless !include_primary_key && column.primary
|
2341
2359
|
end
|
2342
|
-
|
2360
|
+
result
|
2343
2361
|
end
|
2344
2362
|
include_readonly_attributes ? quoted : remove_readonly_attributes(quoted)
|
2345
2363
|
end
|
@@ -2379,6 +2397,10 @@ module ActiveRecord #:nodoc:
|
|
2379
2397
|
end
|
2380
2398
|
|
2381
2399
|
# Includes an ugly hack for Time.local instead of Time.new because the latter is reserved by Time itself.
|
2400
|
+
def instantiate_time_object(*values)
|
2401
|
+
@@default_timezone == :utc ? Time.utc(*values) : Time.local(*values)
|
2402
|
+
end
|
2403
|
+
|
2382
2404
|
def execute_callstack_for_multiparameter_attributes(callstack)
|
2383
2405
|
errors = []
|
2384
2406
|
callstack.each do |name, values|
|
@@ -2387,7 +2409,19 @@ module ActiveRecord #:nodoc:
|
|
2387
2409
|
send(name + "=", nil)
|
2388
2410
|
else
|
2389
2411
|
begin
|
2390
|
-
|
2412
|
+
value = if Time == klass
|
2413
|
+
instantiate_time_object(*values)
|
2414
|
+
elsif Date == klass
|
2415
|
+
begin
|
2416
|
+
Date.new(*values)
|
2417
|
+
rescue ArgumentError => ex # if Date.new raises an exception on an invalid date
|
2418
|
+
instantiate_time_object(*values).to_date # we instantiate Time object and convert it back to a date thus using Time's logic in handling invalid dates
|
2419
|
+
end
|
2420
|
+
else
|
2421
|
+
klass.new(*values)
|
2422
|
+
end
|
2423
|
+
|
2424
|
+
send(name + "=", value)
|
2391
2425
|
rescue => ex
|
2392
2426
|
errors << AttributeAssignmentError.new("error on assignment #{values.inspect} to #{name}", ex, name)
|
2393
2427
|
end
|
@@ -2455,9 +2489,9 @@ module ActiveRecord #:nodoc:
|
|
2455
2489
|
end
|
2456
2490
|
|
2457
2491
|
def clone_attributes(reader_method = :read_attribute, attributes = {})
|
2458
|
-
self.attribute_names.inject(attributes) do |
|
2459
|
-
|
2460
|
-
|
2492
|
+
self.attribute_names.inject(attributes) do |attrs, name|
|
2493
|
+
attrs[name] = clone_attribute_value(reader_method, name)
|
2494
|
+
attrs
|
2461
2495
|
end
|
2462
2496
|
end
|
2463
2497
|
|
@@ -155,6 +155,7 @@ module ActiveRecord
|
|
155
155
|
scope = scope(:find)
|
156
156
|
merged_includes = merge_includes(scope ? scope[:include] : [], options[:include])
|
157
157
|
aggregate_alias = column_alias_for(operation, column_name)
|
158
|
+
column_name = "#{connection.quote_table_name(table_name)}.#{column_name}" unless column_name == "*" || column_name.to_s.include?('.')
|
158
159
|
|
159
160
|
if operation == 'count'
|
160
161
|
if merged_includes.any?
|
@@ -213,7 +214,7 @@ module ActiveRecord
|
|
213
214
|
group_attr = options[:group].to_s
|
214
215
|
association = reflect_on_association(group_attr.to_sym)
|
215
216
|
associated = association && association.macro == :belongs_to # only count belongs_to associations
|
216
|
-
group_field =
|
217
|
+
group_field = associated ? association.primary_key_name : group_attr
|
217
218
|
group_alias = column_alias_for(group_field)
|
218
219
|
group_column = column_for group_field
|
219
220
|
sql = construct_calculation_sql(operation, column_name, options.merge(:group_field => group_field, :group_alias => group_alias))
|
File without changes
|
@@ -71,7 +71,7 @@ module ActiveRecord
|
|
71
71
|
# also be used to "borrow" the connection to do database work unrelated
|
72
72
|
# to any of the specific Active Records.
|
73
73
|
def connection
|
74
|
-
if @active_connection_name && (conn = active_connections[@active_connection_name])
|
74
|
+
if defined?(@active_connection_name) && (conn = active_connections[@active_connection_name])
|
75
75
|
conn
|
76
76
|
else
|
77
77
|
# retrieve_connection sets the cache key.
|
@@ -192,14 +192,14 @@ module ActiveRecord
|
|
192
192
|
end
|
193
193
|
|
194
194
|
def fallback_string_to_date(string)
|
195
|
-
new_date
|
195
|
+
new_date(*ParseDate.parsedate(string)[0..2])
|
196
196
|
end
|
197
197
|
|
198
198
|
def fallback_string_to_time(string)
|
199
199
|
time_hash = Date._parse(string)
|
200
200
|
time_hash[:sec_fraction] = microseconds(time_hash)
|
201
201
|
|
202
|
-
new_time
|
202
|
+
new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction))
|
203
203
|
end
|
204
204
|
end
|
205
205
|
|
@@ -417,7 +417,11 @@ module ActiveRecord
|
|
417
417
|
# end
|
418
418
|
def column(name, type, options = {})
|
419
419
|
column = self[name] || ColumnDefinition.new(@base, name, type)
|
420
|
-
|
420
|
+
if options[:limit]
|
421
|
+
column.limit = options[:limit]
|
422
|
+
elsif native[type.to_sym].is_a?(Hash)
|
423
|
+
column.limit = native[type.to_sym][:limit]
|
424
|
+
end
|
421
425
|
column.precision = options[:precision]
|
422
426
|
column.scale = options[:scale]
|
423
427
|
column.default = options[:default]
|
@@ -449,9 +453,7 @@ module ActiveRecord
|
|
449
453
|
polymorphic = options.delete(:polymorphic)
|
450
454
|
args.each do |col|
|
451
455
|
column("#{col}_id", :integer, options)
|
452
|
-
unless polymorphic.nil?
|
453
|
-
column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : {})
|
454
|
-
end
|
456
|
+
column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) unless polymorphic.nil?
|
455
457
|
end
|
456
458
|
end
|
457
459
|
alias :belongs_to :references
|