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.
- data/CHANGELOG +3043 -0
- data/README +360 -0
- data/RUNNING_UNIT_TESTS +64 -0
- data/Rakefile +226 -0
- data/examples/associations.png +0 -0
- data/examples/associations.rb +87 -0
- data/examples/shared_setup.rb +15 -0
- data/examples/validation.rb +85 -0
- data/install.rb +30 -0
- data/lib/active_record.rb +85 -0
- data/lib/active_record/acts/list.rb +244 -0
- data/lib/active_record/acts/nested_set.rb +211 -0
- data/lib/active_record/acts/tree.rb +89 -0
- data/lib/active_record/aggregations.rb +191 -0
- data/lib/active_record/associations.rb +1637 -0
- data/lib/active_record/associations/association_collection.rb +190 -0
- data/lib/active_record/associations/association_proxy.rb +158 -0
- data/lib/active_record/associations/belongs_to_association.rb +56 -0
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +50 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +169 -0
- data/lib/active_record/associations/has_many_association.rb +210 -0
- data/lib/active_record/associations/has_many_through_association.rb +247 -0
- data/lib/active_record/associations/has_one_association.rb +80 -0
- data/lib/active_record/attribute_methods.rb +75 -0
- data/lib/active_record/base.rb +2164 -0
- data/lib/active_record/calculations.rb +270 -0
- data/lib/active_record/callbacks.rb +367 -0
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +279 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +130 -0
- data/lib/active_record/connection_adapters/abstract/quoting.rb +58 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +343 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +310 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +161 -0
- data/lib/active_record/connection_adapters/db2_adapter.rb +228 -0
- data/lib/active_record/connection_adapters/firebird_adapter.rb +728 -0
- data/lib/active_record/connection_adapters/frontbase_adapter.rb +861 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +414 -0
- data/lib/active_record/connection_adapters/openbase_adapter.rb +350 -0
- data/lib/active_record/connection_adapters/oracle_adapter.rb +689 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +584 -0
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +407 -0
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +591 -0
- data/lib/active_record/connection_adapters/sybase_adapter.rb +662 -0
- data/lib/active_record/deprecated_associations.rb +104 -0
- data/lib/active_record/deprecated_finders.rb +44 -0
- data/lib/active_record/fixtures.rb +628 -0
- data/lib/active_record/locking/optimistic.rb +106 -0
- data/lib/active_record/locking/pessimistic.rb +77 -0
- data/lib/active_record/migration.rb +394 -0
- data/lib/active_record/observer.rb +178 -0
- data/lib/active_record/query_cache.rb +64 -0
- data/lib/active_record/reflection.rb +222 -0
- data/lib/active_record/schema.rb +58 -0
- data/lib/active_record/schema_dumper.rb +149 -0
- data/lib/active_record/timestamp.rb +51 -0
- data/lib/active_record/transactions.rb +136 -0
- data/lib/active_record/validations.rb +843 -0
- data/lib/active_record/vendor/db2.rb +362 -0
- data/lib/active_record/vendor/mysql.rb +1214 -0
- data/lib/active_record/vendor/simple.rb +693 -0
- data/lib/active_record/version.rb +9 -0
- data/lib/active_record/wrappers/yaml_wrapper.rb +15 -0
- data/lib/active_record/wrappings.rb +58 -0
- data/lib/active_record/xml_serialization.rb +308 -0
- data/test/aaa_create_tables_test.rb +59 -0
- data/test/abstract_unit.rb +77 -0
- data/test/active_schema_test_mysql.rb +31 -0
- data/test/adapter_test.rb +87 -0
- data/test/adapter_test_sqlserver.rb +81 -0
- data/test/aggregations_test.rb +95 -0
- data/test/all.sh +8 -0
- data/test/ar_schema_test.rb +33 -0
- data/test/association_inheritance_reload.rb +14 -0
- data/test/associations/callbacks_test.rb +126 -0
- data/test/associations/cascaded_eager_loading_test.rb +138 -0
- data/test/associations/eager_test.rb +393 -0
- data/test/associations/extension_test.rb +42 -0
- data/test/associations/join_model_test.rb +497 -0
- data/test/associations_test.rb +1809 -0
- data/test/attribute_methods_test.rb +49 -0
- data/test/base_test.rb +1586 -0
- data/test/binary_test.rb +37 -0
- data/test/calculations_test.rb +219 -0
- data/test/callbacks_test.rb +377 -0
- data/test/class_inheritable_attributes_test.rb +32 -0
- data/test/column_alias_test.rb +17 -0
- data/test/connection_test_firebird.rb +8 -0
- data/test/connections/native_db2/connection.rb +25 -0
- data/test/connections/native_firebird/connection.rb +26 -0
- data/test/connections/native_frontbase/connection.rb +27 -0
- data/test/connections/native_mysql/connection.rb +24 -0
- data/test/connections/native_openbase/connection.rb +21 -0
- data/test/connections/native_oracle/connection.rb +27 -0
- data/test/connections/native_postgresql/connection.rb +23 -0
- data/test/connections/native_sqlite/connection.rb +34 -0
- data/test/connections/native_sqlite3/connection.rb +34 -0
- data/test/connections/native_sqlite3/in_memory_connection.rb +18 -0
- data/test/connections/native_sqlserver/connection.rb +23 -0
- data/test/connections/native_sqlserver_odbc/connection.rb +25 -0
- data/test/connections/native_sybase/connection.rb +23 -0
- data/test/copy_table_sqlite.rb +64 -0
- data/test/datatype_test_postgresql.rb +52 -0
- data/test/default_test_firebird.rb +16 -0
- data/test/defaults_test.rb +60 -0
- data/test/deprecated_associations_test.rb +396 -0
- data/test/deprecated_finder_test.rb +151 -0
- data/test/empty_date_time_test.rb +25 -0
- data/test/finder_test.rb +504 -0
- data/test/fixtures/accounts.yml +28 -0
- data/test/fixtures/author.rb +99 -0
- data/test/fixtures/author_favorites.yml +4 -0
- data/test/fixtures/authors.yml +7 -0
- data/test/fixtures/auto_id.rb +4 -0
- data/test/fixtures/bad_fixtures/attr_with_numeric_first_char +1 -0
- data/test/fixtures/bad_fixtures/attr_with_spaces +1 -0
- data/test/fixtures/bad_fixtures/blank_line +3 -0
- data/test/fixtures/bad_fixtures/duplicate_attributes +3 -0
- data/test/fixtures/bad_fixtures/missing_value +1 -0
- data/test/fixtures/binary.rb +2 -0
- data/test/fixtures/categories.yml +14 -0
- data/test/fixtures/categories/special_categories.yml +9 -0
- data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
- data/test/fixtures/categories_ordered.yml +7 -0
- data/test/fixtures/categories_posts.yml +23 -0
- data/test/fixtures/categorization.rb +5 -0
- data/test/fixtures/categorizations.yml +17 -0
- data/test/fixtures/category.rb +20 -0
- data/test/fixtures/column_name.rb +3 -0
- data/test/fixtures/comment.rb +23 -0
- data/test/fixtures/comments.yml +59 -0
- data/test/fixtures/companies.yml +55 -0
- data/test/fixtures/company.rb +107 -0
- data/test/fixtures/company_in_module.rb +59 -0
- data/test/fixtures/computer.rb +3 -0
- data/test/fixtures/computers.yml +4 -0
- data/test/fixtures/course.rb +3 -0
- data/test/fixtures/courses.yml +7 -0
- data/test/fixtures/customer.rb +55 -0
- data/test/fixtures/customers.yml +17 -0
- data/test/fixtures/db_definitions/db2.drop.sql +32 -0
- data/test/fixtures/db_definitions/db2.sql +231 -0
- data/test/fixtures/db_definitions/db22.drop.sql +2 -0
- data/test/fixtures/db_definitions/db22.sql +5 -0
- data/test/fixtures/db_definitions/firebird.drop.sql +63 -0
- data/test/fixtures/db_definitions/firebird.sql +304 -0
- data/test/fixtures/db_definitions/firebird2.drop.sql +2 -0
- data/test/fixtures/db_definitions/firebird2.sql +6 -0
- data/test/fixtures/db_definitions/frontbase.drop.sql +32 -0
- data/test/fixtures/db_definitions/frontbase.sql +268 -0
- data/test/fixtures/db_definitions/frontbase2.drop.sql +1 -0
- data/test/fixtures/db_definitions/frontbase2.sql +4 -0
- data/test/fixtures/db_definitions/mysql.drop.sql +32 -0
- data/test/fixtures/db_definitions/mysql.sql +234 -0
- data/test/fixtures/db_definitions/mysql2.drop.sql +2 -0
- data/test/fixtures/db_definitions/mysql2.sql +5 -0
- data/test/fixtures/db_definitions/openbase.drop.sql +2 -0
- data/test/fixtures/db_definitions/openbase.sql +302 -0
- data/test/fixtures/db_definitions/openbase2.drop.sql +2 -0
- data/test/fixtures/db_definitions/openbase2.sql +7 -0
- data/test/fixtures/db_definitions/oracle.drop.sql +65 -0
- data/test/fixtures/db_definitions/oracle.sql +325 -0
- data/test/fixtures/db_definitions/oracle2.drop.sql +2 -0
- data/test/fixtures/db_definitions/oracle2.sql +6 -0
- data/test/fixtures/db_definitions/postgresql.drop.sql +37 -0
- data/test/fixtures/db_definitions/postgresql.sql +263 -0
- data/test/fixtures/db_definitions/postgresql2.drop.sql +2 -0
- data/test/fixtures/db_definitions/postgresql2.sql +5 -0
- data/test/fixtures/db_definitions/schema.rb +60 -0
- data/test/fixtures/db_definitions/sqlite.drop.sql +32 -0
- data/test/fixtures/db_definitions/sqlite.sql +215 -0
- data/test/fixtures/db_definitions/sqlite2.drop.sql +2 -0
- data/test/fixtures/db_definitions/sqlite2.sql +5 -0
- data/test/fixtures/db_definitions/sqlserver.drop.sql +34 -0
- data/test/fixtures/db_definitions/sqlserver.sql +243 -0
- data/test/fixtures/db_definitions/sqlserver2.drop.sql +2 -0
- data/test/fixtures/db_definitions/sqlserver2.sql +5 -0
- data/test/fixtures/db_definitions/sybase.drop.sql +34 -0
- data/test/fixtures/db_definitions/sybase.sql +218 -0
- data/test/fixtures/db_definitions/sybase2.drop.sql +4 -0
- data/test/fixtures/db_definitions/sybase2.sql +5 -0
- data/test/fixtures/default.rb +2 -0
- data/test/fixtures/developer.rb +52 -0
- data/test/fixtures/developers.yml +21 -0
- data/test/fixtures/developers_projects.yml +17 -0
- data/test/fixtures/developers_projects/david_action_controller +3 -0
- data/test/fixtures/developers_projects/david_active_record +3 -0
- data/test/fixtures/developers_projects/jamis_active_record +2 -0
- data/test/fixtures/edge.rb +5 -0
- data/test/fixtures/edges.yml +6 -0
- data/test/fixtures/entrant.rb +3 -0
- data/test/fixtures/entrants.yml +14 -0
- data/test/fixtures/fk_test_has_fk.yml +3 -0
- data/test/fixtures/fk_test_has_pk.yml +2 -0
- data/test/fixtures/flowers.jpg +0 -0
- data/test/fixtures/funny_jokes.yml +10 -0
- data/test/fixtures/joke.rb +6 -0
- data/test/fixtures/keyboard.rb +3 -0
- data/test/fixtures/legacy_thing.rb +3 -0
- data/test/fixtures/legacy_things.yml +3 -0
- data/test/fixtures/migrations/1_people_have_last_names.rb +9 -0
- data/test/fixtures/migrations/2_we_need_reminders.rb +12 -0
- data/test/fixtures/migrations/3_innocent_jointable.rb +12 -0
- data/test/fixtures/migrations_with_decimal/1_give_me_big_numbers.rb +15 -0
- data/test/fixtures/migrations_with_duplicate/1_people_have_last_names.rb +9 -0
- data/test/fixtures/migrations_with_duplicate/2_we_need_reminders.rb +12 -0
- data/test/fixtures/migrations_with_duplicate/3_foo.rb +7 -0
- data/test/fixtures/migrations_with_duplicate/3_innocent_jointable.rb +12 -0
- data/test/fixtures/migrations_with_missing_versions/1000_people_have_middle_names.rb +9 -0
- data/test/fixtures/migrations_with_missing_versions/1_people_have_last_names.rb +9 -0
- data/test/fixtures/migrations_with_missing_versions/3_we_need_reminders.rb +12 -0
- data/test/fixtures/migrations_with_missing_versions/4_innocent_jointable.rb +12 -0
- data/test/fixtures/mixed_case_monkey.rb +3 -0
- data/test/fixtures/mixed_case_monkeys.yml +6 -0
- data/test/fixtures/mixin.rb +63 -0
- data/test/fixtures/mixins.yml +127 -0
- data/test/fixtures/movie.rb +5 -0
- data/test/fixtures/movies.yml +7 -0
- data/test/fixtures/naked/csv/accounts.csv +1 -0
- data/test/fixtures/naked/yml/accounts.yml +1 -0
- data/test/fixtures/naked/yml/companies.yml +1 -0
- data/test/fixtures/naked/yml/courses.yml +1 -0
- data/test/fixtures/order.rb +4 -0
- data/test/fixtures/people.yml +3 -0
- data/test/fixtures/person.rb +4 -0
- data/test/fixtures/post.rb +58 -0
- data/test/fixtures/posts.yml +48 -0
- data/test/fixtures/project.rb +27 -0
- data/test/fixtures/projects.yml +7 -0
- data/test/fixtures/reader.rb +4 -0
- data/test/fixtures/readers.yml +4 -0
- data/test/fixtures/reply.rb +37 -0
- data/test/fixtures/subject.rb +4 -0
- data/test/fixtures/subscriber.rb +6 -0
- data/test/fixtures/subscribers/first +2 -0
- data/test/fixtures/subscribers/second +2 -0
- data/test/fixtures/tag.rb +7 -0
- data/test/fixtures/tagging.rb +6 -0
- data/test/fixtures/taggings.yml +18 -0
- data/test/fixtures/tags.yml +7 -0
- data/test/fixtures/task.rb +3 -0
- data/test/fixtures/tasks.yml +7 -0
- data/test/fixtures/topic.rb +25 -0
- data/test/fixtures/topics.yml +22 -0
- data/test/fixtures/vertex.rb +9 -0
- data/test/fixtures/vertices.yml +4 -0
- data/test/fixtures_test.rb +401 -0
- data/test/inheritance_test.rb +205 -0
- data/test/lifecycle_test.rb +137 -0
- data/test/locking_test.rb +190 -0
- data/test/method_scoping_test.rb +416 -0
- data/test/migration_test.rb +768 -0
- data/test/migration_test_firebird.rb +124 -0
- data/test/mixin_nested_set_test.rb +196 -0
- data/test/mixin_test.rb +550 -0
- data/test/modules_test.rb +34 -0
- data/test/multiple_db_test.rb +60 -0
- data/test/pk_test.rb +104 -0
- data/test/readonly_test.rb +107 -0
- data/test/reflection_test.rb +159 -0
- data/test/schema_authorization_test_postgresql.rb +75 -0
- data/test/schema_dumper_test.rb +96 -0
- data/test/schema_test_postgresql.rb +64 -0
- data/test/synonym_test_oracle.rb +17 -0
- data/test/table_name_test_sqlserver.rb +23 -0
- data/test/threaded_connections_test.rb +48 -0
- data/test/transactions_test.rb +230 -0
- data/test/unconnected_test.rb +32 -0
- data/test/validations_test.rb +1097 -0
- data/test/xml_serialization_test.rb +125 -0
- metadata +365 -0
|
@@ -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
|