activerecord 3.0.0.beta3 → 3.0.0.beta4
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 +27 -0
- data/lib/active_record.rb +5 -1
- data/lib/active_record/aggregations.rb +1 -0
- data/lib/active_record/association_preload.rb +1 -1
- data/lib/active_record/associations.rb +88 -33
- data/lib/active_record/associations/association_collection.rb +12 -11
- data/lib/active_record/associations/association_proxy.rb +1 -1
- data/lib/active_record/attribute_methods.rb +10 -1
- data/lib/active_record/attribute_methods/dirty.rb +50 -50
- data/lib/active_record/attribute_methods/primary_key.rb +1 -1
- data/lib/active_record/autosave_association.rb +20 -5
- data/lib/active_record/base.rb +28 -343
- data/lib/active_record/callbacks.rb +23 -34
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +57 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +56 -0
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +11 -18
- data/lib/active_record/connection_adapters/abstract/quoting.rb +3 -7
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +61 -7
- data/lib/active_record/connection_adapters/abstract_adapter.rb +3 -1
- data/lib/active_record/connection_adapters/mysql_adapter.rb +22 -50
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +31 -143
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +6 -2
- data/lib/active_record/counter_cache.rb +105 -0
- data/lib/active_record/fixtures.rb +16 -15
- data/lib/active_record/locale/en.yml +2 -2
- data/lib/active_record/locking/optimistic.rb +37 -16
- data/lib/active_record/migration.rb +7 -3
- data/lib/active_record/named_scope.rb +1 -5
- data/lib/active_record/nested_attributes.rb +13 -2
- data/lib/active_record/observer.rb +19 -7
- data/lib/active_record/persistence.rb +230 -0
- data/lib/active_record/railtie.rb +17 -23
- data/lib/active_record/railties/databases.rake +3 -2
- data/lib/active_record/relation.rb +5 -2
- data/lib/active_record/relation/batches.rb +6 -1
- data/lib/active_record/relation/calculations.rb +12 -9
- data/lib/active_record/relation/finder_methods.rb +14 -10
- data/lib/active_record/relation/query_methods.rb +62 -44
- data/lib/active_record/relation/spawn_methods.rb +6 -1
- data/lib/active_record/schema_dumper.rb +3 -0
- data/lib/active_record/serializers/xml_serializer.rb +30 -56
- data/lib/active_record/session_store.rb +1 -1
- data/lib/active_record/timestamp.rb +22 -26
- data/lib/active_record/transactions.rb +168 -50
- data/lib/active_record/validations.rb +33 -49
- data/lib/active_record/version.rb +1 -1
- data/lib/rails/generators/active_record.rb +6 -9
- metadata +27 -10
@@ -15,6 +15,12 @@ module ActiveRecord
|
|
15
15
|
config.generators.orm :active_record, :migration => true,
|
16
16
|
:timestamps => true
|
17
17
|
|
18
|
+
config.app_middleware.insert_after "::ActionDispatch::Callbacks",
|
19
|
+
"ActiveRecord::QueryCache"
|
20
|
+
|
21
|
+
config.app_middleware.insert_after "::ActionDispatch::Callbacks",
|
22
|
+
"ActiveRecord::ConnectionAdapters::ConnectionManagement"
|
23
|
+
|
18
24
|
rake_tasks do
|
19
25
|
load "active_record/railties/databases.rake"
|
20
26
|
end
|
@@ -58,37 +64,25 @@ module ActiveRecord
|
|
58
64
|
end
|
59
65
|
end
|
60
66
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
middleware.use ActiveRecord::QueryCache
|
67
|
+
initializer "active_record.set_dispatch_hooks", :before => :set_clear_dependencies_hook do |app|
|
68
|
+
unless app.config.cache_classes
|
69
|
+
ActiveSupport.on_load(:active_record) do
|
70
|
+
ActionDispatch::Callbacks.after do
|
71
|
+
ActiveRecord::Base.reset_subclasses
|
72
|
+
ActiveRecord::Base.clear_reloadable_connections!
|
73
|
+
end
|
74
|
+
end
|
70
75
|
end
|
71
76
|
end
|
72
77
|
|
73
|
-
|
74
|
-
ActiveSupport.on_load(:active_record) { instantiate_observers }
|
75
|
-
|
78
|
+
config.after_initialize do
|
76
79
|
ActiveSupport.on_load(:active_record) do
|
80
|
+
instantiate_observers
|
81
|
+
|
77
82
|
ActionDispatch::Callbacks.to_prepare(:activerecord_instantiate_observers) do
|
78
83
|
ActiveRecord::Base.instantiate_observers
|
79
84
|
end
|
80
85
|
end
|
81
86
|
end
|
82
|
-
|
83
|
-
initializer "active_record.set_dispatch_hooks", :before => :set_clear_dependencies_hook do |app|
|
84
|
-
ActiveSupport.on_load(:active_record) do
|
85
|
-
unless app.config.cache_classes
|
86
|
-
ActionDispatch::Callbacks.after do
|
87
|
-
ActiveRecord::Base.reset_subclasses
|
88
|
-
ActiveRecord::Base.clear_reloadable_connections!
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
87
|
end
|
94
88
|
end
|
@@ -258,8 +258,8 @@ namespace :db do
|
|
258
258
|
base_dir = ENV['FIXTURES_PATH'] ? File.join(Rails.root, ENV['FIXTURES_PATH']) : File.join(Rails.root, 'test', 'fixtures')
|
259
259
|
fixtures_dir = ENV['FIXTURES_DIR'] ? File.join(base_dir, ENV['FIXTURES_DIR']) : base_dir
|
260
260
|
|
261
|
-
(ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/).map {|f| File.join(fixtures_dir, f) } : Dir
|
262
|
-
Fixtures.create_fixtures(
|
261
|
+
(ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/).map {|f| File.join(fixtures_dir, f) } : Dir["#{fixtures_dir}/**/*.{yml,csv}"]).each do |fixture_file|
|
262
|
+
Fixtures.create_fixtures(fixtures_dir, fixture_file[(fixtures_dir.size + 1)..-5])
|
263
263
|
end
|
264
264
|
end
|
265
265
|
|
@@ -435,6 +435,7 @@ namespace :db do
|
|
435
435
|
task :create => :environment do
|
436
436
|
raise "Task unavailable to this database (no migration support)" unless ActiveRecord::Base.connection.supports_migrations?
|
437
437
|
require 'rails/generators'
|
438
|
+
Rails::Generators.configure!
|
438
439
|
require 'rails/generators/rails/session_migration/session_migration_generator'
|
439
440
|
Rails::Generators::SessionMigrationGenerator.start [ ENV["MIGRATION"] || "add_sessions_table" ]
|
440
441
|
end
|
@@ -356,13 +356,16 @@ module ActiveRecord
|
|
356
356
|
end
|
357
357
|
|
358
358
|
def references_eager_loaded_tables?
|
359
|
-
|
359
|
+
# always convert table names to downcase as in Oracle quoted table names are in uppercase
|
360
|
+
joined_tables = (tables_in_string(arel.joins(arel)) + [table.name, table.table_alias]).compact.map(&:downcase).uniq
|
360
361
|
(tables_in_string(to_sql) - joined_tables).any?
|
361
362
|
end
|
362
363
|
|
363
364
|
def tables_in_string(string)
|
364
365
|
return [] if string.blank?
|
365
|
-
|
366
|
+
# always convert table names to downcase as in Oracle quoted table names are in uppercase
|
367
|
+
# ignore raw_sql_ that is used by Oracle adapter as alias for limit/offset subqueries
|
368
|
+
string.scan(/([a-zA-Z_][\.\w]+).?\./).flatten.map(&:downcase).uniq - ['raw_sql_']
|
366
369
|
end
|
367
370
|
|
368
371
|
end
|
@@ -71,7 +71,12 @@ module ActiveRecord
|
|
71
71
|
yield records
|
72
72
|
|
73
73
|
break if records.size < batch_size
|
74
|
-
|
74
|
+
|
75
|
+
if primary_key_offset = records.last.id
|
76
|
+
records = relation.where(primary_key.gt(primary_key_offset)).all
|
77
|
+
else
|
78
|
+
raise "Primary key not included in the custom select clause"
|
79
|
+
end
|
75
80
|
end
|
76
81
|
end
|
77
82
|
|
@@ -45,9 +45,8 @@ module ActiveRecord
|
|
45
45
|
calculate(:count, column_name, options)
|
46
46
|
end
|
47
47
|
|
48
|
-
# Calculates the average value on a given column.
|
49
|
-
#
|
50
|
-
# options.
|
48
|
+
# Calculates the average value on a given column. Returns +nil+ if there's
|
49
|
+
# no row. See +calculate+ for examples with options.
|
51
50
|
#
|
52
51
|
# Person.average('age') # => 35.8
|
53
52
|
def average(column_name, options = {})
|
@@ -195,7 +194,7 @@ module ActiveRecord
|
|
195
194
|
|
196
195
|
select_statement << ", #{group_field} AS #{group_alias}"
|
197
196
|
|
198
|
-
relation = select(select_statement).group(group)
|
197
|
+
relation = except(:group).select(select_statement).group(group)
|
199
198
|
|
200
199
|
calculated_data = @klass.connection.select_all(relation.to_sql)
|
201
200
|
|
@@ -239,11 +238,15 @@ module ActiveRecord
|
|
239
238
|
end
|
240
239
|
|
241
240
|
def type_cast_calculated_value(value, column, operation = nil)
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
241
|
+
if value.is_a?(String) || value.nil?
|
242
|
+
case operation
|
243
|
+
when 'count' then value.to_i
|
244
|
+
when 'sum' then type_cast_using_column(value || '0', column)
|
245
|
+
when 'average' then value.try(:to_d)
|
246
|
+
else type_cast_using_column(value, column)
|
247
|
+
end
|
248
|
+
else
|
249
|
+
value
|
247
250
|
end
|
248
251
|
end
|
249
252
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'active_support/core_ext/object/blank'
|
2
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
2
3
|
|
3
4
|
module ActiveRecord
|
4
5
|
module FinderMethods
|
@@ -187,7 +188,6 @@ module ActiveRecord
|
|
187
188
|
def construct_relation_for_association_calculations
|
188
189
|
including = (@eager_load_values + @includes_values).uniq
|
189
190
|
join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, including, arel.joins(arel))
|
190
|
-
|
191
191
|
relation = except(:includes, :eager_load, :preload)
|
192
192
|
apply_join_dependency(relation, join_dependency)
|
193
193
|
end
|
@@ -234,20 +234,24 @@ module ActiveRecord
|
|
234
234
|
end
|
235
235
|
|
236
236
|
def find_or_instantiator_by_attributes(match, attributes, *args)
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
attributes_for_create = conditions = attributes.inject({}) {|h, a| h[a] = args[attributes.index(a)]; h}
|
237
|
+
protected_attributes_for_create, unprotected_attributes_for_create = {}, {}
|
238
|
+
args.each_with_index do |arg, i|
|
239
|
+
if arg.is_a?(Hash)
|
240
|
+
protected_attributes_for_create = args[i].with_indifferent_access
|
241
|
+
else
|
242
|
+
unprotected_attributes_for_create[attributes[i]] = args[i]
|
243
|
+
end
|
245
244
|
end
|
246
245
|
|
246
|
+
conditions = (protected_attributes_for_create.merge(unprotected_attributes_for_create)).slice(*attributes).symbolize_keys
|
247
|
+
|
247
248
|
record = where(conditions).first
|
248
249
|
|
249
250
|
unless record
|
250
|
-
record = @klass.new
|
251
|
+
record = @klass.new do |r|
|
252
|
+
r.send(:attributes=, protected_attributes_for_create, true) unless protected_attributes_for_create.empty?
|
253
|
+
r.send(:attributes=, unprotected_attributes_for_create, false) unless unprotected_attributes_for_create.empty?
|
254
|
+
end
|
251
255
|
yield(record) if block_given?
|
252
256
|
record.save if match.instantiator == :create
|
253
257
|
end
|
@@ -9,8 +9,8 @@ module ActiveRecord
|
|
9
9
|
(ActiveRecord::Relation::ASSOCIATION_METHODS + ActiveRecord::Relation::MULTI_VALUE_METHODS).each do |query_method|
|
10
10
|
attr_accessor :"#{query_method}_values"
|
11
11
|
|
12
|
-
next if [:where, :having].include?(query_method)
|
13
|
-
class_eval <<-CEVAL, __FILE__
|
12
|
+
next if [:where, :having, :select].include?(query_method)
|
13
|
+
class_eval <<-CEVAL, __FILE__, __LINE__ + 1
|
14
14
|
def #{query_method}(*args, &block)
|
15
15
|
new_relation = clone
|
16
16
|
new_relation.send(:apply_modules, Module.new(&block)) if block_given?
|
@@ -21,8 +21,21 @@ module ActiveRecord
|
|
21
21
|
CEVAL
|
22
22
|
end
|
23
23
|
|
24
|
+
class_eval <<-CEVAL, __FILE__, __LINE__ + 1
|
25
|
+
def select(*args, &block)
|
26
|
+
if block_given?
|
27
|
+
to_a.select(&block)
|
28
|
+
else
|
29
|
+
new_relation = clone
|
30
|
+
value = Array.wrap(args.flatten).reject {|x| x.blank? }
|
31
|
+
new_relation.select_values += value if value.present?
|
32
|
+
new_relation
|
33
|
+
end
|
34
|
+
end
|
35
|
+
CEVAL
|
36
|
+
|
24
37
|
[:where, :having].each do |query_method|
|
25
|
-
class_eval <<-CEVAL, __FILE__
|
38
|
+
class_eval <<-CEVAL, __FILE__, __LINE__ + 1
|
26
39
|
def #{query_method}(*args, &block)
|
27
40
|
new_relation = clone
|
28
41
|
new_relation.send(:apply_modules, Module.new(&block)) if block_given?
|
@@ -36,7 +49,7 @@ module ActiveRecord
|
|
36
49
|
ActiveRecord::Relation::SINGLE_VALUE_METHODS.each do |query_method|
|
37
50
|
attr_accessor :"#{query_method}_value"
|
38
51
|
|
39
|
-
class_eval <<-CEVAL, __FILE__
|
52
|
+
class_eval <<-CEVAL, __FILE__, __LINE__ + 1
|
40
53
|
def #{query_method}(value = true, &block)
|
41
54
|
new_relation = clone
|
42
55
|
new_relation.send(:apply_modules, Module.new(&block)) if block_given?
|
@@ -80,6 +93,26 @@ module ActiveRecord
|
|
80
93
|
@arel ||= build_arel
|
81
94
|
end
|
82
95
|
|
96
|
+
def custom_join_sql(*joins)
|
97
|
+
arel = table
|
98
|
+
joins.each do |join|
|
99
|
+
next if join.blank?
|
100
|
+
|
101
|
+
@implicit_readonly = true
|
102
|
+
|
103
|
+
case join
|
104
|
+
when Hash, Array, Symbol
|
105
|
+
if array_of_strings?(join)
|
106
|
+
join_string = join.join(' ')
|
107
|
+
arel = arel.join(join_string)
|
108
|
+
end
|
109
|
+
else
|
110
|
+
arel = arel.join(join)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
arel.joins(arel)
|
114
|
+
end
|
115
|
+
|
83
116
|
def build_arel
|
84
117
|
arel = table
|
85
118
|
|
@@ -88,50 +121,41 @@ module ActiveRecord
|
|
88
121
|
|
89
122
|
joins = @joins_values.map {|j| j.respond_to?(:strip) ? j.strip : j}.uniq
|
90
123
|
|
91
|
-
# Build association joins first
|
92
124
|
joins.each do |join|
|
93
125
|
association_joins << join if [Hash, Array, Symbol].include?(join.class) && !array_of_strings?(join)
|
94
126
|
end
|
95
127
|
|
96
|
-
|
97
|
-
join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins.uniq, nil)
|
98
|
-
to_join = []
|
128
|
+
stashed_association_joins = joins.select {|j| j.is_a?(ActiveRecord::Associations::ClassMethods::JoinDependency::JoinAssociation)}
|
99
129
|
|
100
|
-
|
101
|
-
|
102
|
-
to_join << [association_relation.first, association.association_join.first]
|
103
|
-
to_join << [association_relation.last, association.association_join.last]
|
104
|
-
else
|
105
|
-
to_join << [association_relation, association.association_join]
|
106
|
-
end
|
107
|
-
end
|
130
|
+
non_association_joins = (joins - association_joins - stashed_association_joins).reject {|j| j.blank?}
|
131
|
+
custom_joins = custom_join_sql(*non_association_joins)
|
108
132
|
|
109
|
-
|
110
|
-
unless joined_associations.detect {|ja| ja[0] == tj[0] && ja[1] == tj[1] }
|
111
|
-
joined_associations << tj
|
112
|
-
arel = arel.join(tj[0]).on(*tj[1])
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
133
|
+
join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, association_joins, custom_joins)
|
116
134
|
|
117
|
-
|
118
|
-
next if join.blank?
|
135
|
+
join_dependency.graft(*stashed_association_joins)
|
119
136
|
|
120
|
-
|
137
|
+
@implicit_readonly = true unless association_joins.empty? && stashed_association_joins.empty?
|
121
138
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
arel = arel.join(join_string)
|
129
|
-
end
|
139
|
+
to_join = []
|
140
|
+
|
141
|
+
join_dependency.join_associations.each do |association|
|
142
|
+
if (association_relation = association.relation).is_a?(Array)
|
143
|
+
to_join << [association_relation.first, association.join_class, association.association_join.first]
|
144
|
+
to_join << [association_relation.last, association.join_class, association.association_join.last]
|
130
145
|
else
|
131
|
-
|
146
|
+
to_join << [association_relation, association.join_class, association.association_join]
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
to_join.each do |tj|
|
151
|
+
unless joined_associations.detect {|ja| ja[0] == tj[0] && ja[1] == tj[1] && ja[2] == tj[2] }
|
152
|
+
joined_associations << tj
|
153
|
+
arel = arel.join(tj[0], tj[1]).on(*tj[2])
|
132
154
|
end
|
133
155
|
end
|
134
156
|
|
157
|
+
arel = arel.join(custom_joins)
|
158
|
+
|
135
159
|
@where_values.uniq.each do |where|
|
136
160
|
next if where.blank?
|
137
161
|
|
@@ -151,13 +175,9 @@ module ActiveRecord
|
|
151
175
|
arel = arel.take(@limit_value) if @limit_value.present?
|
152
176
|
arel = arel.skip(@offset_value) if @offset_value.present?
|
153
177
|
|
154
|
-
|
155
|
-
arel = arel.group(g) if g.present?
|
156
|
-
end
|
178
|
+
arel = arel.group(*@group_values.uniq.select{|g| g.present?})
|
157
179
|
|
158
|
-
|
159
|
-
arel = arel.order(Arel::SqlLiteral.new(o.to_s)) if o.present?
|
160
|
-
end
|
180
|
+
arel = arel.order(*@order_values.uniq.select{|o| o.present?}.map(&:to_s))
|
161
181
|
|
162
182
|
selects = @select_values.uniq
|
163
183
|
|
@@ -187,15 +207,13 @@ module ActiveRecord
|
|
187
207
|
def build_where(*args)
|
188
208
|
return if args.blank?
|
189
209
|
|
190
|
-
builder = PredicateBuilder.new(table.engine)
|
191
|
-
|
192
210
|
opts = args.first
|
193
211
|
case opts
|
194
212
|
when String, Array
|
195
213
|
@klass.send(:sanitize_sql, args.size > 1 ? args : opts)
|
196
214
|
when Hash
|
197
215
|
attributes = @klass.send(:expand_hash_conditions_for_aggregates, opts)
|
198
|
-
|
216
|
+
PredicateBuilder.new(table.engine).build_from_hash(attributes, table)
|
199
217
|
else
|
200
218
|
opts
|
201
219
|
end
|
@@ -80,10 +80,15 @@ module ActiveRecord
|
|
80
80
|
|
81
81
|
options.assert_valid_keys(VALID_FIND_OPTIONS)
|
82
82
|
|
83
|
-
[:joins, :select, :group, :having, :
|
83
|
+
[:joins, :select, :group, :having, :limit, :offset, :from, :lock, :readonly].each do |finder|
|
84
84
|
relation = relation.send(finder, options[finder]) if options.has_key?(finder)
|
85
85
|
end
|
86
86
|
|
87
|
+
# Give precedence to newly-applied orders and groups to play nicely with with_scope
|
88
|
+
[:group, :order].each do |finder|
|
89
|
+
relation.send("#{finder}_values=", Array.wrap(options[finder]) + relation.send("#{finder}_values")) if options.has_key?(finder)
|
90
|
+
end
|
91
|
+
|
87
92
|
relation = relation.where(options[:conditions]) if options.has_key?(:conditions)
|
88
93
|
relation = relation.includes(options[:include]) if options.has_key?(:include)
|
89
94
|
relation = relation.extending(options[:extend]) if options.has_key?(:extend)
|
@@ -178,6 +178,9 @@ HEADER
|
|
178
178
|
statment_parts << (':name => ' + index.name.inspect)
|
179
179
|
statment_parts << ':unique => true' if index.unique
|
180
180
|
|
181
|
+
index_lengths = index.lengths.compact if index.lengths.is_a?(Array)
|
182
|
+
statment_parts << (':length => ' + Hash[*index.columns.zip(index.lengths).flatten].inspect) if index_lengths.present?
|
183
|
+
|
181
184
|
' ' + statment_parts.join(', ')
|
182
185
|
end
|
183
186
|
|
@@ -182,27 +182,31 @@ module ActiveRecord #:nodoc:
|
|
182
182
|
options[:except] |= Array.wrap(@serializable.class.inheritance_column)
|
183
183
|
end
|
184
184
|
|
185
|
-
def
|
186
|
-
|
185
|
+
def add_extra_behavior
|
186
|
+
add_includes
|
187
187
|
end
|
188
188
|
|
189
|
-
def
|
190
|
-
|
191
|
-
|
192
|
-
|
189
|
+
def add_includes
|
190
|
+
procs = options.delete(:procs)
|
191
|
+
@serializable.send(:serializable_add_includes, options) do |association, records, opts|
|
192
|
+
add_associations(association, records, opts)
|
193
193
|
end
|
194
|
+
options[:procs] = procs
|
194
195
|
end
|
195
196
|
|
197
|
+
# TODO This can likely be cleaned up to simple use ActiveSupport::XmlMini.to_tag as well.
|
196
198
|
def add_associations(association, records, opts)
|
199
|
+
association_name = association.to_s.singularize
|
200
|
+
merged_options = options.merge(opts).merge!(:root => association_name, :skip_instruct => true)
|
201
|
+
|
197
202
|
if records.is_a?(Enumerable)
|
198
|
-
tag
|
199
|
-
type = options[:skip_types] ? {} : {:type => "array"}
|
203
|
+
tag = ActiveSupport::XmlMini.rename_key(association.to_s, options)
|
204
|
+
type = options[:skip_types] ? { } : {:type => "array"}
|
200
205
|
|
201
206
|
if records.empty?
|
202
|
-
builder.tag!(tag, type)
|
207
|
+
@builder.tag!(tag, type)
|
203
208
|
else
|
204
|
-
builder.tag!(tag, type) do
|
205
|
-
association_name = association.to_s.singularize
|
209
|
+
@builder.tag!(tag, type) do
|
206
210
|
records.each do |record|
|
207
211
|
if options[:skip_types]
|
208
212
|
record_type = {}
|
@@ -211,60 +215,30 @@ module ActiveRecord #:nodoc:
|
|
211
215
|
record_type = {:type => record_class}
|
212
216
|
end
|
213
217
|
|
214
|
-
record.to_xml
|
218
|
+
record.to_xml merged_options.merge(record_type)
|
215
219
|
end
|
216
220
|
end
|
217
221
|
end
|
218
|
-
|
219
|
-
|
220
|
-
record.to_xml(opts.merge(:root => association))
|
221
|
-
end
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
def serialize
|
226
|
-
args = [root]
|
227
|
-
if options[:namespace]
|
228
|
-
args << {:xmlns=>options[:namespace]}
|
229
|
-
end
|
230
|
-
|
231
|
-
if options[:type]
|
232
|
-
args << {:type=>options[:type]}
|
233
|
-
end
|
234
|
-
|
235
|
-
builder.tag!(*args) do
|
236
|
-
add_attributes
|
237
|
-
procs = options.delete(:procs)
|
238
|
-
@serializable.send(:serializable_add_includes, options) { |association, records, opts|
|
239
|
-
add_associations(association, records, opts)
|
240
|
-
}
|
241
|
-
options[:procs] = procs
|
242
|
-
add_procs
|
243
|
-
yield builder if block_given?
|
222
|
+
elsif record = @serializable.send(association)
|
223
|
+
record.to_xml(merged_options)
|
244
224
|
end
|
245
225
|
end
|
246
226
|
|
247
227
|
class Attribute < ActiveModel::Serializers::Xml::Serializer::Attribute #:nodoc:
|
248
|
-
|
249
|
-
|
250
|
-
|
228
|
+
def compute_type
|
229
|
+
type = @serializable.class.serialized_attributes.has_key?(name) ?
|
230
|
+
super : @serializable.class.columns_hash[name].type
|
251
231
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
end
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
|
-
class MethodAttribute < Attribute #:nodoc:
|
264
|
-
protected
|
265
|
-
def compute_type
|
266
|
-
Hash::XML_TYPE_NAMES[@serializable.send(name).class.name] || :string
|
232
|
+
case type
|
233
|
+
when :text
|
234
|
+
:string
|
235
|
+
when :time
|
236
|
+
:datetime
|
237
|
+
else
|
238
|
+
type
|
267
239
|
end
|
240
|
+
end
|
241
|
+
protected :compute_type
|
268
242
|
end
|
269
243
|
end
|
270
244
|
end
|