activerecord 2.3.3 → 2.3.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 +8 -1
- data/Rakefile +32 -15
- data/examples/performance.rb +162 -0
- data/lib/active_record/associations.rb +37 -5
- data/lib/active_record/associations/association_collection.rb +1 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +16 -0
- data/lib/active_record/associations/has_many_association.rb +1 -0
- data/lib/active_record/associations/has_many_through_association.rb +13 -3
- data/lib/active_record/associations/has_one_through_association.rb +8 -2
- data/lib/active_record/autosave_association.rb +4 -3
- data/lib/active_record/base.rb +18 -10
- data/lib/active_record/calculations.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +16 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +2 -2
- data/lib/active_record/connection_adapters/abstract_adapter.rb +7 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +17 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +32 -13
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +12 -0
- data/lib/active_record/dirty.rb +1 -1
- data/lib/active_record/fixtures.rb +9 -7
- data/lib/active_record/i18n_interpolation_deprecation.rb +1 -1
- data/lib/active_record/locale/en.yml +4 -0
- data/lib/active_record/named_scope.rb +1 -6
- data/lib/active_record/reflection.rb +1 -1
- data/lib/active_record/schema_dumper.rb +1 -2
- data/lib/active_record/serializers/json_serializer.rb +5 -3
- data/lib/active_record/serializers/xml_serializer.rb +6 -2
- data/lib/active_record/validations.rb +148 -79
- data/lib/active_record/version.rb +1 -1
- data/test/cases/adapter_test.rb +12 -0
- data/test/cases/associations/belongs_to_associations_test.rb +0 -18
- data/test/cases/associations/eager_load_nested_include_test.rb +5 -5
- data/test/cases/associations/habtm_join_table_test.rb +56 -0
- data/test/cases/associations/has_many_associations_test.rb +56 -2
- data/test/cases/associations/has_many_through_associations_test.rb +46 -1
- data/test/cases/associations/has_one_through_associations_test.rb +10 -0
- data/test/cases/associations/join_model_test.rb +4 -4
- data/test/cases/base_test.rb +49 -4
- data/test/cases/calculations_test.rb +6 -0
- data/test/cases/column_definition_test.rb +34 -0
- data/test/cases/dirty_test.rb +10 -0
- data/test/cases/finder_test.rb +15 -50
- data/test/cases/fixtures_test.rb +1 -1
- data/test/cases/i18n_test.rb +5 -0
- data/test/cases/method_scoping_test.rb +1 -1
- data/test/cases/migration_test.rb +39 -11
- data/test/cases/modules_test.rb +42 -0
- data/test/cases/named_scope_test.rb +6 -4
- data/test/cases/pk_test.rb +18 -0
- data/test/cases/reflection_test.rb +2 -2
- data/test/cases/schema_dumper_test.rb +19 -1
- data/test/cases/validations_i18n_test.rb +656 -624
- data/test/cases/validations_test.rb +12 -2
- data/test/cases/xml_serialization_test.rb +20 -0
- data/test/fixtures/fixture_database.sqlite +0 -0
- data/test/fixtures/fixture_database.sqlite3 +0 -0
- data/test/fixtures/fixture_database_2.sqlite +0 -0
- data/test/fixtures/fixture_database_2.sqlite3 +0 -0
- data/test/fixtures/posts.yml +3 -0
- data/test/models/author.rb +1 -0
- data/test/models/comment.rb +5 -1
- data/test/models/company.rb +2 -0
- data/test/models/company_in_module.rb +1 -1
- data/test/models/contract.rb +5 -0
- data/test/models/organization.rb +2 -0
- data/test/models/topic.rb +0 -2
- data/test/schema/postgresql_specific_schema.rb +13 -2
- data/test/schema/schema.rb +4 -0
- metadata +12 -54
- data/test/debug.log +0 -415
@@ -249,9 +249,10 @@ module ActiveRecord
|
|
249
249
|
unless valid = association.valid?
|
250
250
|
if reflection.options[:autosave]
|
251
251
|
unless association.marked_for_destruction?
|
252
|
-
association.errors.
|
253
|
-
|
254
|
-
|
252
|
+
association.errors.each_error do |attribute, error|
|
253
|
+
error = error.dup
|
254
|
+
error.attribute = "#{reflection.name}_#{attribute}"
|
255
|
+
errors.add(error) unless errors.on(error.attribute)
|
255
256
|
end
|
256
257
|
end
|
257
258
|
else
|
data/lib/active_record/base.rb
CHANGED
@@ -1364,7 +1364,7 @@ module ActiveRecord #:nodoc:
|
|
1364
1364
|
end
|
1365
1365
|
defaults << options[:default] if options[:default]
|
1366
1366
|
defaults.flatten!
|
1367
|
-
defaults << attribute_key_name.humanize
|
1367
|
+
defaults << attribute_key_name.to_s.humanize
|
1368
1368
|
options[:count] ||= 1
|
1369
1369
|
I18n.translate(defaults.shift, options.merge(:default => defaults, :scope => [:activerecord, :attributes]))
|
1370
1370
|
end
|
@@ -2294,20 +2294,24 @@ module ActiveRecord #:nodoc:
|
|
2294
2294
|
# And for value objects on a composed_of relationship:
|
2295
2295
|
# { :address => Address.new("123 abc st.", "chicago") }
|
2296
2296
|
# # => "address_street='123 abc st.' and address_city='chicago'"
|
2297
|
-
def sanitize_sql_hash_for_conditions(attrs,
|
2297
|
+
def sanitize_sql_hash_for_conditions(attrs, default_table_name = quoted_table_name)
|
2298
2298
|
attrs = expand_hash_conditions_for_aggregates(attrs)
|
2299
2299
|
|
2300
2300
|
conditions = attrs.map do |attr, value|
|
2301
|
+
table_name = default_table_name
|
2302
|
+
|
2301
2303
|
unless value.is_a?(Hash)
|
2302
2304
|
attr = attr.to_s
|
2303
2305
|
|
2304
2306
|
# Extract table name from qualified attribute names.
|
2305
2307
|
if attr.include?('.')
|
2306
|
-
|
2307
|
-
|
2308
|
+
attr_table_name, attr = attr.split('.', 2)
|
2309
|
+
attr_table_name = connection.quote_table_name(attr_table_name)
|
2310
|
+
else
|
2311
|
+
attr_table_name = table_name
|
2308
2312
|
end
|
2309
2313
|
|
2310
|
-
attribute_condition("#{
|
2314
|
+
attribute_condition("#{attr_table_name}.#{connection.quote_column_name(attr)}", value)
|
2311
2315
|
else
|
2312
2316
|
sanitize_sql_hash_for_conditions(value, connection.quote_table_name(attr.to_s))
|
2313
2317
|
end
|
@@ -3028,16 +3032,22 @@ module ActiveRecord #:nodoc:
|
|
3028
3032
|
|
3029
3033
|
def execute_callstack_for_multiparameter_attributes(callstack)
|
3030
3034
|
errors = []
|
3031
|
-
callstack.each do |name,
|
3035
|
+
callstack.each do |name, values_with_empty_parameters|
|
3032
3036
|
begin
|
3033
3037
|
klass = (self.class.reflect_on_aggregation(name.to_sym) || column_for_attribute(name)).klass
|
3038
|
+
# in order to allow a date to be set without a year, we must keep the empty values.
|
3039
|
+
# Otherwise, we wouldn't be able to distinguish it from a date with an empty day.
|
3040
|
+
values = values_with_empty_parameters.reject(&:nil?)
|
3041
|
+
|
3034
3042
|
if values.empty?
|
3035
3043
|
send(name + "=", nil)
|
3036
3044
|
else
|
3045
|
+
|
3037
3046
|
value = if Time == klass
|
3038
3047
|
instantiate_time_object(name, values)
|
3039
3048
|
elsif Date == klass
|
3040
3049
|
begin
|
3050
|
+
values = values_with_empty_parameters.collect do |v| v.nil? ? 1 : v end
|
3041
3051
|
Date.new(*values)
|
3042
3052
|
rescue ArgumentError => ex # if Date.new raises an exception on an invalid date
|
3043
3053
|
instantiate_time_object(name, values).to_date # we instantiate Time object and convert it back to a date thus using Time's logic in handling invalid dates
|
@@ -3065,10 +3075,8 @@ module ActiveRecord #:nodoc:
|
|
3065
3075
|
attribute_name = multiparameter_name.split("(").first
|
3066
3076
|
attributes[attribute_name] = [] unless attributes.include?(attribute_name)
|
3067
3077
|
|
3068
|
-
|
3069
|
-
|
3070
|
-
[ find_parameter_position(multiparameter_name), type_cast_attribute_value(multiparameter_name, value) ]
|
3071
|
-
end
|
3078
|
+
parameter_value = value.empty? ? nil : type_cast_attribute_value(multiparameter_name, value)
|
3079
|
+
attributes[attribute_name] << [ find_parameter_position(multiparameter_name), parameter_value ]
|
3072
3080
|
end
|
3073
3081
|
|
3074
3082
|
attributes.each { |name, values| attributes[name] = values.sort_by{ |v| v.first }.collect { |v| v.last } }
|
@@ -190,6 +190,8 @@ module ActiveRecord
|
|
190
190
|
sql << ", #{options[:group_field]} AS #{options[:group_alias]}" if options[:group]
|
191
191
|
if options[:from]
|
192
192
|
sql << " FROM #{options[:from]} "
|
193
|
+
elsif scope && scope[:from] && !use_workaround
|
194
|
+
sql << " FROM #{scope[:from]} "
|
193
195
|
else
|
194
196
|
sql << " FROM (SELECT #{distinct}#{column_name}" if use_workaround
|
195
197
|
sql << " FROM #{connection.quote_table_name(table_name)} "
|
@@ -277,7 +277,6 @@ module ActiveRecord
|
|
277
277
|
add_column_options!(column_sql, column_options) unless type.to_sym == :primary_key
|
278
278
|
column_sql
|
279
279
|
end
|
280
|
-
alias to_s :to_sql
|
281
280
|
|
282
281
|
private
|
283
282
|
|
@@ -316,6 +315,20 @@ module ActiveRecord
|
|
316
315
|
@base = base
|
317
316
|
end
|
318
317
|
|
318
|
+
#Handles non supported datatypes - e.g. XML
|
319
|
+
def method_missing(symbol, *args)
|
320
|
+
if symbol.to_s == 'xml'
|
321
|
+
xml_column_fallback(args)
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
def xml_column_fallback(*args)
|
326
|
+
case @base.adapter_name.downcase
|
327
|
+
when 'sqlite', 'mysql'
|
328
|
+
options = args.extract_options!
|
329
|
+
column(args[0], :text, options)
|
330
|
+
end
|
331
|
+
end
|
319
332
|
# Appends a primary key definition to the table definition.
|
320
333
|
# Can be called multiple times, but this is probably not a good idea.
|
321
334
|
def primary_key(name)
|
@@ -508,7 +521,7 @@ module ActiveRecord
|
|
508
521
|
# concatenated together. This string can then be prepended and appended to
|
509
522
|
# to generate the final SQL to create the table.
|
510
523
|
def to_sql
|
511
|
-
@columns * ', '
|
524
|
+
@columns.map(&:to_sql) * ', '
|
512
525
|
end
|
513
526
|
|
514
527
|
private
|
@@ -706,3 +719,4 @@ module ActiveRecord
|
|
706
719
|
|
707
720
|
end
|
708
721
|
end
|
722
|
+
|
@@ -99,7 +99,7 @@ module ActiveRecord
|
|
99
99
|
# See also TableDefinition#column for details on how to create columns.
|
100
100
|
def create_table(table_name, options = {})
|
101
101
|
table_definition = TableDefinition.new(self)
|
102
|
-
table_definition.primary_key(options[:primary_key] || Base.get_primary_key(table_name)) unless options[:id] == false
|
102
|
+
table_definition.primary_key(options[:primary_key] || Base.get_primary_key(table_name.to_s.singularize)) unless options[:id] == false
|
103
103
|
|
104
104
|
yield table_definition
|
105
105
|
|
@@ -321,7 +321,7 @@ module ActiveRecord
|
|
321
321
|
schema_migrations_table.column :version, :string, :null => false
|
322
322
|
end
|
323
323
|
add_index sm_table, :version, :unique => true,
|
324
|
-
:name =>
|
324
|
+
:name => "#{Base.table_name_prefix}unique_schema_migrations#{Base.table_name_suffix}"
|
325
325
|
|
326
326
|
# Backwards-compatibility: if we find schema_info, assume we've
|
327
327
|
# migrated up to that point:
|
@@ -54,6 +54,13 @@ module ActiveRecord
|
|
54
54
|
false
|
55
55
|
end
|
56
56
|
|
57
|
+
# Can this adapter determine the primary key for tables not attached
|
58
|
+
# to an ActiveRecord class, such as join tables? Backend specific, as
|
59
|
+
# the abstract adapter always returns +false+.
|
60
|
+
def supports_primary_key?
|
61
|
+
false
|
62
|
+
end
|
63
|
+
|
57
64
|
# Does this adapter support using DISTINCT within COUNT? This is +true+
|
58
65
|
# for all adapters except sqlite.
|
59
66
|
def supports_count_distinct?
|
@@ -52,12 +52,7 @@ module ActiveRecord
|
|
52
52
|
socket = config[:socket]
|
53
53
|
username = config[:username] ? config[:username].to_s : 'root'
|
54
54
|
password = config[:password].to_s
|
55
|
-
|
56
|
-
if config.has_key?(:database)
|
57
|
-
database = config[:database]
|
58
|
-
else
|
59
|
-
raise ArgumentError, "No database specified. Missing argument: database."
|
60
|
-
end
|
55
|
+
database = config[:database]
|
61
56
|
|
62
57
|
# Require the MySQL driver and define Mysql::Result.all_hashes
|
63
58
|
unless defined? Mysql
|
@@ -80,7 +75,7 @@ module ActiveRecord
|
|
80
75
|
module ConnectionAdapters
|
81
76
|
class MysqlColumn < Column #:nodoc:
|
82
77
|
def extract_default(default)
|
83
|
-
if
|
78
|
+
if sql_type =~ /blob/i || type == :text
|
84
79
|
if default.blank?
|
85
80
|
return null ? nil : ''
|
86
81
|
else
|
@@ -94,7 +89,7 @@ module ActiveRecord
|
|
94
89
|
end
|
95
90
|
|
96
91
|
def has_default?
|
97
|
-
return false if
|
92
|
+
return false if sql_type =~ /blob/i || type == :text #mysql forbids defaults on blob and text columns
|
98
93
|
super
|
99
94
|
end
|
100
95
|
|
@@ -212,6 +207,10 @@ module ActiveRecord
|
|
212
207
|
true
|
213
208
|
end
|
214
209
|
|
210
|
+
def supports_primary_key? #:nodoc:
|
211
|
+
true
|
212
|
+
end
|
213
|
+
|
215
214
|
def supports_savepoints? #:nodoc:
|
216
215
|
true
|
217
216
|
end
|
@@ -554,6 +553,12 @@ module ActiveRecord
|
|
554
553
|
keys.length == 1 ? [keys.first, nil] : nil
|
555
554
|
end
|
556
555
|
|
556
|
+
# Returns just a table's primary key
|
557
|
+
def primary_key(table)
|
558
|
+
pk_and_sequence = pk_and_sequence_for(table)
|
559
|
+
pk_and_sequence && pk_and_sequence.first
|
560
|
+
end
|
561
|
+
|
557
562
|
def case_sensitive_equality_operator
|
558
563
|
"= BINARY"
|
559
564
|
end
|
@@ -573,6 +578,10 @@ module ActiveRecord
|
|
573
578
|
@connection.ssl_set(@config[:sslkey], @config[:sslcert], @config[:sslca], @config[:sslcapath], @config[:sslcipher])
|
574
579
|
end
|
575
580
|
|
581
|
+
@connection.options(Mysql::OPT_CONNECT_TIMEOUT, @config[:connect_timeout]) if @config[:connect_timeout]
|
582
|
+
@connection.options(Mysql::OPT_READ_TIMEOUT, @config[:read_timeout]) if @config[:read_timeout]
|
583
|
+
@connection.options(Mysql::OPT_WRITE_TIMEOUT, @config[:write_timeout]) if @config[:write_timeout]
|
584
|
+
|
576
585
|
@connection.real_connect(*@connection_options)
|
577
586
|
|
578
587
|
# reconnect must be set after real_connect is called, because real_connect sets it to false internally
|
@@ -39,6 +39,12 @@ module ActiveRecord
|
|
39
39
|
end
|
40
40
|
|
41
41
|
module ConnectionAdapters
|
42
|
+
class TableDefinition
|
43
|
+
def xml(*args)
|
44
|
+
options = args.extract_options!
|
45
|
+
column(args[0], 'xml', options)
|
46
|
+
end
|
47
|
+
end
|
42
48
|
# PostgreSQL-specific extensions to column definitions in a table.
|
43
49
|
class PostgreSQLColumn < Column #:nodoc:
|
44
50
|
# Instantiates a new PostgreSQL column definition in a table.
|
@@ -67,7 +73,7 @@ module ActiveRecord
|
|
67
73
|
# depending on the server specifics
|
68
74
|
super
|
69
75
|
end
|
70
|
-
|
76
|
+
|
71
77
|
# Maps PostgreSQL-specific data types to logical Rails types.
|
72
78
|
def simplified_type(field_type)
|
73
79
|
case field_type
|
@@ -99,10 +105,10 @@ module ActiveRecord
|
|
99
105
|
:string
|
100
106
|
# XML type
|
101
107
|
when /^xml$/
|
102
|
-
:
|
108
|
+
:xml
|
103
109
|
# Arrays
|
104
110
|
when /^\D+\[\]$/
|
105
|
-
:string
|
111
|
+
:string
|
106
112
|
# Object identifier types
|
107
113
|
when /^oid$/
|
108
114
|
:integer
|
@@ -111,7 +117,7 @@ module ActiveRecord
|
|
111
117
|
super
|
112
118
|
end
|
113
119
|
end
|
114
|
-
|
120
|
+
|
115
121
|
# Extracts the value from a PostgreSQL column default definition.
|
116
122
|
def self.extract_value_from_default(default)
|
117
123
|
case default
|
@@ -194,7 +200,8 @@ module ActiveRecord
|
|
194
200
|
:time => { :name => "time" },
|
195
201
|
:date => { :name => "date" },
|
196
202
|
:binary => { :name => "bytea" },
|
197
|
-
:boolean => { :name => "boolean" }
|
203
|
+
:boolean => { :name => "boolean" },
|
204
|
+
:xml => { :name => "xml" }
|
198
205
|
}
|
199
206
|
|
200
207
|
# Returns 'PostgreSQL' as adapter name for identification purposes.
|
@@ -249,6 +256,11 @@ module ActiveRecord
|
|
249
256
|
true
|
250
257
|
end
|
251
258
|
|
259
|
+
# Does PostgreSQL support finding primary key on non-ActiveRecord tables?
|
260
|
+
def supports_primary_key? #:nodoc:
|
261
|
+
true
|
262
|
+
end
|
263
|
+
|
252
264
|
# Does PostgreSQL support standard conforming strings?
|
253
265
|
def supports_standard_conforming_strings?
|
254
266
|
# Temporarily set the client message level above error to prevent unintentional
|
@@ -272,7 +284,7 @@ module ActiveRecord
|
|
272
284
|
def supports_ddl_transactions?
|
273
285
|
true
|
274
286
|
end
|
275
|
-
|
287
|
+
|
276
288
|
def supports_savepoints?
|
277
289
|
true
|
278
290
|
end
|
@@ -364,7 +376,7 @@ module ActiveRecord
|
|
364
376
|
if value.kind_of?(String) && column && column.type == :binary
|
365
377
|
"#{quoted_string_prefix}'#{escape_bytea(value)}'"
|
366
378
|
elsif value.kind_of?(String) && column && column.sql_type =~ /^xml$/
|
367
|
-
"xml '#{quote_string(value)}'"
|
379
|
+
"xml E'#{quote_string(value)}'"
|
368
380
|
elsif value.kind_of?(Numeric) && column && column.sql_type =~ /^money$/
|
369
381
|
# Not truly string input, so doesn't require (or allow) escape string syntax.
|
370
382
|
"'#{value.to_s}'"
|
@@ -563,7 +575,7 @@ module ActiveRecord
|
|
563
575
|
def rollback_db_transaction
|
564
576
|
execute "ROLLBACK"
|
565
577
|
end
|
566
|
-
|
578
|
+
|
567
579
|
if defined?(PGconn::PQTRANS_IDLE)
|
568
580
|
# The ruby-pg driver supports inspecting the transaction status,
|
569
581
|
# while the ruby-postgres driver does not.
|
@@ -810,6 +822,12 @@ module ActiveRecord
|
|
810
822
|
nil
|
811
823
|
end
|
812
824
|
|
825
|
+
# Returns just a table's primary key
|
826
|
+
def primary_key(table)
|
827
|
+
pk_and_sequence = pk_and_sequence_for(table)
|
828
|
+
pk_and_sequence && pk_and_sequence.first
|
829
|
+
end
|
830
|
+
|
813
831
|
# Renames a table.
|
814
832
|
def rename_table(name, new_name)
|
815
833
|
execute "ALTER TABLE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}"
|
@@ -908,18 +926,18 @@ module ActiveRecord
|
|
908
926
|
sql = "DISTINCT ON (#{columns}) #{columns}, "
|
909
927
|
sql << order_columns * ', '
|
910
928
|
end
|
911
|
-
|
929
|
+
|
912
930
|
# Returns an ORDER BY clause for the passed order option.
|
913
|
-
#
|
931
|
+
#
|
914
932
|
# PostgreSQL does not allow arbitrary ordering when using DISTINCT ON, so we work around this
|
915
933
|
# by wrapping the +sql+ string as a sub-select and ordering in that query.
|
916
934
|
def add_order_by_for_association_limiting!(sql, options) #:nodoc:
|
917
935
|
return sql if options[:order].blank?
|
918
|
-
|
936
|
+
|
919
937
|
order = options[:order].split(',').collect { |s| s.strip }.reject(&:blank?)
|
920
938
|
order.map! { |s| 'DESC' if s =~ /\bdesc$/i }
|
921
939
|
order = order.zip((0...order.size).to_a).map { |s,i| "id_list.alias_#{i} #{s}" }.join(', ')
|
922
|
-
|
940
|
+
|
923
941
|
sql.replace "SELECT * FROM (#{sql}) AS id_list ORDER BY #{order}"
|
924
942
|
end
|
925
943
|
|
@@ -1032,7 +1050,7 @@ module ActiveRecord
|
|
1032
1050
|
if res.ftype(cell_index) == MONEY_COLUMN_TYPE_OID
|
1033
1051
|
# Because money output is formatted according to the locale, there are two
|
1034
1052
|
# cases to consider (note the decimal separators):
|
1035
|
-
# (1) $12,345,678.12
|
1053
|
+
# (1) $12,345,678.12
|
1036
1054
|
# (2) $12.345.678,12
|
1037
1055
|
case column = row[cell_index]
|
1038
1056
|
when /^-?\D+[\d,]+\.\d{2}$/ # (1)
|
@@ -1092,3 +1110,4 @@ module ActiveRecord
|
|
1092
1110
|
end
|
1093
1111
|
end
|
1094
1112
|
end
|
1113
|
+
|
@@ -16,6 +16,10 @@ module ActiveRecord
|
|
16
16
|
db.results_as_hash = true if defined? SQLite::Version
|
17
17
|
db.type_translation = false
|
18
18
|
|
19
|
+
message = "Support for SQLite2Adapter and DeprecatedSQLiteAdapter has been removed from Rails 3. "
|
20
|
+
message << "You should migrate to SQLite 3+ or use the plugin from git://github.com/rails/sqlite2_adapter.git with Rails 3."
|
21
|
+
ActiveSupport::Deprecation.warn(message)
|
22
|
+
|
19
23
|
# "Downgrade" deprecated sqlite API
|
20
24
|
if SQLite.const_defined?(:Version)
|
21
25
|
ConnectionAdapters::SQLite2Adapter.new(db, logger, config)
|
@@ -27,6 +31,10 @@ module ActiveRecord
|
|
27
31
|
|
28
32
|
private
|
29
33
|
def parse_sqlite_config!(config)
|
34
|
+
if config.include?(:dbfile)
|
35
|
+
ActiveSupport::Deprecation.warn "Please update config/database.yml to use 'database' instead of 'dbfile'"
|
36
|
+
end
|
37
|
+
|
30
38
|
config[:database] ||= config[:dbfile]
|
31
39
|
# Require database.
|
32
40
|
unless config[:database]
|
@@ -104,6 +112,10 @@ module ActiveRecord
|
|
104
112
|
true
|
105
113
|
end
|
106
114
|
|
115
|
+
def supports_primary_key? #:nodoc:
|
116
|
+
true
|
117
|
+
end
|
118
|
+
|
107
119
|
def requires_reloading?
|
108
120
|
true
|
109
121
|
end
|
data/lib/active_record/dirty.rb
CHANGED
@@ -143,7 +143,7 @@ module ActiveRecord
|
|
143
143
|
if partial_updates?
|
144
144
|
# Serialized attributes should always be written in case they've been
|
145
145
|
# changed in place.
|
146
|
-
update_without_dirty(changed | self.class.serialized_attributes.keys)
|
146
|
+
update_without_dirty(changed | (attributes.keys & self.class.serialized_attributes.keys))
|
147
147
|
else
|
148
148
|
update_without_dirty
|
149
149
|
end
|
@@ -621,7 +621,8 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
|
|
621
621
|
targets.each do |target|
|
622
622
|
join_fixtures["#{label}_#{target}"] = Fixture.new(
|
623
623
|
{ association.primary_key_name => row[primary_key_name],
|
624
|
-
association.association_foreign_key => Fixtures.identify(target) },
|
624
|
+
association.association_foreign_key => Fixtures.identify(target) },
|
625
|
+
nil, @connection)
|
625
626
|
end
|
626
627
|
end
|
627
628
|
end
|
@@ -705,12 +706,12 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
|
|
705
706
|
|
706
707
|
yaml_value.each do |fixture|
|
707
708
|
raise Fixture::FormatError, "Bad data for #{@class_name} fixture named #{fixture}" unless fixture.respond_to?(:each)
|
708
|
-
|
709
|
+
fixture.each do |name, data|
|
709
710
|
unless data
|
710
711
|
raise Fixture::FormatError, "Bad data for #{@class_name} fixture named #{name} (nil)"
|
711
712
|
end
|
712
713
|
|
713
|
-
self[name] = Fixture.new(data, model_class)
|
714
|
+
self[name] = Fixture.new(data, model_class, @connection)
|
714
715
|
end
|
715
716
|
end
|
716
717
|
end
|
@@ -723,7 +724,7 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
|
|
723
724
|
reader.each do |row|
|
724
725
|
data = {}
|
725
726
|
row.each_with_index { |cell, j| data[header[j].to_s.strip] = cell.to_s.strip }
|
726
|
-
self["#{@class_name.to_s.underscore}_#{i+=1}"] = Fixture.new(data, model_class)
|
727
|
+
self["#{@class_name.to_s.underscore}_#{i+=1}"] = Fixture.new(data, model_class, @connection)
|
727
728
|
end
|
728
729
|
end
|
729
730
|
|
@@ -761,7 +762,8 @@ class Fixture #:nodoc:
|
|
761
762
|
|
762
763
|
attr_reader :model_class
|
763
764
|
|
764
|
-
def initialize(fixture, model_class)
|
765
|
+
def initialize(fixture, model_class, connection = ActiveRecord::Base.connection)
|
766
|
+
@connection = connection
|
765
767
|
@fixture = fixture
|
766
768
|
@model_class = model_class.is_a?(Class) ? model_class : model_class.constantize rescue nil
|
767
769
|
end
|
@@ -783,14 +785,14 @@ class Fixture #:nodoc:
|
|
783
785
|
end
|
784
786
|
|
785
787
|
def key_list
|
786
|
-
columns = @fixture.keys.collect{ |column_name|
|
788
|
+
columns = @fixture.keys.collect{ |column_name| @connection.quote_column_name(column_name) }
|
787
789
|
columns.join(", ")
|
788
790
|
end
|
789
791
|
|
790
792
|
def value_list
|
791
793
|
list = @fixture.inject([]) do |fixtures, (key, value)|
|
792
794
|
col = model_class.columns_hash[key] if model_class.respond_to?(:ancestors) && model_class.ancestors.include?(ActiveRecord::Base)
|
793
|
-
fixtures <<
|
795
|
+
fixtures << @connection.quote(value, col).gsub('[^\]\\n', "\n").gsub('[^\]\\r', "\r")
|
794
796
|
end
|
795
797
|
list * ', '
|
796
798
|
end
|