activerecord 3.0.20 → 3.1.0.beta1
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 +220 -91
- data/README.rdoc +3 -3
- data/examples/performance.rb +88 -109
- data/lib/active_record.rb +6 -2
- data/lib/active_record/aggregations.rb +22 -45
- data/lib/active_record/associations.rb +264 -991
- data/lib/active_record/associations/alias_tracker.rb +85 -0
- data/lib/active_record/associations/association.rb +231 -0
- data/lib/active_record/associations/association_scope.rb +120 -0
- data/lib/active_record/associations/belongs_to_association.rb +40 -60
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +15 -63
- data/lib/active_record/associations/builder/association.rb +53 -0
- data/lib/active_record/associations/builder/belongs_to.rb +85 -0
- data/lib/active_record/associations/builder/collection_association.rb +75 -0
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +63 -0
- data/lib/active_record/associations/builder/has_many.rb +65 -0
- data/lib/active_record/associations/builder/has_one.rb +63 -0
- data/lib/active_record/associations/builder/singular_association.rb +32 -0
- data/lib/active_record/associations/collection_association.rb +524 -0
- data/lib/active_record/associations/collection_proxy.rb +125 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +27 -118
- data/lib/active_record/associations/has_many_association.rb +50 -79
- data/lib/active_record/associations/has_many_through_association.rb +98 -67
- data/lib/active_record/associations/has_one_association.rb +45 -115
- data/lib/active_record/associations/has_one_through_association.rb +21 -25
- data/lib/active_record/associations/join_dependency.rb +215 -0
- data/lib/active_record/associations/join_dependency/join_association.rb +150 -0
- data/lib/active_record/associations/join_dependency/join_base.rb +24 -0
- data/lib/active_record/associations/join_dependency/join_part.rb +78 -0
- data/lib/active_record/associations/join_helper.rb +56 -0
- data/lib/active_record/associations/preloader.rb +177 -0
- data/lib/active_record/associations/preloader/association.rb +126 -0
- data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
- data/lib/active_record/associations/preloader/collection_association.rb +24 -0
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +60 -0
- data/lib/active_record/associations/preloader/has_many.rb +17 -0
- data/lib/active_record/associations/preloader/has_many_through.rb +15 -0
- data/lib/active_record/associations/preloader/has_one.rb +23 -0
- data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
- data/lib/active_record/associations/preloader/singular_association.rb +21 -0
- data/lib/active_record/associations/preloader/through_association.rb +67 -0
- data/lib/active_record/associations/singular_association.rb +55 -0
- data/lib/active_record/associations/through_association.rb +80 -0
- data/lib/active_record/attribute_methods.rb +19 -5
- data/lib/active_record/attribute_methods/before_type_cast.rb +9 -8
- data/lib/active_record/attribute_methods/dirty.rb +8 -2
- data/lib/active_record/attribute_methods/primary_key.rb +33 -13
- data/lib/active_record/attribute_methods/read.rb +17 -17
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +7 -4
- data/lib/active_record/attribute_methods/write.rb +2 -1
- data/lib/active_record/autosave_association.rb +66 -45
- data/lib/active_record/base.rb +445 -273
- data/lib/active_record/callbacks.rb +24 -33
- data/lib/active_record/coders/yaml_column.rb +41 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +106 -13
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +16 -2
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +12 -11
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +83 -12
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +16 -16
- data/lib/active_record/connection_adapters/abstract/quoting.rb +61 -22
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +16 -273
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +80 -42
- data/lib/active_record/connection_adapters/abstract_adapter.rb +44 -25
- data/lib/active_record/connection_adapters/column.rb +268 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +686 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +331 -88
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +295 -267
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +3 -7
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +108 -26
- data/lib/active_record/counter_cache.rb +7 -4
- data/lib/active_record/fixtures.rb +174 -192
- data/lib/active_record/identity_map.rb +131 -0
- data/lib/active_record/locking/optimistic.rb +20 -14
- data/lib/active_record/locking/pessimistic.rb +4 -4
- data/lib/active_record/log_subscriber.rb +24 -4
- data/lib/active_record/migration.rb +265 -144
- data/lib/active_record/migration/command_recorder.rb +103 -0
- data/lib/active_record/named_scope.rb +68 -25
- data/lib/active_record/nested_attributes.rb +58 -15
- data/lib/active_record/observer.rb +3 -7
- data/lib/active_record/persistence.rb +58 -38
- data/lib/active_record/query_cache.rb +25 -3
- data/lib/active_record/railtie.rb +21 -12
- data/lib/active_record/railties/console_sandbox.rb +6 -0
- data/lib/active_record/railties/databases.rake +147 -116
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/reflection.rb +176 -44
- data/lib/active_record/relation.rb +125 -49
- data/lib/active_record/relation/batches.rb +7 -5
- data/lib/active_record/relation/calculations.rb +50 -18
- data/lib/active_record/relation/finder_methods.rb +47 -26
- data/lib/active_record/relation/predicate_builder.rb +24 -21
- data/lib/active_record/relation/query_methods.rb +117 -101
- data/lib/active_record/relation/spawn_methods.rb +27 -20
- data/lib/active_record/result.rb +34 -0
- data/lib/active_record/schema.rb +5 -6
- data/lib/active_record/schema_dumper.rb +11 -13
- data/lib/active_record/serialization.rb +2 -2
- data/lib/active_record/serializers/xml_serializer.rb +10 -10
- data/lib/active_record/session_store.rb +8 -2
- data/lib/active_record/test_case.rb +9 -20
- data/lib/active_record/timestamp.rb +21 -9
- data/lib/active_record/transactions.rb +16 -15
- data/lib/active_record/validations.rb +21 -22
- data/lib/active_record/validations/associated.rb +3 -1
- data/lib/active_record/validations/uniqueness.rb +48 -58
- data/lib/active_record/version.rb +3 -3
- data/lib/rails/generators/active_record.rb +6 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb +10 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +2 -1
- data/lib/rails/generators/active_record/model/templates/migration.rb +6 -5
- data/lib/rails/generators/active_record/model/templates/model.rb +2 -0
- data/lib/rails/generators/active_record/model/templates/module.rb +2 -0
- data/lib/rails/generators/active_record/observer/templates/observer.rb +2 -0
- data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +2 -1
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +2 -2
- metadata +106 -77
- checksums.yaml +0 -7
- data/lib/active_record/association_preload.rb +0 -431
- data/lib/active_record/associations/association_collection.rb +0 -572
- data/lib/active_record/associations/association_proxy.rb +0 -304
- data/lib/active_record/associations/through_association_scope.rb +0 -160
@@ -1,113 +1,144 @@
|
|
1
|
-
require "active_record/associations/through_association_scope"
|
2
1
|
require 'active_support/core_ext/object/blank'
|
3
2
|
|
4
3
|
module ActiveRecord
|
5
4
|
# = Active Record Has Many Through Association
|
6
5
|
module Associations
|
7
6
|
class HasManyThroughAssociation < HasManyAssociation #:nodoc:
|
8
|
-
include
|
7
|
+
include ThroughAssociation
|
9
8
|
|
10
9
|
alias_method :new, :build
|
11
10
|
|
12
|
-
def create!(attrs = nil)
|
13
|
-
create_record(attrs, true)
|
14
|
-
end
|
15
|
-
|
16
|
-
def create(attrs = nil)
|
17
|
-
create_record(attrs, false)
|
18
|
-
end
|
19
|
-
|
20
|
-
def destroy(*records)
|
21
|
-
transaction do
|
22
|
-
delete_records(flatten_deeper(records))
|
23
|
-
super
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
11
|
# Returns the size of the collection by executing a SELECT COUNT(*) query if the collection hasn't been
|
28
12
|
# loaded and calling collection.size if it has. If it's more likely than not that the collection does
|
29
13
|
# have a size larger than zero, and you need to fetch that collection afterwards, it'll take one fewer
|
30
14
|
# SELECT query if you use #length.
|
31
15
|
def size
|
32
|
-
|
33
|
-
|
34
|
-
|
16
|
+
if has_cached_counter?
|
17
|
+
owner.send(:read_attribute, cached_counter_attribute_name)
|
18
|
+
elsif loaded?
|
19
|
+
target.size
|
20
|
+
else
|
21
|
+
count
|
22
|
+
end
|
35
23
|
end
|
36
24
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
object = @reflection.klass.new(attrs)
|
43
|
-
add_record_to_target_with_callbacks(object) {|r| insert_record(object, force) }
|
44
|
-
object
|
25
|
+
def concat(*records)
|
26
|
+
unless owner.new_record?
|
27
|
+
records.flatten.each do |record|
|
28
|
+
raise_on_type_mismatch(record)
|
29
|
+
record.save! if record.new_record?
|
45
30
|
end
|
46
31
|
end
|
47
32
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
33
|
+
super
|
34
|
+
end
|
35
|
+
|
36
|
+
def insert_record(record, validate = true)
|
37
|
+
ensure_not_nested
|
38
|
+
return if record.new_record? && !record.save(:validate => validate)
|
39
|
+
|
40
|
+
through_record(record).save!
|
41
|
+
update_counter(1)
|
42
|
+
record
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def through_record(record)
|
48
|
+
through_association = owner.association(through_reflection.name)
|
49
|
+
attributes = construct_join_attributes(record)
|
50
|
+
|
51
|
+
through_record = Array.wrap(through_association.target).find { |candidate|
|
52
|
+
candidate.attributes.slice(*attributes.keys) == attributes
|
53
|
+
}
|
54
|
+
|
55
|
+
unless through_record
|
56
|
+
through_record = through_association.build(attributes)
|
57
|
+
through_record.send("#{source_reflection.name}=", record)
|
53
58
|
end
|
54
|
-
end
|
55
59
|
|
56
|
-
|
57
|
-
options[:joins] = construct_joins(options[:joins])
|
58
|
-
options[:include] = @reflection.source_reflection.options[:include] if options[:include].nil? && @reflection.source_reflection.options[:include]
|
60
|
+
through_record
|
59
61
|
end
|
60
62
|
|
61
|
-
def
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
63
|
+
def build_record(attributes, options = {})
|
64
|
+
ensure_not_nested
|
65
|
+
|
66
|
+
record = super(attributes, options)
|
67
|
+
|
68
|
+
inverse = source_reflection.inverse_of
|
69
|
+
if inverse
|
70
|
+
if inverse.macro == :has_many
|
71
|
+
record.send(inverse.name) << through_record(record)
|
72
|
+
elsif inverse.macro == :has_one
|
73
|
+
record.send("#{inverse.name}=", through_record(record))
|
67
74
|
end
|
68
75
|
end
|
69
76
|
|
70
|
-
|
71
|
-
through_association.create!(construct_join_attributes(record))
|
77
|
+
record
|
72
78
|
end
|
73
79
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
80
|
+
def target_reflection_has_associated_record?
|
81
|
+
if through_reflection.macro == :belongs_to && owner[through_reflection.foreign_key].blank?
|
82
|
+
false
|
83
|
+
else
|
84
|
+
true
|
79
85
|
end
|
80
86
|
end
|
81
87
|
|
82
|
-
def
|
83
|
-
|
84
|
-
|
88
|
+
def update_through_counter?(method)
|
89
|
+
case method
|
90
|
+
when :destroy
|
91
|
+
!inverse_updates_counter_cache?(through_reflection)
|
92
|
+
when :nullify
|
93
|
+
false
|
94
|
+
else
|
95
|
+
true
|
96
|
+
end
|
85
97
|
end
|
86
98
|
|
87
|
-
def
|
88
|
-
|
89
|
-
when @reflection.options[:finder_sql]
|
90
|
-
@finder_sql = interpolate_and_sanitize_sql(@reflection.options[:finder_sql])
|
99
|
+
def delete_records(records, method)
|
100
|
+
ensure_not_nested
|
91
101
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
102
|
+
through = owner.association(through_reflection.name)
|
103
|
+
scope = through.scoped.where(construct_join_attributes(*records))
|
104
|
+
|
105
|
+
case method
|
106
|
+
when :destroy
|
107
|
+
count = scope.destroy_all.length
|
108
|
+
when :nullify
|
109
|
+
count = scope.update_all(source_reflection.foreign_key => nil)
|
110
|
+
else
|
111
|
+
count = scope.delete_all
|
112
|
+
end
|
113
|
+
|
114
|
+
delete_through_records(through, records)
|
115
|
+
|
116
|
+
if through_reflection.macro == :has_many && update_through_counter?(method)
|
117
|
+
update_counter(-count, through_reflection)
|
96
118
|
end
|
97
119
|
|
98
|
-
|
120
|
+
update_counter(-count)
|
99
121
|
end
|
100
122
|
|
101
|
-
def
|
102
|
-
|
123
|
+
def delete_through_records(through, records)
|
124
|
+
if through_reflection.macro == :has_many
|
125
|
+
records.each do |record|
|
126
|
+
through.target.delete(through_record(record))
|
127
|
+
end
|
128
|
+
else
|
129
|
+
records.each do |record|
|
130
|
+
through.target = nil if through.target == through_record(record)
|
131
|
+
end
|
132
|
+
end
|
103
133
|
end
|
104
134
|
|
105
|
-
def
|
106
|
-
|
135
|
+
def find_target
|
136
|
+
return [] unless target_reflection_has_associated_record?
|
137
|
+
scoped.all
|
107
138
|
end
|
108
139
|
|
109
140
|
# NOTE - not sure that we can actually cope with inverses here
|
110
|
-
def
|
141
|
+
def invertible_for?(record)
|
111
142
|
false
|
112
143
|
end
|
113
144
|
end
|
@@ -1,142 +1,72 @@
|
|
1
|
+
require 'active_support/core_ext/object/inclusion'
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
# = Active Record Belongs To Has One Association
|
3
5
|
module Associations
|
4
|
-
class HasOneAssociation <
|
5
|
-
def
|
6
|
-
|
7
|
-
|
8
|
-
end
|
6
|
+
class HasOneAssociation < SingularAssociation #:nodoc:
|
7
|
+
def replace(record, save = true)
|
8
|
+
raise_on_type_mismatch(record) if record
|
9
|
+
load_target
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
end
|
15
|
-
end
|
11
|
+
reflection.klass.transaction do
|
12
|
+
if target && target != record
|
13
|
+
remove_target!(options[:dependent])
|
14
|
+
end
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
reflection.create_association!(attrs)
|
21
|
-
end
|
22
|
-
end
|
16
|
+
if record
|
17
|
+
set_inverse_instance(record)
|
18
|
+
set_owner_attributes(record)
|
23
19
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
20
|
+
if owner.persisted? && save && !record.save
|
21
|
+
nullify_owner_attributes(record)
|
22
|
+
set_owner_attributes(target)
|
23
|
+
raise RecordNotSaved, "Failed to save the new associated #{reflection.name}."
|
24
|
+
end
|
25
|
+
end
|
28
26
|
end
|
29
|
-
end
|
30
27
|
|
31
|
-
|
32
|
-
|
28
|
+
self.target = record
|
29
|
+
end
|
33
30
|
|
34
|
-
|
35
|
-
|
36
|
-
|
31
|
+
def delete(method = options[:dependent])
|
32
|
+
if load_target
|
33
|
+
case method
|
37
34
|
when :delete
|
38
|
-
|
39
|
-
@owner.clear_association_cache
|
35
|
+
target.delete
|
40
36
|
when :destroy
|
41
|
-
|
42
|
-
@owner.clear_association_cache
|
37
|
+
target.destroy
|
43
38
|
when :nullify
|
44
|
-
|
45
|
-
@target.save unless @owner.new_record? || @target.new_record?
|
46
|
-
end
|
47
|
-
else
|
48
|
-
@target[@reflection.primary_key_name] = nil
|
49
|
-
@target.save unless @owner.new_record? || @target.new_record?
|
39
|
+
target.update_attribute(reflection.foreign_key, nil)
|
50
40
|
end
|
51
41
|
end
|
52
|
-
|
53
|
-
if obj.nil?
|
54
|
-
@target = nil
|
55
|
-
else
|
56
|
-
raise_on_type_mismatch(obj)
|
57
|
-
set_belongs_to_association_for(obj)
|
58
|
-
@target = (AssociationProxy === obj ? obj.target : obj)
|
59
|
-
end
|
60
|
-
|
61
|
-
set_inverse_instance(obj, @owner)
|
62
|
-
@loaded = true
|
63
|
-
|
64
|
-
unless @owner.new_record? or obj.nil? or dont_save
|
65
|
-
return (obj.save ? self : false)
|
66
|
-
else
|
67
|
-
return (obj.nil? ? nil : self)
|
68
|
-
end
|
69
42
|
end
|
70
43
|
|
71
|
-
protected
|
72
|
-
def owner_quoted_id
|
73
|
-
if @reflection.options[:primary_key]
|
74
|
-
@owner.class.quote_value(@owner.send(@reflection.options[:primary_key]))
|
75
|
-
else
|
76
|
-
@owner.quoted_id
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
44
|
private
|
81
|
-
def find_target
|
82
|
-
options = @reflection.options.dup
|
83
|
-
(options.keys - [:select, :order, :include, :readonly]).each do |key|
|
84
|
-
options.delete key
|
85
|
-
end
|
86
|
-
options[:conditions] = @finder_sql
|
87
|
-
|
88
|
-
the_target = @reflection.klass.find(:first, options)
|
89
|
-
set_inverse_instance(the_target, @owner)
|
90
|
-
the_target
|
91
|
-
end
|
92
|
-
|
93
|
-
def construct_sql
|
94
|
-
case
|
95
|
-
when @reflection.options[:as]
|
96
|
-
@finder_sql =
|
97
|
-
"#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_id = #{owner_quoted_id} AND " +
|
98
|
-
"#{@reflection.quoted_table_name}.#{@reflection.options[:as]}_type = #{@owner.class.quote_value(@owner.class.base_class.name.to_s)}"
|
99
|
-
else
|
100
|
-
@finder_sql = "#{@reflection.quoted_table_name}.#{@reflection.primary_key_name} = #{owner_quoted_id}"
|
101
|
-
end
|
102
|
-
@finder_sql << " AND (#{conditions})" if conditions
|
103
|
-
end
|
104
45
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
46
|
+
# The reason that the save param for replace is false, if for create (not just build),
|
47
|
+
# is because the setting of the foreign keys is actually handled by the scoping when
|
48
|
+
# the record is instantiated, and so they are set straight away and do not need to be
|
49
|
+
# updated within replace.
|
50
|
+
def set_new_record(record)
|
51
|
+
replace(record, false)
|
109
52
|
end
|
110
53
|
|
111
|
-
def
|
112
|
-
|
113
|
-
|
114
|
-
# elsewhere, the instance we create will get orphaned.
|
115
|
-
load_target if replace_existing
|
116
|
-
record = @reflection.klass.send(:with_scope, :create => construct_scope[:create]) do
|
117
|
-
yield @reflection
|
118
|
-
end
|
119
|
-
|
120
|
-
if replace_existing
|
121
|
-
replace(record, true)
|
54
|
+
def remove_target!(method)
|
55
|
+
if method.in?([:delete, :destroy])
|
56
|
+
target.send(method)
|
122
57
|
else
|
123
|
-
|
124
|
-
self.target = record
|
125
|
-
set_inverse_instance(record, @owner)
|
126
|
-
end
|
58
|
+
nullify_owner_attributes(target)
|
127
59
|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
60
|
+
if target.persisted? && owner.persisted? && !target.save
|
61
|
+
set_owner_attributes(target)
|
62
|
+
raise RecordNotSaved, "Failed to remove the existing associated #{reflection.name}. " +
|
63
|
+
"The record failed to save when after its foreign key was set to nil."
|
64
|
+
end
|
65
|
+
end
|
134
66
|
end
|
135
67
|
|
136
|
-
def
|
137
|
-
|
138
|
-
attrs.update(@reflection.options[:conditions]) if @reflection.options[:conditions].is_a?(Hash)
|
139
|
-
attrs
|
68
|
+
def nullify_owner_attributes(record)
|
69
|
+
record[reflection.foreign_key] = nil
|
140
70
|
end
|
141
71
|
end
|
142
72
|
end
|
@@ -1,40 +1,36 @@
|
|
1
|
-
require "active_record/associations/through_association_scope"
|
2
|
-
|
3
1
|
module ActiveRecord
|
4
2
|
# = Active Record Has One Through Association
|
5
3
|
module Associations
|
6
|
-
class HasOneThroughAssociation < HasOneAssociation
|
7
|
-
include
|
4
|
+
class HasOneThroughAssociation < HasOneAssociation #:nodoc:
|
5
|
+
include ThroughAssociation
|
8
6
|
|
9
|
-
def replace(
|
10
|
-
create_through_record(
|
11
|
-
|
7
|
+
def replace(record)
|
8
|
+
create_through_record(record)
|
9
|
+
self.target = record
|
12
10
|
end
|
13
11
|
|
14
12
|
private
|
15
13
|
|
16
|
-
|
17
|
-
|
14
|
+
def create_through_record(record)
|
15
|
+
ensure_not_nested
|
16
|
+
|
17
|
+
through_proxy = owner.association(through_reflection.name)
|
18
|
+
through_record = through_proxy.send(:load_target)
|
18
19
|
|
19
|
-
|
20
|
+
if through_record && !record
|
21
|
+
through_record.destroy
|
22
|
+
elsif record
|
23
|
+
attributes = construct_join_attributes(record)
|
20
24
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
else
|
29
|
-
@owner.send(@reflection.through_reflection.name, klass.create(construct_join_attributes(new_value)))
|
25
|
+
if through_record
|
26
|
+
through_record.update_attributes(attributes)
|
27
|
+
elsif owner.new_record?
|
28
|
+
through_proxy.build(attributes)
|
29
|
+
else
|
30
|
+
through_proxy.create(attributes)
|
31
|
+
end
|
30
32
|
end
|
31
33
|
end
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
def find_target
|
36
|
-
with_scope(construct_scope) { @reflection.klass.find(:first) }
|
37
|
-
end
|
38
34
|
end
|
39
35
|
end
|
40
36
|
end
|