activerecord 1.3.0 → 1.4.0
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 +77 -2
- data/install.rb +5 -0
- data/lib/active_record.rb +6 -2
- data/lib/active_record/acts/list.rb +56 -45
- data/lib/active_record/acts/tree.rb +3 -2
- data/lib/active_record/associations.rb +10 -62
- data/lib/active_record/associations/association_collection.rb +20 -23
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +36 -10
- data/lib/active_record/associations/has_many_association.rb +50 -25
- data/lib/active_record/base.rb +118 -80
- data/lib/active_record/callbacks.rb +51 -50
- data/lib/active_record/connection_adapters/abstract_adapter.rb +33 -12
- data/lib/active_record/connection_adapters/db2_adapter.rb +129 -0
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +23 -1
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +80 -90
- data/lib/active_record/fixtures.rb +1 -1
- data/lib/active_record/locking.rb +57 -0
- data/lib/active_record/support/class_attribute_accessors.rb +19 -5
- data/lib/active_record/support/class_inheritable_attributes.rb +4 -3
- data/lib/active_record/support/dependencies.rb +71 -0
- data/lib/active_record/support/inflector.rb +1 -0
- data/lib/active_record/support/misc.rb +29 -3
- data/lib/active_record/support/module_attribute_accessors.rb +57 -0
- data/lib/active_record/transactions.rb +18 -11
- data/lib/active_record/validations.rb +3 -3
- data/lib/active_record/vendor/db2.rb +357 -0
- data/lib/active_record/vendor/mysql.rb +1 -1
- data/rakefile +17 -5
- data/test/associations_test.rb +39 -4
- data/test/base_test.rb +13 -4
- data/test/binary_test.rb +43 -0
- data/test/callbacks_test.rb +230 -0
- data/test/connections/native_db2/connection.rb +24 -0
- data/test/connections/native_sqlserver/connection.rb +9 -3
- data/test/deprecated_associations_test.rb +16 -10
- data/test/finder_test.rb +65 -13
- data/test/fixtures/associations.png +0 -0
- data/test/fixtures/binary.rb +2 -0
- data/test/fixtures/companies.yml +21 -0
- data/test/fixtures/courses.yml +7 -0
- data/test/fixtures/customers.yml +7 -0
- data/test/fixtures/db_definitions/db2.sql +124 -0
- data/test/fixtures/db_definitions/db22.sql +4 -0
- data/test/fixtures/db_definitions/mysql.sql +12 -0
- data/test/fixtures/db_definitions/postgresql.sql +13 -0
- data/test/fixtures/db_definitions/sqlite.sql +9 -0
- data/test/fixtures/db_definitions/sqlserver.sql +13 -0
- data/test/fixtures/developers_projects.yml +13 -0
- data/test/fixtures/entrants.yml +14 -0
- data/test/fixtures/fixture_database.sqlite +0 -0
- data/test/fixtures/movies.yml +7 -0
- data/test/fixtures/people.yml +3 -0
- data/test/fixtures/person.rb +1 -0
- data/test/fixtures/projects.yml +7 -0
- data/test/fixtures/topics.yml +21 -0
- data/test/locking_test.rb +34 -0
- data/test/mixin_test.rb +6 -0
- data/test/validations_test.rb +1 -1
- metadata +33 -29
- data/test/fixtures/companies/first_client +0 -6
- data/test/fixtures/companies/first_firm +0 -4
- data/test/fixtures/companies/second_client +0 -6
- data/test/fixtures/courses/java +0 -2
- data/test/fixtures/courses/ruby +0 -2
- data/test/fixtures/customers/david +0 -6
- data/test/fixtures/entrants/first +0 -3
- data/test/fixtures/entrants/second +0 -3
- data/test/fixtures/entrants/third +0 -3
- data/test/fixtures/movies/first +0 -2
- data/test/fixtures/movies/second +0 -2
- data/test/fixtures/projects/action_controller +0 -2
- data/test/fixtures/projects/active_record +0 -2
- data/test/fixtures/topics/first +0 -10
- data/test/fixtures/topics/second +0 -8
- data/test/inflector_test.rb +0 -122
data/CHANGELOG
CHANGED
@@ -1,4 +1,79 @@
|
|
1
|
-
*1.
|
1
|
+
*1.4.0* (January 4th, 2005)
|
2
|
+
|
3
|
+
* Added automated optimistic locking if the field <tt>lock_version</tt> is present. Each update to the
|
4
|
+
record increments the lock_version column and the locking facilities ensure that records instantiated twice
|
5
|
+
will let the last one saved raise a StaleObjectError if the first was also updated. Example:
|
6
|
+
|
7
|
+
p1 = Person.find(1)
|
8
|
+
p2 = Person.find(1)
|
9
|
+
|
10
|
+
p1.first_name = "Michael"
|
11
|
+
p1.save
|
12
|
+
|
13
|
+
p2.first_name = "should fail"
|
14
|
+
p2.save # Raises a ActiveRecord::StaleObjectError
|
15
|
+
|
16
|
+
You're then responsible for dealing with the conflict by rescuing the exception and either rolling back, merging,
|
17
|
+
or otherwise apply the business logic needed to resolve the conflict.
|
18
|
+
|
19
|
+
#384 [Michael Koziarski]
|
20
|
+
|
21
|
+
* Added dynamic attribute-based finders as a cleaner way of getting objects by simple queries without turning to SQL.
|
22
|
+
They work by appending the name of an attribute to <tt>find_by_</tt>, so you get finders like <tt>Person.find_by_user_name,
|
23
|
+
Payment.find_by_transaction_id</tt>. So instead of writing <tt>Person.find_first(["user_name = ?", user_name])</tt>, you just do
|
24
|
+
<tt>Person.find_by_user_name(user_name)</tt>.
|
25
|
+
|
26
|
+
It's also possible to use multiple attributes in the same find by separating them with "_and_", so you get finders like
|
27
|
+
<tt>Person.find_by_user_name_and_password</tt> or even <tt>Payment.find_by_purchaser_and_state_and_country</tt>. So instead of writing
|
28
|
+
<tt>Person.find_first(["user_name = ? AND password = ?", user_name, password])</tt>, you just do
|
29
|
+
<tt>Person.find_by_user_name_and_password(user_name, password)</tt>.
|
30
|
+
|
31
|
+
While primarily a construct for easier find_firsts, it can also be used as a construct for find_all by using calls like
|
32
|
+
<tt>Payment.find_all_by_amount(50)</tt> that is turned into <tt>Payment.find_all(["amount = ?", 50])</tt>. This is something not as equally useful,
|
33
|
+
though, as it's not possible to specify the order in which the objects are returned.
|
34
|
+
|
35
|
+
* Added block-style for callbacks #332 [bitsweat].
|
36
|
+
|
37
|
+
Before:
|
38
|
+
before_destroy(Proc.new{ |record| Person.destroy_all "firm_id = #{record.id}" })
|
39
|
+
|
40
|
+
After:
|
41
|
+
before_destroy { |record| Person.destroy_all "firm_id = #{record.id}" }
|
42
|
+
|
43
|
+
* Added :counter_cache option to acts_as_tree that works just like the one you can define on belongs_to #371 [Josh]
|
44
|
+
|
45
|
+
* Added Base.default_timezone accessor that determines whether to use Time.local (using :local) or Time.utc (using :utc) when pulling dates
|
46
|
+
and times from the database. This is set to :local by default.
|
47
|
+
|
48
|
+
* Added the possibility for adapters to overwrite add_limit! to implement a different limiting scheme than "LIMIT X" used by MySQL, PostgreSQL, and SQLite.
|
49
|
+
|
50
|
+
* Added the possibility of having objects with acts_as_list created before their scope is available or...
|
51
|
+
|
52
|
+
* Added a db2 adapter that only depends on the Ruby/DB2 bindings (http://raa.ruby-lang.org/project/ruby-db2/) #386 [Maik Schmidt]
|
53
|
+
|
54
|
+
* Added the final touches to the Microsoft SQL Server adapter by Joey Gibson that makes it suitable for actual use #394 [DeLynn Barry]
|
55
|
+
|
56
|
+
* Added that Base#find takes an optional options hash, including :conditions. Base#find_on_conditions deprecated in favor of #find with :conditions #407 [bitsweat]
|
57
|
+
|
58
|
+
* Added HasManyAssociation#count that works like Base#count #413 [intinig]
|
59
|
+
|
60
|
+
* Fixed handling of binary content in blobs and similar fields for Ruby/MySQL and SQLite #409 [xal]
|
61
|
+
|
62
|
+
* Fixed a bug in the Ruby/MySQL that caused binary content to be escaped badly and come back mangled #405 [Tobias Luetke]
|
63
|
+
|
64
|
+
* Fixed that the const_missing autoload assumes the requested constant is set by require_association and calls const_get to retrieve it.
|
65
|
+
If require_association did not set the constant then const_get will call const_missing, resulting in an infinite loop #380 [bitsweat]
|
66
|
+
|
67
|
+
* Fixed broken transactions that were actually only running object-level and not db level transactions [andreas]
|
68
|
+
|
69
|
+
* Fixed that validates_uniqueness_of used 'id' instead of defined primary key #406
|
70
|
+
|
71
|
+
* Fixed that the overwritten respond_to? method didn't take two parameters like the original #391
|
72
|
+
|
73
|
+
* Fixed quoting in validates_format_of that would allow some rules to pass regardless of input #390 [Dmitry V. Sabanin]
|
74
|
+
|
75
|
+
|
76
|
+
*1.3.0* (December 23, 2004)
|
2
77
|
|
3
78
|
* Added a require_association hook on const_missing that makes it possible to use any model class without requiring it first. This makes STI look like:
|
4
79
|
|
@@ -638,7 +713,7 @@
|
|
638
713
|
* Fixed PostgreSQL adapter so default values are displayed properly when used in conjunction with
|
639
714
|
Action Pack scaffolding.
|
640
715
|
|
641
|
-
* Fixed booleans support for PostgreSQL (use real true/false
|
716
|
+
* Fixed booleans support for PostgreSQL (use real true/false on boolean fields instead of 0/1 on tinyints) [radsaq]
|
642
717
|
|
643
718
|
|
644
719
|
*0.9.2*
|
data/install.rb
CHANGED
@@ -35,11 +35,14 @@ files = %w-
|
|
35
35
|
active_record/base.rb
|
36
36
|
active_record/callbacks.rb
|
37
37
|
active_record/connection_adapters/abstract_adapter.rb
|
38
|
+
active_record/connection_adapters/db2_adapter.rb
|
38
39
|
active_record/connection_adapters/mysql_adapter.rb
|
39
40
|
active_record/connection_adapters/postgresql_adapter.rb
|
40
41
|
active_record/connection_adapters/sqlite_adapter.rb
|
42
|
+
active_record/connection_adapters/sqlserver_adapter.rb
|
41
43
|
active_record/deprecated_associations.rb
|
42
44
|
active_record/fixtures.rb
|
45
|
+
active_record/locking.rb
|
43
46
|
active_record/observer.rb
|
44
47
|
active_record/reflection.rb
|
45
48
|
active_record/acts/list.rb
|
@@ -48,6 +51,8 @@ files = %w-
|
|
48
51
|
active_record/support/class_inheritable_attributes.rb
|
49
52
|
active_record/support/clean_logger.rb
|
50
53
|
active_record/support/inflector.rb
|
54
|
+
active_record/support/misc.rb
|
55
|
+
active_record/timestamp.rb
|
51
56
|
active_record/transactions.rb
|
52
57
|
active_record/validations.rb
|
53
58
|
active_record/vendor/mysql.rb
|
data/lib/active_record.rb
CHANGED
@@ -26,6 +26,7 @@ $:.unshift(File.dirname(__FILE__))
|
|
26
26
|
|
27
27
|
require 'active_record/support/clean_logger'
|
28
28
|
require 'active_record/support/misc'
|
29
|
+
require 'active_record/support/dependencies'
|
29
30
|
|
30
31
|
require 'active_record/base'
|
31
32
|
require 'active_record/observer'
|
@@ -38,11 +39,13 @@ require 'active_record/reflection'
|
|
38
39
|
require 'active_record/timestamp'
|
39
40
|
require 'active_record/acts/list'
|
40
41
|
require 'active_record/acts/tree'
|
42
|
+
require 'active_record/locking'
|
41
43
|
|
42
44
|
ActiveRecord::Base.class_eval do
|
43
45
|
include ActiveRecord::Validations
|
44
|
-
include ActiveRecord::Timestamp
|
45
46
|
include ActiveRecord::Callbacks
|
47
|
+
include ActiveRecord::Locking
|
48
|
+
include ActiveRecord::Timestamp
|
46
49
|
include ActiveRecord::Associations
|
47
50
|
include ActiveRecord::Aggregations
|
48
51
|
include ActiveRecord::Transactions
|
@@ -54,4 +57,5 @@ end
|
|
54
57
|
require 'active_record/connection_adapters/mysql_adapter'
|
55
58
|
require 'active_record/connection_adapters/postgresql_adapter'
|
56
59
|
require 'active_record/connection_adapters/sqlite_adapter'
|
57
|
-
require 'active_record/connection_adapters/sqlserver_adapter'
|
60
|
+
require 'active_record/connection_adapters/sqlserver_adapter'
|
61
|
+
require 'active_record/connection_adapters/db2_adapter'
|
@@ -36,19 +36,31 @@ module ActiveRecord
|
|
36
36
|
|
37
37
|
configuration[:scope] = "#{configuration[:scope]}_id".intern if configuration[:scope].is_a?(Symbol) && configuration[:scope].to_s !~ /_id$/
|
38
38
|
|
39
|
+
if configuration[:scope].is_a?(Symbol)
|
40
|
+
scope_condition_method = %(
|
41
|
+
def scope_condition
|
42
|
+
if #{configuration[:scope].to_s}.nil?
|
43
|
+
"#{configuration[:scope].to_s} IS NULL"
|
44
|
+
else
|
45
|
+
"#{configuration[:scope].to_s} = \#{#{configuration[:scope].to_s}}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
)
|
49
|
+
else
|
50
|
+
scope_condition_method = "def scope_condition() \"#{configuration[:scope]}\" end"
|
51
|
+
end
|
52
|
+
|
39
53
|
class_eval <<-EOV
|
40
54
|
include ActiveRecord::Acts::List::InstanceMethods
|
41
55
|
|
42
56
|
def position_column
|
43
57
|
'#{configuration[:column]}'
|
44
58
|
end
|
45
|
-
|
46
|
-
|
47
|
-
"#{configuration[:scope].is_a?(Symbol) ? configuration[:scope].to_s + " = \#{" + configuration[:scope].to_s + "}" : configuration[:scope]}"
|
48
|
-
end
|
59
|
+
|
60
|
+
#{scope_condition_method}
|
49
61
|
|
50
62
|
before_destroy :remove_from_list
|
51
|
-
before_create
|
63
|
+
before_create :add_to_list_bottom
|
52
64
|
EOV
|
53
65
|
end
|
54
66
|
end
|
@@ -123,55 +135,54 @@ module ActiveRecord
|
|
123
135
|
end
|
124
136
|
|
125
137
|
private
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
end
|
138
|
+
def add_to_list_top
|
139
|
+
increment_positions_on_all_items
|
140
|
+
end
|
130
141
|
|
131
|
-
|
132
|
-
|
133
|
-
|
142
|
+
def add_to_list_bottom
|
143
|
+
write_attribute(position_column, bottom_position_in_list.to_i + 1)
|
144
|
+
end
|
134
145
|
|
135
|
-
|
136
|
-
|
146
|
+
# Overwrite this method to define the scope of the list changes
|
147
|
+
def scope_condition() "1" end
|
137
148
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
149
|
+
def bottom_position_in_list
|
150
|
+
item = bottom_item
|
151
|
+
item ? item.send(position_column) : 0
|
152
|
+
end
|
142
153
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
154
|
+
def bottom_item
|
155
|
+
self.class.find_first(
|
156
|
+
"#{scope_condition} ",
|
157
|
+
"#{position_column} DESC"
|
158
|
+
)
|
159
|
+
end
|
149
160
|
|
150
|
-
|
151
|
-
|
152
|
-
|
161
|
+
def assume_bottom_position
|
162
|
+
update_attribute position_column, bottom_position_in_list.to_i + 1
|
163
|
+
end
|
153
164
|
|
154
|
-
|
155
|
-
|
156
|
-
|
165
|
+
def assume_top_position
|
166
|
+
update_attribute position_column, 1
|
167
|
+
end
|
157
168
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
169
|
+
def decrement_positions_on_lower_items
|
170
|
+
self.class.update_all(
|
171
|
+
"#{position_column} = (#{position_column} - 1)", "#{scope_condition} AND #{position_column} > #{send(position_column).to_i}"
|
172
|
+
)
|
173
|
+
end
|
163
174
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
175
|
+
def increment_positions_on_higher_items
|
176
|
+
self.class.update_all(
|
177
|
+
"#{position_column} = (#{position_column} + 1)", "#{scope_condition} AND #{position_column} < #{send(position_column).to_i}"
|
178
|
+
)
|
179
|
+
end
|
169
180
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
181
|
+
def increment_positions_on_all_items
|
182
|
+
self.class.update_all(
|
183
|
+
"#{position_column} = (#{position_column} + 1)", "#{scope_condition}"
|
184
|
+
)
|
185
|
+
end
|
175
186
|
end
|
176
187
|
end
|
177
188
|
end
|
@@ -31,11 +31,12 @@ module ActiveRecord
|
|
31
31
|
#
|
32
32
|
# * <tt>foreign_key</tt> - specifies the column name to use for track of the tree (default: parent_id)
|
33
33
|
# * <tt>order</tt> - makes it possible to sort the children according to this SQL snippet.
|
34
|
+
# * <tt>counter_cache</tt> - keeps a count in a children_count column if set to true (default: false).
|
34
35
|
def acts_as_tree(options = {})
|
35
|
-
configuration = { :foreign_key => "parent_id", :order => nil }
|
36
|
+
configuration = { :foreign_key => "parent_id", :order => nil, :counter_cache => nil }
|
36
37
|
configuration.update(options) if options.is_a?(Hash)
|
37
38
|
|
38
|
-
belongs_to :parent, :class_name => name, :foreign_key => configuration[:foreign_key]
|
39
|
+
belongs_to :parent, :class_name => name, :foreign_key => configuration[:foreign_key], :counter_cache => configuration[:counter_cache]
|
39
40
|
has_many :children, :class_name => name, :foreign_key => configuration[:foreign_key], :order => configuration[:order], :dependent => true
|
40
41
|
end
|
41
42
|
end
|
@@ -3,30 +3,6 @@ require 'active_record/associations/has_many_association'
|
|
3
3
|
require 'active_record/associations/has_and_belongs_to_many_association'
|
4
4
|
require 'active_record/deprecated_associations'
|
5
5
|
|
6
|
-
|
7
|
-
unless Object.respond_to?(:require_association)
|
8
|
-
Object.send(:define_method, :require_association) { |file_name| ActiveRecord::Base.require_association(file_name) }
|
9
|
-
end
|
10
|
-
|
11
|
-
class Object
|
12
|
-
class << self
|
13
|
-
# Use const_missing to autoload associations so we don't have to
|
14
|
-
# require_association when using single-table inheritance.
|
15
|
-
unless respond_to?(:pre_association_const_missing)
|
16
|
-
alias_method :pre_association_const_missing, :const_missing
|
17
|
-
|
18
|
-
def const_missing(class_id)
|
19
|
-
begin
|
20
|
-
require_association(Inflector.underscore(Inflector.demodulize(class_id.to_s)))
|
21
|
-
return Object.const_get(class_id) if Object.const_get(class_id).ancestors.include?(ActiveRecord::Base)
|
22
|
-
rescue LoadError
|
23
|
-
pre_association_const_missing(class_id)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
6
|
module ActiveRecord
|
31
7
|
module Associations # :nodoc:
|
32
8
|
def self.append_features(base)
|
@@ -146,7 +122,7 @@ module ActiveRecord
|
|
146
122
|
# All of the association macros can be specialized through options which makes more complex cases than the simple and guessable ones
|
147
123
|
# possible.
|
148
124
|
module ClassMethods
|
149
|
-
# Adds the following methods for
|
125
|
+
# Adds the following methods for retrieval and query of collections of associated objects.
|
150
126
|
# +collection+ is replaced with the symbol passed as the first argument, so
|
151
127
|
# <tt>has_many :clients</tt> would add among others <tt>has_clients?</tt>.
|
152
128
|
# * <tt>collection(force_reload = false)</tt> - returns an array of all the associated objects.
|
@@ -248,7 +224,7 @@ module ActiveRecord
|
|
248
224
|
deprecated_build_method(association_name)
|
249
225
|
end
|
250
226
|
|
251
|
-
# Adds the following methods for
|
227
|
+
# Adds the following methods for retrieval and query of a single associated object.
|
252
228
|
# +association+ is replaced with the symbol passed as the first argument, so
|
253
229
|
# <tt>has_one :manager</tt> would add among others <tt>has_manager?</tt>.
|
254
230
|
# * <tt>association(force_reload = false)</tt> - returns the associated object. Nil is returned if none is found.
|
@@ -304,7 +280,7 @@ module ActiveRecord
|
|
304
280
|
module_eval "before_destroy '#{association_name}.destroy if has_#{association_name}?'" if options[:dependent]
|
305
281
|
end
|
306
282
|
|
307
|
-
# Adds the following methods for
|
283
|
+
# Adds the following methods for retrieval and query for a single associated object that this object holds an id to.
|
308
284
|
# +association+ is replaced with the symbol passed as the first argument, so
|
309
285
|
# <tt>belongs_to :author</tt> would add among others <tt>has_author?</tt>.
|
310
286
|
# * <tt>association(force_reload = false)</tt> - returns the associated object. Nil is returned if none is found.
|
@@ -313,7 +289,7 @@ module ActiveRecord
|
|
313
289
|
# same id as the associated object.
|
314
290
|
# * <tt>association.nil?</tt> - returns true if there is no associated object.
|
315
291
|
#
|
316
|
-
# Example:
|
292
|
+
# Example: A Post class declares <tt>has_one :author</tt>, which will add:
|
317
293
|
# * <tt>Post#author</tt> (similar to <tt>Author.find(author_id)</tt>)
|
318
294
|
# * <tt>Post#author=(author)</tt> (similar to <tt>post.author_id = author.id</tt>)
|
319
295
|
# * <tt>Post#author?</tt> (similar to <tt>post.author == some_author</tt>)
|
@@ -388,9 +364,12 @@ module ActiveRecord
|
|
388
364
|
#
|
389
365
|
# Any additional fields added to the join table will be placed as attributes when pulling records out through
|
390
366
|
# has_and_belongs_to_many associations. This is helpful when have information about the association itself
|
391
|
-
# that you want available on
|
367
|
+
# that you want available on retrieval. Note that any fields in the join table will override matching field names
|
368
|
+
# in the two joined tables. As a consequence, having an "id" field in the join table usually has the undesirable
|
369
|
+
# result of clobbering the "id" fields in either of the other two tables.
|
370
|
+
#
|
392
371
|
#
|
393
|
-
# Adds the following methods for
|
372
|
+
# Adds the following methods for retrieval and query.
|
394
373
|
# +collection+ is replaced with the symbol passed as the first argument, so
|
395
374
|
# <tt>has_and_belongs_to_many :categories</tt> would add among others +add_categories+.
|
396
375
|
# * <tt>collection(force_reload = false)</tt> - returns an array of all the associated objects.
|
@@ -478,31 +457,6 @@ module ActiveRecord
|
|
478
457
|
deprecated_has_collection_method(association_name)
|
479
458
|
end
|
480
459
|
|
481
|
-
# Loads the <tt>file_name</tt> if reload_associations is true or requires if it's false.
|
482
|
-
def require_association(file_name)
|
483
|
-
if !associations_loaded.include?(file_name)
|
484
|
-
associations_loaded << file_name
|
485
|
-
reload_associations ? silence_warnings { load("#{file_name}.rb") } : require(file_name)
|
486
|
-
end
|
487
|
-
end
|
488
|
-
|
489
|
-
# Resets the list of dependencies loaded (typically to be called by the end of a request), so when require_association is
|
490
|
-
# called for that dependency it'll be loaded anew.
|
491
|
-
def reset_associations_loaded
|
492
|
-
self.associations_loaded = []
|
493
|
-
end
|
494
|
-
|
495
|
-
# Reload all the associations that have already been loaded once.
|
496
|
-
def reload_associations_loaded
|
497
|
-
associations_loaded.each do |file_name|
|
498
|
-
begin
|
499
|
-
silence_warnings { load("#{file_name}.rb") }
|
500
|
-
rescue LoadError
|
501
|
-
# The association didn't reside in its own file, so we assume it was required by other means
|
502
|
-
end
|
503
|
-
end
|
504
|
-
end
|
505
|
-
|
506
460
|
private
|
507
461
|
# Raises an exception if an invalid option has been specified to prevent misspellings from slipping through
|
508
462
|
def validate_options(valid_option_keys, supplied_option_keys)
|
@@ -619,13 +573,7 @@ module ActiveRecord
|
|
619
573
|
end
|
620
574
|
|
621
575
|
def require_association_class(class_name)
|
622
|
-
|
623
|
-
|
624
|
-
begin
|
625
|
-
require_association(Inflector.underscore(class_name))
|
626
|
-
rescue LoadError
|
627
|
-
# Failed to load the associated class -- let's hope the developer is doing the requiring himself.
|
628
|
-
end
|
576
|
+
require_association(Inflector.underscore(class_name)) if class_name
|
629
577
|
end
|
630
578
|
end
|
631
579
|
end
|
@@ -22,8 +22,8 @@ module ActiveRecord
|
|
22
22
|
@collection.to_ary
|
23
23
|
end
|
24
24
|
|
25
|
-
def respond_to?(symbol)
|
26
|
-
proxy_respond_to?(symbol) || [].respond_to?(symbol)
|
25
|
+
def respond_to?(symbol, include_priv = false)
|
26
|
+
proxy_respond_to?(symbol, include_priv) || [].respond_to?(symbol, include_priv)
|
27
27
|
end
|
28
28
|
|
29
29
|
def loaded?
|
@@ -100,13 +100,25 @@ module ActiveRecord
|
|
100
100
|
def interpolate_sql(sql, record = nil)
|
101
101
|
@owner.send(:interpolate_sql, sql, record)
|
102
102
|
end
|
103
|
-
|
103
|
+
|
104
|
+
def sanitize_sql(sql)
|
105
|
+
@association_class.send(:sanitize_sql, sql)
|
106
|
+
end
|
107
|
+
|
108
|
+
def extract_options_from_args!(args)
|
109
|
+
@owner.send(:extract_options_from_args!, args)
|
110
|
+
end
|
111
|
+
|
104
112
|
private
|
105
113
|
def load_collection
|
106
|
-
|
107
|
-
@collection
|
108
|
-
|
109
|
-
|
114
|
+
if loaded?
|
115
|
+
@collection
|
116
|
+
else
|
117
|
+
begin
|
118
|
+
@collection = find_all_records
|
119
|
+
rescue ActiveRecord::RecordNotFound
|
120
|
+
@collection = []
|
121
|
+
end
|
110
122
|
end
|
111
123
|
end
|
112
124
|
|
@@ -114,25 +126,10 @@ module ActiveRecord
|
|
114
126
|
raise ActiveRecord::AssociationTypeMismatch, "#{@association_class} expected, got #{record.class}" unless record.is_a?(@association_class)
|
115
127
|
end
|
116
128
|
|
117
|
-
|
118
|
-
def load_collection_to_array
|
119
|
-
return unless @collection_array.nil?
|
120
|
-
begin
|
121
|
-
@collection_array = find_all_records
|
122
|
-
rescue ActiveRecord::StatementInvalid, ActiveRecord::RecordNotFound
|
123
|
-
@collection_array = []
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
def duplicated_records_array(records)
|
128
|
-
records = [records] unless records.is_a?(Array) || records.is_a?(ActiveRecord::Associations::AssociationCollection)
|
129
|
-
records.dup
|
130
|
-
end
|
131
|
-
|
132
129
|
# Array#flatten has problems with rescursive arrays. Going one level deeper solves the majority of the problems.
|
133
130
|
def flatten_deeper(array)
|
134
131
|
array.collect { |element| element.respond_to?(:flatten) ? element.flatten : element }.flatten
|
135
132
|
end
|
136
133
|
end
|
137
134
|
end
|
138
|
-
end
|
135
|
+
end
|