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.

Files changed (51) hide show
  1. data/CHANGELOG +27 -0
  2. data/lib/active_record.rb +5 -1
  3. data/lib/active_record/aggregations.rb +1 -0
  4. data/lib/active_record/association_preload.rb +1 -1
  5. data/lib/active_record/associations.rb +88 -33
  6. data/lib/active_record/associations/association_collection.rb +12 -11
  7. data/lib/active_record/associations/association_proxy.rb +1 -1
  8. data/lib/active_record/attribute_methods.rb +10 -1
  9. data/lib/active_record/attribute_methods/dirty.rb +50 -50
  10. data/lib/active_record/attribute_methods/primary_key.rb +1 -1
  11. data/lib/active_record/autosave_association.rb +20 -5
  12. data/lib/active_record/base.rb +28 -343
  13. data/lib/active_record/callbacks.rb +23 -34
  14. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +1 -1
  15. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +3 -3
  16. data/lib/active_record/connection_adapters/abstract/database_limits.rb +57 -0
  17. data/lib/active_record/connection_adapters/abstract/database_statements.rb +56 -0
  18. data/lib/active_record/connection_adapters/abstract/query_cache.rb +11 -18
  19. data/lib/active_record/connection_adapters/abstract/quoting.rb +3 -7
  20. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +3 -3
  21. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +61 -7
  22. data/lib/active_record/connection_adapters/abstract_adapter.rb +3 -1
  23. data/lib/active_record/connection_adapters/mysql_adapter.rb +22 -50
  24. data/lib/active_record/connection_adapters/postgresql_adapter.rb +31 -143
  25. data/lib/active_record/connection_adapters/sqlite_adapter.rb +6 -2
  26. data/lib/active_record/counter_cache.rb +105 -0
  27. data/lib/active_record/fixtures.rb +16 -15
  28. data/lib/active_record/locale/en.yml +2 -2
  29. data/lib/active_record/locking/optimistic.rb +37 -16
  30. data/lib/active_record/migration.rb +7 -3
  31. data/lib/active_record/named_scope.rb +1 -5
  32. data/lib/active_record/nested_attributes.rb +13 -2
  33. data/lib/active_record/observer.rb +19 -7
  34. data/lib/active_record/persistence.rb +230 -0
  35. data/lib/active_record/railtie.rb +17 -23
  36. data/lib/active_record/railties/databases.rake +3 -2
  37. data/lib/active_record/relation.rb +5 -2
  38. data/lib/active_record/relation/batches.rb +6 -1
  39. data/lib/active_record/relation/calculations.rb +12 -9
  40. data/lib/active_record/relation/finder_methods.rb +14 -10
  41. data/lib/active_record/relation/query_methods.rb +62 -44
  42. data/lib/active_record/relation/spawn_methods.rb +6 -1
  43. data/lib/active_record/schema_dumper.rb +3 -0
  44. data/lib/active_record/serializers/xml_serializer.rb +30 -56
  45. data/lib/active_record/session_store.rb +1 -1
  46. data/lib/active_record/timestamp.rb +22 -26
  47. data/lib/active_record/transactions.rb +168 -50
  48. data/lib/active_record/validations.rb +33 -49
  49. data/lib/active_record/version.rb +1 -1
  50. data/lib/rails/generators/active_record.rb +6 -9
  51. 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
- # Setup database middleware after initializers have run
62
- initializer "active_record.initialize_database_middleware", :after => "action_controller.set_configs" do |app|
63
- middleware = app.config.middleware
64
- if middleware.include?("ActiveRecord::SessionStore")
65
- middleware.insert_before "ActiveRecord::SessionStore", ActiveRecord::ConnectionAdapters::ConnectionManagement
66
- middleware.insert_before "ActiveRecord::SessionStore", ActiveRecord::QueryCache
67
- else
68
- middleware.use ActiveRecord::ConnectionAdapters::ConnectionManagement
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
- initializer "active_record.load_observers" do
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.glob(File.join(fixtures_dir, '*.{yml,csv}'))).each do |fixture_file|
262
- Fixtures.create_fixtures(File.dirname(fixture_file), File.basename(fixture_file, '.*'))
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
- joined_tables = (tables_in_string(arel.joins(arel)) + [table.name, table.table_alias]).compact.uniq
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
- string.scan(/([a-zA-Z_][\.\w]+).?\./).flatten.uniq
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
- records = relation.where(primary_key.gt(records.last.id)).all
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. The value is returned as
49
- # a float, or +nil+ if there's no row. See +calculate+ for examples with
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
- 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 && (value.is_a?(Fixnum) ? value.to_f : value).to_d
246
- else type_cast_using_column(value, column)
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
- guard_protected_attributes = false
238
-
239
- if args[0].is_a?(Hash)
240
- guard_protected_attributes = true
241
- attributes_for_create = args[0].with_indifferent_access
242
- conditions = attributes_for_create.slice(*attributes).symbolize_keys
243
- else
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 { |r| r.send(:attributes=, attributes_for_create, guard_protected_attributes) }
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
- if association_joins.any?
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
- join_dependency.join_associations.each do |association|
101
- if (association_relation = association.relation).is_a?(Array)
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
- to_join.each do |tj|
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
- joins.each do |join|
118
- next if join.blank?
135
+ join_dependency.graft(*stashed_association_joins)
119
136
 
120
- @implicit_readonly = true
137
+ @implicit_readonly = true unless association_joins.empty? && stashed_association_joins.empty?
121
138
 
122
- case join
123
- when Relation::JoinOperation
124
- arel = arel.join(join.relation, join.join_class).on(*join.on)
125
- when Hash, Array, Symbol
126
- if array_of_strings?(join)
127
- join_string = join.join(' ')
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
- arel = arel.join(join)
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
- @group_values.uniq.each do |g|
155
- arel = arel.group(g) if g.present?
156
- end
178
+ arel = arel.group(*@group_values.uniq.select{|g| g.present?})
157
179
 
158
- @order_values.uniq.each do |o|
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
- builder.build_from_hash(attributes, table)
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, :order, :limit, :offset, :from, :lock, :readonly].each do |finder|
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 serializable_attributes
186
- serializable_attribute_names.collect { |name| Attribute.new(name, @serializable) }
185
+ def add_extra_behavior
186
+ add_includes
187
187
  end
188
188
 
189
- def serializable_method_attributes
190
- Array.wrap(options[:methods]).inject([]) do |method_attributes, name|
191
- method_attributes << MethodAttribute.new(name.to_s, @serializable) if @serializable.respond_to?(name.to_s)
192
- method_attributes
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 = reformat_name(association.to_s)
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 opts.merge(:root => association_name).merge(record_type)
218
+ record.to_xml merged_options.merge(record_type)
215
219
  end
216
220
  end
217
221
  end
218
- else
219
- if record = @serializable.send(association)
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
- protected
249
- def compute_type
250
- type = @serializable.class.serialized_attributes.has_key?(name) ? :yaml : @serializable.class.columns_hash[name].type
228
+ def compute_type
229
+ type = @serializable.class.serialized_attributes.has_key?(name) ?
230
+ super : @serializable.class.columns_hash[name].type
251
231
 
252
- case type
253
- when :text
254
- :string
255
- when :time
256
- :datetime
257
- else
258
- type
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