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,75 @@
1
+ require 'abstract_unit'
2
+
3
+ class SchemaThing < ActiveRecord::Base
4
+ end
5
+
6
+ class SchemaAuthorizationTest < Test::Unit::TestCase
7
+ self.use_transactional_fixtures = false
8
+
9
+ TABLE_NAME = 'schema_things'
10
+ COLUMNS = [
11
+ 'id serial primary key',
12
+ 'name character varying(50)'
13
+ ]
14
+ USERS = ['rails_pg_schema_user1', 'rails_pg_schema_user2']
15
+
16
+ def setup
17
+ @connection = ActiveRecord::Base.connection
18
+ @connection.execute "SET search_path TO '$user',public"
19
+ set_session_auth
20
+ USERS.each do |u|
21
+ @connection.execute "CREATE ROLE #{u}"
22
+ @connection.execute "CREATE SCHEMA AUTHORIZATION #{u}"
23
+ set_session_auth u
24
+ @connection.execute "CREATE TABLE #{TABLE_NAME} (#{COLUMNS.join(',')})"
25
+ @connection.execute "INSERT INTO #{TABLE_NAME} (name) VALUES ('#{u}')"
26
+ set_session_auth
27
+ end
28
+ end
29
+
30
+ def teardown
31
+ set_session_auth
32
+ @connection.execute "RESET search_path"
33
+ USERS.each do |u|
34
+ @connection.execute "DROP SCHEMA #{u} CASCADE"
35
+ @connection.execute "DROP ROLE #{u}"
36
+ end
37
+ end
38
+
39
+ def test_schema_invisible
40
+ assert_raise(ActiveRecord::StatementInvalid) do
41
+ set_session_auth
42
+ @connection.execute "SELECT * FROM #{TABLE_NAME}"
43
+ end
44
+ end
45
+
46
+ def test_schema_uniqueness
47
+ assert_nothing_raised do
48
+ set_session_auth
49
+ USERS.each do |u|
50
+ set_session_auth u
51
+ assert_equal u, @connection.select_value("SELECT name FROM #{TABLE_NAME} WHERE id = 1")
52
+ set_session_auth
53
+ end
54
+ end
55
+ end
56
+
57
+ def test_sequence_schema_caching
58
+ assert_nothing_raised do
59
+ USERS.each do |u|
60
+ set_session_auth u
61
+ st = SchemaThing.new :name => 'TEST1'
62
+ st.save!
63
+ st = SchemaThing.new :id => 5, :name => 'TEST2'
64
+ st.save!
65
+ set_session_auth
66
+ end
67
+ end
68
+ end
69
+
70
+ private
71
+ def set_session_auth auth = nil
72
+ @connection.execute "SET SESSION AUTHORIZATION #{auth || 'default'}"
73
+ end
74
+
75
+ end
@@ -0,0 +1,96 @@
1
+ require 'abstract_unit'
2
+ require "#{File.dirname(__FILE__)}/../lib/active_record/schema_dumper"
3
+ require 'stringio'
4
+
5
+ if ActiveRecord::Base.connection.respond_to?(:tables)
6
+
7
+ class SchemaDumperTest < Test::Unit::TestCase
8
+ def standard_dump
9
+ stream = StringIO.new
10
+ ActiveRecord::SchemaDumper.ignore_tables = []
11
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
12
+ stream.string
13
+ end
14
+
15
+ def test_schema_dump
16
+ output = standard_dump
17
+ assert_match %r{create_table "accounts"}, output
18
+ assert_match %r{create_table "authors"}, output
19
+ assert_no_match %r{create_table "schema_info"}, output
20
+ end
21
+
22
+ def assert_line_up(lines, pattern, required = false)
23
+ return assert(true) if lines.empty?
24
+ matches = lines.map { |line| line.match(pattern) }
25
+ assert matches.all? if required
26
+ matches.compact!
27
+ return assert(true) if matches.empty?
28
+ assert_equal 1, matches.map{ |match| match.offset(0).first }.uniq.length
29
+ end
30
+
31
+ def test_arguments_line_up
32
+ output = standard_dump
33
+ output.scan(/^( *)create_table.*?\n(.*?)^\1end/m).map{ |m| m.last.split(/\n/) }.each do |column_set|
34
+ assert_line_up(column_set, /:(?:integer|decimal|float|datetime|timestamp|time|date|text|binary|string|boolean)/, true)
35
+ assert_line_up(column_set, /:default => /)
36
+ assert_line_up(column_set, /:limit => /)
37
+ assert_line_up(column_set, /:null => /)
38
+ end
39
+ end
40
+
41
+ def test_no_dump_errors
42
+ output = standard_dump
43
+ assert_no_match %r{\# Could not dump table}, output
44
+ end
45
+
46
+ def test_schema_dump_includes_not_null_columns
47
+ stream = StringIO.new
48
+
49
+ ActiveRecord::SchemaDumper.ignore_tables = [/^[^r]/]
50
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
51
+ output = stream.string
52
+ assert_match %r{:null => false}, output
53
+ end
54
+
55
+ def test_schema_dump_with_string_ignored_table
56
+ stream = StringIO.new
57
+
58
+ ActiveRecord::SchemaDumper.ignore_tables = ['accounts']
59
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
60
+ output = stream.string
61
+ assert_no_match %r{create_table "accounts"}, output
62
+ assert_match %r{create_table "authors"}, output
63
+ assert_no_match %r{create_table "schema_info"}, output
64
+ end
65
+
66
+
67
+ def test_schema_dump_with_regexp_ignored_table
68
+ stream = StringIO.new
69
+
70
+ ActiveRecord::SchemaDumper.ignore_tables = [/^account/]
71
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
72
+ output = stream.string
73
+ assert_no_match %r{create_table "accounts"}, output
74
+ assert_match %r{create_table "authors"}, output
75
+ assert_no_match %r{create_table "schema_info"}, output
76
+ end
77
+
78
+
79
+ def test_schema_dump_illegal_ignored_table_value
80
+ stream = StringIO.new
81
+ ActiveRecord::SchemaDumper.ignore_tables = [5]
82
+ assert_raise(StandardError) do
83
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
84
+ end
85
+ end
86
+
87
+ def test_schema_dump_includes_decimal_options
88
+ stream = StringIO.new
89
+ ActiveRecord::SchemaDumper.ignore_tables = [/^[^n]/]
90
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
91
+ output = stream.string
92
+ assert_match %r{:precision => 3,[[:space:]]+:scale => 2,[[:space:]]+:default => 2.78}, output
93
+ end
94
+ end
95
+
96
+ end
@@ -0,0 +1,64 @@
1
+ require 'abstract_unit'
2
+
3
+ class SchemaTest < Test::Unit::TestCase
4
+ self.use_transactional_fixtures = false
5
+
6
+ SCHEMA_NAME = 'test_schema'
7
+ TABLE_NAME = 'things'
8
+ COLUMNS = [
9
+ 'id integer',
10
+ 'name character varying(50)',
11
+ 'moment timestamp without time zone default now()'
12
+ ]
13
+
14
+ def setup
15
+ @connection = ActiveRecord::Base.connection
16
+ @connection.execute "CREATE SCHEMA #{SCHEMA_NAME} CREATE TABLE #{TABLE_NAME} (#{COLUMNS.join(',')})"
17
+ end
18
+
19
+ def teardown
20
+ @connection.execute "DROP SCHEMA #{SCHEMA_NAME} CASCADE"
21
+ end
22
+
23
+ def test_with_schema_prefixed_table_name
24
+ assert_nothing_raised do
25
+ assert_equal COLUMNS, columns("#{SCHEMA_NAME}.#{TABLE_NAME}")
26
+ end
27
+ end
28
+
29
+ def test_with_schema_search_path
30
+ assert_nothing_raised do
31
+ with_schema_search_path(SCHEMA_NAME) do
32
+ assert_equal COLUMNS, columns(TABLE_NAME)
33
+ end
34
+ end
35
+ end
36
+
37
+ def test_raise_on_unquoted_schema_name
38
+ assert_raise(ActiveRecord::StatementInvalid) do
39
+ with_schema_search_path '$user,public'
40
+ end
41
+ end
42
+
43
+ def test_without_schema_search_path
44
+ assert_raise(ActiveRecord::StatementInvalid) { columns(TABLE_NAME) }
45
+ end
46
+
47
+ def test_ignore_nil_schema_search_path
48
+ assert_nothing_raised { with_schema_search_path nil }
49
+ end
50
+
51
+ private
52
+ def columns(table_name)
53
+ @connection.send(:column_definitions, table_name).map do |name, type, default|
54
+ "#{name} #{type}" + (default ? " default #{default}" : '')
55
+ end
56
+ end
57
+
58
+ def with_schema_search_path(schema_search_path)
59
+ @connection.schema_search_path = schema_search_path
60
+ yield if block_given?
61
+ ensure
62
+ @connection.schema_search_path = "'$user', public"
63
+ end
64
+ end
@@ -0,0 +1,17 @@
1
+ require 'abstract_unit'
2
+ require 'fixtures/topic'
3
+ require 'fixtures/subject'
4
+
5
+ # confirm that synonyms work just like tables; in this case
6
+ # the "subjects" table in Oracle (defined in oci.sql) is just
7
+ # a synonym to the "topics" table
8
+
9
+ class TestOracleSynonym < Test::Unit::TestCase
10
+
11
+ def test_oracle_synonym
12
+ topic = Topic.new
13
+ subject = Subject.new
14
+ assert_equal(topic.attributes, subject.attributes)
15
+ end
16
+
17
+ end
@@ -0,0 +1,23 @@
1
+ require 'abstract_unit'
2
+ require "#{File.dirname(__FILE__)}/../lib/active_record/schema"
3
+
4
+ if ActiveRecord::Base.connection.supports_migrations?
5
+ class Order < ActiveRecord::Base
6
+ self.table_name = '[order]'
7
+ end
8
+
9
+ class TableNameTest < Test::Unit::TestCase
10
+ self.use_transactional_fixtures = false
11
+
12
+ # Ensures Model.columns works when using SQLServer escape characters.
13
+ # Enables legacy schemas using SQL reserved words as table names.
14
+ # Should work with table names with spaces as well ('table name').
15
+ def test_escaped_table_name
16
+ assert_nothing_raised do
17
+ ActiveRecord::Base.connection.select_all 'SELECT * FROM [order]'
18
+ end
19
+ assert_equal '[order]', Order.table_name
20
+ assert_equal 5, Order.columns.length
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,48 @@
1
+ require 'abstract_unit'
2
+ require 'fixtures/topic'
3
+ require 'fixtures/reply'
4
+
5
+ unless %w(FrontBase).include? ActiveRecord::Base.connection.adapter_name
6
+ class ThreadedConnectionsTest < Test::Unit::TestCase
7
+ self.use_transactional_fixtures = false
8
+
9
+ fixtures :topics
10
+
11
+ def setup
12
+ @connection = ActiveRecord::Base.remove_connection
13
+ @connections = []
14
+ @allow_concurrency = ActiveRecord::Base.allow_concurrency
15
+ end
16
+
17
+ def teardown
18
+ # clear the connection cache
19
+ ActiveRecord::Base.send(:clear_all_cached_connections!)
20
+ # set allow_concurrency to saved value
21
+ ActiveRecord::Base.allow_concurrency = @allow_concurrency
22
+ # reestablish old connection
23
+ ActiveRecord::Base.establish_connection(@connection)
24
+ end
25
+
26
+ def gather_connections(use_threaded_connections)
27
+ ActiveRecord::Base.allow_concurrency = use_threaded_connections
28
+ ActiveRecord::Base.establish_connection(@connection)
29
+
30
+ 5.times do
31
+ Thread.new do
32
+ Topic.find :first
33
+ @connections << ActiveRecord::Base.active_connections.values.first
34
+ end.join
35
+ end
36
+ end
37
+
38
+ def test_threaded_connections
39
+ gather_connections(true)
40
+ assert_equal @connections.uniq.length, 5
41
+ end
42
+
43
+ def test_unthreaded_connections
44
+ gather_connections(false)
45
+ assert_equal @connections.uniq.length, 1
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,230 @@
1
+ require 'abstract_unit'
2
+ require 'fixtures/topic'
3
+ require 'fixtures/reply'
4
+ require 'fixtures/developer'
5
+
6
+ class TransactionTest < Test::Unit::TestCase
7
+ self.use_transactional_fixtures = false
8
+ fixtures :topics, :developers
9
+
10
+ def setup
11
+ @first, @second = Topic.find(1, 2).sort_by { |t| t.id }
12
+ end
13
+
14
+ def test_successful
15
+ Topic.transaction do
16
+ @first.approved = true
17
+ @second.approved = false
18
+ @first.save
19
+ @second.save
20
+ end
21
+
22
+ assert Topic.find(1).approved?, "First should have been approved"
23
+ assert !Topic.find(2).approved?, "Second should have been unapproved"
24
+ end
25
+
26
+ def transaction_with_return
27
+ Topic.transaction do
28
+ @first.approved = true
29
+ @second.approved = false
30
+ @first.save
31
+ @second.save
32
+ return
33
+ end
34
+ end
35
+
36
+ def test_successful_with_return
37
+ class << Topic.connection
38
+ alias :real_commit_db_transaction :commit_db_transaction
39
+ def commit_db_transaction
40
+ $committed = true
41
+ real_commit_db_transaction
42
+ end
43
+ end
44
+
45
+ $committed = false
46
+ transaction_with_return
47
+ assert $committed
48
+
49
+ assert Topic.find(1).approved?, "First should have been approved"
50
+ assert !Topic.find(2).approved?, "Second should have been unapproved"
51
+ ensure
52
+ class << Topic.connection
53
+ alias :commit_db_transaction :real_commit_db_transaction rescue nil
54
+ end
55
+ end
56
+
57
+ def test_successful_with_instance_method
58
+ @first.transaction do
59
+ @first.approved = true
60
+ @second.approved = false
61
+ @first.save
62
+ @second.save
63
+ end
64
+
65
+ assert Topic.find(1).approved?, "First should have been approved"
66
+ assert !Topic.find(2).approved?, "Second should have been unapproved"
67
+ end
68
+
69
+ def test_failing_on_exception
70
+ begin
71
+ Topic.transaction do
72
+ @first.approved = true
73
+ @second.approved = false
74
+ @first.save
75
+ @second.save
76
+ raise "Bad things!"
77
+ end
78
+ rescue
79
+ # caught it
80
+ end
81
+
82
+ assert @first.approved?, "First should still be changed in the objects"
83
+ assert !@second.approved?, "Second should still be changed in the objects"
84
+
85
+ assert !Topic.find(1).approved?, "First shouldn't have been approved"
86
+ assert Topic.find(2).approved?, "Second should still be approved"
87
+ end
88
+
89
+ def test_failing_with_object_rollback
90
+ assert !@first.approved?, "First should be unapproved initially"
91
+
92
+ begin
93
+ assert_deprecated /Object transactions/ do
94
+ Topic.transaction(@first, @second) do
95
+ @first.approved = true
96
+ @second.approved = false
97
+ @first.save
98
+ @second.save
99
+ raise "Bad things!"
100
+ end
101
+ end
102
+ rescue
103
+ # caught it
104
+ end
105
+
106
+ assert !@first.approved?, "First shouldn't have been approved"
107
+ assert @second.approved?, "Second should still be approved"
108
+ end
109
+
110
+ def test_callback_rollback_in_save
111
+ add_exception_raising_after_save_callback_to_topic
112
+
113
+ begin
114
+ @first.approved = true
115
+ @first.save
116
+ flunk
117
+ rescue => e
118
+ assert_equal "Make the transaction rollback", e.message
119
+ assert !Topic.find(1).approved?
120
+ ensure
121
+ remove_exception_raising_after_save_callback_to_topic
122
+ end
123
+ end
124
+
125
+ def test_nested_explicit_transactions
126
+ Topic.transaction do
127
+ Topic.transaction do
128
+ @first.approved = true
129
+ @second.approved = false
130
+ @first.save
131
+ @second.save
132
+ end
133
+ end
134
+
135
+ assert Topic.find(1).approved?, "First should have been approved"
136
+ assert !Topic.find(2).approved?, "Second should have been unapproved"
137
+ end
138
+
139
+ private
140
+ def add_exception_raising_after_save_callback_to_topic
141
+ Topic.class_eval { def after_save() raise "Make the transaction rollback" end }
142
+ end
143
+
144
+ def remove_exception_raising_after_save_callback_to_topic
145
+ Topic.class_eval { remove_method :after_save }
146
+ end
147
+ end
148
+
149
+ if current_adapter?(:PostgreSQLAdapter)
150
+ class ConcurrentTransactionTest < TransactionTest
151
+ def setup
152
+ @allow_concurrency = ActiveRecord::Base.allow_concurrency
153
+ ActiveRecord::Base.allow_concurrency = true
154
+ super
155
+ end
156
+
157
+ def teardown
158
+ super
159
+ ActiveRecord::Base.allow_concurrency = @allow_concurrency
160
+ end
161
+
162
+ # This will cause transactions to overlap and fail unless they are performed on
163
+ # separate database connections.
164
+ def test_transaction_per_thread
165
+ assert_nothing_raised do
166
+ threads = (1..3).map do
167
+ Thread.new do
168
+ Topic.transaction do
169
+ topic = Topic.find(1)
170
+ topic.approved = !topic.approved?
171
+ topic.save!
172
+ topic.approved = !topic.approved?
173
+ topic.save!
174
+ end
175
+ end
176
+ end
177
+
178
+ threads.each { |t| t.join }
179
+ end
180
+ end
181
+
182
+ # Test for dirty reads among simultaneous transactions.
183
+ def test_transaction_isolation__read_committed
184
+ # Should be invariant.
185
+ original_salary = Developer.find(1).salary
186
+ temporary_salary = 200000
187
+
188
+ assert_nothing_raised do
189
+ threads = (1..3).map do
190
+ Thread.new do
191
+ Developer.transaction do
192
+ # Expect original salary.
193
+ dev = Developer.find(1)
194
+ assert_equal original_salary, dev.salary
195
+
196
+ dev.salary = temporary_salary
197
+ dev.save!
198
+
199
+ # Expect temporary salary.
200
+ dev = Developer.find(1)
201
+ assert_equal temporary_salary, dev.salary
202
+
203
+ dev.salary = original_salary
204
+ dev.save!
205
+
206
+ # Expect original salary.
207
+ dev = Developer.find(1)
208
+ assert_equal original_salary, dev.salary
209
+ end
210
+ end
211
+ end
212
+
213
+ # Keep our eyes peeled.
214
+ threads << Thread.new do
215
+ 10.times do
216
+ sleep 0.05
217
+ Developer.transaction do
218
+ # Always expect original salary.
219
+ assert_equal original_salary, Developer.find(1).salary
220
+ end
221
+ end
222
+ end
223
+
224
+ threads.each { |t| t.join }
225
+ end
226
+
227
+ assert_equal original_salary, Developer.find(1).salary
228
+ end
229
+ end
230
+ end