activerecord 3.1.0.rc4 → 3.1.0.rc5
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/lib/active_record/associations.rb +6 -5
- data/lib/active_record/associations/alias_tracker.rb +12 -24
- data/lib/active_record/associations/association.rb +56 -6
- data/lib/active_record/associations/belongs_to_association.rb +1 -1
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +10 -12
- data/lib/active_record/associations/collection_association.rb +44 -31
- data/lib/active_record/associations/collection_proxy.rb +11 -4
- data/lib/active_record/associations/has_one_association.rb +1 -1
- data/lib/active_record/associations/join_helper.rb +1 -2
- data/lib/active_record/associations/preloader/association.rb +3 -2
- data/lib/active_record/associations/singular_association.rb +12 -4
- data/lib/active_record/attribute_methods.rb +1 -1
- data/lib/active_record/attribute_methods/primary_key.rb +1 -1
- data/lib/active_record/attribute_methods/read.rb +3 -2
- data/lib/active_record/autosave_association.rb +1 -1
- data/lib/active_record/base.rb +78 -30
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +18 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +6 -6
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +4 -4
- data/lib/active_record/connection_adapters/column.rb +2 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +5 -0
- data/lib/active_record/locking/optimistic.rb +1 -1
- data/lib/active_record/migration.rb +6 -2
- data/lib/active_record/migration/command_recorder.rb +1 -1
- data/lib/active_record/named_scope.rb +19 -0
- data/lib/active_record/nested_attributes.rb +18 -12
- data/lib/active_record/persistence.rb +8 -3
- data/lib/active_record/query_cache.rb +8 -0
- data/lib/active_record/railtie.rb +23 -0
- data/lib/active_record/railties/databases.rake +18 -13
- data/lib/active_record/reflection.rb +26 -26
- data/lib/active_record/relation.rb +20 -12
- data/lib/active_record/relation/batches.rb +0 -2
- data/lib/active_record/relation/calculations.rb +11 -5
- data/lib/active_record/relation/finder_methods.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +16 -7
- data/lib/active_record/relation/spawn_methods.rb +1 -1
- data/lib/active_record/session_store.rb +19 -9
- data/lib/active_record/test_case.rb +0 -1
- data/lib/active_record/version.rb +1 -1
- metadata +15 -29
@@ -346,11 +346,11 @@ module ActiveRecord
|
|
346
346
|
|
347
347
|
# Remove the given index from the table.
|
348
348
|
#
|
349
|
-
# Remove the
|
350
|
-
# remove_index :
|
351
|
-
# Remove the index named
|
349
|
+
# Remove the index_accounts_on_column in the accounts table.
|
350
|
+
# remove_index :accounts, :column
|
351
|
+
# Remove the index named index_accounts_on_branch_id in the accounts table.
|
352
352
|
# remove_index :accounts, :column => :branch_id
|
353
|
-
# Remove the index named
|
353
|
+
# Remove the index named index_accounts_on_branch_id_and_party_id in the accounts table.
|
354
354
|
# remove_index :accounts, :column => [:branch_id, :party_id]
|
355
355
|
# Remove the index named by_branch_party in the accounts table.
|
356
356
|
# remove_index :accounts, :name => :by_branch_party
|
@@ -929,7 +929,7 @@ module ActiveRecord
|
|
929
929
|
|
930
930
|
# Construct a clean list of column names from the ORDER BY clause, removing
|
931
931
|
# any ASC/DESC modifiers
|
932
|
-
order_columns = orders.collect { |s| s
|
932
|
+
order_columns = orders.collect { |s| s.gsub(/\s+(ASC|DESC)\s*/i, '') }
|
933
933
|
order_columns.delete_if { |c| c.blank? }
|
934
934
|
order_columns = order_columns.zip((0...order_columns.size).to_a).map { |s,i| "#{s} AS alias_#{i}" }
|
935
935
|
|
@@ -73,7 +73,7 @@ module ActiveRecord
|
|
73
73
|
# <tt>locking_enabled?</tt> at this point as
|
74
74
|
# <tt>@attributes</tt> may not have been initialized yet.
|
75
75
|
|
76
|
-
if
|
76
|
+
if result.key?(self.class.locking_column) && lock_optimistically
|
77
77
|
result[self.class.locking_column] ||= 0
|
78
78
|
end
|
79
79
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "active_support/core_ext/module/delegation"
|
2
|
+
require "active_support/core_ext/class/attribute_accessors"
|
1
3
|
require "active_support/core_ext/array/wrap"
|
2
4
|
|
3
5
|
module ActiveRecord
|
@@ -116,8 +118,10 @@ module ActiveRecord
|
|
116
118
|
# with the name of the column. Other options include
|
117
119
|
# <tt>:name</tt> and <tt>:unique</tt> (e.g.
|
118
120
|
# <tt>{ :name => "users_name_index", :unique => true }</tt>).
|
119
|
-
# * <tt>remove_index(table_name,
|
120
|
-
# by +
|
121
|
+
# * <tt>remove_index(table_name, :column => column_name)</tt>: Removes the index
|
122
|
+
# specified by +column_name+.
|
123
|
+
# * <tt>remove_index(table_name, :name => index_name)</tt>: Removes the index
|
124
|
+
# specified by +index_name+.
|
121
125
|
#
|
122
126
|
# == Irreversible transformations
|
123
127
|
#
|
@@ -48,7 +48,7 @@ module ActiveRecord
|
|
48
48
|
super || delegate.respond_to?(*args)
|
49
49
|
end
|
50
50
|
|
51
|
-
[:create_table, :rename_table, :add_column, :remove_column, :rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps, :change_column, :change_column_default].each do |method|
|
51
|
+
[:create_table, :change_table, :rename_table, :add_column, :remove_column, :rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps, :change_column, :change_column_default].each do |method|
|
52
52
|
class_eval <<-EOV, __FILE__, __LINE__ + 1
|
53
53
|
def #{method}(*args) # def create_table(*args)
|
54
54
|
record(:"#{method}", args) # record(:create_table, args)
|
@@ -40,6 +40,25 @@ module ActiveRecord
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
+
##
|
44
|
+
# Collects attributes from scopes that should be applied when creating
|
45
|
+
# an AR instance for the particular class this is called on.
|
46
|
+
def scope_attributes # :nodoc:
|
47
|
+
if current_scope
|
48
|
+
current_scope.scope_for_create
|
49
|
+
else
|
50
|
+
scope = relation.clone
|
51
|
+
scope.default_scoped = true
|
52
|
+
scope.scope_for_create
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# Are there default attributes associated with this scope?
|
58
|
+
def scope_attributes? # :nodoc:
|
59
|
+
current_scope || default_scopes.any?
|
60
|
+
end
|
61
|
+
|
43
62
|
# Adds a class method for retrieving and querying objects. A \scope represents a narrowing of a database query,
|
44
63
|
# such as <tt>where(:color => :red).select('shirts.*').includes(:washing_instructions)</tt>.
|
45
64
|
#
|
@@ -277,14 +277,14 @@ module ActiveRecord
|
|
277
277
|
type = (reflection.collection? ? :collection : :one_to_one)
|
278
278
|
|
279
279
|
# def pirate_attributes=(attributes)
|
280
|
-
# assign_nested_attributes_for_one_to_one_association(:pirate, attributes)
|
280
|
+
# assign_nested_attributes_for_one_to_one_association(:pirate, attributes, mass_assignment_options)
|
281
281
|
# end
|
282
282
|
class_eval <<-eoruby, __FILE__, __LINE__ + 1
|
283
283
|
if method_defined?(:#{association_name}_attributes=)
|
284
284
|
remove_method(:#{association_name}_attributes=)
|
285
285
|
end
|
286
286
|
def #{association_name}_attributes=(attributes)
|
287
|
-
assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes)
|
287
|
+
assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes, mass_assignment_options)
|
288
288
|
end
|
289
289
|
eoruby
|
290
290
|
else
|
@@ -319,21 +319,21 @@ module ActiveRecord
|
|
319
319
|
# If the given attributes include a matching <tt>:id</tt> attribute, or
|
320
320
|
# update_only is true, and a <tt>:_destroy</tt> key set to a truthy value,
|
321
321
|
# then the existing record will be marked for destruction.
|
322
|
-
def assign_nested_attributes_for_one_to_one_association(association_name, attributes)
|
322
|
+
def assign_nested_attributes_for_one_to_one_association(association_name, attributes, assignment_opts = {})
|
323
323
|
options = self.nested_attributes_options[association_name]
|
324
324
|
attributes = attributes.with_indifferent_access
|
325
325
|
|
326
326
|
if (options[:update_only] || !attributes['id'].blank?) && (record = send(association_name)) &&
|
327
327
|
(options[:update_only] || record.id.to_s == attributes['id'].to_s)
|
328
|
-
assign_to_or_mark_for_destruction(record, attributes, options[:allow_destroy]) unless call_reject_if(association_name, attributes)
|
328
|
+
assign_to_or_mark_for_destruction(record, attributes, options[:allow_destroy], assignment_opts) unless call_reject_if(association_name, attributes)
|
329
329
|
|
330
|
-
elsif attributes['id'].present?
|
330
|
+
elsif attributes['id'].present? && !assignment_opts[:without_protection]
|
331
331
|
raise_nested_attributes_record_not_found(association_name, attributes['id'])
|
332
332
|
|
333
333
|
elsif !reject_new_record?(association_name, attributes)
|
334
334
|
method = "build_#{association_name}"
|
335
335
|
if respond_to?(method)
|
336
|
-
send(method, attributes.except(*
|
336
|
+
send(method, attributes.except(*unassignable_keys(assignment_opts)), assignment_opts)
|
337
337
|
else
|
338
338
|
raise ArgumentError, "Cannot build association #{association_name}. Are you trying to build a polymorphic one-to-one association?"
|
339
339
|
end
|
@@ -367,7 +367,7 @@ module ActiveRecord
|
|
367
367
|
# { :name => 'John' },
|
368
368
|
# { :id => '2', :_destroy => true }
|
369
369
|
# ])
|
370
|
-
def assign_nested_attributes_for_collection_association(association_name, attributes_collection)
|
370
|
+
def assign_nested_attributes_for_collection_association(association_name, attributes_collection, assignment_opts = {})
|
371
371
|
options = self.nested_attributes_options[association_name]
|
372
372
|
|
373
373
|
unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array)
|
@@ -383,7 +383,7 @@ module ActiveRecord
|
|
383
383
|
attributes_collection = if keys.include?('id') || keys.include?(:id)
|
384
384
|
Array.wrap(attributes_collection)
|
385
385
|
else
|
386
|
-
attributes_collection.
|
386
|
+
attributes_collection.values
|
387
387
|
end
|
388
388
|
end
|
389
389
|
|
@@ -401,7 +401,7 @@ module ActiveRecord
|
|
401
401
|
|
402
402
|
if attributes['id'].blank?
|
403
403
|
unless reject_new_record?(association_name, attributes)
|
404
|
-
association.build(attributes.except(*
|
404
|
+
association.build(attributes.except(*unassignable_keys(assignment_opts)), assignment_opts)
|
405
405
|
end
|
406
406
|
elsif existing_record = existing_records.detect { |record| record.id.to_s == attributes['id'].to_s }
|
407
407
|
unless association.loaded? || call_reject_if(association_name, attributes)
|
@@ -418,8 +418,10 @@ module ActiveRecord
|
|
418
418
|
end
|
419
419
|
|
420
420
|
if !call_reject_if(association_name, attributes)
|
421
|
-
assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
|
421
|
+
assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy], assignment_opts)
|
422
422
|
end
|
423
|
+
elsif assignment_opts[:without_protection]
|
424
|
+
association.build(attributes.except(*unassignable_keys(assignment_opts)), assignment_opts)
|
423
425
|
else
|
424
426
|
raise_nested_attributes_record_not_found(association_name, attributes['id'])
|
425
427
|
end
|
@@ -428,8 +430,8 @@ module ActiveRecord
|
|
428
430
|
|
429
431
|
# Updates a record with the +attributes+ or marks it for destruction if
|
430
432
|
# +allow_destroy+ is +true+ and has_destroy_flag? returns +true+.
|
431
|
-
def assign_to_or_mark_for_destruction(record, attributes, allow_destroy)
|
432
|
-
record.attributes
|
433
|
+
def assign_to_or_mark_for_destruction(record, attributes, allow_destroy, assignment_opts)
|
434
|
+
record.assign_attributes(attributes.except(*unassignable_keys(assignment_opts)), assignment_opts)
|
433
435
|
record.mark_for_destruction if has_destroy_flag?(attributes) && allow_destroy
|
434
436
|
end
|
435
437
|
|
@@ -458,5 +460,9 @@ module ActiveRecord
|
|
458
460
|
def raise_nested_attributes_record_not_found(association_name, record_id)
|
459
461
|
raise RecordNotFound, "Couldn't find #{self.class.reflect_on_association(association_name).klass.name} with ID=#{record_id} for #{self.class.name} with ID=#{id}"
|
460
462
|
end
|
463
|
+
|
464
|
+
def unassignable_keys(assignment_opts)
|
465
|
+
assignment_opts[:without_protection] ? UNASSIGNABLE_KEYS - %w[id] : UNASSIGNABLE_KEYS
|
466
|
+
end
|
461
467
|
end
|
462
468
|
end
|
@@ -79,6 +79,8 @@ module ActiveRecord
|
|
79
79
|
# Deletes the record in the database and freezes this instance to reflect
|
80
80
|
# that no changes should be made (since they can't be persisted).
|
81
81
|
def destroy
|
82
|
+
destroy_associations
|
83
|
+
|
82
84
|
if persisted?
|
83
85
|
IdentityMap.remove(self) if IdentityMap.enabled?
|
84
86
|
pk = self.class.primary_key
|
@@ -282,6 +284,11 @@ module ActiveRecord
|
|
282
284
|
end
|
283
285
|
|
284
286
|
private
|
287
|
+
|
288
|
+
# A hook to be overridden by association modules.
|
289
|
+
def destroy_associations
|
290
|
+
end
|
291
|
+
|
285
292
|
def create_or_update
|
286
293
|
raise ReadOnlyRecord if readonly?
|
287
294
|
result = new_record? ? create : update
|
@@ -317,9 +324,7 @@ module ActiveRecord
|
|
317
324
|
# that a new instance, or one populated from a passed-in Hash, still has all the attributes
|
318
325
|
# that instances loaded from the database would.
|
319
326
|
def attributes_from_column_definition
|
320
|
-
|
321
|
-
[column.name, column.default]
|
322
|
-
end]
|
327
|
+
self.class.column_defaults.dup
|
323
328
|
end
|
324
329
|
end
|
325
330
|
end
|
@@ -33,6 +33,14 @@ module ActiveRecord
|
|
33
33
|
@target = target
|
34
34
|
end
|
35
35
|
|
36
|
+
def method_missing(method_sym, *arguments, &block)
|
37
|
+
@target.send(method_sym, *arguments, &block)
|
38
|
+
end
|
39
|
+
|
40
|
+
def respond_to?(method_sym, include_private = false)
|
41
|
+
super || @target.respond_to?(method_sym)
|
42
|
+
end
|
43
|
+
|
36
44
|
def each(&block)
|
37
45
|
@target.each(&block)
|
38
46
|
end
|
@@ -96,5 +96,28 @@ module ActiveRecord
|
|
96
96
|
end
|
97
97
|
end
|
98
98
|
end
|
99
|
+
|
100
|
+
config.after_initialize do
|
101
|
+
container = :"activerecord.attributes"
|
102
|
+
lookup = I18n.t(container, :default => {})
|
103
|
+
if lookup.is_a?(Hash)
|
104
|
+
lookup.each do |key, value|
|
105
|
+
if value.is_a?(Hash) && value.any? { |k,v| v.is_a?(Hash) }
|
106
|
+
$stderr.puts "[DEPRECATION WARNING] Nested I18n namespace lookup under \"#{container}.#{key}\" is no longer supported"
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
container = :"activerecord.models"
|
112
|
+
lookup = I18n.t(container, :default => {})
|
113
|
+
if lookup.is_a?(Hash)
|
114
|
+
lookup.each do |key, value|
|
115
|
+
if value.is_a?(Hash) && !value.key?(:one)
|
116
|
+
$stderr.puts "[DEPRECATION WARNING] Nested I18n namespace lookup under \"#{container}.#{key}\" is no longer supported"
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
99
122
|
end
|
100
123
|
end
|
@@ -44,6 +44,12 @@ db_namespace = namespace :db do
|
|
44
44
|
create_database(ActiveRecord::Base.configurations[Rails.env])
|
45
45
|
end
|
46
46
|
|
47
|
+
def mysql_creation_options(config)
|
48
|
+
@charset = ENV['CHARSET'] || 'utf8'
|
49
|
+
@collation = ENV['COLLATION'] || 'utf8_unicode_ci'
|
50
|
+
{:charset => (config['charset'] || @charset), :collation => (config['collation'] || @collation)}
|
51
|
+
end
|
52
|
+
|
47
53
|
def create_database(config)
|
48
54
|
begin
|
49
55
|
if config['adapter'] =~ /sqlite/
|
@@ -67,9 +73,6 @@ db_namespace = namespace :db do
|
|
67
73
|
rescue
|
68
74
|
case config['adapter']
|
69
75
|
when /mysql/
|
70
|
-
@charset = ENV['CHARSET'] || 'utf8'
|
71
|
-
@collation = ENV['COLLATION'] || 'utf8_unicode_ci'
|
72
|
-
creation_options = {:charset => (config['charset'] || @charset), :collation => (config['collation'] || @collation)}
|
73
76
|
if config['adapter'] =~ /jdbc/
|
74
77
|
#FIXME After Jdbcmysql gives this class
|
75
78
|
require 'active_record/railties/jdbcmysql_error'
|
@@ -80,7 +83,7 @@ db_namespace = namespace :db do
|
|
80
83
|
access_denied_error = 1045
|
81
84
|
begin
|
82
85
|
ActiveRecord::Base.establish_connection(config.merge('database' => nil))
|
83
|
-
ActiveRecord::Base.connection.create_database(config['database'],
|
86
|
+
ActiveRecord::Base.connection.create_database(config['database'], mysql_creation_options(config))
|
84
87
|
ActiveRecord::Base.establish_connection(config)
|
85
88
|
rescue error_class => sqlerr
|
86
89
|
if sqlerr.errno == access_denied_error
|
@@ -112,7 +115,8 @@ db_namespace = namespace :db do
|
|
112
115
|
end
|
113
116
|
end
|
114
117
|
else
|
115
|
-
|
118
|
+
# Bug with 1.9.2 Calling return within begin still executes else
|
119
|
+
$stderr.puts "#{config['database']} already exists" unless config['adapter'] =~ /sqlite/
|
116
120
|
end
|
117
121
|
end
|
118
122
|
|
@@ -377,8 +381,7 @@ db_namespace = namespace :db do
|
|
377
381
|
dbfile = abcs[Rails.env]['database'] || abcs[Rails.env]['dbfile']
|
378
382
|
`sqlite3 #{dbfile} .schema > db/#{Rails.env}_structure.sql`
|
379
383
|
when 'sqlserver'
|
380
|
-
`
|
381
|
-
`scptxfr /s #{abcs[Rails.env]['host']} /d #{abcs[Rails.env]['database']} /I /F db\ /q /A /r`
|
384
|
+
`smoscript -s #{abcs[Rails.env]['host']} -d #{abcs[Rails.env]['database']} -u #{abcs[Rails.env]['username']} -p #{abcs[Rails.env]['password']} -f db\\#{Rails.env}_structure.sql -A -U`
|
382
385
|
when "firebird"
|
383
386
|
set_firebird_env(abcs[Rails.env])
|
384
387
|
db_string = firebird_db_string(abcs[Rails.env])
|
@@ -423,7 +426,7 @@ db_namespace = namespace :db do
|
|
423
426
|
dbfile = abcs['test']['database'] || abcs['test']['dbfile']
|
424
427
|
`sqlite3 #{dbfile} < #{Rails.root}/db/#{Rails.env}_structure.sql`
|
425
428
|
when 'sqlserver'
|
426
|
-
`
|
429
|
+
`sqlcmd -S #{abcs['test']['host']} -d #{abcs['test']['database']} -U #{abcs['test']['username']} -P #{abcs['test']['password']} -i db\\#{Rails.env}_structure.sql`
|
427
430
|
when 'oci', 'oracle'
|
428
431
|
ActiveRecord::Base.establish_connection(:test)
|
429
432
|
IO.readlines("#{Rails.root}/db/#{Rails.env}_structure.sql").join.split(";\n\n").each do |ddl|
|
@@ -444,7 +447,7 @@ db_namespace = namespace :db do
|
|
444
447
|
case abcs['test']['adapter']
|
445
448
|
when /mysql/
|
446
449
|
ActiveRecord::Base.establish_connection(:test)
|
447
|
-
ActiveRecord::Base.connection.recreate_database(abcs['test']['database'], abcs['test'])
|
450
|
+
ActiveRecord::Base.connection.recreate_database(abcs['test']['database'], mysql_creation_options(abcs['test']))
|
448
451
|
when /postgresql/
|
449
452
|
ActiveRecord::Base.clear_active_connections!
|
450
453
|
drop_database(abcs['test'])
|
@@ -453,9 +456,11 @@ db_namespace = namespace :db do
|
|
453
456
|
dbfile = abcs['test']['database'] || abcs['test']['dbfile']
|
454
457
|
File.delete(dbfile) if File.exist?(dbfile)
|
455
458
|
when 'sqlserver'
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
+
test = abcs.deep_dup['test']
|
460
|
+
test_database = test['database']
|
461
|
+
test['database'] = 'master'
|
462
|
+
ActiveRecord::Base.establish_connection(test)
|
463
|
+
ActiveRecord::Base.connection.recreate_database!(test_database)
|
459
464
|
when "oci", "oracle"
|
460
465
|
ActiveRecord::Base.establish_connection(:test)
|
461
466
|
ActiveRecord::Base.connection.structure_drop.split(";\n\n").each do |ddl|
|
@@ -499,7 +504,7 @@ namespace :railties do
|
|
499
504
|
# desc "Copies missing migrations from Railties (e.g. plugins, engines). You can specify Railties to use with FROM=railtie1,railtie2"
|
500
505
|
task :migrations => :'db:load_config' do
|
501
506
|
to_load = ENV['FROM'].blank? ? :all : ENV['FROM'].split(",").map {|n| n.strip }
|
502
|
-
railties =
|
507
|
+
railties = ActiveSupport::OrderedHash.new
|
503
508
|
Rails.application.railties.all do |railtie|
|
504
509
|
next unless to_load == :all || to_load.include?(railtie.railtie_name)
|
505
510
|
|
@@ -81,12 +81,6 @@ module ActiveRecord
|
|
81
81
|
# Abstract base class for AggregateReflection and AssociationReflection. Objects of
|
82
82
|
# AggregateReflection and AssociationReflection are returned by the Reflection::ClassMethods.
|
83
83
|
class MacroReflection
|
84
|
-
attr_reader :active_record
|
85
|
-
|
86
|
-
def initialize(macro, name, options, active_record)
|
87
|
-
@macro, @name, @options, @active_record = macro, name, options, active_record
|
88
|
-
end
|
89
|
-
|
90
84
|
# Returns the name of the macro.
|
91
85
|
#
|
92
86
|
# <tt>composed_of :balance, :class_name => 'Money'</tt> returns <tt>:balance</tt>
|
@@ -105,6 +99,19 @@ module ActiveRecord
|
|
105
99
|
# <tt>has_many :clients</tt> returns +{}+
|
106
100
|
attr_reader :options
|
107
101
|
|
102
|
+
attr_reader :active_record
|
103
|
+
|
104
|
+
attr_reader :plural_name # :nodoc:
|
105
|
+
|
106
|
+
def initialize(macro, name, options, active_record)
|
107
|
+
@macro = macro
|
108
|
+
@name = name
|
109
|
+
@options = options
|
110
|
+
@active_record = active_record
|
111
|
+
@plural_name = active_record.pluralize_table_names ?
|
112
|
+
name.to_s.pluralize : name.to_s
|
113
|
+
end
|
114
|
+
|
108
115
|
# Returns the class for the macro.
|
109
116
|
#
|
110
117
|
# <tt>composed_of :balance, :class_name => 'Money'</tt> returns the Money class
|
@@ -124,7 +131,11 @@ module ActiveRecord
|
|
124
131
|
# Returns +true+ if +self+ and +other_aggregation+ have the same +name+ attribute, +active_record+ attribute,
|
125
132
|
# and +other_aggregation+ has an options hash assigned to it.
|
126
133
|
def ==(other_aggregation)
|
127
|
-
|
134
|
+
super ||
|
135
|
+
other_aggregation.kind_of?(self.class) &&
|
136
|
+
name == other_aggregation.name &&
|
137
|
+
other_aggregation.options &&
|
138
|
+
active_record == other_aggregation.active_record
|
128
139
|
end
|
129
140
|
|
130
141
|
def sanitized_conditions #:nodoc:
|
@@ -167,27 +178,16 @@ module ActiveRecord
|
|
167
178
|
@collection = macro.in?([:has_many, :has_and_belongs_to_many])
|
168
179
|
end
|
169
180
|
|
181
|
+
# This is a hack so that we can tell if build_association was overridden, in order to
|
182
|
+
# provide an appropriate deprecation if the overridden method ignored the &block. Please
|
183
|
+
# see Association#build_record for details.
|
184
|
+
attr_accessor :original_build_association_called # :nodoc
|
185
|
+
|
170
186
|
# Returns a new, unsaved instance of the associated class. +options+ will
|
171
187
|
# be passed to the class's constructor.
|
172
|
-
def build_association(*options)
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
# Creates a new instance of the associated class, and immediately saves it
|
177
|
-
# with ActiveRecord::Base#save. +options+ will be passed to the class's
|
178
|
-
# creation method. Returns the newly created object.
|
179
|
-
def create_association(*options)
|
180
|
-
klass.create(*options)
|
181
|
-
end
|
182
|
-
|
183
|
-
# Creates a new instance of the associated class, and immediately saves it
|
184
|
-
# with ActiveRecord::Base#save!. +options+ will be passed to the class's
|
185
|
-
# creation method. If the created record doesn't pass validations, then an
|
186
|
-
# exception will be raised.
|
187
|
-
#
|
188
|
-
# Returns the newly created object.
|
189
|
-
def create_association!(*options)
|
190
|
-
klass.create!(*options)
|
188
|
+
def build_association(*options, &block)
|
189
|
+
@original_build_association_called = true
|
190
|
+
klass.new(*options, &block)
|
191
191
|
end
|
192
192
|
|
193
193
|
def table_name
|