activerecord_authorails 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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,9 @@
1
+ module ActiveRecord
2
+ module VERSION #:nodoc:
3
+ MAJOR = 1
4
+ MINOR = 15
5
+ TINY = 3
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1,15 @@
1
+ require 'yaml'
2
+
3
+ module ActiveRecord
4
+ module Wrappings #:nodoc:
5
+ class YamlWrapper < AbstractWrapper #:nodoc:
6
+ def wrap(attribute) attribute.to_yaml end
7
+ def unwrap(attribute) YAML::load(attribute) end
8
+ end
9
+
10
+ module ClassMethods #:nodoc:
11
+ # Wraps the attribute in Yaml encoding
12
+ def wrap_in_yaml(*attributes) wrap_with(YamlWrapper, attributes) end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,58 @@
1
+ module ActiveRecord
2
+ # A plugin framework for wrapping attribute values before they go in and unwrapping them after they go out of the database.
3
+ # This was intended primarily for YAML wrapping of arrays and hashes, but this behavior is now native in the Base class.
4
+ # So for now this framework is laying dormant until a need pops up.
5
+ module Wrappings #:nodoc:
6
+ module ClassMethods #:nodoc:
7
+ def wrap_with(wrapper, *attributes)
8
+ [ attributes ].flat.each { |attribute| wrapper.wrap(attribute) }
9
+ end
10
+ end
11
+
12
+ def self.included(base)
13
+ base.extend(ClassMethods)
14
+ end
15
+
16
+ class AbstractWrapper #:nodoc:
17
+ def self.wrap(attribute, record_binding) #:nodoc:
18
+ %w( before_save after_save after_initialize ).each do |callback|
19
+ eval "#{callback} #{name}.new('#{attribute}')", record_binding
20
+ end
21
+ end
22
+
23
+ def initialize(attribute) #:nodoc:
24
+ @attribute = attribute
25
+ end
26
+
27
+ def save_wrapped_attribute(record) #:nodoc:
28
+ if record.attribute_present?(@attribute)
29
+ record.send(
30
+ "write_attribute",
31
+ @attribute,
32
+ wrap(record.send("read_attribute", @attribute))
33
+ )
34
+ end
35
+ end
36
+
37
+ def load_wrapped_attribute(record) #:nodoc:
38
+ if record.attribute_present?(@attribute)
39
+ record.send(
40
+ "write_attribute",
41
+ @attribute,
42
+ unwrap(record.send("read_attribute", @attribute))
43
+ )
44
+ end
45
+ end
46
+
47
+ alias_method :before_save, :save_wrapped_attribute #:nodoc:
48
+ alias_method :after_save, :load_wrapped_attribute #:nodoc:
49
+ alias_method :after_initialize, :after_save #:nodoc:
50
+
51
+ # Overwrite to implement the logic that'll take the regular attribute and wrap it.
52
+ def wrap(attribute) end
53
+
54
+ # Overwrite to implement the logic that'll take the wrapped attribute and unwrap it.
55
+ def unwrap(attribute) end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,308 @@
1
+ module ActiveRecord #:nodoc:
2
+ module XmlSerialization
3
+ # Builds an XML document to represent the model. Some configuration is
4
+ # availble through +options+, however more complicated cases should use
5
+ # override ActiveRecord's to_xml.
6
+ #
7
+ # By default the generated XML document will include the processing
8
+ # instruction and all object's attributes. For example:
9
+ #
10
+ # <?xml version="1.0" encoding="UTF-8"?>
11
+ # <topic>
12
+ # <title>The First Topic</title>
13
+ # <author-name>David</author-name>
14
+ # <id type="integer">1</id>
15
+ # <approved type="boolean">false</approved>
16
+ # <replies-count type="integer">0</replies-count>
17
+ # <bonus-time type="datetime">2000-01-01T08:28:00+12:00</bonus-time>
18
+ # <written-on type="datetime">2003-07-16T09:28:00+1200</written-on>
19
+ # <content>Have a nice day</content>
20
+ # <author-email-address>david@loudthinking.com</author-email-address>
21
+ # <parent-id></parent-id>
22
+ # <last-read type="date">2004-04-15</last-read>
23
+ # </topic>
24
+ #
25
+ # This behavior can be controlled with :only, :except,
26
+ # :skip_instruct, :skip_types and :dasherize. The :only and
27
+ # :except options are the same as for the #attributes method.
28
+ # The default is to dasherize all column names, to disable this,
29
+ # set :dasherize to false. To not have the column type included
30
+ # in the XML output, set :skip_types to false.
31
+ #
32
+ # For instance:
33
+ #
34
+ # topic.to_xml(:skip_instruct => true, :except => [ :id, :bonus_time, :written_on, :replies_count ])
35
+ #
36
+ # <topic>
37
+ # <title>The First Topic</title>
38
+ # <author-name>David</author-name>
39
+ # <approved type="boolean">false</approved>
40
+ # <content>Have a nice day</content>
41
+ # <author-email-address>david@loudthinking.com</author-email-address>
42
+ # <parent-id></parent-id>
43
+ # <last-read type="date">2004-04-15</last-read>
44
+ # </topic>
45
+ #
46
+ # To include first level associations use :include
47
+ #
48
+ # firm.to_xml :include => [ :account, :clients ]
49
+ #
50
+ # <?xml version="1.0" encoding="UTF-8"?>
51
+ # <firm>
52
+ # <id type="integer">1</id>
53
+ # <rating type="integer">1</rating>
54
+ # <name>37signals</name>
55
+ # <clients>
56
+ # <client>
57
+ # <rating type="integer">1</rating>
58
+ # <name>Summit</name>
59
+ # </client>
60
+ # <client>
61
+ # <rating type="integer">1</rating>
62
+ # <name>Microsoft</name>
63
+ # </client>
64
+ # </clients>
65
+ # <account>
66
+ # <id type="integer">1</id>
67
+ # <credit-limit type="integer">50</credit-limit>
68
+ # </account>
69
+ # </firm>
70
+ #
71
+ # To include any methods on the object(s) being called use :methods
72
+ #
73
+ # firm.to_xml :methods => [ :calculated_earnings, :real_earnings ]
74
+ #
75
+ # <firm>
76
+ # # ... normal attributes as shown above ...
77
+ # <calculated-earnings>100000000000000000</calculated-earnings>
78
+ # <real-earnings>5</real-earnings>
79
+ # </firm>
80
+ #
81
+ # To call any Proc's on the object(s) use :procs. The Proc's
82
+ # are passed a modified version of the options hash that was
83
+ # given to #to_xml.
84
+ #
85
+ # proc = Proc.new { |options| options[:builder].tag!('abc', 'def') }
86
+ # firm.to_xml :procs => [ proc ]
87
+ #
88
+ # <firm>
89
+ # # ... normal attributes as shown above ...
90
+ # <abc>def</abc>
91
+ # </firm>
92
+ #
93
+ # You may override the to_xml method in your ActiveRecord::Base
94
+ # subclasses if you need to. The general form of doing this is
95
+ #
96
+ # class IHaveMyOwnXML < ActiveRecord::Base
97
+ # def to_xml(options = {})
98
+ # options[:indent] ||= 2
99
+ # xml = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
100
+ # xml.instruct! unless options[:skip_instruct]
101
+ # xml.level_one do
102
+ # xml.tag!(:second_level, 'content')
103
+ # end
104
+ # end
105
+ # end
106
+ def to_xml(options = {})
107
+ XmlSerializer.new(self, options).to_s
108
+ end
109
+ end
110
+
111
+ class XmlSerializer #:nodoc:
112
+ attr_reader :options
113
+
114
+ def initialize(record, options = {})
115
+ @record, @options = record, options.dup
116
+ end
117
+
118
+ def builder
119
+ @builder ||= begin
120
+ options[:indent] ||= 2
121
+ builder = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
122
+
123
+ unless options[:skip_instruct]
124
+ builder.instruct!
125
+ options[:skip_instruct] = true
126
+ end
127
+
128
+ builder
129
+ end
130
+ end
131
+
132
+ def root
133
+ root = (options[:root] || @record.class.to_s.underscore).to_s
134
+ dasherize? ? root.dasherize : root
135
+ end
136
+
137
+ def dasherize?
138
+ !options.has_key?(:dasherize) || options[:dasherize]
139
+ end
140
+
141
+
142
+ # To replicate the behavior in ActiveRecord#attributes,
143
+ # :except takes precedence over :only. If :only is not set
144
+ # for a N level model but is set for the N+1 level models,
145
+ # then because :except is set to a default value, the second
146
+ # level model can have both :except and :only set. So if
147
+ # :only is set, always delete :except.
148
+ def serializable_attributes
149
+ attribute_names = @record.attribute_names
150
+
151
+ if options[:only]
152
+ options.delete(:except)
153
+ attribute_names = attribute_names & Array(options[:only]).collect { |n| n.to_s }
154
+ else
155
+ options[:except] = Array(options[:except]) | Array(@record.class.inheritance_column)
156
+ attribute_names = attribute_names - options[:except].collect { |n| n.to_s }
157
+ end
158
+
159
+ attribute_names.collect { |name| Attribute.new(name, @record) }
160
+ end
161
+
162
+ def serializable_method_attributes
163
+ Array(options[:methods]).collect { |name| MethodAttribute.new(name.to_s, @record) }
164
+ end
165
+
166
+
167
+ def add_attributes
168
+ (serializable_attributes + serializable_method_attributes).each do |attribute|
169
+ add_tag(attribute)
170
+ end
171
+ end
172
+
173
+ def add_includes
174
+ if include_associations = options.delete(:include)
175
+ root_only_or_except = { :except => options[:except],
176
+ :only => options[:only] }
177
+
178
+ include_has_options = include_associations.is_a?(Hash)
179
+
180
+ for association in include_has_options ? include_associations.keys : Array(include_associations)
181
+ association_options = include_has_options ? include_associations[association] : root_only_or_except
182
+
183
+ opts = options.merge(association_options)
184
+
185
+ case @record.class.reflect_on_association(association).macro
186
+ when :has_many, :has_and_belongs_to_many
187
+ records = @record.send(association).to_a
188
+ unless records.empty?
189
+ tag = records.first.class.to_s.underscore.pluralize
190
+ tag = tag.dasherize if dasherize?
191
+
192
+ builder.tag!(tag) do
193
+ records.each { |r| r.to_xml(opts.merge(:root => association.to_s.singularize)) }
194
+ end
195
+ end
196
+ when :has_one, :belongs_to
197
+ if record = @record.send(association)
198
+ record.to_xml(opts.merge(:root => association))
199
+ end
200
+ end
201
+ end
202
+
203
+ options[:include] = include_associations
204
+ end
205
+ end
206
+
207
+ def add_procs
208
+ if procs = options.delete(:procs)
209
+ [ *procs ].each do |proc|
210
+ proc.call(options)
211
+ end
212
+ end
213
+ end
214
+
215
+
216
+ def add_tag(attribute)
217
+ builder.tag!(
218
+ dasherize? ? attribute.name.dasherize : attribute.name,
219
+ attribute.value.to_s,
220
+ attribute.decorations(!options[:skip_types])
221
+ )
222
+ end
223
+
224
+ def serialize
225
+ args = [root]
226
+ if options[:namespace]
227
+ args << {:xmlns=>options[:namespace]}
228
+ end
229
+
230
+ builder.tag!(*args) do
231
+ add_attributes
232
+ add_includes
233
+ add_procs
234
+ end
235
+ end
236
+
237
+ alias_method :to_s, :serialize
238
+
239
+ class Attribute #:nodoc:
240
+ attr_reader :name, :value, :type
241
+
242
+ def initialize(name, record)
243
+ @name, @record = name, record
244
+
245
+ @type = compute_type
246
+ @value = compute_value
247
+ end
248
+
249
+ # There is a significant speed improvement if the value
250
+ # does not need to be escaped, as #tag! escapes all values
251
+ # to ensure that valid XML is generated. For known binary
252
+ # values, it is at least an order of magnitude faster to
253
+ # Base64 encode binary values and directly put them in the
254
+ # output XML than to pass the original value or the Base64
255
+ # encoded value to the #tag! method. It definitely makes
256
+ # no sense to Base64 encode the value and then give it to
257
+ # #tag!, since that just adds additional overhead.
258
+ def needs_encoding?
259
+ ![ :binary, :date, :datetime, :boolean, :float, :integer ].include?(type)
260
+ end
261
+
262
+ def decorations(include_types = true)
263
+ decorations = {}
264
+
265
+ if type == :binary
266
+ decorations[:encoding] = 'base64'
267
+ end
268
+
269
+ if include_types && type != :string
270
+ decorations[:type] = type
271
+ end
272
+
273
+ decorations
274
+ end
275
+
276
+ protected
277
+ def compute_type
278
+ type = @record.class.columns_hash[name].type
279
+
280
+ case type
281
+ when :text
282
+ :string
283
+ when :time
284
+ :datetime
285
+ else
286
+ type
287
+ end
288
+ end
289
+
290
+ def compute_value
291
+ value = @record.send(name)
292
+
293
+ if formatter = Hash::XML_FORMATTING[type.to_s]
294
+ value ? formatter.call(value) : nil
295
+ else
296
+ value
297
+ end
298
+ end
299
+ end
300
+
301
+ class MethodAttribute < Attribute #:nodoc:
302
+ protected
303
+ def compute_type
304
+ Hash::XML_TYPE_NAMES[@record.send(name).class.name] || :string
305
+ end
306
+ end
307
+ end
308
+ end
@@ -0,0 +1,59 @@
1
+ # The filename begins with "aaa" to ensure this is the first test.
2
+ require 'abstract_unit'
3
+
4
+ class AAACreateTablesTest < Test::Unit::TestCase
5
+ self.use_transactional_fixtures = false
6
+
7
+ def setup
8
+ @base_path = "#{File.dirname(__FILE__)}/fixtures/db_definitions"
9
+ end
10
+
11
+ def test_drop_and_create_main_tables
12
+ recreate ActiveRecord::Base
13
+ assert true
14
+ end
15
+
16
+ def test_load_schema
17
+ if ActiveRecord::Base.connection.supports_migrations?
18
+ eval(File.read("#{File.dirname(__FILE__)}/fixtures/db_definitions/schema.rb"))
19
+ else
20
+ recreate ActiveRecord::Base, '3'
21
+ end
22
+ assert true
23
+ end
24
+
25
+ def test_drop_and_create_courses_table
26
+ recreate Course, '2'
27
+ assert true
28
+ end
29
+
30
+ private
31
+ def recreate(base, suffix = nil)
32
+ connection = base.connection
33
+ adapter_name = connection.adapter_name.downcase + suffix.to_s
34
+ execute_sql_file "#{@base_path}/#{adapter_name}.drop.sql", connection
35
+ execute_sql_file "#{@base_path}/#{adapter_name}.sql", connection
36
+ end
37
+
38
+ def execute_sql_file(path, connection)
39
+ # OpenBase has a different format for sql files
40
+ if current_adapter?(:OpenBaseAdapter) then
41
+ File.read(path).split("go").each_with_index do |sql, i|
42
+ begin
43
+ # OpenBase does not support comments embedded in sql
44
+ connection.execute(sql,"SQL statement ##{i}") unless sql.blank?
45
+ rescue ActiveRecord::StatementInvalid
46
+ #$stderr.puts "warning: #{$!}"
47
+ end
48
+ end
49
+ else
50
+ File.read(path).split(';').each_with_index do |sql, i|
51
+ begin
52
+ connection.execute("\n\n-- statement ##{i}\n#{sql}\n") unless sql.blank?
53
+ rescue ActiveRecord::StatementInvalid
54
+ #$stderr.puts "warning: #{$!}"
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end