activerecord_authorails 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (270) hide show
  1. data/CHANGELOG +3043 -0
  2. data/README +360 -0
  3. data/RUNNING_UNIT_TESTS +64 -0
  4. data/Rakefile +226 -0
  5. data/examples/associations.png +0 -0
  6. data/examples/associations.rb +87 -0
  7. data/examples/shared_setup.rb +15 -0
  8. data/examples/validation.rb +85 -0
  9. data/install.rb +30 -0
  10. data/lib/active_record.rb +85 -0
  11. data/lib/active_record/acts/list.rb +244 -0
  12. data/lib/active_record/acts/nested_set.rb +211 -0
  13. data/lib/active_record/acts/tree.rb +89 -0
  14. data/lib/active_record/aggregations.rb +191 -0
  15. data/lib/active_record/associations.rb +1637 -0
  16. data/lib/active_record/associations/association_collection.rb +190 -0
  17. data/lib/active_record/associations/association_proxy.rb +158 -0
  18. data/lib/active_record/associations/belongs_to_association.rb +56 -0
  19. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +50 -0
  20. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +169 -0
  21. data/lib/active_record/associations/has_many_association.rb +210 -0
  22. data/lib/active_record/associations/has_many_through_association.rb +247 -0
  23. data/lib/active_record/associations/has_one_association.rb +80 -0
  24. data/lib/active_record/attribute_methods.rb +75 -0
  25. data/lib/active_record/base.rb +2164 -0
  26. data/lib/active_record/calculations.rb +270 -0
  27. data/lib/active_record/callbacks.rb +367 -0
  28. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +279 -0
  29. data/lib/active_record/connection_adapters/abstract/database_statements.rb +130 -0
  30. data/lib/active_record/connection_adapters/abstract/quoting.rb +58 -0
  31. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +343 -0
  32. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +310 -0
  33. data/lib/active_record/connection_adapters/abstract_adapter.rb +161 -0
  34. data/lib/active_record/connection_adapters/db2_adapter.rb +228 -0
  35. data/lib/active_record/connection_adapters/firebird_adapter.rb +728 -0
  36. data/lib/active_record/connection_adapters/frontbase_adapter.rb +861 -0
  37. data/lib/active_record/connection_adapters/mysql_adapter.rb +414 -0
  38. data/lib/active_record/connection_adapters/openbase_adapter.rb +350 -0
  39. data/lib/active_record/connection_adapters/oracle_adapter.rb +689 -0
  40. data/lib/active_record/connection_adapters/postgresql_adapter.rb +584 -0
  41. data/lib/active_record/connection_adapters/sqlite_adapter.rb +407 -0
  42. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +591 -0
  43. data/lib/active_record/connection_adapters/sybase_adapter.rb +662 -0
  44. data/lib/active_record/deprecated_associations.rb +104 -0
  45. data/lib/active_record/deprecated_finders.rb +44 -0
  46. data/lib/active_record/fixtures.rb +628 -0
  47. data/lib/active_record/locking/optimistic.rb +106 -0
  48. data/lib/active_record/locking/pessimistic.rb +77 -0
  49. data/lib/active_record/migration.rb +394 -0
  50. data/lib/active_record/observer.rb +178 -0
  51. data/lib/active_record/query_cache.rb +64 -0
  52. data/lib/active_record/reflection.rb +222 -0
  53. data/lib/active_record/schema.rb +58 -0
  54. data/lib/active_record/schema_dumper.rb +149 -0
  55. data/lib/active_record/timestamp.rb +51 -0
  56. data/lib/active_record/transactions.rb +136 -0
  57. data/lib/active_record/validations.rb +843 -0
  58. data/lib/active_record/vendor/db2.rb +362 -0
  59. data/lib/active_record/vendor/mysql.rb +1214 -0
  60. data/lib/active_record/vendor/simple.rb +693 -0
  61. data/lib/active_record/version.rb +9 -0
  62. data/lib/active_record/wrappers/yaml_wrapper.rb +15 -0
  63. data/lib/active_record/wrappings.rb +58 -0
  64. data/lib/active_record/xml_serialization.rb +308 -0
  65. data/test/aaa_create_tables_test.rb +59 -0
  66. data/test/abstract_unit.rb +77 -0
  67. data/test/active_schema_test_mysql.rb +31 -0
  68. data/test/adapter_test.rb +87 -0
  69. data/test/adapter_test_sqlserver.rb +81 -0
  70. data/test/aggregations_test.rb +95 -0
  71. data/test/all.sh +8 -0
  72. data/test/ar_schema_test.rb +33 -0
  73. data/test/association_inheritance_reload.rb +14 -0
  74. data/test/associations/callbacks_test.rb +126 -0
  75. data/test/associations/cascaded_eager_loading_test.rb +138 -0
  76. data/test/associations/eager_test.rb +393 -0
  77. data/test/associations/extension_test.rb +42 -0
  78. data/test/associations/join_model_test.rb +497 -0
  79. data/test/associations_test.rb +1809 -0
  80. data/test/attribute_methods_test.rb +49 -0
  81. data/test/base_test.rb +1586 -0
  82. data/test/binary_test.rb +37 -0
  83. data/test/calculations_test.rb +219 -0
  84. data/test/callbacks_test.rb +377 -0
  85. data/test/class_inheritable_attributes_test.rb +32 -0
  86. data/test/column_alias_test.rb +17 -0
  87. data/test/connection_test_firebird.rb +8 -0
  88. data/test/connections/native_db2/connection.rb +25 -0
  89. data/test/connections/native_firebird/connection.rb +26 -0
  90. data/test/connections/native_frontbase/connection.rb +27 -0
  91. data/test/connections/native_mysql/connection.rb +24 -0
  92. data/test/connections/native_openbase/connection.rb +21 -0
  93. data/test/connections/native_oracle/connection.rb +27 -0
  94. data/test/connections/native_postgresql/connection.rb +23 -0
  95. data/test/connections/native_sqlite/connection.rb +34 -0
  96. data/test/connections/native_sqlite3/connection.rb +34 -0
  97. data/test/connections/native_sqlite3/in_memory_connection.rb +18 -0
  98. data/test/connections/native_sqlserver/connection.rb +23 -0
  99. data/test/connections/native_sqlserver_odbc/connection.rb +25 -0
  100. data/test/connections/native_sybase/connection.rb +23 -0
  101. data/test/copy_table_sqlite.rb +64 -0
  102. data/test/datatype_test_postgresql.rb +52 -0
  103. data/test/default_test_firebird.rb +16 -0
  104. data/test/defaults_test.rb +60 -0
  105. data/test/deprecated_associations_test.rb +396 -0
  106. data/test/deprecated_finder_test.rb +151 -0
  107. data/test/empty_date_time_test.rb +25 -0
  108. data/test/finder_test.rb +504 -0
  109. data/test/fixtures/accounts.yml +28 -0
  110. data/test/fixtures/author.rb +99 -0
  111. data/test/fixtures/author_favorites.yml +4 -0
  112. data/test/fixtures/authors.yml +7 -0
  113. data/test/fixtures/auto_id.rb +4 -0
  114. data/test/fixtures/bad_fixtures/attr_with_numeric_first_char +1 -0
  115. data/test/fixtures/bad_fixtures/attr_with_spaces +1 -0
  116. data/test/fixtures/bad_fixtures/blank_line +3 -0
  117. data/test/fixtures/bad_fixtures/duplicate_attributes +3 -0
  118. data/test/fixtures/bad_fixtures/missing_value +1 -0
  119. data/test/fixtures/binary.rb +2 -0
  120. data/test/fixtures/categories.yml +14 -0
  121. data/test/fixtures/categories/special_categories.yml +9 -0
  122. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
  123. data/test/fixtures/categories_ordered.yml +7 -0
  124. data/test/fixtures/categories_posts.yml +23 -0
  125. data/test/fixtures/categorization.rb +5 -0
  126. data/test/fixtures/categorizations.yml +17 -0
  127. data/test/fixtures/category.rb +20 -0
  128. data/test/fixtures/column_name.rb +3 -0
  129. data/test/fixtures/comment.rb +23 -0
  130. data/test/fixtures/comments.yml +59 -0
  131. data/test/fixtures/companies.yml +55 -0
  132. data/test/fixtures/company.rb +107 -0
  133. data/test/fixtures/company_in_module.rb +59 -0
  134. data/test/fixtures/computer.rb +3 -0
  135. data/test/fixtures/computers.yml +4 -0
  136. data/test/fixtures/course.rb +3 -0
  137. data/test/fixtures/courses.yml +7 -0
  138. data/test/fixtures/customer.rb +55 -0
  139. data/test/fixtures/customers.yml +17 -0
  140. data/test/fixtures/db_definitions/db2.drop.sql +32 -0
  141. data/test/fixtures/db_definitions/db2.sql +231 -0
  142. data/test/fixtures/db_definitions/db22.drop.sql +2 -0
  143. data/test/fixtures/db_definitions/db22.sql +5 -0
  144. data/test/fixtures/db_definitions/firebird.drop.sql +63 -0
  145. data/test/fixtures/db_definitions/firebird.sql +304 -0
  146. data/test/fixtures/db_definitions/firebird2.drop.sql +2 -0
  147. data/test/fixtures/db_definitions/firebird2.sql +6 -0
  148. data/test/fixtures/db_definitions/frontbase.drop.sql +32 -0
  149. data/test/fixtures/db_definitions/frontbase.sql +268 -0
  150. data/test/fixtures/db_definitions/frontbase2.drop.sql +1 -0
  151. data/test/fixtures/db_definitions/frontbase2.sql +4 -0
  152. data/test/fixtures/db_definitions/mysql.drop.sql +32 -0
  153. data/test/fixtures/db_definitions/mysql.sql +234 -0
  154. data/test/fixtures/db_definitions/mysql2.drop.sql +2 -0
  155. data/test/fixtures/db_definitions/mysql2.sql +5 -0
  156. data/test/fixtures/db_definitions/openbase.drop.sql +2 -0
  157. data/test/fixtures/db_definitions/openbase.sql +302 -0
  158. data/test/fixtures/db_definitions/openbase2.drop.sql +2 -0
  159. data/test/fixtures/db_definitions/openbase2.sql +7 -0
  160. data/test/fixtures/db_definitions/oracle.drop.sql +65 -0
  161. data/test/fixtures/db_definitions/oracle.sql +325 -0
  162. data/test/fixtures/db_definitions/oracle2.drop.sql +2 -0
  163. data/test/fixtures/db_definitions/oracle2.sql +6 -0
  164. data/test/fixtures/db_definitions/postgresql.drop.sql +37 -0
  165. data/test/fixtures/db_definitions/postgresql.sql +263 -0
  166. data/test/fixtures/db_definitions/postgresql2.drop.sql +2 -0
  167. data/test/fixtures/db_definitions/postgresql2.sql +5 -0
  168. data/test/fixtures/db_definitions/schema.rb +60 -0
  169. data/test/fixtures/db_definitions/sqlite.drop.sql +32 -0
  170. data/test/fixtures/db_definitions/sqlite.sql +215 -0
  171. data/test/fixtures/db_definitions/sqlite2.drop.sql +2 -0
  172. data/test/fixtures/db_definitions/sqlite2.sql +5 -0
  173. data/test/fixtures/db_definitions/sqlserver.drop.sql +34 -0
  174. data/test/fixtures/db_definitions/sqlserver.sql +243 -0
  175. data/test/fixtures/db_definitions/sqlserver2.drop.sql +2 -0
  176. data/test/fixtures/db_definitions/sqlserver2.sql +5 -0
  177. data/test/fixtures/db_definitions/sybase.drop.sql +34 -0
  178. data/test/fixtures/db_definitions/sybase.sql +218 -0
  179. data/test/fixtures/db_definitions/sybase2.drop.sql +4 -0
  180. data/test/fixtures/db_definitions/sybase2.sql +5 -0
  181. data/test/fixtures/default.rb +2 -0
  182. data/test/fixtures/developer.rb +52 -0
  183. data/test/fixtures/developers.yml +21 -0
  184. data/test/fixtures/developers_projects.yml +17 -0
  185. data/test/fixtures/developers_projects/david_action_controller +3 -0
  186. data/test/fixtures/developers_projects/david_active_record +3 -0
  187. data/test/fixtures/developers_projects/jamis_active_record +2 -0
  188. data/test/fixtures/edge.rb +5 -0
  189. data/test/fixtures/edges.yml +6 -0
  190. data/test/fixtures/entrant.rb +3 -0
  191. data/test/fixtures/entrants.yml +14 -0
  192. data/test/fixtures/fk_test_has_fk.yml +3 -0
  193. data/test/fixtures/fk_test_has_pk.yml +2 -0
  194. data/test/fixtures/flowers.jpg +0 -0
  195. data/test/fixtures/funny_jokes.yml +10 -0
  196. data/test/fixtures/joke.rb +6 -0
  197. data/test/fixtures/keyboard.rb +3 -0
  198. data/test/fixtures/legacy_thing.rb +3 -0
  199. data/test/fixtures/legacy_things.yml +3 -0
  200. data/test/fixtures/migrations/1_people_have_last_names.rb +9 -0
  201. data/test/fixtures/migrations/2_we_need_reminders.rb +12 -0
  202. data/test/fixtures/migrations/3_innocent_jointable.rb +12 -0
  203. data/test/fixtures/migrations_with_decimal/1_give_me_big_numbers.rb +15 -0
  204. data/test/fixtures/migrations_with_duplicate/1_people_have_last_names.rb +9 -0
  205. data/test/fixtures/migrations_with_duplicate/2_we_need_reminders.rb +12 -0
  206. data/test/fixtures/migrations_with_duplicate/3_foo.rb +7 -0
  207. data/test/fixtures/migrations_with_duplicate/3_innocent_jointable.rb +12 -0
  208. data/test/fixtures/migrations_with_missing_versions/1000_people_have_middle_names.rb +9 -0
  209. data/test/fixtures/migrations_with_missing_versions/1_people_have_last_names.rb +9 -0
  210. data/test/fixtures/migrations_with_missing_versions/3_we_need_reminders.rb +12 -0
  211. data/test/fixtures/migrations_with_missing_versions/4_innocent_jointable.rb +12 -0
  212. data/test/fixtures/mixed_case_monkey.rb +3 -0
  213. data/test/fixtures/mixed_case_monkeys.yml +6 -0
  214. data/test/fixtures/mixin.rb +63 -0
  215. data/test/fixtures/mixins.yml +127 -0
  216. data/test/fixtures/movie.rb +5 -0
  217. data/test/fixtures/movies.yml +7 -0
  218. data/test/fixtures/naked/csv/accounts.csv +1 -0
  219. data/test/fixtures/naked/yml/accounts.yml +1 -0
  220. data/test/fixtures/naked/yml/companies.yml +1 -0
  221. data/test/fixtures/naked/yml/courses.yml +1 -0
  222. data/test/fixtures/order.rb +4 -0
  223. data/test/fixtures/people.yml +3 -0
  224. data/test/fixtures/person.rb +4 -0
  225. data/test/fixtures/post.rb +58 -0
  226. data/test/fixtures/posts.yml +48 -0
  227. data/test/fixtures/project.rb +27 -0
  228. data/test/fixtures/projects.yml +7 -0
  229. data/test/fixtures/reader.rb +4 -0
  230. data/test/fixtures/readers.yml +4 -0
  231. data/test/fixtures/reply.rb +37 -0
  232. data/test/fixtures/subject.rb +4 -0
  233. data/test/fixtures/subscriber.rb +6 -0
  234. data/test/fixtures/subscribers/first +2 -0
  235. data/test/fixtures/subscribers/second +2 -0
  236. data/test/fixtures/tag.rb +7 -0
  237. data/test/fixtures/tagging.rb +6 -0
  238. data/test/fixtures/taggings.yml +18 -0
  239. data/test/fixtures/tags.yml +7 -0
  240. data/test/fixtures/task.rb +3 -0
  241. data/test/fixtures/tasks.yml +7 -0
  242. data/test/fixtures/topic.rb +25 -0
  243. data/test/fixtures/topics.yml +22 -0
  244. data/test/fixtures/vertex.rb +9 -0
  245. data/test/fixtures/vertices.yml +4 -0
  246. data/test/fixtures_test.rb +401 -0
  247. data/test/inheritance_test.rb +205 -0
  248. data/test/lifecycle_test.rb +137 -0
  249. data/test/locking_test.rb +190 -0
  250. data/test/method_scoping_test.rb +416 -0
  251. data/test/migration_test.rb +768 -0
  252. data/test/migration_test_firebird.rb +124 -0
  253. data/test/mixin_nested_set_test.rb +196 -0
  254. data/test/mixin_test.rb +550 -0
  255. data/test/modules_test.rb +34 -0
  256. data/test/multiple_db_test.rb +60 -0
  257. data/test/pk_test.rb +104 -0
  258. data/test/readonly_test.rb +107 -0
  259. data/test/reflection_test.rb +159 -0
  260. data/test/schema_authorization_test_postgresql.rb +75 -0
  261. data/test/schema_dumper_test.rb +96 -0
  262. data/test/schema_test_postgresql.rb +64 -0
  263. data/test/synonym_test_oracle.rb +17 -0
  264. data/test/table_name_test_sqlserver.rb +23 -0
  265. data/test/threaded_connections_test.rb +48 -0
  266. data/test/transactions_test.rb +230 -0
  267. data/test/unconnected_test.rb +32 -0
  268. data/test/validations_test.rb +1097 -0
  269. data/test/xml_serialization_test.rb +125 -0
  270. metadata +365 -0
@@ -0,0 +1,124 @@
1
+ require 'abstract_unit'
2
+ require 'fixtures/course'
3
+
4
+ class FirebirdMigrationTest < Test::Unit::TestCase
5
+ self.use_transactional_fixtures = false
6
+
7
+ def setup
8
+ # using Course connection for tests -- need a db that doesn't already have a BOOLEAN domain
9
+ @connection = Course.connection
10
+ @fireruby_connection = @connection.instance_variable_get(:@connection)
11
+ end
12
+
13
+ def teardown
14
+ @connection.drop_table :foo rescue nil
15
+ @connection.execute("DROP DOMAIN D_BOOLEAN") rescue nil
16
+ end
17
+
18
+ def test_create_table_with_custom_sequence_name
19
+ assert_nothing_raised do
20
+ @connection.create_table(:foo, :sequence => 'foo_custom_seq') do |f|
21
+ f.column :bar, :string
22
+ end
23
+ end
24
+ assert !sequence_exists?('foo_seq')
25
+ assert sequence_exists?('foo_custom_seq')
26
+
27
+ assert_nothing_raised { @connection.drop_table(:foo, :sequence => 'foo_custom_seq') }
28
+ assert !sequence_exists?('foo_custom_seq')
29
+ ensure
30
+ FireRuby::Generator.new('foo_custom_seq', @fireruby_connection).drop rescue nil
31
+ end
32
+
33
+ def test_create_table_without_sequence
34
+ assert_nothing_raised do
35
+ @connection.create_table(:foo, :sequence => false) do |f|
36
+ f.column :bar, :string
37
+ end
38
+ end
39
+ assert !sequence_exists?('foo_seq')
40
+ assert_nothing_raised { @connection.drop_table :foo }
41
+
42
+ assert_nothing_raised do
43
+ @connection.create_table(:foo, :id => false) do |f|
44
+ f.column :bar, :string
45
+ end
46
+ end
47
+ assert !sequence_exists?('foo_seq')
48
+ assert_nothing_raised { @connection.drop_table :foo }
49
+ end
50
+
51
+ def test_create_table_with_boolean_column
52
+ assert !boolean_domain_exists?
53
+ assert_nothing_raised do
54
+ @connection.create_table :foo do |f|
55
+ f.column :bar, :string
56
+ f.column :baz, :boolean
57
+ end
58
+ end
59
+ assert boolean_domain_exists?
60
+ end
61
+
62
+ def test_add_boolean_column
63
+ assert !boolean_domain_exists?
64
+ @connection.create_table :foo do |f|
65
+ f.column :bar, :string
66
+ end
67
+
68
+ assert_nothing_raised { @connection.add_column :foo, :baz, :boolean }
69
+ assert boolean_domain_exists?
70
+ assert_equal :boolean, @connection.columns(:foo).find { |c| c.name == "baz" }.type
71
+ end
72
+
73
+ def test_change_column_to_boolean
74
+ assert !boolean_domain_exists?
75
+ # Manually create table with a SMALLINT column, which can be changed to a BOOLEAN
76
+ @connection.execute "CREATE TABLE foo (bar SMALLINT)"
77
+ assert_equal :integer, @connection.columns(:foo).find { |c| c.name == "bar" }.type
78
+
79
+ assert_nothing_raised { @connection.change_column :foo, :bar, :boolean }
80
+ assert boolean_domain_exists?
81
+ assert_equal :boolean, @connection.columns(:foo).find { |c| c.name == "bar" }.type
82
+ end
83
+
84
+ def test_rename_table_with_data_and_index
85
+ @connection.create_table :foo do |f|
86
+ f.column :baz, :string, :limit => 50
87
+ end
88
+ 100.times { |i| @connection.execute "INSERT INTO foo VALUES (GEN_ID(foo_seq, 1), 'record #{i+1}')" }
89
+ @connection.add_index :foo, :baz
90
+
91
+ assert_nothing_raised { @connection.rename_table :foo, :bar }
92
+ assert !@connection.tables.include?("foo")
93
+ assert @connection.tables.include?("bar")
94
+ assert_equal "index_bar_on_baz", @connection.indexes("bar").first.name
95
+ assert_equal 100, FireRuby::Generator.new("bar_seq", @fireruby_connection).last
96
+ assert_equal 100, @connection.select_one("SELECT COUNT(*) FROM bar")["count"]
97
+ ensure
98
+ @connection.drop_table :bar rescue nil
99
+ end
100
+
101
+ def test_renaming_table_with_fk_constraint_raises_error
102
+ @connection.create_table :parent do |p|
103
+ p.column :name, :string
104
+ end
105
+ @connection.create_table :child do |c|
106
+ c.column :parent_id, :integer
107
+ end
108
+ @connection.execute "ALTER TABLE child ADD CONSTRAINT fk_child_parent FOREIGN KEY(parent_id) REFERENCES parent(id)"
109
+ assert_raise(ActiveRecord::ActiveRecordError) { @connection.rename_table :child, :descendant }
110
+ ensure
111
+ @connection.drop_table :child rescue nil
112
+ @connection.drop_table :descendant rescue nil
113
+ @connection.drop_table :parent rescue nil
114
+ end
115
+
116
+ private
117
+ def boolean_domain_exists?
118
+ !@connection.select_one("SELECT 1 FROM rdb$fields WHERE rdb$field_name = 'D_BOOLEAN'").nil?
119
+ end
120
+
121
+ def sequence_exists?(sequence_name)
122
+ FireRuby::Generator.exists?(sequence_name, @fireruby_connection)
123
+ end
124
+ end
@@ -0,0 +1,196 @@
1
+ require 'abstract_unit'
2
+ require 'active_record/acts/nested_set'
3
+ require 'fixtures/mixin'
4
+ require 'pp'
5
+
6
+ class MixinNestedSetTest < Test::Unit::TestCase
7
+ fixtures :mixins
8
+
9
+ def test_mixing_in_methods
10
+ ns = NestedSet.new
11
+ assert( ns.respond_to?( :all_children ) )
12
+ assert_equal( ns.scope_condition, "root_id IS NULL" )
13
+
14
+ check_method_mixins ns
15
+ end
16
+
17
+ def test_string_scope
18
+ ns = NestedSetWithStringScope.new
19
+
20
+ ns.root_id = 1
21
+ assert_equal( ns.scope_condition, "root_id = 1" )
22
+ ns.root_id = 42
23
+ assert_equal( ns.scope_condition, "root_id = 42" )
24
+ check_method_mixins ns
25
+ end
26
+
27
+ def test_symbol_scope
28
+ ns = NestedSetWithSymbolScope.new
29
+ ns.root_id = 1
30
+ assert_equal( ns.scope_condition, "root_id = 1" )
31
+ ns.root_id = 42
32
+ assert_equal( ns.scope_condition, "root_id = 42" )
33
+ check_method_mixins ns
34
+ end
35
+
36
+ def check_method_mixins( obj )
37
+ [:scope_condition, :left_col_name, :right_col_name, :parent_column, :root?, :add_child,
38
+ :children_count, :full_set, :all_children, :direct_children].each { |symbol| assert( obj.respond_to?(symbol)) }
39
+ end
40
+
41
+ def set( id )
42
+ NestedSet.find( 3000 + id )
43
+ end
44
+
45
+ def test_adding_children
46
+ assert( set(1).unknown? )
47
+ assert( set(2).unknown? )
48
+ set(1).add_child set(2)
49
+
50
+ # Did we maintain adding the parent_ids?
51
+ assert( set(1).root? )
52
+ assert( set(2).child? )
53
+ assert( set(2).parent_id == set(1).id )
54
+
55
+ # Check boundies
56
+ assert_equal( set(1).lft, 1 )
57
+ assert_equal( set(2).lft, 2 )
58
+ assert_equal( set(2).rgt, 3 )
59
+ assert_equal( set(1).rgt, 4 )
60
+
61
+ # Check children cound
62
+ assert_equal( set(1).children_count, 1 )
63
+
64
+ set(1).add_child set(3)
65
+
66
+ #check boundries
67
+ assert_equal( set(1).lft, 1 )
68
+ assert_equal( set(2).lft, 2 )
69
+ assert_equal( set(2).rgt, 3 )
70
+ assert_equal( set(3).lft, 4 )
71
+ assert_equal( set(3).rgt, 5 )
72
+ assert_equal( set(1).rgt, 6 )
73
+
74
+ # How is the count looking?
75
+ assert_equal( set(1).children_count, 2 )
76
+
77
+ set(2).add_child set(4)
78
+
79
+ # boundries
80
+ assert_equal( set(1).lft, 1 )
81
+ assert_equal( set(2).lft, 2 )
82
+ assert_equal( set(4).lft, 3 )
83
+ assert_equal( set(4).rgt, 4 )
84
+ assert_equal( set(2).rgt, 5 )
85
+ assert_equal( set(3).lft, 6 )
86
+ assert_equal( set(3).rgt, 7 )
87
+ assert_equal( set(1).rgt, 8 )
88
+
89
+ # Children count
90
+ assert_equal( set(1).children_count, 3 )
91
+ assert_equal( set(2).children_count, 1 )
92
+ assert_equal( set(3).children_count, 0 )
93
+ assert_equal( set(4).children_count, 0 )
94
+
95
+ set(2).add_child set(5)
96
+ set(4).add_child set(6)
97
+
98
+ assert_equal( set(2).children_count, 3 )
99
+
100
+
101
+ # Children accessors
102
+ assert_equal( set(1).full_set.length, 6 )
103
+ assert_equal( set(2).full_set.length, 4 )
104
+ assert_equal( set(4).full_set.length, 2 )
105
+
106
+ assert_equal( set(1).all_children.length, 5 )
107
+ assert_equal( set(6).all_children.length, 0 )
108
+
109
+ assert_equal( set(1).direct_children.length, 2 )
110
+
111
+ end
112
+
113
+ def test_snipping_tree
114
+ big_tree = NestedSetWithStringScope.find( 4001 )
115
+
116
+ # Make sure we have the right one
117
+ assert_equal( 3, big_tree.direct_children.length )
118
+ assert_equal( 10, big_tree.full_set.length )
119
+
120
+ NestedSetWithStringScope.find( 4005 ).destroy
121
+
122
+ big_tree = NestedSetWithStringScope.find( 4001 )
123
+
124
+ assert_equal( 7, big_tree.full_set.length )
125
+ assert_equal( 2, big_tree.direct_children.length )
126
+
127
+ assert_equal( 1, NestedSetWithStringScope.find(4001).lft )
128
+ assert_equal( 2, NestedSetWithStringScope.find(4002).lft )
129
+ assert_equal( 3, NestedSetWithStringScope.find(4003).lft )
130
+ assert_equal( 4, NestedSetWithStringScope.find(4003).rgt )
131
+ assert_equal( 5, NestedSetWithStringScope.find(4004).lft )
132
+ assert_equal( 6, NestedSetWithStringScope.find(4004).rgt )
133
+ assert_equal( 7, NestedSetWithStringScope.find(4002).rgt )
134
+ assert_equal( 8, NestedSetWithStringScope.find(4008).lft )
135
+ assert_equal( 9, NestedSetWithStringScope.find(4009).lft )
136
+ assert_equal(10, NestedSetWithStringScope.find(4009).rgt )
137
+ assert_equal(11, NestedSetWithStringScope.find(4010).lft )
138
+ assert_equal(12, NestedSetWithStringScope.find(4010).rgt )
139
+ assert_equal(13, NestedSetWithStringScope.find(4008).rgt )
140
+ assert_equal(14, NestedSetWithStringScope.find(4001).rgt )
141
+ end
142
+
143
+ def test_deleting_root
144
+ NestedSetWithStringScope.find(4001).destroy
145
+
146
+ assert( NestedSetWithStringScope.count == 0 )
147
+ end
148
+
149
+ def test_common_usage
150
+ mixins(:set_1).add_child( mixins(:set_2) )
151
+ assert_equal( 1, mixins(:set_1).direct_children.length )
152
+
153
+ mixins(:set_2).add_child( mixins(:set_3) )
154
+ assert_equal( 1, mixins(:set_1).direct_children.length )
155
+
156
+ # Local cache is now out of date!
157
+ # Problem: the update_alls update all objects up the tree
158
+ mixins(:set_1).reload
159
+ assert_equal( 2, mixins(:set_1).all_children.length )
160
+
161
+ assert_equal( 1, mixins(:set_1).lft )
162
+ assert_equal( 2, mixins(:set_2).lft )
163
+ assert_equal( 3, mixins(:set_3).lft )
164
+ assert_equal( 4, mixins(:set_3).rgt )
165
+ assert_equal( 5, mixins(:set_2).rgt )
166
+ assert_equal( 6, mixins(:set_1).rgt )
167
+
168
+ assert( mixins(:set_1).root? )
169
+
170
+ begin
171
+ mixins(:set_4).add_child( mixins(:set_1) )
172
+ fail
173
+ rescue
174
+ end
175
+
176
+ assert_equal( 2, mixins(:set_1).all_children.length )
177
+
178
+ mixins(:set_1).add_child mixins(:set_4)
179
+
180
+ assert_equal( 3, mixins(:set_1).all_children.length )
181
+ end
182
+
183
+ def test_inheritance
184
+ parent = mixins(:sti_set_3100)
185
+ child = mixins(:sti_set_3101)
186
+ grandchild = mixins(:sti_set_3102)
187
+ assert_equal 5, parent.full_set.size
188
+ assert_equal 2, child.full_set.size
189
+ assert_equal 4, parent.all_children.size
190
+ assert_equal 1, child.all_children.size
191
+ assert_equal 2, parent.direct_children.size
192
+ assert_equal 1, child.direct_children.size
193
+ child.destroy
194
+ assert_equal 3, parent.full_set.size
195
+ end
196
+ end
@@ -0,0 +1,550 @@
1
+ require 'abstract_unit'
2
+ require 'active_record/acts/tree'
3
+ require 'active_record/acts/list'
4
+ require 'active_record/acts/nested_set'
5
+ require 'fixtures/mixin'
6
+
7
+ # Let us control what Time.now returns for the TouchTest suite
8
+ class Time
9
+ @@forced_now_time = nil
10
+ cattr_accessor :forced_now_time
11
+
12
+ class << self
13
+ def now_with_forcing
14
+ if @@forced_now_time
15
+ @@forced_now_time
16
+ else
17
+ now_without_forcing
18
+ end
19
+ end
20
+ alias_method_chain :now, :forcing
21
+ end
22
+ end
23
+
24
+ class ListTest < Test::Unit::TestCase
25
+ fixtures :mixins
26
+
27
+ def test_reordering
28
+ assert_equal [mixins(:list_1),
29
+ mixins(:list_2),
30
+ mixins(:list_3),
31
+ mixins(:list_4)],
32
+ ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos')
33
+
34
+ mixins(:list_2).move_lower
35
+
36
+ assert_equal [mixins(:list_1),
37
+ mixins(:list_3),
38
+ mixins(:list_2),
39
+ mixins(:list_4)],
40
+ ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos')
41
+
42
+ mixins(:list_2).move_higher
43
+
44
+ assert_equal [mixins(:list_1),
45
+ mixins(:list_2),
46
+ mixins(:list_3),
47
+ mixins(:list_4)],
48
+ ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos')
49
+
50
+ mixins(:list_1).move_to_bottom
51
+
52
+ assert_equal [mixins(:list_2),
53
+ mixins(:list_3),
54
+ mixins(:list_4),
55
+ mixins(:list_1)],
56
+ ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos')
57
+
58
+ mixins(:list_1).move_to_top
59
+
60
+ assert_equal [mixins(:list_1),
61
+ mixins(:list_2),
62
+ mixins(:list_3),
63
+ mixins(:list_4)],
64
+ ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos')
65
+
66
+
67
+ mixins(:list_2).move_to_bottom
68
+
69
+ assert_equal [mixins(:list_1),
70
+ mixins(:list_3),
71
+ mixins(:list_4),
72
+ mixins(:list_2)],
73
+ ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos')
74
+
75
+ mixins(:list_4).move_to_top
76
+
77
+ assert_equal [mixins(:list_4),
78
+ mixins(:list_1),
79
+ mixins(:list_3),
80
+ mixins(:list_2)],
81
+ ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos')
82
+
83
+ end
84
+
85
+ def test_move_to_bottom_with_next_to_last_item
86
+ assert_equal [mixins(:list_1),
87
+ mixins(:list_2),
88
+ mixins(:list_3),
89
+ mixins(:list_4)],
90
+ ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos')
91
+
92
+ mixins(:list_3).move_to_bottom
93
+
94
+ assert_equal [mixins(:list_1),
95
+ mixins(:list_2),
96
+ mixins(:list_4),
97
+ mixins(:list_3)],
98
+ ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos')
99
+ end
100
+
101
+ def test_next_prev
102
+ assert_equal mixins(:list_2), mixins(:list_1).lower_item
103
+ assert_nil mixins(:list_1).higher_item
104
+ assert_equal mixins(:list_3), mixins(:list_4).higher_item
105
+ assert_nil mixins(:list_4).lower_item
106
+ end
107
+
108
+
109
+ def test_injection
110
+ item = ListMixin.new("parent_id"=>1)
111
+ assert_equal "parent_id = 1", item.scope_condition
112
+ assert_equal "pos", item.position_column
113
+ end
114
+
115
+ def test_insert
116
+ new = ListMixin.create("parent_id"=>20)
117
+ assert_equal 1, new.pos
118
+ assert new.first?
119
+ assert new.last?
120
+
121
+ new = ListMixin.create("parent_id"=>20)
122
+ assert_equal 2, new.pos
123
+ assert !new.first?
124
+ assert new.last?
125
+
126
+ new = ListMixin.create("parent_id"=>20)
127
+ assert_equal 3, new.pos
128
+ assert !new.first?
129
+ assert new.last?
130
+
131
+ new = ListMixin.create("parent_id"=>0)
132
+ assert_equal 1, new.pos
133
+ assert new.first?
134
+ assert new.last?
135
+ end
136
+
137
+ def test_insert_at
138
+ new = ListMixin.create("parent_id" => 20)
139
+ assert_equal 1, new.pos
140
+
141
+ new = ListMixin.create("parent_id" => 20)
142
+ assert_equal 2, new.pos
143
+
144
+ new = ListMixin.create("parent_id" => 20)
145
+ assert_equal 3, new.pos
146
+
147
+ new4 = ListMixin.create("parent_id" => 20)
148
+ assert_equal 4, new4.pos
149
+
150
+ new4.insert_at(3)
151
+ assert_equal 3, new4.pos
152
+
153
+ new.reload
154
+ assert_equal 4, new.pos
155
+
156
+ new.insert_at(2)
157
+ assert_equal 2, new.pos
158
+
159
+ new4.reload
160
+ assert_equal 4, new4.pos
161
+
162
+ new5 = ListMixin.create("parent_id" => 20)
163
+ assert_equal 5, new5.pos
164
+
165
+ new5.insert_at(1)
166
+ assert_equal 1, new5.pos
167
+
168
+ new4.reload
169
+ assert_equal 5, new4.pos
170
+ end
171
+
172
+ def test_delete_middle
173
+ assert_equal [mixins(:list_1),
174
+ mixins(:list_2),
175
+ mixins(:list_3),
176
+ mixins(:list_4)],
177
+ ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos')
178
+
179
+ mixins(:list_2).destroy
180
+
181
+ assert_equal [mixins(:list_1, :reload),
182
+ mixins(:list_3, :reload),
183
+ mixins(:list_4, :reload)],
184
+ ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos')
185
+
186
+ assert_equal 1, mixins(:list_1).pos
187
+ assert_equal 2, mixins(:list_3).pos
188
+ assert_equal 3, mixins(:list_4).pos
189
+
190
+ mixins(:list_1).destroy
191
+
192
+ assert_equal [mixins(:list_3, :reload),
193
+ mixins(:list_4, :reload)],
194
+ ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos')
195
+
196
+ assert_equal 1, mixins(:list_3).pos
197
+ assert_equal 2, mixins(:list_4).pos
198
+
199
+ end
200
+
201
+ def test_with_string_based_scope
202
+ new = ListWithStringScopeMixin.create("parent_id"=>500)
203
+ assert_equal 1, new.pos
204
+ assert new.first?
205
+ assert new.last?
206
+ end
207
+
208
+ def test_nil_scope
209
+ new1, new2, new3 = ListMixin.create, ListMixin.create, ListMixin.create
210
+ new2.move_higher
211
+ assert_equal [new2, new1, new3], ListMixin.find(:all, :conditions => 'parent_id IS NULL', :order => 'pos')
212
+ end
213
+
214
+ end
215
+
216
+ class TreeTest < Test::Unit::TestCase
217
+ fixtures :mixins
218
+
219
+ def test_has_child
220
+ assert_deprecated 'has_children?' do
221
+ assert_equal true, mixins(:tree_1).has_children?
222
+ assert_equal true, mixins(:tree_2).has_children?
223
+ assert_equal false, mixins(:tree_3).has_children?
224
+ assert_equal false, mixins(:tree_4).has_children?
225
+ end
226
+ end
227
+
228
+ def test_children
229
+ assert_equal mixins(:tree_1).children, [mixins(:tree_2), mixins(:tree_4)]
230
+ assert_equal mixins(:tree_2).children, [mixins(:tree_3)]
231
+ assert_equal mixins(:tree_3).children, []
232
+ assert_equal mixins(:tree_4).children, []
233
+ end
234
+
235
+ def test_has_parent
236
+ assert_deprecated 'has_parent?' do
237
+ assert_equal false, mixins(:tree_1).has_parent?
238
+ assert_equal true, mixins(:tree_2).has_parent?
239
+ assert_equal true, mixins(:tree_3).has_parent?
240
+ assert_equal true, mixins(:tree_4).has_parent?
241
+ end
242
+ end
243
+
244
+ def test_parent
245
+ assert_equal mixins(:tree_2).parent, mixins(:tree_1)
246
+ assert_equal mixins(:tree_2).parent, mixins(:tree_4).parent
247
+ assert_nil mixins(:tree_1).parent
248
+ end
249
+
250
+ def test_delete
251
+ assert_equal 6, TreeMixin.count
252
+ mixins(:tree_1).destroy
253
+ assert_equal 2, TreeMixin.count
254
+ mixins(:tree2_1).destroy
255
+ mixins(:tree3_1).destroy
256
+ assert_equal 0, TreeMixin.count
257
+ end
258
+
259
+ def test_insert
260
+ @extra = mixins(:tree_1).children.create
261
+
262
+ assert @extra
263
+
264
+ assert_equal @extra.parent, mixins(:tree_1)
265
+
266
+ assert_equal 3, mixins(:tree_1).children.size
267
+ assert mixins(:tree_1).children.include?(@extra)
268
+ assert mixins(:tree_1).children.include?(mixins(:tree_2))
269
+ assert mixins(:tree_1).children.include?(mixins(:tree_4))
270
+ end
271
+
272
+ def test_ancestors
273
+ assert_equal [], mixins(:tree_1).ancestors
274
+ assert_equal [mixins(:tree_1)], mixins(:tree_2).ancestors
275
+ assert_equal [mixins(:tree_2), mixins(:tree_1)], mixins(:tree_3).ancestors
276
+ assert_equal [mixins(:tree_1)], mixins(:tree_4).ancestors
277
+ assert_equal [], mixins(:tree2_1).ancestors
278
+ assert_equal [], mixins(:tree3_1).ancestors
279
+ end
280
+
281
+ def test_root
282
+ assert_equal mixins(:tree_1), TreeMixin.root
283
+ assert_equal mixins(:tree_1), mixins(:tree_1).root
284
+ assert_equal mixins(:tree_1), mixins(:tree_2).root
285
+ assert_equal mixins(:tree_1), mixins(:tree_3).root
286
+ assert_equal mixins(:tree_1), mixins(:tree_4).root
287
+ assert_equal mixins(:tree2_1), mixins(:tree2_1).root
288
+ assert_equal mixins(:tree3_1), mixins(:tree3_1).root
289
+ end
290
+
291
+ def test_roots
292
+ assert_equal [mixins(:tree_1), mixins(:tree2_1), mixins(:tree3_1)], TreeMixin.roots
293
+ end
294
+
295
+ def test_siblings
296
+ assert_equal [mixins(:tree2_1), mixins(:tree3_1)], mixins(:tree_1).siblings
297
+ assert_equal [mixins(:tree_4)], mixins(:tree_2).siblings
298
+ assert_equal [], mixins(:tree_3).siblings
299
+ assert_equal [mixins(:tree_2)], mixins(:tree_4).siblings
300
+ assert_equal [mixins(:tree_1), mixins(:tree3_1)], mixins(:tree2_1).siblings
301
+ assert_equal [mixins(:tree_1), mixins(:tree2_1)], mixins(:tree3_1).siblings
302
+ end
303
+
304
+ def test_self_and_siblings
305
+ assert_equal [mixins(:tree_1), mixins(:tree2_1), mixins(:tree3_1)], mixins(:tree_1).self_and_siblings
306
+ assert_equal [mixins(:tree_2), mixins(:tree_4)], mixins(:tree_2).self_and_siblings
307
+ assert_equal [mixins(:tree_3)], mixins(:tree_3).self_and_siblings
308
+ assert_equal [mixins(:tree_2), mixins(:tree_4)], mixins(:tree_4).self_and_siblings
309
+ assert_equal [mixins(:tree_1), mixins(:tree2_1), mixins(:tree3_1)], mixins(:tree2_1).self_and_siblings
310
+ assert_equal [mixins(:tree_1), mixins(:tree2_1), mixins(:tree3_1)], mixins(:tree3_1).self_and_siblings
311
+ end
312
+ end
313
+
314
+ class TreeTestWithoutOrder < Test::Unit::TestCase
315
+ fixtures :mixins
316
+
317
+ def test_root
318
+ assert [mixins(:tree_without_order_1), mixins(:tree_without_order_2)].include?(TreeMixinWithoutOrder.root)
319
+ end
320
+
321
+ def test_roots
322
+ assert_equal [], [mixins(:tree_without_order_1), mixins(:tree_without_order_2)] - TreeMixinWithoutOrder.roots
323
+ end
324
+ end
325
+
326
+ class TouchTest < Test::Unit::TestCase
327
+ fixtures :mixins
328
+
329
+ def setup
330
+ Time.forced_now_time = Time.now
331
+ end
332
+
333
+ def teardown
334
+ Time.forced_now_time = nil
335
+ end
336
+
337
+ def test_time_mocking
338
+ five_minutes_ago = 5.minutes.ago
339
+ Time.forced_now_time = five_minutes_ago
340
+ assert_equal five_minutes_ago, Time.now
341
+
342
+ Time.forced_now_time = nil
343
+ assert_not_equal five_minutes_ago, Time.now
344
+ end
345
+
346
+ def test_update
347
+ stamped = Mixin.new
348
+
349
+ assert_nil stamped.updated_at
350
+ assert_nil stamped.created_at
351
+ stamped.save
352
+ assert_equal Time.now, stamped.updated_at
353
+ assert_equal Time.now, stamped.created_at
354
+ end
355
+
356
+ def test_create
357
+ obj = Mixin.create
358
+ assert_equal Time.now, obj.updated_at
359
+ assert_equal Time.now, obj.created_at
360
+ end
361
+
362
+ def test_many_updates
363
+ stamped = Mixin.new
364
+
365
+ assert_nil stamped.updated_at
366
+ assert_nil stamped.created_at
367
+ stamped.save
368
+ assert_equal Time.now, stamped.created_at
369
+ assert_equal Time.now, stamped.updated_at
370
+
371
+ old_updated_at = stamped.updated_at
372
+
373
+ Time.forced_now_time = 5.minutes.from_now
374
+ stamped.save
375
+
376
+ assert_equal Time.now, stamped.updated_at
377
+ assert_equal old_updated_at, stamped.created_at
378
+ end
379
+
380
+ def test_create_turned_off
381
+ Mixin.record_timestamps = false
382
+
383
+ assert_nil mixins(:tree_1).updated_at
384
+ mixins(:tree_1).save
385
+ assert_nil mixins(:tree_1).updated_at
386
+
387
+ Mixin.record_timestamps = true
388
+ end
389
+
390
+ end
391
+
392
+
393
+ class ListSubTest < Test::Unit::TestCase
394
+ fixtures :mixins
395
+
396
+ def test_reordering
397
+ assert_equal [mixins(:list_sub_1),
398
+ mixins(:list_sub_2),
399
+ mixins(:list_sub_3),
400
+ mixins(:list_sub_4)],
401
+ ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
402
+
403
+ mixins(:list_sub_2).move_lower
404
+
405
+ assert_equal [mixins(:list_sub_1),
406
+ mixins(:list_sub_3),
407
+ mixins(:list_sub_2),
408
+ mixins(:list_sub_4)],
409
+ ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
410
+
411
+ mixins(:list_sub_2).move_higher
412
+
413
+ assert_equal [mixins(:list_sub_1),
414
+ mixins(:list_sub_2),
415
+ mixins(:list_sub_3),
416
+ mixins(:list_sub_4)],
417
+ ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
418
+
419
+ mixins(:list_sub_1).move_to_bottom
420
+
421
+ assert_equal [mixins(:list_sub_2),
422
+ mixins(:list_sub_3),
423
+ mixins(:list_sub_4),
424
+ mixins(:list_sub_1)],
425
+ ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
426
+
427
+ mixins(:list_sub_1).move_to_top
428
+
429
+ assert_equal [mixins(:list_sub_1),
430
+ mixins(:list_sub_2),
431
+ mixins(:list_sub_3),
432
+ mixins(:list_sub_4)],
433
+ ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
434
+
435
+
436
+ mixins(:list_sub_2).move_to_bottom
437
+
438
+ assert_equal [mixins(:list_sub_1),
439
+ mixins(:list_sub_3),
440
+ mixins(:list_sub_4),
441
+ mixins(:list_sub_2)],
442
+ ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
443
+
444
+ mixins(:list_sub_4).move_to_top
445
+
446
+ assert_equal [mixins(:list_sub_4),
447
+ mixins(:list_sub_1),
448
+ mixins(:list_sub_3),
449
+ mixins(:list_sub_2)],
450
+ ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
451
+
452
+ end
453
+
454
+ def test_move_to_bottom_with_next_to_last_item
455
+ assert_equal [mixins(:list_sub_1),
456
+ mixins(:list_sub_2),
457
+ mixins(:list_sub_3),
458
+ mixins(:list_sub_4)],
459
+ ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
460
+
461
+ mixins(:list_sub_3).move_to_bottom
462
+
463
+ assert_equal [mixins(:list_sub_1),
464
+ mixins(:list_sub_2),
465
+ mixins(:list_sub_4),
466
+ mixins(:list_sub_3)],
467
+ ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
468
+ end
469
+
470
+ def test_next_prev
471
+ assert_equal mixins(:list_sub_2), mixins(:list_sub_1).lower_item
472
+ assert_nil mixins(:list_sub_1).higher_item
473
+ assert_equal mixins(:list_sub_3), mixins(:list_sub_4).higher_item
474
+ assert_nil mixins(:list_sub_4).lower_item
475
+ end
476
+
477
+
478
+ def test_injection
479
+ item = ListMixin.new("parent_id"=>1)
480
+ assert_equal "parent_id = 1", item.scope_condition
481
+ assert_equal "pos", item.position_column
482
+ end
483
+
484
+
485
+ def test_insert_at
486
+ new = ListMixin.create("parent_id" => 20)
487
+ assert_equal 1, new.pos
488
+
489
+ new = ListMixinSub1.create("parent_id" => 20)
490
+ assert_equal 2, new.pos
491
+
492
+ new = ListMixinSub2.create("parent_id" => 20)
493
+ assert_equal 3, new.pos
494
+
495
+ new4 = ListMixin.create("parent_id" => 20)
496
+ assert_equal 4, new4.pos
497
+
498
+ new4.insert_at(3)
499
+ assert_equal 3, new4.pos
500
+
501
+ new.reload
502
+ assert_equal 4, new.pos
503
+
504
+ new.insert_at(2)
505
+ assert_equal 2, new.pos
506
+
507
+ new4.reload
508
+ assert_equal 4, new4.pos
509
+
510
+ new5 = ListMixinSub1.create("parent_id" => 20)
511
+ assert_equal 5, new5.pos
512
+
513
+ new5.insert_at(1)
514
+ assert_equal 1, new5.pos
515
+
516
+ new4.reload
517
+ assert_equal 5, new4.pos
518
+ end
519
+
520
+ def test_delete_middle
521
+ assert_equal [mixins(:list_sub_1),
522
+ mixins(:list_sub_2),
523
+ mixins(:list_sub_3),
524
+ mixins(:list_sub_4)],
525
+ ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
526
+
527
+ mixins(:list_sub_2).destroy
528
+
529
+ assert_equal [mixins(:list_sub_1, :reload),
530
+ mixins(:list_sub_3, :reload),
531
+ mixins(:list_sub_4, :reload)],
532
+ ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
533
+
534
+ assert_equal 1, mixins(:list_sub_1).pos
535
+ assert_equal 2, mixins(:list_sub_3).pos
536
+ assert_equal 3, mixins(:list_sub_4).pos
537
+
538
+ mixins(:list_sub_1).destroy
539
+
540
+ assert_equal [mixins(:list_sub_3, :reload),
541
+ mixins(:list_sub_4, :reload)],
542
+ ListMixin.find(:all, :conditions => 'parent_id = 5000', :order => 'pos')
543
+
544
+ assert_equal 1, mixins(:list_sub_3).pos
545
+ assert_equal 2, mixins(:list_sub_4).pos
546
+
547
+ end
548
+
549
+ end
550
+