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,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