activerecord 3.0.0 → 3.0.3
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 +42 -0
- data/examples/performance.rb +18 -1
- data/lib/active_record.rb +3 -3
- data/lib/active_record/aggregations.rb +2 -2
- data/lib/active_record/association_preload.rb +1 -1
- data/lib/active_record/associations.rb +59 -26
- data/lib/active_record/associations/association_collection.rb +28 -18
- data/lib/active_record/associations/association_proxy.rb +4 -4
- data/lib/active_record/associations/belongs_to_association.rb +3 -3
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +10 -13
- data/lib/active_record/associations/has_many_through_association.rb +2 -3
- data/lib/active_record/associations/has_one_association.rb +6 -6
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/attribute_methods/before_type_cast.rb +1 -4
- data/lib/active_record/attribute_methods/primary_key.rb +4 -3
- data/lib/active_record/autosave_association.rb +7 -7
- data/lib/active_record/base.rb +71 -47
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +6 -8
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +5 -9
- data/lib/active_record/connection_adapters/mysql_adapter.rb +7 -7
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +2 -2
- data/lib/active_record/dynamic_finder_match.rb +20 -17
- data/lib/active_record/dynamic_scope_match.rb +6 -15
- data/lib/active_record/fixtures.rb +3 -5
- data/lib/active_record/locking/optimistic.rb +1 -1
- data/lib/active_record/locking/pessimistic.rb +4 -4
- data/lib/active_record/nested_attributes.rb +17 -13
- data/lib/active_record/persistence.rb +7 -8
- data/lib/active_record/railties/databases.rake +7 -7
- data/lib/active_record/relation.rb +16 -18
- data/lib/active_record/relation/batches.rb +1 -1
- data/lib/active_record/relation/calculations.rb +37 -28
- data/lib/active_record/relation/finder_methods.rb +19 -19
- data/lib/active_record/relation/predicate_builder.rb +8 -1
- data/lib/active_record/relation/query_methods.rb +100 -75
- data/lib/active_record/relation/spawn_methods.rb +50 -39
- data/lib/active_record/serialization.rb +1 -1
- data/lib/active_record/session_store.rb +4 -4
- data/lib/active_record/transactions.rb +6 -6
- data/lib/active_record/validations.rb +1 -1
- data/lib/active_record/validations/uniqueness.rb +6 -1
- data/lib/active_record/version.rb +2 -2
- data/lib/rails/generators/active_record.rb +2 -10
- data/lib/rails/generators/active_record/migration.rb +15 -0
- metadata +15 -14
data/CHANGELOG
CHANGED
@@ -1,3 +1,45 @@
|
|
1
|
+
*Rails 3.0.3 (November 16, 2010)*
|
2
|
+
|
3
|
+
* Support find by class like this: Post.where(:name => Post)
|
4
|
+
|
5
|
+
|
6
|
+
*Rails 3.0.2 (November 15, 2010)*
|
7
|
+
|
8
|
+
* Dramatic speed increase (see: http://engineering.attinteractive.com/2010/10/arel-two-point-ohhhhh-yaaaaaa/) [Aaron Patterson]
|
9
|
+
|
10
|
+
* reorder is deprecated in favor of except(:order).order(...) [Santiago Pastorino]
|
11
|
+
|
12
|
+
* except is now AR public API
|
13
|
+
|
14
|
+
Model.order('name').except(:order).order('salary')
|
15
|
+
|
16
|
+
generates:
|
17
|
+
|
18
|
+
SELECT * FROM models ORDER BY salary
|
19
|
+
|
20
|
+
[Santiago Pastorino]
|
21
|
+
|
22
|
+
* The following code:
|
23
|
+
|
24
|
+
Model.limit(10).scoping { Model.count }
|
25
|
+
|
26
|
+
now generates the following SQL:
|
27
|
+
|
28
|
+
SELECT COUNT(*) FROM models LIMIT 10
|
29
|
+
|
30
|
+
This may not return what you want. Instead, you may with to do something
|
31
|
+
like this:
|
32
|
+
|
33
|
+
Model.limit(10).scoping { Model.all.size }
|
34
|
+
|
35
|
+
[Aaron Patterson]
|
36
|
+
|
37
|
+
|
38
|
+
*Rails 3.0.1 (October 15, 2010)*
|
39
|
+
|
40
|
+
* Introduce a fix for CVE-2010-3993
|
41
|
+
|
42
|
+
|
1
43
|
*Rails 3.0.0 (August 29, 2010)*
|
2
44
|
|
3
45
|
* Changed update_attribute to not run callbacks and update the record directly in the database [Neeraj Singh]
|
data/examples/performance.rb
CHANGED
@@ -25,7 +25,7 @@ conn[:socket] = Pathname.glob(%w[
|
|
25
25
|
/tmp/mysql.sock
|
26
26
|
/var/mysql/mysql.sock
|
27
27
|
/var/run/mysqld/mysqld.sock
|
28
|
-
]).find { |path| path.socket? }
|
28
|
+
]).find { |path| path.socket? }.to_s
|
29
29
|
|
30
30
|
ActiveRecord::Base.establish_connection(conn)
|
31
31
|
|
@@ -155,6 +155,23 @@ RBench.run(TIMES) do
|
|
155
155
|
ar { Exhibit.transaction { Exhibit.new } }
|
156
156
|
end
|
157
157
|
|
158
|
+
report 'Model.find(id)' do
|
159
|
+
id = Exhibit.first.id
|
160
|
+
ar { Exhibit.find(id) }
|
161
|
+
end
|
162
|
+
|
163
|
+
report 'Model.find_by_sql' do
|
164
|
+
ar { Exhibit.find_by_sql("SELECT * FROM exhibits WHERE id = #{(rand * 1000 + 1).to_i}").first }
|
165
|
+
end
|
166
|
+
|
167
|
+
report 'Model.log', (TIMES * 10) do
|
168
|
+
ar { Exhibit.connection.send(:log, "hello", "world") {} }
|
169
|
+
end
|
170
|
+
|
171
|
+
report 'AR.execute(query)', (TIMES / 2) do
|
172
|
+
ar { ActiveRecord::Base.connection.execute("Select * from exhibits where id = #{(rand * 1000 + 1).to_i}") }
|
173
|
+
end
|
174
|
+
|
158
175
|
summary 'Total'
|
159
176
|
end
|
160
177
|
|
data/lib/active_record.rb
CHANGED
@@ -33,12 +33,12 @@ require 'active_support/i18n'
|
|
33
33
|
require 'active_model'
|
34
34
|
require 'arel'
|
35
35
|
|
36
|
+
require 'active_record/version'
|
37
|
+
|
36
38
|
module ActiveRecord
|
37
39
|
extend ActiveSupport::Autoload
|
38
40
|
|
39
41
|
eager_autoload do
|
40
|
-
autoload :VERSION
|
41
|
-
|
42
42
|
autoload :ActiveRecordError, 'active_record/errors'
|
43
43
|
autoload :ConnectionNotEstablished, 'active_record/errors'
|
44
44
|
|
@@ -118,7 +118,7 @@ module ActiveRecord
|
|
118
118
|
end
|
119
119
|
|
120
120
|
ActiveSupport.on_load(:active_record) do
|
121
|
-
Arel::Table.engine =
|
121
|
+
Arel::Table.engine = self
|
122
122
|
end
|
123
123
|
|
124
124
|
I18n.load_path << File.dirname(__FILE__) + '/active_record/locale/en.yml'
|
@@ -6,7 +6,7 @@ module ActiveRecord
|
|
6
6
|
def clear_aggregation_cache #:nodoc:
|
7
7
|
self.class.reflect_on_all_aggregations.to_a.each do |assoc|
|
8
8
|
instance_variable_set "@#{assoc.name}", nil
|
9
|
-
end
|
9
|
+
end if self.persisted?
|
10
10
|
end
|
11
11
|
|
12
12
|
# Active Record implements aggregation through a macro-like class method called +composed_of+
|
@@ -161,7 +161,7 @@ module ActiveRecord
|
|
161
161
|
# by specifying an instance of the value object in the conditions hash. The following example
|
162
162
|
# finds all customers with +balance_amount+ equal to 20 and +balance_currency+ equal to "USD":
|
163
163
|
#
|
164
|
-
# Customer.
|
164
|
+
# Customer.where(:balance => Money.new(20, "USD")).all
|
165
165
|
#
|
166
166
|
module ClassMethods
|
167
167
|
# Adds reader and writer methods for manipulating a value object:
|
@@ -284,7 +284,7 @@ module ActiveRecord
|
|
284
284
|
end
|
285
285
|
else
|
286
286
|
options = {}
|
287
|
-
options[:include] = reflection.options[:include] || reflection.options[:source] if reflection.options[:conditions]
|
287
|
+
options[:include] = reflection.options[:include] || reflection.options[:source] if reflection.options[:conditions] || reflection.options[:order]
|
288
288
|
options[:order] = reflection.options[:order]
|
289
289
|
options[:conditions] = reflection.options[:conditions]
|
290
290
|
records.first.class.preload_associations(records, through_association, options)
|
@@ -118,7 +118,7 @@ module ActiveRecord
|
|
118
118
|
def clear_association_cache #:nodoc:
|
119
119
|
self.class.reflect_on_all_associations.to_a.each do |assoc|
|
120
120
|
instance_variable_set "@#{assoc.name}", nil
|
121
|
-
end
|
121
|
+
end if self.persisted?
|
122
122
|
end
|
123
123
|
|
124
124
|
private
|
@@ -602,7 +602,7 @@ module ActiveRecord
|
|
602
602
|
# other than the main one. If this is the case Active Record falls back to the previously
|
603
603
|
# used LEFT OUTER JOIN based strategy. For example
|
604
604
|
#
|
605
|
-
# Post.
|
605
|
+
# Post.includes([:author, :comments]).where(['comments.approved = ?', true]).all
|
606
606
|
#
|
607
607
|
# This will result in a single SQL query with joins along the lines of:
|
608
608
|
# <tt>LEFT OUTER JOIN comments ON comments.post_id = posts.id</tt> and
|
@@ -1416,8 +1416,8 @@ module ActiveRecord
|
|
1416
1416
|
include Module.new {
|
1417
1417
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
1418
1418
|
def destroy # def destroy
|
1419
|
-
super # super
|
1420
1419
|
#{reflection.name}.clear # posts.clear
|
1420
|
+
super # super
|
1421
1421
|
end # end
|
1422
1422
|
RUBY
|
1423
1423
|
}
|
@@ -1840,7 +1840,7 @@ module ActiveRecord
|
|
1840
1840
|
|
1841
1841
|
def initialize(base, associations, joins)
|
1842
1842
|
@joins = [JoinBase.new(base, joins)]
|
1843
|
-
@associations =
|
1843
|
+
@associations = {}
|
1844
1844
|
@reflections = []
|
1845
1845
|
@base_records_hash = {}
|
1846
1846
|
@base_records_in_order = []
|
@@ -1852,7 +1852,7 @@ module ActiveRecord
|
|
1852
1852
|
def graft(*associations)
|
1853
1853
|
associations.each do |association|
|
1854
1854
|
join_associations.detect {|a| association == a} ||
|
1855
|
-
build(association.reflection.name, association.find_parent_in(self) || join_base, association.
|
1855
|
+
build(association.reflection.name, association.find_parent_in(self) || join_base, association.join_type)
|
1856
1856
|
end
|
1857
1857
|
self
|
1858
1858
|
end
|
@@ -1920,28 +1920,57 @@ module ActiveRecord
|
|
1920
1920
|
|
1921
1921
|
protected
|
1922
1922
|
|
1923
|
-
def
|
1923
|
+
def cache_joined_association(association)
|
1924
|
+
associations = []
|
1925
|
+
parent = association.parent
|
1926
|
+
while parent != join_base
|
1927
|
+
associations.unshift(parent.reflection.name)
|
1928
|
+
parent = parent.parent
|
1929
|
+
end
|
1930
|
+
ref = @associations
|
1931
|
+
associations.each do |key|
|
1932
|
+
ref = ref[key]
|
1933
|
+
end
|
1934
|
+
ref[association.reflection.name] ||= {}
|
1935
|
+
end
|
1936
|
+
|
1937
|
+
def build(associations, parent = nil, join_type = Arel::InnerJoin)
|
1924
1938
|
parent ||= @joins.last
|
1925
1939
|
case associations
|
1926
1940
|
when Symbol, String
|
1927
1941
|
reflection = parent.reflections[associations.to_s.intern] or
|
1928
1942
|
raise ConfigurationError, "Association named '#{ associations }' was not found; perhaps you misspelled it?"
|
1929
|
-
|
1930
|
-
|
1943
|
+
unless join_association = find_join_association(reflection, parent)
|
1944
|
+
@reflections << reflection
|
1945
|
+
join_association = build_join_association(reflection, parent)
|
1946
|
+
join_association.join_type = join_type
|
1947
|
+
@joins << join_association
|
1948
|
+
cache_joined_association(join_association)
|
1949
|
+
end
|
1950
|
+
join_association
|
1931
1951
|
when Array
|
1932
1952
|
associations.each do |association|
|
1933
|
-
build(association, parent,
|
1953
|
+
build(association, parent, join_type)
|
1934
1954
|
end
|
1935
1955
|
when Hash
|
1936
1956
|
associations.keys.sort{|a,b|a.to_s<=>b.to_s}.each do |name|
|
1937
|
-
build(name, parent,
|
1938
|
-
build(associations[name],
|
1957
|
+
join_association = build(name, parent, join_type)
|
1958
|
+
build(associations[name], join_association, join_type)
|
1939
1959
|
end
|
1940
1960
|
else
|
1941
1961
|
raise ConfigurationError, associations.inspect
|
1942
1962
|
end
|
1943
1963
|
end
|
1944
1964
|
|
1965
|
+
def find_join_association(name_or_reflection, parent)
|
1966
|
+
case name_or_reflection
|
1967
|
+
when Symbol, String
|
1968
|
+
join_associations.detect {|j| (j.reflection.name == name_or_reflection.to_s.intern) && (j.parent == parent)}
|
1969
|
+
else
|
1970
|
+
join_associations.detect {|j| (j.reflection == name_or_reflection) && (j.parent == parent)}
|
1971
|
+
end
|
1972
|
+
end
|
1973
|
+
|
1945
1974
|
def remove_uniq_by_reflection(reflection, records)
|
1946
1975
|
if reflection && reflection.collection?
|
1947
1976
|
records.each { |record| record.send(reflection.name).target.uniq! }
|
@@ -2020,8 +2049,7 @@ module ActiveRecord
|
|
2020
2049
|
|
2021
2050
|
def ==(other)
|
2022
2051
|
other.class == self.class &&
|
2023
|
-
other.active_record == active_record
|
2024
|
-
other.table_joins == table_joins
|
2052
|
+
other.active_record == active_record
|
2025
2053
|
end
|
2026
2054
|
|
2027
2055
|
def aliased_prefix
|
@@ -2049,7 +2077,7 @@ module ActiveRecord
|
|
2049
2077
|
end
|
2050
2078
|
|
2051
2079
|
def extract_record(row)
|
2052
|
-
column_names_with_alias.
|
2080
|
+
Hash[column_names_with_alias.map{|cn, an| [cn, row[an]]}]
|
2053
2081
|
end
|
2054
2082
|
|
2055
2083
|
def record_id(row)
|
@@ -2062,7 +2090,9 @@ module ActiveRecord
|
|
2062
2090
|
end
|
2063
2091
|
|
2064
2092
|
class JoinAssociation < JoinBase # :nodoc:
|
2065
|
-
attr_reader :reflection, :parent, :aliased_table_name, :aliased_prefix, :aliased_join_table_name, :parent_table_name
|
2093
|
+
attr_reader :reflection, :parent, :aliased_table_name, :aliased_prefix, :aliased_join_table_name, :parent_table_name
|
2094
|
+
# What type of join will be generated, either Arel::InnerJoin (default) or Arel::OuterJoin
|
2095
|
+
attr_accessor :join_type
|
2066
2096
|
delegate :options, :klass, :through_reflection, :source_reflection, :to => :reflection
|
2067
2097
|
|
2068
2098
|
def initialize(reflection, join_dependency, parent = nil)
|
@@ -2079,7 +2109,7 @@ module ActiveRecord
|
|
2079
2109
|
@parent_table_name = parent.active_record.table_name
|
2080
2110
|
@aliased_table_name = aliased_table_name_for(table_name)
|
2081
2111
|
@join = nil
|
2082
|
-
@
|
2112
|
+
@join_type = Arel::InnerJoin
|
2083
2113
|
|
2084
2114
|
if reflection.macro == :has_and_belongs_to_many
|
2085
2115
|
@aliased_join_table_name = aliased_table_name_for(reflection.options[:join_table], "_join")
|
@@ -2102,16 +2132,16 @@ module ActiveRecord
|
|
2102
2132
|
end
|
2103
2133
|
end
|
2104
2134
|
|
2105
|
-
def with_join_class(join_class)
|
2106
|
-
@join_class = join_class
|
2107
|
-
self
|
2108
|
-
end
|
2109
|
-
|
2110
2135
|
def association_join
|
2111
2136
|
return @join if @join
|
2112
2137
|
|
2113
|
-
aliased_table = Arel::Table.new(table_name, :as
|
2114
|
-
|
2138
|
+
aliased_table = Arel::Table.new(table_name, :as => @aliased_table_name,
|
2139
|
+
:engine => arel_engine,
|
2140
|
+
:columns => klass.columns)
|
2141
|
+
|
2142
|
+
parent_table = Arel::Table.new(parent.table_name, :as => parent.aliased_table_name,
|
2143
|
+
:engine => arel_engine,
|
2144
|
+
:columns => parent.active_record.columns)
|
2115
2145
|
|
2116
2146
|
@join = case reflection.macro
|
2117
2147
|
when :has_and_belongs_to_many
|
@@ -2194,7 +2224,9 @@ module ActiveRecord
|
|
2194
2224
|
end
|
2195
2225
|
|
2196
2226
|
def relation
|
2197
|
-
aliased = Arel::Table.new(table_name, :as => @aliased_table_name,
|
2227
|
+
aliased = Arel::Table.new(table_name, :as => @aliased_table_name,
|
2228
|
+
:engine => arel_engine,
|
2229
|
+
:columns => klass.columns)
|
2198
2230
|
|
2199
2231
|
if reflection.macro == :has_and_belongs_to_many
|
2200
2232
|
[Arel::Table.new(options[:join_table], :as => aliased_join_table_name, :engine => arel_engine), aliased]
|
@@ -2205,8 +2237,9 @@ module ActiveRecord
|
|
2205
2237
|
end
|
2206
2238
|
end
|
2207
2239
|
|
2208
|
-
def join_relation(joining_relation
|
2209
|
-
|
2240
|
+
def join_relation(joining_relation)
|
2241
|
+
self.join_type = Arel::OuterJoin
|
2242
|
+
joining_relation.joins(self)
|
2210
2243
|
end
|
2211
2244
|
|
2212
2245
|
protected
|
@@ -127,13 +127,13 @@ module ActiveRecord
|
|
127
127
|
# Since << flattens its argument list and inserts each record, +push+ and +concat+ behave identically.
|
128
128
|
def <<(*records)
|
129
129
|
result = true
|
130
|
-
load_target
|
130
|
+
load_target unless @owner.persisted?
|
131
131
|
|
132
132
|
transaction do
|
133
133
|
flatten_deeper(records).each do |record|
|
134
134
|
raise_on_type_mismatch(record)
|
135
135
|
add_record_to_target_with_callbacks(record) do |r|
|
136
|
-
result &&= insert_record(record)
|
136
|
+
result &&= insert_record(record) if @owner.persisted?
|
137
137
|
end
|
138
138
|
end
|
139
139
|
end
|
@@ -291,12 +291,12 @@ module ActiveRecord
|
|
291
291
|
# This method is abstract in the sense that it relies on
|
292
292
|
# +count_records+, which is a method descendants have to provide.
|
293
293
|
def size
|
294
|
-
if
|
294
|
+
if !@owner.persisted? || (loaded? && !@reflection.options[:uniq])
|
295
295
|
@target.size
|
296
296
|
elsif !loaded? && @reflection.options[:group]
|
297
297
|
load_target.size
|
298
298
|
elsif !loaded? && !@reflection.options[:uniq] && @target.is_a?(Array)
|
299
|
-
unsaved_records = @target.
|
299
|
+
unsaved_records = @target.reject { |r| r.persisted? }
|
300
300
|
unsaved_records.size + count_records
|
301
301
|
else
|
302
302
|
count_records
|
@@ -338,13 +338,12 @@ module ActiveRecord
|
|
338
338
|
|
339
339
|
def uniq(collection = self)
|
340
340
|
seen = Set.new
|
341
|
-
collection.
|
341
|
+
collection.map do |record|
|
342
342
|
unless seen.include?(record.id)
|
343
|
-
kept << record
|
344
343
|
seen << record.id
|
344
|
+
record
|
345
345
|
end
|
346
|
-
|
347
|
-
end
|
346
|
+
end.compact
|
348
347
|
end
|
349
348
|
|
350
349
|
# Replace this collection with +other_array+
|
@@ -364,6 +363,7 @@ module ActiveRecord
|
|
364
363
|
|
365
364
|
def include?(record)
|
366
365
|
return false unless record.is_a?(@reflection.klass)
|
366
|
+
return include_in_memory?(record) unless record.persisted?
|
367
367
|
load_target if @reflection.options[:finder_sql] && !loaded?
|
368
368
|
return @target.include?(record) if loaded?
|
369
369
|
exists?(record)
|
@@ -390,7 +390,7 @@ module ActiveRecord
|
|
390
390
|
end
|
391
391
|
|
392
392
|
def load_target
|
393
|
-
if
|
393
|
+
if @owner.persisted? || foreign_key_present
|
394
394
|
begin
|
395
395
|
if !loaded?
|
396
396
|
if @target.is_a?(Array) && @target.any?
|
@@ -493,11 +493,9 @@ module ActiveRecord
|
|
493
493
|
attrs.update(@reflection.options[:conditions]) if @reflection.options[:conditions].is_a?(Hash)
|
494
494
|
ensure_owner_is_not_new
|
495
495
|
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
record = @reflection.klass.send(:with_scope, :create => options) do
|
496
|
+
scoped_where = scoped.where_values_hash
|
497
|
+
create_scope = scoped_where ? construct_scope[:create].merge(scoped_where) : construct_scope[:create]
|
498
|
+
record = @reflection.klass.send(:with_scope, :create => create_scope) do
|
501
499
|
@reflection.build_association(attrs)
|
502
500
|
end
|
503
501
|
if block_given?
|
@@ -523,7 +521,7 @@ module ActiveRecord
|
|
523
521
|
|
524
522
|
transaction do
|
525
523
|
records.each { |record| callback(:before_remove, record) }
|
526
|
-
old_records = records.
|
524
|
+
old_records = records.select { |r| r.persisted? }
|
527
525
|
yield(records, old_records)
|
528
526
|
records.each { |record| callback(:after_remove, record) }
|
529
527
|
end
|
@@ -548,14 +546,26 @@ module ActiveRecord
|
|
548
546
|
end
|
549
547
|
|
550
548
|
def ensure_owner_is_not_new
|
551
|
-
|
549
|
+
unless @owner.persisted?
|
552
550
|
raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
|
553
551
|
end
|
554
552
|
end
|
555
553
|
|
556
554
|
def fetch_first_or_last_using_find?(args)
|
557
|
-
args.first.kind_of?(Hash) || !(loaded? ||
|
558
|
-
|
555
|
+
args.first.kind_of?(Hash) || !(loaded? || !@owner.persisted? || @reflection.options[:finder_sql] ||
|
556
|
+
!@target.all? { |record| record.persisted? } || args.first.kind_of?(Integer))
|
557
|
+
end
|
558
|
+
|
559
|
+
def include_in_memory?(record)
|
560
|
+
if @reflection.is_a?(ActiveRecord::Reflection::ThroughReflection)
|
561
|
+
@owner.send(proxy_reflection.through_reflection.name.to_sym).map do |source|
|
562
|
+
source_reflection_target = source.send(proxy_reflection.source_reflection.name)
|
563
|
+
return true if source_reflection_target.respond_to?(:include?) ? source_reflection_target.include?(record) : source_reflection_target == record
|
564
|
+
end
|
565
|
+
false
|
566
|
+
else
|
567
|
+
@target.include?(record)
|
568
|
+
end
|
559
569
|
end
|
560
570
|
end
|
561
571
|
end
|
@@ -53,7 +53,7 @@ module ActiveRecord
|
|
53
53
|
alias_method :proxy_respond_to?, :respond_to?
|
54
54
|
alias_method :proxy_extend, :extend
|
55
55
|
delegate :to_param, :to => :proxy_target
|
56
|
-
instance_methods.each { |m| undef_method m unless m.to_s =~ /^(?:nil\?|send|object_id|to_a)$|^__|proxy_/ }
|
56
|
+
instance_methods.each { |m| undef_method m unless m.to_s =~ /^(?:nil\?|send|object_id|to_a)$|^__|^respond_to_missing|proxy_/ }
|
57
57
|
|
58
58
|
def initialize(owner, reflection)
|
59
59
|
@owner, @reflection = owner, reflection
|
@@ -174,10 +174,10 @@ module ActiveRecord
|
|
174
174
|
# If the association is polymorphic the type of the owner is also set.
|
175
175
|
def set_belongs_to_association_for(record)
|
176
176
|
if @reflection.options[:as]
|
177
|
-
record["#{@reflection.options[:as]}_id"] = @owner.id
|
177
|
+
record["#{@reflection.options[:as]}_id"] = @owner.id if @owner.persisted?
|
178
178
|
record["#{@reflection.options[:as]}_type"] = @owner.class.base_class.name.to_s
|
179
179
|
else
|
180
|
-
|
180
|
+
if @owner.persisted?
|
181
181
|
primary_key = @reflection.options[:primary_key] || :id
|
182
182
|
record[@reflection.primary_key_name] = @owner.send(primary_key)
|
183
183
|
end
|
@@ -233,7 +233,7 @@ module ActiveRecord
|
|
233
233
|
def load_target
|
234
234
|
return nil unless defined?(@loaded)
|
235
235
|
|
236
|
-
if !loaded? and (
|
236
|
+
if !loaded? and (@owner.persisted? || foreign_key_present)
|
237
237
|
@target = find_target
|
238
238
|
end
|
239
239
|
|