activerecord_csi 2.3.5.p6
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 +5858 -0
- data/README +351 -0
- data/RUNNING_UNIT_TESTS +36 -0
- data/Rakefile +270 -0
- data/examples/associations.png +0 -0
- data/examples/performance.rb +162 -0
- data/install.rb +30 -0
- data/lib/active_record/aggregations.rb +261 -0
- data/lib/active_record/association_preload.rb +389 -0
- data/lib/active_record/associations/association_collection.rb +475 -0
- data/lib/active_record/associations/association_proxy.rb +278 -0
- data/lib/active_record/associations/belongs_to_association.rb +76 -0
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +53 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +143 -0
- data/lib/active_record/associations/has_many_association.rb +122 -0
- data/lib/active_record/associations/has_many_through_association.rb +266 -0
- data/lib/active_record/associations/has_one_association.rb +133 -0
- data/lib/active_record/associations/has_one_through_association.rb +37 -0
- data/lib/active_record/associations.rb +2241 -0
- data/lib/active_record/attribute_methods.rb +388 -0
- data/lib/active_record/autosave_association.rb +364 -0
- data/lib/active_record/base.rb +3171 -0
- data/lib/active_record/batches.rb +81 -0
- data/lib/active_record/calculations.rb +311 -0
- data/lib/active_record/callbacks.rb +360 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +371 -0
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +139 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +289 -0
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +94 -0
- data/lib/active_record/connection_adapters/abstract/quoting.rb +69 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +722 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +434 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +241 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +630 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1113 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +34 -0
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +453 -0
- data/lib/active_record/dirty.rb +183 -0
- data/lib/active_record/dynamic_finder_match.rb +41 -0
- data/lib/active_record/dynamic_scope_match.rb +25 -0
- data/lib/active_record/fixtures.rb +996 -0
- data/lib/active_record/i18n_interpolation_deprecation.rb +26 -0
- data/lib/active_record/locale/en.yml +58 -0
- data/lib/active_record/locking/optimistic.rb +148 -0
- data/lib/active_record/locking/pessimistic.rb +55 -0
- data/lib/active_record/migration.rb +566 -0
- data/lib/active_record/named_scope.rb +192 -0
- data/lib/active_record/nested_attributes.rb +392 -0
- data/lib/active_record/observer.rb +197 -0
- data/lib/active_record/query_cache.rb +33 -0
- data/lib/active_record/reflection.rb +320 -0
- data/lib/active_record/schema.rb +51 -0
- data/lib/active_record/schema_dumper.rb +182 -0
- data/lib/active_record/serialization.rb +101 -0
- data/lib/active_record/serializers/json_serializer.rb +91 -0
- data/lib/active_record/serializers/xml_serializer.rb +357 -0
- data/lib/active_record/session_store.rb +326 -0
- data/lib/active_record/test_case.rb +66 -0
- data/lib/active_record/timestamp.rb +71 -0
- data/lib/active_record/transactions.rb +235 -0
- data/lib/active_record/validations.rb +1135 -0
- data/lib/active_record/version.rb +9 -0
- data/lib/active_record.rb +84 -0
- data/lib/activerecord.rb +2 -0
- data/test/assets/example.log +1 -0
- data/test/assets/flowers.jpg +0 -0
- data/test/cases/aaa_create_tables_test.rb +24 -0
- data/test/cases/active_schema_test_mysql.rb +100 -0
- data/test/cases/active_schema_test_postgresql.rb +24 -0
- data/test/cases/adapter_test.rb +145 -0
- data/test/cases/aggregations_test.rb +167 -0
- data/test/cases/ar_schema_test.rb +32 -0
- data/test/cases/associations/belongs_to_associations_test.rb +425 -0
- data/test/cases/associations/callbacks_test.rb +161 -0
- data/test/cases/associations/cascaded_eager_loading_test.rb +131 -0
- data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -0
- data/test/cases/associations/eager_load_nested_include_test.rb +130 -0
- data/test/cases/associations/eager_singularization_test.rb +145 -0
- data/test/cases/associations/eager_test.rb +834 -0
- data/test/cases/associations/extension_test.rb +62 -0
- data/test/cases/associations/habtm_join_table_test.rb +56 -0
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +822 -0
- data/test/cases/associations/has_many_associations_test.rb +1134 -0
- data/test/cases/associations/has_many_through_associations_test.rb +346 -0
- data/test/cases/associations/has_one_associations_test.rb +330 -0
- data/test/cases/associations/has_one_through_associations_test.rb +209 -0
- data/test/cases/associations/inner_join_association_test.rb +93 -0
- data/test/cases/associations/join_model_test.rb +712 -0
- data/test/cases/associations_test.rb +262 -0
- data/test/cases/attribute_methods_test.rb +305 -0
- data/test/cases/autosave_association_test.rb +1142 -0
- data/test/cases/base_test.rb +2154 -0
- data/test/cases/batches_test.rb +61 -0
- data/test/cases/binary_test.rb +30 -0
- data/test/cases/calculations_test.rb +348 -0
- data/test/cases/callbacks_observers_test.rb +38 -0
- data/test/cases/callbacks_test.rb +438 -0
- data/test/cases/class_inheritable_attributes_test.rb +32 -0
- data/test/cases/column_alias_test.rb +17 -0
- data/test/cases/column_definition_test.rb +70 -0
- data/test/cases/connection_pool_test.rb +25 -0
- data/test/cases/connection_test_firebird.rb +8 -0
- data/test/cases/connection_test_mysql.rb +64 -0
- data/test/cases/copy_table_test_sqlite.rb +80 -0
- data/test/cases/database_statements_test.rb +12 -0
- data/test/cases/datatype_test_postgresql.rb +204 -0
- data/test/cases/date_time_test.rb +37 -0
- data/test/cases/default_test_firebird.rb +16 -0
- data/test/cases/defaults_test.rb +111 -0
- data/test/cases/deprecated_finder_test.rb +30 -0
- data/test/cases/dirty_test.rb +316 -0
- data/test/cases/finder_respond_to_test.rb +76 -0
- data/test/cases/finder_test.rb +1066 -0
- data/test/cases/fixtures_test.rb +656 -0
- data/test/cases/helper.rb +68 -0
- data/test/cases/i18n_test.rb +46 -0
- data/test/cases/inheritance_test.rb +262 -0
- data/test/cases/invalid_date_test.rb +24 -0
- data/test/cases/json_serialization_test.rb +205 -0
- data/test/cases/lifecycle_test.rb +193 -0
- data/test/cases/locking_test.rb +304 -0
- data/test/cases/method_scoping_test.rb +704 -0
- data/test/cases/migration_test.rb +1523 -0
- data/test/cases/migration_test_firebird.rb +124 -0
- data/test/cases/mixin_test.rb +96 -0
- data/test/cases/modules_test.rb +81 -0
- data/test/cases/multiple_db_test.rb +85 -0
- data/test/cases/named_scope_test.rb +361 -0
- data/test/cases/nested_attributes_test.rb +581 -0
- data/test/cases/pk_test.rb +119 -0
- data/test/cases/pooled_connections_test.rb +103 -0
- data/test/cases/query_cache_test.rb +123 -0
- data/test/cases/readonly_test.rb +107 -0
- data/test/cases/reflection_test.rb +194 -0
- data/test/cases/reload_models_test.rb +22 -0
- data/test/cases/repair_helper.rb +50 -0
- data/test/cases/reserved_word_test_mysql.rb +176 -0
- data/test/cases/sanitize_test.rb +25 -0
- data/test/cases/schema_authorization_test_postgresql.rb +75 -0
- data/test/cases/schema_dumper_test.rb +211 -0
- data/test/cases/schema_test_postgresql.rb +178 -0
- data/test/cases/serialization_test.rb +47 -0
- data/test/cases/synonym_test_oracle.rb +17 -0
- data/test/cases/timestamp_test.rb +75 -0
- data/test/cases/transactions_test.rb +522 -0
- data/test/cases/unconnected_test.rb +32 -0
- data/test/cases/validations_i18n_test.rb +955 -0
- data/test/cases/validations_test.rb +1640 -0
- data/test/cases/xml_serialization_test.rb +240 -0
- data/test/config.rb +5 -0
- data/test/connections/jdbc_jdbcderby/connection.rb +18 -0
- data/test/connections/jdbc_jdbch2/connection.rb +18 -0
- data/test/connections/jdbc_jdbchsqldb/connection.rb +18 -0
- data/test/connections/jdbc_jdbcmysql/connection.rb +26 -0
- data/test/connections/jdbc_jdbcpostgresql/connection.rb +26 -0
- data/test/connections/jdbc_jdbcsqlite3/connection.rb +25 -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 +25 -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 +25 -0
- data/test/connections/native_sqlite/connection.rb +25 -0
- data/test/connections/native_sqlite3/connection.rb +25 -0
- data/test/connections/native_sqlite3/in_memory_connection.rb +18 -0
- data/test/connections/native_sybase/connection.rb +23 -0
- data/test/fixtures/accounts.yml +29 -0
- data/test/fixtures/all/developers.yml +0 -0
- data/test/fixtures/all/people.csv +0 -0
- data/test/fixtures/all/tasks.yml +0 -0
- data/test/fixtures/author_addresses.yml +5 -0
- data/test/fixtures/author_favorites.yml +4 -0
- data/test/fixtures/authors.yml +9 -0
- data/test/fixtures/binaries.yml +132 -0
- data/test/fixtures/books.yml +7 -0
- data/test/fixtures/categories/special_categories.yml +9 -0
- data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
- data/test/fixtures/categories.yml +14 -0
- data/test/fixtures/categories_ordered.yml +7 -0
- data/test/fixtures/categories_posts.yml +23 -0
- data/test/fixtures/categorizations.yml +17 -0
- data/test/fixtures/clubs.yml +6 -0
- data/test/fixtures/comments.yml +59 -0
- data/test/fixtures/companies.yml +56 -0
- data/test/fixtures/computers.yml +4 -0
- data/test/fixtures/courses.yml +7 -0
- data/test/fixtures/customers.yml +26 -0
- data/test/fixtures/developers.yml +21 -0
- data/test/fixtures/developers_projects.yml +17 -0
- data/test/fixtures/edges.yml +6 -0
- data/test/fixtures/entrants.yml +14 -0
- data/test/fixtures/fixture_database.sqlite3 +0 -0
- data/test/fixtures/fixture_database_2.sqlite3 +0 -0
- data/test/fixtures/fk_test_has_fk.yml +3 -0
- data/test/fixtures/fk_test_has_pk.yml +2 -0
- data/test/fixtures/funny_jokes.yml +10 -0
- data/test/fixtures/items.yml +4 -0
- data/test/fixtures/jobs.yml +7 -0
- data/test/fixtures/legacy_things.yml +3 -0
- data/test/fixtures/mateys.yml +4 -0
- data/test/fixtures/member_types.yml +6 -0
- data/test/fixtures/members.yml +6 -0
- data/test/fixtures/memberships.yml +20 -0
- data/test/fixtures/minimalistics.yml +2 -0
- data/test/fixtures/mixed_case_monkeys.yml +6 -0
- data/test/fixtures/mixins.yml +29 -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/organizations.yml +5 -0
- data/test/fixtures/owners.yml +7 -0
- data/test/fixtures/parrots.yml +27 -0
- data/test/fixtures/parrots_pirates.yml +7 -0
- data/test/fixtures/people.yml +15 -0
- data/test/fixtures/pets.yml +14 -0
- data/test/fixtures/pirates.yml +9 -0
- data/test/fixtures/posts.yml +52 -0
- data/test/fixtures/price_estimates.yml +7 -0
- data/test/fixtures/projects.yml +7 -0
- data/test/fixtures/readers.yml +9 -0
- data/test/fixtures/references.yml +17 -0
- data/test/fixtures/reserved_words/distinct.yml +5 -0
- data/test/fixtures/reserved_words/distincts_selects.yml +11 -0
- data/test/fixtures/reserved_words/group.yml +14 -0
- data/test/fixtures/reserved_words/select.yml +8 -0
- data/test/fixtures/reserved_words/values.yml +7 -0
- data/test/fixtures/ships.yml +5 -0
- data/test/fixtures/sponsors.yml +9 -0
- data/test/fixtures/subscribers.yml +7 -0
- data/test/fixtures/subscriptions.yml +12 -0
- data/test/fixtures/taggings.yml +28 -0
- data/test/fixtures/tags.yml +7 -0
- data/test/fixtures/tasks.yml +7 -0
- data/test/fixtures/topics.yml +42 -0
- data/test/fixtures/toys.yml +4 -0
- data/test/fixtures/treasures.yml +10 -0
- data/test/fixtures/vertices.yml +4 -0
- data/test/fixtures/warehouse-things.yml +3 -0
- data/test/migrations/broken/100_migration_that_raises_exception.rb +10 -0
- data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -0
- data/test/migrations/duplicate/1_people_have_last_names.rb +9 -0
- data/test/migrations/duplicate/2_we_need_reminders.rb +12 -0
- data/test/migrations/duplicate/3_foo.rb +7 -0
- data/test/migrations/duplicate/3_innocent_jointable.rb +12 -0
- data/test/migrations/duplicate_names/20080507052938_chunky.rb +7 -0
- data/test/migrations/duplicate_names/20080507053028_chunky.rb +7 -0
- data/test/migrations/interleaved/pass_1/3_innocent_jointable.rb +12 -0
- data/test/migrations/interleaved/pass_2/1_people_have_last_names.rb +9 -0
- data/test/migrations/interleaved/pass_2/3_innocent_jointable.rb +12 -0
- data/test/migrations/interleaved/pass_3/1_people_have_last_names.rb +9 -0
- data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +8 -0
- data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +12 -0
- data/test/migrations/missing/1000_people_have_middle_names.rb +9 -0
- data/test/migrations/missing/1_people_have_last_names.rb +9 -0
- data/test/migrations/missing/3_we_need_reminders.rb +12 -0
- data/test/migrations/missing/4_innocent_jointable.rb +12 -0
- data/test/migrations/valid/1_people_have_last_names.rb +9 -0
- data/test/migrations/valid/2_we_need_reminders.rb +12 -0
- data/test/migrations/valid/3_innocent_jointable.rb +12 -0
- data/test/models/author.rb +146 -0
- data/test/models/auto_id.rb +4 -0
- data/test/models/binary.rb +2 -0
- data/test/models/bird.rb +3 -0
- data/test/models/book.rb +4 -0
- data/test/models/categorization.rb +5 -0
- data/test/models/category.rb +34 -0
- data/test/models/citation.rb +6 -0
- data/test/models/club.rb +13 -0
- data/test/models/column_name.rb +3 -0
- data/test/models/comment.rb +29 -0
- data/test/models/company.rb +171 -0
- data/test/models/company_in_module.rb +61 -0
- data/test/models/computer.rb +3 -0
- data/test/models/contact.rb +16 -0
- data/test/models/contract.rb +5 -0
- data/test/models/course.rb +3 -0
- data/test/models/customer.rb +73 -0
- data/test/models/default.rb +2 -0
- data/test/models/developer.rb +101 -0
- data/test/models/edge.rb +5 -0
- data/test/models/entrant.rb +3 -0
- data/test/models/essay.rb +3 -0
- data/test/models/event.rb +3 -0
- data/test/models/guid.rb +2 -0
- data/test/models/item.rb +7 -0
- data/test/models/job.rb +5 -0
- data/test/models/joke.rb +3 -0
- data/test/models/keyboard.rb +3 -0
- data/test/models/legacy_thing.rb +3 -0
- data/test/models/matey.rb +4 -0
- data/test/models/member.rb +12 -0
- data/test/models/member_detail.rb +5 -0
- data/test/models/member_type.rb +3 -0
- data/test/models/membership.rb +9 -0
- data/test/models/minimalistic.rb +2 -0
- data/test/models/mixed_case_monkey.rb +3 -0
- data/test/models/movie.rb +5 -0
- data/test/models/order.rb +4 -0
- data/test/models/organization.rb +6 -0
- data/test/models/owner.rb +5 -0
- data/test/models/parrot.rb +16 -0
- data/test/models/person.rb +16 -0
- data/test/models/pet.rb +5 -0
- data/test/models/pirate.rb +70 -0
- data/test/models/post.rb +100 -0
- data/test/models/price_estimate.rb +3 -0
- data/test/models/project.rb +30 -0
- data/test/models/reader.rb +4 -0
- data/test/models/reference.rb +4 -0
- data/test/models/reply.rb +46 -0
- data/test/models/ship.rb +10 -0
- data/test/models/ship_part.rb +5 -0
- data/test/models/sponsor.rb +4 -0
- data/test/models/subject.rb +4 -0
- data/test/models/subscriber.rb +8 -0
- data/test/models/subscription.rb +4 -0
- data/test/models/tag.rb +7 -0
- data/test/models/tagging.rb +10 -0
- data/test/models/task.rb +3 -0
- data/test/models/topic.rb +80 -0
- data/test/models/toy.rb +6 -0
- data/test/models/treasure.rb +8 -0
- data/test/models/vertex.rb +9 -0
- data/test/models/warehouse_thing.rb +5 -0
- data/test/schema/mysql_specific_schema.rb +24 -0
- data/test/schema/postgresql_specific_schema.rb +114 -0
- data/test/schema/schema.rb +493 -0
- data/test/schema/schema2.rb +6 -0
- data/test/schema/sqlite_specific_schema.rb +25 -0
- metadata +420 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
require 'stringio'
|
|
2
|
+
require 'bigdecimal'
|
|
3
|
+
|
|
4
|
+
module ActiveRecord
|
|
5
|
+
# This class is used to dump the database schema for some connection to some
|
|
6
|
+
# output format (i.e., ActiveRecord::Schema).
|
|
7
|
+
class SchemaDumper #:nodoc:
|
|
8
|
+
private_class_method :new
|
|
9
|
+
|
|
10
|
+
##
|
|
11
|
+
# :singleton-method:
|
|
12
|
+
# A list of tables which should not be dumped to the schema.
|
|
13
|
+
# Acceptable values are strings as well as regexp.
|
|
14
|
+
# This setting is only used if ActiveRecord::Base.schema_format == :ruby
|
|
15
|
+
cattr_accessor :ignore_tables
|
|
16
|
+
@@ignore_tables = []
|
|
17
|
+
|
|
18
|
+
def self.dump(connection=ActiveRecord::Base.connection, stream=STDOUT)
|
|
19
|
+
new(connection).dump(stream)
|
|
20
|
+
stream
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def dump(stream)
|
|
24
|
+
header(stream)
|
|
25
|
+
tables(stream)
|
|
26
|
+
trailer(stream)
|
|
27
|
+
stream
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def initialize(connection)
|
|
33
|
+
@connection = connection
|
|
34
|
+
@types = @connection.native_database_types
|
|
35
|
+
@version = Migrator::current_version rescue nil
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def header(stream)
|
|
39
|
+
define_params = @version ? ":version => #{@version}" : ""
|
|
40
|
+
|
|
41
|
+
stream.puts <<HEADER
|
|
42
|
+
# This file is auto-generated from the current state of the database. Instead of editing this file,
|
|
43
|
+
# please use the migrations feature of Active Record to incrementally modify your database, and
|
|
44
|
+
# then regenerate this schema definition.
|
|
45
|
+
#
|
|
46
|
+
# Note that this schema.rb definition is the authoritative source for your database schema. If you need
|
|
47
|
+
# to create the application database on another system, you should be using db:schema:load, not running
|
|
48
|
+
# all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
|
49
|
+
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
|
50
|
+
#
|
|
51
|
+
# It's strongly recommended to check this file into your version control system.
|
|
52
|
+
|
|
53
|
+
ActiveRecord::Schema.define(#{define_params}) do
|
|
54
|
+
|
|
55
|
+
HEADER
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def trailer(stream)
|
|
59
|
+
stream.puts "end"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def tables(stream)
|
|
63
|
+
@connection.tables.sort.each do |tbl|
|
|
64
|
+
next if ['schema_migrations', ignore_tables].flatten.any? do |ignored|
|
|
65
|
+
case ignored
|
|
66
|
+
when String; tbl == ignored
|
|
67
|
+
when Regexp; tbl =~ ignored
|
|
68
|
+
else
|
|
69
|
+
raise StandardError, 'ActiveRecord::SchemaDumper.ignore_tables accepts an array of String and / or Regexp values.'
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
table(tbl, stream)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def table(table, stream)
|
|
77
|
+
columns = @connection.columns(table)
|
|
78
|
+
begin
|
|
79
|
+
tbl = StringIO.new
|
|
80
|
+
|
|
81
|
+
# first dump primary key column
|
|
82
|
+
if @connection.respond_to?(:pk_and_sequence_for)
|
|
83
|
+
pk, pk_seq = @connection.pk_and_sequence_for(table)
|
|
84
|
+
elsif @connection.respond_to?(:primary_key)
|
|
85
|
+
pk = @connection.primary_key(table)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
tbl.print " create_table #{table.inspect}"
|
|
89
|
+
if columns.detect { |c| c.name == pk }
|
|
90
|
+
if pk != 'id'
|
|
91
|
+
tbl.print %Q(, :primary_key => "#{pk}")
|
|
92
|
+
end
|
|
93
|
+
else
|
|
94
|
+
tbl.print ", :id => false"
|
|
95
|
+
end
|
|
96
|
+
tbl.print ", :force => true"
|
|
97
|
+
tbl.puts " do |t|"
|
|
98
|
+
|
|
99
|
+
# then dump all non-primary key columns
|
|
100
|
+
column_specs = columns.map do |column|
|
|
101
|
+
raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" if @types[column.type].nil?
|
|
102
|
+
next if column.name == pk
|
|
103
|
+
spec = {}
|
|
104
|
+
spec[:name] = column.name.inspect
|
|
105
|
+
spec[:type] = column.type.to_s
|
|
106
|
+
spec[:limit] = column.limit.inspect if column.limit != @types[column.type][:limit] && column.type != :decimal
|
|
107
|
+
spec[:precision] = column.precision.inspect if !column.precision.nil?
|
|
108
|
+
spec[:scale] = column.scale.inspect if !column.scale.nil?
|
|
109
|
+
spec[:null] = 'false' if !column.null
|
|
110
|
+
spec[:default] = default_string(column.default) if column.has_default?
|
|
111
|
+
(spec.keys - [:name, :type]).each{ |k| spec[k].insert(0, "#{k.inspect} => ")}
|
|
112
|
+
spec
|
|
113
|
+
end.compact
|
|
114
|
+
|
|
115
|
+
# find all migration keys used in this table
|
|
116
|
+
keys = [:name, :limit, :precision, :scale, :default, :null] & column_specs.map(&:keys).flatten
|
|
117
|
+
|
|
118
|
+
# figure out the lengths for each column based on above keys
|
|
119
|
+
lengths = keys.map{ |key| column_specs.map{ |spec| spec[key] ? spec[key].length + 2 : 0 }.max }
|
|
120
|
+
|
|
121
|
+
# the string we're going to sprintf our values against, with standardized column widths
|
|
122
|
+
format_string = lengths.map{ |len| "%-#{len}s" }
|
|
123
|
+
|
|
124
|
+
# find the max length for the 'type' column, which is special
|
|
125
|
+
type_length = column_specs.map{ |column| column[:type].length }.max
|
|
126
|
+
|
|
127
|
+
# add column type definition to our format string
|
|
128
|
+
format_string.unshift " t.%-#{type_length}s "
|
|
129
|
+
|
|
130
|
+
format_string *= ''
|
|
131
|
+
|
|
132
|
+
column_specs.each do |colspec|
|
|
133
|
+
values = keys.zip(lengths).map{ |key, len| colspec.key?(key) ? colspec[key] + ", " : " " * len }
|
|
134
|
+
values.unshift colspec[:type]
|
|
135
|
+
tbl.print((format_string % values).gsub(/,\s*$/, ''))
|
|
136
|
+
tbl.puts
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
tbl.puts " end"
|
|
140
|
+
tbl.puts
|
|
141
|
+
|
|
142
|
+
indexes(table, tbl)
|
|
143
|
+
|
|
144
|
+
tbl.rewind
|
|
145
|
+
stream.print tbl.read
|
|
146
|
+
rescue => e
|
|
147
|
+
stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}"
|
|
148
|
+
stream.puts "# #{e.message}"
|
|
149
|
+
stream.puts
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
stream
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def default_string(value)
|
|
156
|
+
case value
|
|
157
|
+
when BigDecimal
|
|
158
|
+
value.to_s
|
|
159
|
+
when Date, DateTime, Time
|
|
160
|
+
"'" + value.to_s(:db) + "'"
|
|
161
|
+
else
|
|
162
|
+
value.inspect
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def indexes(table, stream)
|
|
167
|
+
if (indexes = @connection.indexes(table)).any?
|
|
168
|
+
add_index_statements = indexes.map do |index|
|
|
169
|
+
statment_parts = [ ('add_index ' + index.table.inspect) ]
|
|
170
|
+
statment_parts << index.columns.inspect
|
|
171
|
+
statment_parts << (':name => ' + index.name.inspect)
|
|
172
|
+
statment_parts << ':unique => true' if index.unique
|
|
173
|
+
|
|
174
|
+
' ' + statment_parts.join(', ')
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
stream.puts add_index_statements.sort.join("\n")
|
|
178
|
+
stream.puts
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
require 'active_support/json'
|
|
2
|
+
|
|
3
|
+
module ActiveRecord #:nodoc:
|
|
4
|
+
module Serialization
|
|
5
|
+
class Serializer #:nodoc:
|
|
6
|
+
attr_reader :options
|
|
7
|
+
|
|
8
|
+
def initialize(record, options = nil)
|
|
9
|
+
@record = record
|
|
10
|
+
@options = options ? options.dup : {}
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# To replicate the behavior in ActiveRecord#attributes,
|
|
14
|
+
# <tt>:except</tt> takes precedence over <tt>:only</tt>. If <tt>:only</tt> is not set
|
|
15
|
+
# for a N level model but is set for the N+1 level models,
|
|
16
|
+
# then because <tt>:except</tt> is set to a default value, the second
|
|
17
|
+
# level model can have both <tt>:except</tt> and <tt>:only</tt> set. So if
|
|
18
|
+
# <tt>:only</tt> is set, always delete <tt>:except</tt>.
|
|
19
|
+
def serializable_attribute_names
|
|
20
|
+
attribute_names = @record.attribute_names
|
|
21
|
+
|
|
22
|
+
if options[:only]
|
|
23
|
+
options.delete(:except)
|
|
24
|
+
attribute_names = attribute_names & Array(options[:only]).collect { |n| n.to_s }
|
|
25
|
+
else
|
|
26
|
+
options[:except] = Array(options[:except]) | Array(@record.class.inheritance_column)
|
|
27
|
+
attribute_names = attribute_names - options[:except].collect { |n| n.to_s }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
attribute_names
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def serializable_method_names
|
|
34
|
+
Array(options[:methods]).inject([]) do |method_attributes, name|
|
|
35
|
+
method_attributes << name if @record.respond_to?(name.to_s)
|
|
36
|
+
method_attributes
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def serializable_names
|
|
41
|
+
serializable_attribute_names + serializable_method_names
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Add associations specified via the <tt>:includes</tt> option.
|
|
45
|
+
# Expects a block that takes as arguments:
|
|
46
|
+
# +association+ - name of the association
|
|
47
|
+
# +records+ - the association record(s) to be serialized
|
|
48
|
+
# +opts+ - options for the association records
|
|
49
|
+
def add_includes(&block)
|
|
50
|
+
if include_associations = options.delete(:include)
|
|
51
|
+
base_only_or_except = { :except => options[:except],
|
|
52
|
+
:only => options[:only] }
|
|
53
|
+
|
|
54
|
+
include_has_options = include_associations.is_a?(Hash)
|
|
55
|
+
associations = include_has_options ? include_associations.keys : Array(include_associations)
|
|
56
|
+
|
|
57
|
+
for association in associations
|
|
58
|
+
records = case @record.class.reflect_on_association(association).macro
|
|
59
|
+
when :has_many, :has_and_belongs_to_many
|
|
60
|
+
@record.send(association).to_a
|
|
61
|
+
when :has_one, :belongs_to
|
|
62
|
+
@record.send(association)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
unless records.nil?
|
|
66
|
+
association_options = include_has_options ? include_associations[association] : base_only_or_except
|
|
67
|
+
opts = options.merge(association_options)
|
|
68
|
+
yield(association, records, opts)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
options[:include] = include_associations
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def serializable_record
|
|
77
|
+
returning(serializable_record = {}) do
|
|
78
|
+
serializable_names.each { |name| serializable_record[name] = @record.send(name) }
|
|
79
|
+
add_includes do |association, records, opts|
|
|
80
|
+
if records.is_a?(Enumerable)
|
|
81
|
+
serializable_record[association] = records.collect { |r| self.class.new(r, opts).serializable_record }
|
|
82
|
+
else
|
|
83
|
+
serializable_record[association] = self.class.new(records, opts).serializable_record
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def serialize
|
|
90
|
+
# overwrite to implement
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def to_s(&block)
|
|
94
|
+
serialize(&block)
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
require 'active_record/serializers/xml_serializer'
|
|
101
|
+
require 'active_record/serializers/json_serializer'
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
require 'active_support/json'
|
|
2
|
+
require 'active_support/core_ext/module/model_naming'
|
|
3
|
+
|
|
4
|
+
module ActiveRecord #:nodoc:
|
|
5
|
+
module Serialization
|
|
6
|
+
def self.included(base)
|
|
7
|
+
base.cattr_accessor :include_root_in_json, :instance_writer => false
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Returns a JSON string representing the model. Some configuration is
|
|
11
|
+
# available through +options+.
|
|
12
|
+
#
|
|
13
|
+
# The option <tt>ActiveRecord::Base.include_root_in_json</tt> controls the
|
|
14
|
+
# top-level behavior of to_json. In a new Rails application, it is set to
|
|
15
|
+
# <tt>true</tt> in initializers/new_rails_defaults.rb. When it is <tt>true</tt>,
|
|
16
|
+
# to_json will emit a single root node named after the object's type. For example:
|
|
17
|
+
#
|
|
18
|
+
# konata = User.find(1)
|
|
19
|
+
# ActiveRecord::Base.include_root_in_json = true
|
|
20
|
+
# konata.to_json
|
|
21
|
+
# # => { "user": {"id": 1, "name": "Konata Izumi", "age": 16,
|
|
22
|
+
# "created_at": "2006/08/01", "awesome": true} }
|
|
23
|
+
#
|
|
24
|
+
# ActiveRecord::Base.include_root_in_json = false
|
|
25
|
+
# konata.to_json
|
|
26
|
+
# # => {"id": 1, "name": "Konata Izumi", "age": 16,
|
|
27
|
+
# "created_at": "2006/08/01", "awesome": true}
|
|
28
|
+
#
|
|
29
|
+
# The remainder of the examples in this section assume include_root_in_json is set to
|
|
30
|
+
# <tt>false</tt>.
|
|
31
|
+
#
|
|
32
|
+
# Without any +options+, the returned JSON string will include all
|
|
33
|
+
# the model's attributes. For example:
|
|
34
|
+
#
|
|
35
|
+
# konata = User.find(1)
|
|
36
|
+
# konata.to_json
|
|
37
|
+
# # => {"id": 1, "name": "Konata Izumi", "age": 16,
|
|
38
|
+
# "created_at": "2006/08/01", "awesome": true}
|
|
39
|
+
#
|
|
40
|
+
# The <tt>:only</tt> and <tt>:except</tt> options can be used to limit the attributes
|
|
41
|
+
# included, and work similar to the +attributes+ method. For example:
|
|
42
|
+
#
|
|
43
|
+
# konata.to_json(:only => [ :id, :name ])
|
|
44
|
+
# # => {"id": 1, "name": "Konata Izumi"}
|
|
45
|
+
#
|
|
46
|
+
# konata.to_json(:except => [ :id, :created_at, :age ])
|
|
47
|
+
# # => {"name": "Konata Izumi", "awesome": true}
|
|
48
|
+
#
|
|
49
|
+
# To include any methods on the model, use <tt>:methods</tt>.
|
|
50
|
+
#
|
|
51
|
+
# konata.to_json(:methods => :permalink)
|
|
52
|
+
# # => {"id": 1, "name": "Konata Izumi", "age": 16,
|
|
53
|
+
# "created_at": "2006/08/01", "awesome": true,
|
|
54
|
+
# "permalink": "1-konata-izumi"}
|
|
55
|
+
#
|
|
56
|
+
# To include associations, use <tt>:include</tt>.
|
|
57
|
+
#
|
|
58
|
+
# konata.to_json(:include => :posts)
|
|
59
|
+
# # => {"id": 1, "name": "Konata Izumi", "age": 16,
|
|
60
|
+
# "created_at": "2006/08/01", "awesome": true,
|
|
61
|
+
# "posts": [{"id": 1, "author_id": 1, "title": "Welcome to the weblog"},
|
|
62
|
+
# {"id": 2, author_id: 1, "title": "So I was thinking"}]}
|
|
63
|
+
#
|
|
64
|
+
# 2nd level and higher order associations work as well:
|
|
65
|
+
#
|
|
66
|
+
# konata.to_json(:include => { :posts => {
|
|
67
|
+
# :include => { :comments => {
|
|
68
|
+
# :only => :body } },
|
|
69
|
+
# :only => :title } })
|
|
70
|
+
# # => {"id": 1, "name": "Konata Izumi", "age": 16,
|
|
71
|
+
# "created_at": "2006/08/01", "awesome": true,
|
|
72
|
+
# "posts": [{"comments": [{"body": "1st post!"}, {"body": "Second!"}],
|
|
73
|
+
# "title": "Welcome to the weblog"},
|
|
74
|
+
# {"comments": [{"body": "Don't think too hard"}],
|
|
75
|
+
# "title": "So I was thinking"}]}
|
|
76
|
+
def to_json(options = {})
|
|
77
|
+
super
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def as_json(options = nil) #:nodoc:
|
|
81
|
+
hash = Serializer.new(self, options).serializable_record
|
|
82
|
+
hash = { self.class.model_name.element => hash } if include_root_in_json
|
|
83
|
+
hash
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def from_json(json)
|
|
87
|
+
self.attributes = ActiveSupport::JSON.decode(json)
|
|
88
|
+
self
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|