activerecord 1.10.1 → 1.11.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.

Files changed (84) hide show
  1. data/CHANGELOG +187 -19
  2. data/RUNNING_UNIT_TESTS +11 -0
  3. data/lib/active_record.rb +3 -1
  4. data/lib/active_record/acts/list.rb +25 -14
  5. data/lib/active_record/acts/nested_set.rb +4 -4
  6. data/lib/active_record/acts/tree.rb +18 -1
  7. data/lib/active_record/associations.rb +90 -17
  8. data/lib/active_record/associations/association_collection.rb +44 -5
  9. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +17 -4
  10. data/lib/active_record/associations/has_many_association.rb +13 -3
  11. data/lib/active_record/associations/has_one_association.rb +19 -0
  12. data/lib/active_record/base.rb +292 -268
  13. data/lib/active_record/callbacks.rb +14 -14
  14. data/lib/active_record/connection_adapters/abstract_adapter.rb +137 -75
  15. data/lib/active_record/connection_adapters/db2_adapter.rb +10 -8
  16. data/lib/active_record/connection_adapters/mysql_adapter.rb +91 -64
  17. data/lib/active_record/connection_adapters/oci_adapter.rb +6 -6
  18. data/lib/active_record/connection_adapters/postgresql_adapter.rb +113 -60
  19. data/lib/active_record/connection_adapters/sqlite_adapter.rb +15 -12
  20. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +159 -132
  21. data/lib/active_record/fixtures.rb +59 -12
  22. data/lib/active_record/locking.rb +10 -9
  23. data/lib/active_record/migration.rb +112 -5
  24. data/lib/active_record/query_cache.rb +64 -0
  25. data/lib/active_record/timestamp.rb +10 -8
  26. data/lib/active_record/validations.rb +121 -26
  27. data/rakefile +16 -10
  28. data/test/aaa_create_tables_test.rb +26 -48
  29. data/test/abstract_unit.rb +3 -0
  30. data/test/aggregations_test.rb +19 -19
  31. data/test/association_callbacks_test.rb +110 -0
  32. data/test/associations_go_eager_test.rb +48 -14
  33. data/test/associations_test.rb +344 -142
  34. data/test/base_test.rb +150 -31
  35. data/test/binary_test.rb +7 -0
  36. data/test/callbacks_test.rb +24 -5
  37. data/test/column_alias_test.rb +2 -2
  38. data/test/connections/native_sqlserver_odbc/connection.rb +26 -0
  39. data/test/deprecated_associations_test.rb +27 -28
  40. data/test/deprecated_finder_test.rb +8 -9
  41. data/test/finder_test.rb +52 -17
  42. data/test/fixtures/author.rb +39 -0
  43. data/test/fixtures/categories.yml +7 -0
  44. data/test/fixtures/categories_posts.yml +8 -0
  45. data/test/fixtures/category.rb +2 -0
  46. data/test/fixtures/comment.rb +3 -1
  47. data/test/fixtures/comments.yml +43 -1
  48. data/test/fixtures/companies.yml +14 -0
  49. data/test/fixtures/company.rb +1 -1
  50. data/test/fixtures/computers.yml +2 -1
  51. data/test/fixtures/db_definitions/db2.sql +7 -2
  52. data/test/fixtures/db_definitions/mysql.drop.sql +2 -0
  53. data/test/fixtures/db_definitions/mysql.sql +11 -6
  54. data/test/fixtures/db_definitions/oci.sql +7 -2
  55. data/test/fixtures/db_definitions/postgresql.drop.sql +3 -1
  56. data/test/fixtures/db_definitions/postgresql.sql +8 -5
  57. data/test/fixtures/db_definitions/sqlite.drop.sql +2 -0
  58. data/test/fixtures/db_definitions/sqlite.sql +9 -4
  59. data/test/fixtures/db_definitions/sqlserver.drop.sql +2 -0
  60. data/test/fixtures/db_definitions/sqlserver.sql +12 -7
  61. data/test/fixtures/developer.rb +8 -1
  62. data/test/fixtures/migrations/3_innocent_jointable.rb +12 -0
  63. data/test/fixtures/post.rb +8 -2
  64. data/test/fixtures/posts.yml +21 -0
  65. data/test/fixtures/project.rb +14 -1
  66. data/test/fixtures/subscriber.rb +3 -0
  67. data/test/fixtures_test.rb +14 -0
  68. data/test/inheritance_test.rb +30 -22
  69. data/test/lifecycle_test.rb +3 -4
  70. data/test/locking_test.rb +2 -4
  71. data/test/migration_test.rb +186 -0
  72. data/test/mixin_nested_set_test.rb +19 -19
  73. data/test/mixin_test.rb +88 -88
  74. data/test/modules_test.rb +5 -10
  75. data/test/multiple_db_test.rb +2 -0
  76. data/test/pk_test.rb +8 -12
  77. data/test/reflection_test.rb +8 -4
  78. data/test/schema_test_postgresql.rb +63 -0
  79. data/test/thread_safety_test.rb +4 -1
  80. data/test/transactions_test.rb +9 -2
  81. data/test/unconnected_test.rb +1 -0
  82. data/test/validations_test.rb +151 -8
  83. metadata +11 -5
  84. data/test/migration_mysql.rb +0 -104
data/CHANGELOG CHANGED
@@ -1,3 +1,171 @@
1
+ *1.11.0* (5th July, 2005)
2
+
3
+ * Fixed that Yaml error message in fixtures hid the real error #1623 [Nicholas Seckar]
4
+
5
+ * Changed logging of SQL statements to use the DEBUG level instead of INFO
6
+
7
+ * Added new Migrations framework for describing schema transformations in a way that can be easily applied across multiple databases #1604 [Tobias Luetke] See documentation under ActiveRecord::Migration and the additional support in the Rails rakefile/generator.
8
+
9
+ * Added callback hooks to association collections #1549 [Florian Weber]. Example:
10
+
11
+ class Project
12
+ has_and_belongs_to_many :developers, :before_add => :evaluate_velocity
13
+
14
+ def evaluate_velocity(developer)
15
+ ...
16
+ end
17
+ end
18
+
19
+ ..raising an exception will cause the object not to be added (or removed, with before_remove).
20
+
21
+
22
+ * Fixed Base.content_columns call for SQL Server adapter #1450 [DeLynn Berry]
23
+
24
+ * Fixed Base#write_attribute to work with both symbols and strings #1190 [Paul Legato]
25
+
26
+ * Fixed that has_and_belongs_to_many didn't respect single table inheritance types #1081 [Florian Weber]
27
+
28
+ * Speed up ActiveRecord#method_missing for the common case (read_attribute).
29
+
30
+ * Only notify observers on after_find and after_initialize if these methods are defined on the model. #1235 [skaes@web.de]
31
+
32
+ * Fixed that single-table inheritance sub-classes couldn't be used to limit the result set with eager loading #1215 [Chris McGrath]
33
+
34
+ * Fixed validates_numericality_of to work with overrided getter-method when :allow_nil is on #1316 [raidel@onemail.at]
35
+
36
+ * Added roots, root, and siblings to the batch of methods added by acts_as_tree #1541 [michael@schuerig.de]
37
+
38
+ * Added support for limit/offset with the MS SQL Server driver so that pagination will now work #1569 [DeLynn Berry]
39
+
40
+ * Added support for ODBC connections to MS SQL Server so you can connect from a non-Windows machine #1569 [Mark Imbriaco/DeLynn Berry]
41
+
42
+ * Fixed that multiparameter posts ignored attr_protected #1532 [alec+rails@veryclever.net]
43
+
44
+ * Fixed problem with eager loading when using a has_and_belongs_to_many association using :association_foreign_key #1504 [flash@vanklinkenbergsoftware.nl]
45
+
46
+ * Fixed Base#find to honor the documentation on how :joins work and make them consistent with Base#count #1405 [pritchie@gmail.com]. What used to be:
47
+
48
+ Developer.find :all, :joins => 'developers_projects', :conditions => 'id=developer_id AND project_id=1'
49
+
50
+ ...should instead be:
51
+
52
+ Developer.find(
53
+ :all,
54
+ :joins => 'LEFT JOIN developers_projects ON developers.id = developers_projects.developer_id',
55
+ :conditions => 'project_id=1'
56
+ )
57
+
58
+ * Fixed that validations didn't respecting custom setting for too_short, too_long messages #1437 [Marcel Molina]
59
+
60
+ * Fixed that clear_association_cache doesn't delete new associations on new records (so you can safely place new records in the session with Action Pack without having new associations wiped) #1494 [cluon]
61
+
62
+ * Fixed that calling Model.find([]) returns [] and doesn't throw an exception #1379
63
+
64
+ * Fixed that adding a record to a has_and_belongs_to collection would always save it -- now it only saves if its a new record #1203 [Alisdair McDiarmid]
65
+
66
+ * Fixed saving of in-memory association structures to happen as a after_create/after_update callback instead of after_save -- that way you can add new associations in after_create/after_update callbacks without getting them saved twice
67
+
68
+ * Allow any Enumerable, not just Array, to work as bind variables #1344 [Jeremy Kemper]
69
+
70
+ * Added actual database-changing behavior to collection assigment for has_many and has_and_belongs_to_many #1425 [Sebastian Kanthak].
71
+ Example:
72
+
73
+ david.projects = [Project.find(1), Project.new("name" => "ActionWebSearch")]
74
+ david.save
75
+
76
+ If david.projects already contain the project with ID 1, this is left unchanged. Any other projects are dropped. And the new
77
+ project is saved when david.save is called.
78
+
79
+ Also included is a way to do assignments through IDs, which is perfect for checkbox updating, so you get to do:
80
+
81
+ david.project_ids = [1, 5, 7]
82
+
83
+ * Corrected typo in find SQL for has_and_belongs_to_many. #1312 [ben@bensinclair.com]
84
+
85
+ * Fixed sanitized conditions for has_many finder method. #1281 [jackc@hylesanderson.com, pragdave, Tobias Luetke]
86
+
87
+ * Comprehensive PostgreSQL schema support. Use the optional schema_search_path directive in database.yml to give a comma-separated list of schemas to search for your tables. This allows you, for example, to have tables in a shared schema without having to use a custom table name. See http://www.postgresql.org/docs/8.0/interactive/ddl-schemas.html to learn more. #827 [dave@cherryville.org]
88
+
89
+ * Corrected @@configurations typo #1410 [david@ruppconsulting.com]
90
+
91
+ * Return PostgreSQL columns in the order they were declared #1374 [perlguy@gmail.com]
92
+
93
+ * Allow before/after update hooks to work on models using optimistic locking
94
+
95
+ * Eager loading of dependent has_one associations won't delete the association #1212
96
+
97
+ * Added a second parameter to the build and create method for has_one that controls whether the existing association should be replaced (which means nullifying its foreign key as well). By default this is true, but false can be passed to prevent it.
98
+
99
+ * Using transactional fixtures now causes the data to be loaded only once.
100
+
101
+ * Added fixture accessor methods that can be used when instantiated fixtures are disabled.
102
+
103
+ fixtures :web_sites
104
+
105
+ def test_something
106
+ assert_equal "Ruby on Rails", web_sites(:rubyonrails).name
107
+ end
108
+
109
+ * Added DoubleRenderError exception that'll be raised if render* is called twice #518 [Nicholas Seckar]
110
+
111
+ * Fixed exceptions occuring after render has been called #1096 [Nicholas Seckar]
112
+
113
+ * CHANGED: validates_presence_of now uses Errors#add_on_blank, which will make " " fail the validation where it didn't before #1309
114
+
115
+ * Added Errors#add_on_blank which works like Errors#add_on_empty, but uses Object#blank? instead
116
+
117
+ * Added the :if option to all validations that can either use a block or a method pointer to determine whether the validation should be run or not. #1324 [Duane Johnson/jhosteny]. Examples:
118
+
119
+ Conditional validations such as the following are made possible:
120
+ validates_numericality_of :income, :if => :employed?
121
+
122
+ Conditional validations can also solve the salted login generator problem:
123
+ validates_confirmation_of :password, :if => :new_password?
124
+
125
+ Using blocks:
126
+ validates_presence_of :username, :if => Proc.new { |user| user.signup_step > 1 }
127
+
128
+ * Fixed use of construct_finder_sql when using :join #1288 [dwlt@dwlt.net]
129
+
130
+ * Fixed that :delete_sql in has_and_belongs_to_many associations couldn't access record properties #1299 [Rick Olson]
131
+
132
+ * Fixed that clone would break when an aggregate had the same name as one of its attributes #1307 [Jeremy Kemper]
133
+
134
+ * Changed that destroying an object will only freeze the attributes hash, which keeps the object from having attributes changed (as that wouldn't make sense), but allows for the querying of associations after it has been destroyed.
135
+
136
+ * Changed the callbacks such that observers are notified before the in-object callbacks are triggered. Without this change, it wasn't possible to act on the whole object in something like a before_destroy observer without having the objects own callbacks (like deleting associations) called first.
137
+
138
+ * Added option for passing an array to the find_all version of the dynamic finders and have it evaluated as an IN fragment. Example:
139
+
140
+ # SELECT * FROM topics WHERE title IN ('First', 'Second')
141
+ Topic.find_all_by_title(["First", "Second"])
142
+
143
+ * Added compatibility with camelCase column names for dynamic finders #533 [Dee.Zsombor]
144
+
145
+ * Fixed extraneous comma in count() function that made it not work with joins #1156 [jarkko/Dee.Zsombor]
146
+
147
+ * Fixed incompatibility with Base#find with an array of ids that would fail when using eager loading #1186 [Alisdair McDiarmid]
148
+
149
+ * Fixed that validate_length_of lost :on option when :within was specified #1195 [jhosteny@mac.com]
150
+
151
+ * Added encoding and min_messages options for PostgreSQL #1205 [shugo]. Configuration example:
152
+
153
+ development:
154
+ adapter: postgresql
155
+ database: rails_development
156
+ host: localhost
157
+ username: postgres
158
+ password:
159
+ encoding: UTF8
160
+ min_messages: ERROR
161
+
162
+ * Fixed acts_as_list where deleting an item that was removed from the list would ruin the positioning of other list items #1197 [Jamis Buck]
163
+
164
+ * Added validates_exclusion_of as a negative of validates_inclusion_of
165
+
166
+ * Optimized counting of has_many associations by setting the association to empty if the count is 0 so repeated calls doesn't trigger database calls
167
+
168
+
1
169
  *1.10.1* (20th April, 2005)
2
170
 
3
171
  * Fixed frivilous database queries being triggered with eager loading on empty associations and other things
@@ -72,7 +240,7 @@
72
240
 
73
241
  * Fixed boolean queries for t/f fields in PostgreSQL #995 [dave@cherryville.org]
74
242
 
75
- * Added that model.items.delete(child) will delete the child, not just set the foreign key to nil, if the child is dependent on the model #978 [bitsweat]
243
+ * Added that model.items.delete(child) will delete the child, not just set the foreign key to nil, if the child is dependent on the model #978 [Jeremy Kemper]
76
244
 
77
245
  * Fixed auto-stamping of dates (created_on/updated_on) for PostgreSQL #985 [dave@cherryville.org]
78
246
 
@@ -148,7 +316,7 @@
148
316
 
149
317
  * Fixed that postgresql adapter would fails when reading bytea fields with null value #771 [rodrigo k]
150
318
 
151
- * Added transactional fixtures that uses rollback to undo changes to fixtures instead of DELETE/INSERT -- it's much faster. See documentation under Fixtures #760 [bitsweat]
319
+ * Added transactional fixtures that uses rollback to undo changes to fixtures instead of DELETE/INSERT -- it's much faster. See documentation under Fixtures #760 [Jeremy Kemper]
152
320
 
153
321
  * Added destruction of dependent objects in has_one associations when a new assignment happens #742 [mindel]. Example:
154
322
 
@@ -236,7 +404,7 @@
236
404
 
237
405
  * Fixed that the dynamic finder like find_all_by_something_boolean(false) didn't work #649 [lmarlow@yahoo.com]
238
406
 
239
- * Added validates_each that validates each specified attribute against a block #610 [bitsweat]. Example:
407
+ * Added validates_each that validates each specified attribute against a block #610 [Jeremy Kemper]. Example:
240
408
 
241
409
  class Person < ActiveRecord::Base
242
410
  validates_each :first_name, :last_name do |record, attr|
@@ -244,7 +412,7 @@
244
412
  end
245
413
  end
246
414
 
247
- * Added :allow_nil as an explicit option for validates_length_of, so unless that's set to true having the attribute as nil will also return an error if a range is specified as :within #610 [bitsweat]
415
+ * Added :allow_nil as an explicit option for validates_length_of, so unless that's set to true having the attribute as nil will also return an error if a range is specified as :within #610 [Jeremy Kemper]
248
416
 
249
417
  * Added that validates_* now accept blocks to perform validations #618 [Tim Bates]. Example:
250
418
 
@@ -284,7 +452,7 @@
284
452
 
285
453
  * Fixed that the dynamic finders didn't treat nil as a "IS NULL" but rather "= NULL" case #515 [Demetrius]
286
454
 
287
- * Added bind-named arrays for interpolating a group of ids or strings in conditions #528 [bitsweat]
455
+ * Added bind-named arrays for interpolating a group of ids or strings in conditions #528 [Jeremy Kemper]
288
456
 
289
457
  * Added that has_and_belongs_to_many associations with additional attributes also can be created between unsaved objects and only committed to the database when Base#save is called on the associator #524 [Eric Anderson]
290
458
 
@@ -367,7 +535,7 @@
367
535
 
368
536
  * Added Base#reload that reloads the attributes of an object from the database #422 [Andreas Schwarz]
369
537
 
370
- * Added SQLite3 compatibility through the sqlite3-ruby adapter by Jamis Buck #381 [bitsweat]
538
+ * Added SQLite3 compatibility through the sqlite3-ruby adapter by Jamis Buck #381 [Jeremy Kemper]
371
539
 
372
540
  * Added support for the new protocol spoken by MySQL 4.1.1+ servers for the Ruby/MySQL adapter that ships with Rails #440 [Matt Mower]
373
541
 
@@ -438,7 +606,7 @@
438
606
  <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,
439
607
  though, as it's not possible to specify the order in which the objects are returned.
440
608
 
441
- * Added block-style for callbacks #332 [bitsweat].
609
+ * Added block-style for callbacks #332 [Jeremy Kemper].
442
610
 
443
611
  Before:
444
612
  before_destroy(Proc.new{ |record| Person.destroy_all "firm_id = #{record.id}" })
@@ -459,7 +627,7 @@
459
627
 
460
628
  * Added the final touches to the Microsoft SQL Server adapter by Joey Gibson that makes it suitable for actual use #394 [DeLynn Barry]
461
629
 
462
- * Added that Base#find takes an optional options hash, including :conditions. Base#find_on_conditions deprecated in favor of #find with :conditions #407 [bitsweat]
630
+ * Added that Base#find takes an optional options hash, including :conditions. Base#find_on_conditions deprecated in favor of #find with :conditions #407 [Jeremy Kemper]
463
631
 
464
632
  * Added HasManyAssociation#count that works like Base#count #413 [intinig]
465
633
 
@@ -468,7 +636,7 @@
468
636
  * Fixed a bug in the Ruby/MySQL that caused binary content to be escaped badly and come back mangled #405 [Tobias Luetke]
469
637
 
470
638
  * Fixed that the const_missing autoload assumes the requested constant is set by require_association and calls const_get to retrieve it.
471
- If require_association did not set the constant then const_get will call const_missing, resulting in an infinite loop #380 [bitsweat]
639
+ If require_association did not set the constant then const_get will call const_missing, resulting in an infinite loop #380 [Jeremy Kemper]
472
640
 
473
641
  * Fixed broken transactions that were actually only running object-level and not db level transactions [andreas]
474
642
 
@@ -508,7 +676,7 @@
508
676
 
509
677
  * Added Base#clear_association_cache to empty all the cached associations #347 [Tobias Luetke]
510
678
 
511
- * Added more informative exceptions in establish_connection #356 [bitsweat]
679
+ * Added more informative exceptions in establish_connection #356 [Jeremy Kemper]
512
680
 
513
681
  * Added Base#update_attributes that'll accept a hash of attributes and save the record (returning true if it passed validation, false otherwise).
514
682
 
@@ -525,7 +693,7 @@
525
693
 
526
694
  * Added higher_item and lower_item as public methods for acts_as_list #342 [Tobias Luetke]
527
695
 
528
- * Fixed that options[:counter_sql] was overwritten with interpolated sql rather than original sql #355 [bitsweat]
696
+ * Fixed that options[:counter_sql] was overwritten with interpolated sql rather than original sql #355 [Jeremy Kemper]
529
697
 
530
698
  * Fixed that overriding an attribute's accessor would be disregarded by add_on_empty and add_on_boundary_breaking because they simply used
531
699
  the attributes[] hash instead of checking for @base.respond_to?(attr.to_s). [Marten]
@@ -689,12 +857,12 @@
689
857
  * Fixed has_and_belongs_to_many guessing of foreign key so that keys are generated correctly for models like SomeVerySpecialClient
690
858
  [Florian Weber]
691
859
 
692
- * Added counter_sql option for has_many associations [bitsweat]. Documentation:
860
+ * Added counter_sql option for has_many associations [Jeremy Kemper]. Documentation:
693
861
 
694
862
  <tt>:counter_sql</tt> - specify a complete SQL statement to fetch the size of the association. If +:finder_sql+ is
695
863
  specified but +:counter_sql+, +:counter_sql+ will be generated by replacing SELECT ... FROM with SELECT COUNT(*) FROM.
696
864
 
697
- * Fixed that methods wrapped in callbacks still return their original result #260 [bitsweat]
865
+ * Fixed that methods wrapped in callbacks still return their original result #260 [Jeremy Kemper]
698
866
 
699
867
  * Fixed the Inflector to handle the movie/movies pair correctly #261 [Scott Baron]
700
868
 
@@ -720,7 +888,7 @@
720
888
 
721
889
  * Added reverse order of deleting fixtures, so referential keys can be maintained #247 [Tim Bates]
722
890
 
723
- * Added relative path search for sqlite dbfiles in database.yml (if RAILS_ROOT is defined) #233 [bitsweat]
891
+ * Added relative path search for sqlite dbfiles in database.yml (if RAILS_ROOT is defined) #233 [Jeremy Kemper]
724
892
 
725
893
  * Added option to establish_connection where you'll be able to leave out the parameter to have it use the RAILS_ENV environment variable
726
894
 
@@ -819,17 +987,17 @@
819
987
 
820
988
  NOTE: The categories table doesn't have a added_on column, it's the categories_post join table that does!
821
989
 
822
- * Fixed that :exclusively_dependent and :dependent can't be activated at the same time on has_many associations [bitsweat]
990
+ * Fixed that :exclusively_dependent and :dependent can't be activated at the same time on has_many associations [Jeremy Kemper]
823
991
 
824
- * Fixed that database passwords couldn't be all numeric [bitsweat]
992
+ * Fixed that database passwords couldn't be all numeric [Jeremy Kemper]
825
993
 
826
- * Fixed that calling id would create the instance variable for new_records preventing them from being saved correctly [bitsweat]
994
+ * Fixed that calling id would create the instance variable for new_records preventing them from being saved correctly [Jeremy Kemper]
827
995
 
828
996
  * Added sanitization feature to HasManyAssociation#find_all so it works just like Base.find_all [Sam Stephenson/bitsweat]
829
997
 
830
- * Added that you can pass overlapping ids to find without getting duplicated records back [bitsweat]
998
+ * Added that you can pass overlapping ids to find without getting duplicated records back [Jeremy Kemper]
831
999
 
832
- * Added that Base.benchmark returns the result of the block [bitsweat]
1000
+ * Added that Base.benchmark returns the result of the block [Jeremy Kemper]
833
1001
 
834
1002
  * Fixed problem with unit tests on Windows with SQLite [paterno]
835
1003
 
@@ -33,3 +33,14 @@ You can also run all the suites on a specific adapter with:
33
33
 
34
34
  cd test; all.sh "connections/native_mysql"
35
35
 
36
+ == Faster tests
37
+
38
+ If you are using a database that supports transactions, you can set the
39
+ "AR_TX_FIXTURES" environment variable to "yes" to use transactional fixtures.
40
+ This gives a very large speed boost. With rake:
41
+
42
+ rake AR_TX_FIXTURES=yes
43
+
44
+ Or, by hand:
45
+
46
+ AR_TX_FIXTURES=yes ruby -I connections/native_sqlite3 base_test.rb
@@ -49,8 +49,8 @@ require 'active_record/migration'
49
49
 
50
50
  ActiveRecord::Base.class_eval do
51
51
  include ActiveRecord::Validations
52
- include ActiveRecord::Callbacks
53
52
  include ActiveRecord::Locking
53
+ include ActiveRecord::Callbacks
54
54
  include ActiveRecord::Timestamp
55
55
  include ActiveRecord::Associations
56
56
  include ActiveRecord::Aggregations
@@ -67,3 +67,5 @@ require 'active_record/connection_adapters/sqlite_adapter'
67
67
  require 'active_record/connection_adapters/sqlserver_adapter'
68
68
  require 'active_record/connection_adapters/db2_adapter'
69
69
  require 'active_record/connection_adapters/oci_adapter'
70
+
71
+ require 'active_record/query_cache'
@@ -94,6 +94,7 @@ module ActiveRecord
94
94
  end
95
95
 
96
96
  def move_to_bottom
97
+ return unless in_list?
97
98
  self.class.transaction do
98
99
  decrement_positions_on_lower_items
99
100
  assume_bottom_position
@@ -101,6 +102,7 @@ module ActiveRecord
101
102
  end
102
103
 
103
104
  def move_to_top
105
+ return unless in_list?
104
106
  self.class.transaction do
105
107
  increment_positions_on_higher_items
106
108
  assume_top_position
@@ -108,37 +110,47 @@ module ActiveRecord
108
110
  end
109
111
 
110
112
  def remove_from_list
111
- decrement_positions_on_lower_items
113
+ decrement_positions_on_lower_items if in_list?
112
114
  end
113
115
 
114
116
  def increment_position
117
+ return unless in_list?
115
118
  update_attribute position_column, self.send(position_column).to_i + 1
116
119
  end
117
120
 
118
121
  def decrement_position
122
+ return unless in_list?
119
123
  update_attribute position_column, self.send(position_column).to_i - 1
120
124
  end
121
125
 
122
126
  def first?
127
+ return false unless in_list?
123
128
  self.send(position_column) == 1
124
129
  end
125
130
 
126
131
  def last?
132
+ return false unless in_list?
127
133
  self.send(position_column) == bottom_position_in_list
128
134
  end
129
135
 
130
136
  def higher_item
131
- self.class.find_first(
137
+ return nil unless in_list?
138
+ self.class.find(:first, :conditions =>
132
139
  "#{scope_condition} AND #{position_column} = #{(send(position_column).to_i - 1).to_s}"
133
140
  )
134
141
  end
135
142
 
136
143
  def lower_item
137
- self.class.find_first(
144
+ return nil unless in_list?
145
+ self.class.find(:first, :conditions =>
138
146
  "#{scope_condition} AND #{position_column} = #{(send(position_column).to_i + 1).to_s}"
139
147
  )
140
148
  end
141
149
 
150
+ def in_list?
151
+ !send(position_column).nil?
152
+ end
153
+
142
154
  private
143
155
  def add_to_list_top
144
156
  increment_positions_on_all_items
@@ -157,10 +169,7 @@ module ActiveRecord
157
169
  end
158
170
 
159
171
  def bottom_item
160
- self.class.find_first(
161
- "#{scope_condition} ",
162
- "#{position_column} DESC"
163
- )
172
+ self.class.find(:first, :conditions => scope_condition, :order => "#{position_column} DESC")
164
173
  end
165
174
 
166
175
  def assume_bottom_position
@@ -176,10 +185,11 @@ module ActiveRecord
176
185
  self.class.update_all(
177
186
  "#{position_column} = (#{position_column} - 1)", "#{scope_condition} AND #{position_column} <= #{position}"
178
187
  )
179
- end
188
+ end
180
189
 
181
190
  # This has the effect of moving all the lower items up one.
182
191
  def decrement_positions_on_lower_items
192
+ return unless in_list?
183
193
  self.class.update_all(
184
194
  "#{position_column} = (#{position_column} - 1)", "#{scope_condition} AND #{position_column} > #{send(position_column).to_i}"
185
195
  )
@@ -187,6 +197,7 @@ module ActiveRecord
187
197
 
188
198
  # This has the effect of moving all the higher items down one.
189
199
  def increment_positions_on_higher_items
200
+ return unless in_list?
190
201
  self.class.update_all(
191
202
  "#{position_column} = (#{position_column} + 1)", "#{scope_condition} AND #{position_column} < #{send(position_column).to_i}"
192
203
  )
@@ -194,10 +205,10 @@ module ActiveRecord
194
205
 
195
206
  # This has the effect of moving all the lower items down one.
196
207
  def increment_positions_on_lower_items(position)
197
- self.class.update_all(
198
- "#{position_column} = (#{position_column} + 1)", "#{scope_condition} AND #{position_column} >= #{position}"
199
- )
200
- end
208
+ self.class.update_all(
209
+ "#{position_column} = (#{position_column} + 1)", "#{scope_condition} AND #{position_column} >= #{position}"
210
+ )
211
+ end
201
212
 
202
213
  def increment_positions_on_all_items
203
214
  self.class.update_all(
@@ -207,10 +218,10 @@ module ActiveRecord
207
218
 
208
219
  def insert_at_position(position)
209
220
  remove_from_list
210
- increment_positions_on_lower_items(position)
221
+ increment_positions_on_lower_items(position)
211
222
  self.update_attribute(position_column, position)
212
223
  end
213
224
  end
214
225
  end
215
226
  end
216
- end
227
+ end