activerecord 2.0.5 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- data/CHANGELOG +168 -6
- data/README +27 -22
- data/RUNNING_UNIT_TESTS +7 -4
- data/Rakefile +22 -25
- data/lib/active_record.rb +8 -2
- data/lib/active_record/aggregations.rb +21 -12
- data/lib/active_record/association_preload.rb +277 -0
- data/lib/active_record/associations.rb +481 -295
- data/lib/active_record/associations/association_collection.rb +162 -37
- data/lib/active_record/associations/association_proxy.rb +71 -7
- data/lib/active_record/associations/belongs_to_association.rb +5 -3
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +5 -6
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +12 -64
- data/lib/active_record/associations/has_many_association.rb +8 -73
- data/lib/active_record/associations/has_many_through_association.rb +68 -117
- data/lib/active_record/associations/has_one_association.rb +7 -5
- data/lib/active_record/associations/has_one_through_association.rb +28 -0
- data/lib/active_record/attribute_methods.rb +69 -19
- data/lib/active_record/base.rb +496 -275
- data/lib/active_record/calculations.rb +28 -21
- data/lib/active_record/callbacks.rb +9 -38
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +3 -2
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +2 -2
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +6 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +232 -45
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +141 -27
- data/lib/active_record/connection_adapters/abstract_adapter.rb +9 -13
- data/lib/active_record/connection_adapters/mysql_adapter.rb +57 -24
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +143 -42
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +18 -10
- data/lib/active_record/dirty.rb +158 -0
- data/lib/active_record/fixtures.rb +121 -156
- data/lib/active_record/locking/optimistic.rb +14 -11
- data/lib/active_record/locking/pessimistic.rb +2 -2
- data/lib/active_record/migration.rb +157 -77
- data/lib/active_record/named_scope.rb +163 -0
- data/lib/active_record/observer.rb +19 -5
- data/lib/active_record/reflection.rb +34 -14
- data/lib/active_record/schema.rb +7 -14
- data/lib/active_record/schema_dumper.rb +4 -4
- data/lib/active_record/serialization.rb +5 -5
- data/lib/active_record/serializers/json_serializer.rb +37 -28
- data/lib/active_record/serializers/xml_serializer.rb +52 -29
- data/lib/active_record/test_case.rb +36 -0
- data/lib/active_record/timestamp.rb +4 -4
- data/lib/active_record/transactions.rb +3 -3
- data/lib/active_record/validations.rb +182 -248
- data/lib/active_record/version.rb +2 -2
- data/test/{fixtures → assets}/example.log +0 -0
- data/test/{fixtures → assets}/flowers.jpg +0 -0
- data/test/cases/aaa_create_tables_test.rb +24 -0
- data/test/cases/active_schema_test_mysql.rb +95 -0
- data/test/cases/active_schema_test_postgresql.rb +24 -0
- data/test/{adapter_test.rb → cases/adapter_test.rb} +15 -14
- data/test/{adapter_test_sqlserver.rb → cases/adapter_test_sqlserver.rb} +95 -95
- data/test/{aggregations_test.rb → cases/aggregations_test.rb} +20 -20
- data/test/{ar_schema_test.rb → cases/ar_schema_test.rb} +6 -6
- data/test/cases/associations/belongs_to_associations_test.rb +412 -0
- data/test/{associations → cases/associations}/callbacks_test.rb +24 -10
- data/test/{associations → cases/associations}/cascaded_eager_loading_test.rb +18 -17
- data/test/cases/associations/eager_load_nested_include_test.rb +83 -0
- data/test/{associations → cases/associations}/eager_singularization_test.rb +5 -5
- data/test/{associations → cases/associations}/eager_test.rb +216 -51
- data/test/{associations → cases/associations}/extension_test.rb +8 -8
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +684 -0
- data/test/cases/associations/has_many_associations_test.rb +932 -0
- data/test/cases/associations/has_many_through_associations_test.rb +190 -0
- data/test/cases/associations/has_one_associations_test.rb +323 -0
- data/test/cases/associations/has_one_through_associations_test.rb +74 -0
- data/test/{associations → cases/associations}/inner_join_association_test.rb +20 -20
- data/test/{associations → cases/associations}/join_model_test.rb +175 -35
- data/test/cases/associations_test.rb +262 -0
- data/test/{attribute_methods_test.rb → cases/attribute_methods_test.rb} +103 -11
- data/test/{base_test.rb → cases/base_test.rb} +338 -191
- data/test/{binary_test.rb → cases/binary_test.rb} +6 -4
- data/test/{calculations_test.rb → cases/calculations_test.rb} +35 -23
- data/test/{callbacks_test.rb → cases/callbacks_test.rb} +7 -7
- data/test/{class_inheritable_attributes_test.rb → cases/class_inheritable_attributes_test.rb} +3 -3
- data/test/{column_alias_test.rb → cases/column_alias_test.rb} +3 -3
- data/test/{connection_test_firebird.rb → cases/connection_test_firebird.rb} +2 -2
- data/test/{connection_test_mysql.rb → cases/connection_test_mysql.rb} +2 -2
- data/test/{copy_table_test_sqlite.rb → cases/copy_table_test_sqlite.rb} +13 -13
- data/test/{datatype_test_postgresql.rb → cases/datatype_test_postgresql.rb} +8 -8
- data/test/{date_time_test.rb → cases/date_time_test.rb} +5 -5
- data/test/{default_test_firebird.rb → cases/default_test_firebird.rb} +3 -3
- data/test/{defaults_test.rb → cases/defaults_test.rb} +8 -6
- data/test/{deprecated_finder_test.rb → cases/deprecated_finder_test.rb} +3 -3
- data/test/cases/dirty_test.rb +163 -0
- data/test/cases/finder_respond_to_test.rb +76 -0
- data/test/{finder_test.rb → cases/finder_test.rb} +266 -33
- data/test/{fixtures_test.rb → cases/fixtures_test.rb} +88 -72
- data/test/cases/helper.rb +47 -0
- data/test/{inheritance_test.rb → cases/inheritance_test.rb} +61 -17
- data/test/cases/invalid_date_test.rb +24 -0
- data/test/{json_serialization_test.rb → cases/json_serialization_test.rb} +36 -11
- data/test/{lifecycle_test.rb → cases/lifecycle_test.rb} +16 -13
- data/test/{locking_test.rb → cases/locking_test.rb} +17 -10
- data/test/{method_scoping_test.rb → cases/method_scoping_test.rb} +75 -39
- data/test/{migration_test.rb → cases/migration_test.rb} +420 -80
- data/test/{migration_test_firebird.rb → cases/migration_test_firebird.rb} +3 -3
- data/test/{mixin_test.rb → cases/mixin_test.rb} +7 -6
- data/test/{modules_test.rb → cases/modules_test.rb} +11 -6
- data/test/{multiple_db_test.rb → cases/multiple_db_test.rb} +5 -5
- data/test/cases/named_scope_test.rb +157 -0
- data/test/{pk_test.rb → cases/pk_test.rb} +10 -10
- data/test/{query_cache_test.rb → cases/query_cache_test.rb} +12 -10
- data/test/{readonly_test.rb → cases/readonly_test.rb} +11 -11
- data/test/{reflection_test.rb → cases/reflection_test.rb} +15 -14
- data/test/{reserved_word_test_mysql.rb → cases/reserved_word_test_mysql.rb} +4 -5
- data/test/{schema_authorization_test_postgresql.rb → cases/schema_authorization_test_postgresql.rb} +5 -5
- data/test/cases/schema_dumper_test.rb +138 -0
- data/test/cases/schema_test_postgresql.rb +102 -0
- data/test/{serialization_test.rb → cases/serialization_test.rb} +7 -7
- data/test/{synonym_test_oracle.rb → cases/synonym_test_oracle.rb} +5 -5
- data/test/{table_name_test_sqlserver.rb → cases/table_name_test_sqlserver.rb} +3 -3
- data/test/{threaded_connections_test.rb → cases/threaded_connections_test.rb} +7 -7
- data/test/{transactions_test.rb → cases/transactions_test.rb} +31 -5
- data/test/{unconnected_test.rb → cases/unconnected_test.rb} +2 -2
- data/test/{validations_test.rb → cases/validations_test.rb} +141 -39
- data/test/{xml_serialization_test.rb → cases/xml_serialization_test.rb} +12 -12
- data/test/config.rb +5 -0
- data/test/connections/native_db2/connection.rb +1 -1
- data/test/connections/native_firebird/connection.rb +1 -1
- data/test/connections/native_frontbase/connection.rb +1 -1
- data/test/connections/native_mysql/connection.rb +1 -1
- data/test/connections/native_openbase/connection.rb +1 -1
- data/test/connections/native_oracle/connection.rb +1 -1
- data/test/connections/native_postgresql/connection.rb +1 -3
- data/test/connections/native_sqlite/connection.rb +2 -2
- data/test/connections/native_sqlite3/connection.rb +2 -2
- data/test/connections/native_sqlite3/in_memory_connection.rb +3 -3
- data/test/connections/native_sybase/connection.rb +1 -1
- data/test/fixtures/author_addresses.yml +5 -0
- data/test/fixtures/authors.yml +2 -0
- data/test/fixtures/clubs.yml +6 -0
- data/test/fixtures/jobs.yml +7 -0
- data/test/fixtures/members.yml +4 -0
- data/test/fixtures/memberships.yml +20 -0
- data/test/fixtures/owners.yml +7 -0
- data/test/fixtures/people.yml +4 -1
- data/test/fixtures/pets.yml +14 -0
- data/test/fixtures/posts.yml +1 -0
- data/test/fixtures/price_estimates.yml +7 -0
- data/test/fixtures/readers.yml +5 -0
- data/test/fixtures/references.yml +17 -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 +4 -1
- data/test/fixtures/topics.yml +22 -2
- data/test/fixtures/warehouse-things.yml +3 -0
- data/test/{fixtures/migrations_with_decimal → migrations/decimal}/1_give_me_big_numbers.rb +0 -0
- data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/1_people_have_last_names.rb +1 -1
- data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/2_we_need_reminders.rb +1 -1
- data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/3_foo.rb +0 -0
- data/test/{fixtures/migrations → migrations/duplicate}/3_innocent_jointable.rb +0 -0
- data/test/migrations/duplicate_names/20080507052938_chunky.rb +7 -0
- data/test/migrations/duplicate_names/20080507053028_chunky.rb +7 -0
- data/test/{fixtures/migrations_with_duplicate → migrations/interleaved/pass_1}/3_innocent_jointable.rb +0 -0
- data/test/{fixtures/migrations → migrations/interleaved/pass_2}/1_people_have_last_names.rb +1 -1
- data/test/{fixtures/migrations_with_missing_versions/4_innocent_jointable.rb → migrations/interleaved/pass_2/3_innocent_jointable.rb} +0 -0
- data/test/{fixtures/migrations_with_missing_versions → migrations/interleaved/pass_3}/1_people_have_last_names.rb +1 -1
- 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/{fixtures/migrations_with_missing_versions → migrations/missing}/1000_people_have_middle_names.rb +1 -1
- data/test/migrations/missing/1_people_have_last_names.rb +9 -0
- data/test/{fixtures/migrations_with_missing_versions → migrations/missing}/3_we_need_reminders.rb +1 -1
- data/test/migrations/missing/4_innocent_jointable.rb +12 -0
- data/test/migrations/valid/1_people_have_last_names.rb +9 -0
- data/test/{fixtures/migrations → migrations/valid}/2_we_need_reminders.rb +1 -1
- data/test/migrations/valid/3_innocent_jointable.rb +12 -0
- data/test/{fixtures → models}/author.rb +28 -4
- data/test/{fixtures → models}/auto_id.rb +0 -0
- data/test/{fixtures → models}/binary.rb +0 -0
- data/test/{fixtures → models}/book.rb +0 -0
- data/test/{fixtures → models}/categorization.rb +0 -0
- data/test/{fixtures → models}/category.rb +8 -5
- data/test/{fixtures → models}/citation.rb +0 -0
- data/test/models/club.rb +7 -0
- data/test/{fixtures → models}/column_name.rb +0 -0
- data/test/{fixtures → models}/comment.rb +5 -3
- data/test/{fixtures → models}/company.rb +15 -6
- data/test/{fixtures → models}/company_in_module.rb +5 -3
- data/test/{fixtures → models}/computer.rb +0 -1
- data/test/{fixtures → models}/contact.rb +1 -1
- data/test/{fixtures → models}/course.rb +0 -0
- data/test/{fixtures → models}/customer.rb +8 -8
- data/test/{fixtures → models}/default.rb +0 -0
- data/test/{fixtures → models}/developer.rb +14 -10
- data/test/{fixtures → models}/edge.rb +0 -0
- data/test/{fixtures → models}/entrant.rb +0 -0
- data/test/models/guid.rb +2 -0
- data/test/{fixtures → models}/item.rb +0 -0
- data/test/models/job.rb +5 -0
- data/test/{fixtures → models}/joke.rb +0 -0
- data/test/{fixtures → models}/keyboard.rb +0 -0
- data/test/{fixtures → models}/legacy_thing.rb +0 -0
- data/test/{fixtures → models}/matey.rb +0 -0
- data/test/models/member.rb +9 -0
- data/test/models/membership.rb +9 -0
- data/test/{fixtures → models}/minimalistic.rb +0 -0
- data/test/{fixtures → models}/mixed_case_monkey.rb +0 -0
- data/test/{fixtures → models}/movie.rb +0 -0
- data/test/{fixtures → models}/order.rb +2 -2
- data/test/models/owner.rb +4 -0
- data/test/{fixtures → models}/parrot.rb +0 -0
- data/test/models/person.rb +10 -0
- data/test/models/pet.rb +4 -0
- data/test/models/pirate.rb +9 -0
- data/test/{fixtures → models}/post.rb +23 -2
- data/test/models/price_estimate.rb +3 -0
- data/test/{fixtures → models}/project.rb +1 -0
- data/test/{fixtures → models}/reader.rb +0 -0
- data/test/models/reference.rb +4 -0
- data/test/{fixtures → models}/reply.rb +7 -5
- data/test/{fixtures → models}/ship.rb +0 -0
- data/test/models/sponsor.rb +4 -0
- data/test/{fixtures → models}/subject.rb +0 -0
- data/test/{fixtures → models}/subscriber.rb +2 -0
- data/test/models/subscription.rb +4 -0
- data/test/{fixtures → models}/tag.rb +0 -0
- data/test/{fixtures → models}/tagging.rb +0 -0
- data/test/{fixtures → models}/task.rb +0 -0
- data/test/{fixtures → models}/topic.rb +32 -4
- data/test/{fixtures → models}/treasure.rb +2 -0
- data/test/{fixtures → models}/vertex.rb +0 -0
- data/test/models/warehouse_thing.rb +5 -0
- data/test/schema/mysql_specific_schema.rb +12 -0
- data/test/schema/postgresql_specific_schema.rb +103 -0
- data/test/schema/schema.rb +421 -0
- data/test/schema/schema2.rb +6 -0
- data/test/schema/sqlite_specific_schema.rb +25 -0
- data/test/schema/sqlserver_specific_schema.rb +5 -0
- metadata +192 -176
- data/test/aaa_create_tables_test.rb +0 -72
- data/test/abstract_unit.rb +0 -84
- data/test/active_schema_test_mysql.rb +0 -46
- data/test/all.sh +0 -8
- data/test/association_inheritance_reload.rb +0 -14
- data/test/associations_test.rb +0 -2177
- data/test/fixtures/bad_fixtures/attr_with_numeric_first_char +0 -1
- data/test/fixtures/bad_fixtures/attr_with_spaces +0 -1
- data/test/fixtures/bad_fixtures/blank_line +0 -3
- data/test/fixtures/bad_fixtures/duplicate_attributes +0 -3
- data/test/fixtures/bad_fixtures/missing_value +0 -1
- data/test/fixtures/db_definitions/db2.drop.sql +0 -33
- data/test/fixtures/db_definitions/db2.sql +0 -235
- data/test/fixtures/db_definitions/db22.drop.sql +0 -2
- data/test/fixtures/db_definitions/db22.sql +0 -5
- data/test/fixtures/db_definitions/firebird.drop.sql +0 -65
- data/test/fixtures/db_definitions/firebird.sql +0 -310
- data/test/fixtures/db_definitions/firebird2.drop.sql +0 -2
- data/test/fixtures/db_definitions/firebird2.sql +0 -6
- data/test/fixtures/db_definitions/frontbase.drop.sql +0 -33
- data/test/fixtures/db_definitions/frontbase.sql +0 -273
- data/test/fixtures/db_definitions/frontbase2.drop.sql +0 -1
- data/test/fixtures/db_definitions/frontbase2.sql +0 -4
- data/test/fixtures/db_definitions/openbase.drop.sql +0 -2
- data/test/fixtures/db_definitions/openbase.sql +0 -318
- data/test/fixtures/db_definitions/openbase2.drop.sql +0 -2
- data/test/fixtures/db_definitions/openbase2.sql +0 -7
- data/test/fixtures/db_definitions/oracle.drop.sql +0 -67
- data/test/fixtures/db_definitions/oracle.sql +0 -330
- data/test/fixtures/db_definitions/oracle2.drop.sql +0 -2
- data/test/fixtures/db_definitions/oracle2.sql +0 -6
- data/test/fixtures/db_definitions/postgresql.drop.sql +0 -44
- data/test/fixtures/db_definitions/postgresql.sql +0 -292
- data/test/fixtures/db_definitions/postgresql2.drop.sql +0 -2
- data/test/fixtures/db_definitions/postgresql2.sql +0 -4
- data/test/fixtures/db_definitions/schema.rb +0 -354
- data/test/fixtures/db_definitions/schema2.rb +0 -11
- data/test/fixtures/db_definitions/sqlite.drop.sql +0 -33
- data/test/fixtures/db_definitions/sqlite.sql +0 -219
- data/test/fixtures/db_definitions/sqlite2.drop.sql +0 -2
- data/test/fixtures/db_definitions/sqlite2.sql +0 -5
- data/test/fixtures/db_definitions/sybase.drop.sql +0 -35
- data/test/fixtures/db_definitions/sybase.sql +0 -222
- data/test/fixtures/db_definitions/sybase2.drop.sql +0 -4
- data/test/fixtures/db_definitions/sybase2.sql +0 -5
- data/test/fixtures/developers_projects/david_action_controller +0 -3
- data/test/fixtures/developers_projects/david_active_record +0 -3
- data/test/fixtures/developers_projects/jamis_active_record +0 -2
- data/test/fixtures/person.rb +0 -4
- data/test/fixtures/pirate.rb +0 -5
- data/test/fixtures/subscribers/first +0 -2
- data/test/fixtures/subscribers/second +0 -2
- data/test/schema_dumper_test.rb +0 -131
- data/test/schema_test_postgresql.rb +0 -64
@@ -9,16 +9,16 @@ module ActiveRecord
|
|
9
9
|
# Count operates using three different approaches.
|
10
10
|
#
|
11
11
|
# * Count all: By not passing any parameters to count, it will return a count of all the rows for the model.
|
12
|
-
# * Count using column
|
12
|
+
# * Count using column: By passing a column name to count, it will return a count of all the rows for the model with supplied column present
|
13
13
|
# * Count using options will find the row count matched by the options used.
|
14
14
|
#
|
15
15
|
# The third approach, count using options, accepts an option hash as the only parameter. The options are:
|
16
16
|
#
|
17
17
|
# * <tt>:conditions</tt>: An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro.
|
18
18
|
# * <tt>:joins</tt>: Either an SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id" (rarely needed)
|
19
|
-
# or named associations in the same form used for the
|
19
|
+
# or named associations in the same form used for the <tt>:include</tt> option, which will perform an INNER JOIN on the associated table(s).
|
20
20
|
# If the value is a string, then the records will be returned read-only since they will have attributes that do not correspond to the table's columns.
|
21
|
-
# Pass
|
21
|
+
# Pass <tt>:readonly => false</tt> to override.
|
22
22
|
# * <tt>:include</tt>: Named associations that should be loaded alongside using LEFT OUTER JOINs. The symbols named refer
|
23
23
|
# to already defined associations. When using named associations, count returns the number of DISTINCT items for the model you're counting.
|
24
24
|
# See eager loading under Associations.
|
@@ -41,45 +41,45 @@ module ActiveRecord
|
|
41
41
|
# Person.count('id', :conditions => "age > 26") # Performs a COUNT(id)
|
42
42
|
# Person.count(:all, :conditions => "age > 26") # Performs a COUNT(*) (:all is an alias for '*')
|
43
43
|
#
|
44
|
-
# Note: Person.count(:all) will not work because it will use
|
44
|
+
# Note: <tt>Person.count(:all)</tt> will not work because it will use <tt>:all</tt> as the condition. Use Person.count instead.
|
45
45
|
def count(*args)
|
46
46
|
calculate(:count, *construct_count_options_from_args(*args))
|
47
47
|
end
|
48
48
|
|
49
|
-
# Calculates the average value on a given column. The value is returned as a float. See
|
49
|
+
# Calculates the average value on a given column. The value is returned as a float. See +calculate+ for examples with options.
|
50
50
|
#
|
51
51
|
# Person.average('age')
|
52
52
|
def average(column_name, options = {})
|
53
53
|
calculate(:avg, column_name, options)
|
54
54
|
end
|
55
55
|
|
56
|
-
# Calculates the minimum value on a given column. The value is returned with the same data type of the column. See
|
56
|
+
# Calculates the minimum value on a given column. The value is returned with the same data type of the column. See +calculate+ for examples with options.
|
57
57
|
#
|
58
58
|
# Person.minimum('age')
|
59
59
|
def minimum(column_name, options = {})
|
60
60
|
calculate(:min, column_name, options)
|
61
61
|
end
|
62
62
|
|
63
|
-
# Calculates the maximum value on a given column. The value is returned with the same data type of the column. See
|
63
|
+
# Calculates the maximum value on a given column. The value is returned with the same data type of the column. See +calculate+ for examples with options.
|
64
64
|
#
|
65
65
|
# Person.maximum('age')
|
66
66
|
def maximum(column_name, options = {})
|
67
67
|
calculate(:max, column_name, options)
|
68
68
|
end
|
69
69
|
|
70
|
-
# Calculates the sum of values on a given column. The value is returned with the same data type of the column. See
|
70
|
+
# Calculates the sum of values on a given column. The value is returned with the same data type of the column. See +calculate+ for examples with options.
|
71
71
|
#
|
72
72
|
# Person.sum('age')
|
73
73
|
def sum(column_name, options = {})
|
74
|
-
calculate(:sum, column_name, options)
|
74
|
+
calculate(:sum, column_name, options) || 0
|
75
75
|
end
|
76
76
|
|
77
77
|
# This calculates aggregate values in the given column. Methods for count, sum, average, minimum, and maximum have been added as shortcuts.
|
78
|
-
# Options such as
|
78
|
+
# Options such as <tt>:conditions</tt>, <tt>:order</tt>, <tt>:group</tt>, <tt>:having</tt>, and <tt>:joins</tt> can be passed to customize the query.
|
79
79
|
#
|
80
80
|
# There are two basic forms of output:
|
81
81
|
# * Single aggregate value: The single value is type cast to Fixnum for COUNT, Float for AVG, and the given column's type for everything else.
|
82
|
-
# * Grouped values: This returns an ordered hash of the values and groups them by the
|
82
|
+
# * Grouped values: This returns an ordered hash of the values and groups them by the <tt>:group</tt> option. It takes either a column name, or the name
|
83
83
|
# of a belongs_to association.
|
84
84
|
#
|
85
85
|
# values = Person.maximum(:age, :group => 'last_name')
|
@@ -111,6 +111,7 @@ module ActiveRecord
|
|
111
111
|
# Person.average(:age) # SELECT AVG(age) FROM people...
|
112
112
|
# Person.minimum(:age, :conditions => ['last_name != ?', 'Drake']) # Selects the minimum age for everyone with a last name other than 'Drake'
|
113
113
|
# Person.minimum(:age, :having => 'min(age) > 17', :group => :last_name) # Selects the minimum age for any family without any minors
|
114
|
+
# Person.sum("2 * age")
|
114
115
|
def calculate(operation, column_name, options = {})
|
115
116
|
validate_calculation_options(operation, options)
|
116
117
|
column_name = options[:select] if options[:select]
|
@@ -155,7 +156,7 @@ module ActiveRecord
|
|
155
156
|
scope = scope(:find)
|
156
157
|
merged_includes = merge_includes(scope ? scope[:include] : [], options[:include])
|
157
158
|
aggregate_alias = column_alias_for(operation, column_name)
|
158
|
-
column_name = "#{connection.quote_table_name(table_name)}.#{column_name}"
|
159
|
+
column_name = "#{connection.quote_table_name(table_name)}.#{column_name}" if column_names.include?(column_name.to_s)
|
159
160
|
|
160
161
|
if operation == 'count'
|
161
162
|
if merged_includes.any?
|
@@ -168,13 +169,16 @@ module ActiveRecord
|
|
168
169
|
end
|
169
170
|
end
|
170
171
|
|
171
|
-
|
172
|
+
if options[:distinct] && column_name.to_s !~ /\s*DISTINCT\s+/i
|
173
|
+
distinct = 'DISTINCT '
|
174
|
+
end
|
175
|
+
sql = "SELECT #{operation}(#{distinct}#{column_name}) AS #{aggregate_alias}"
|
172
176
|
|
173
177
|
# A (slower) workaround if we're using a backend, like sqlite, that doesn't support COUNT DISTINCT.
|
174
178
|
sql = "SELECT COUNT(*) AS #{aggregate_alias}" if use_workaround
|
175
179
|
|
176
180
|
sql << ", #{options[:group_field]} AS #{options[:group_alias]}" if options[:group]
|
177
|
-
sql << " FROM (SELECT
|
181
|
+
sql << " FROM (SELECT #{distinct}#{column_name}" if use_workaround
|
178
182
|
sql << " FROM #{connection.quote_table_name(table_name)} "
|
179
183
|
if merged_includes.any?
|
180
184
|
join_dependency = ActiveRecord::Associations::ClassMethods::JoinDependency.new(self, merged_includes, options[:joins])
|
@@ -231,7 +235,8 @@ module ActiveRecord
|
|
231
235
|
key = type_cast_calculated_value(row[group_alias], group_column)
|
232
236
|
key = key_records[key] if associated
|
233
237
|
value = row[aggregate_alias]
|
234
|
-
all
|
238
|
+
all[key] = type_cast_calculated_value(value, column, operation)
|
239
|
+
all
|
235
240
|
end
|
236
241
|
end
|
237
242
|
|
@@ -240,12 +245,14 @@ module ActiveRecord
|
|
240
245
|
options.assert_valid_keys(CALCULATIONS_OPTIONS)
|
241
246
|
end
|
242
247
|
|
243
|
-
# Converts
|
244
|
-
# a usable column name
|
245
|
-
#
|
246
|
-
#
|
247
|
-
#
|
248
|
-
# count(
|
248
|
+
# Converts the given keys to the value that the database adapter returns as
|
249
|
+
# a usable column name:
|
250
|
+
#
|
251
|
+
# column_alias_for("users.id") # => "users_id"
|
252
|
+
# column_alias_for("sum(id)") # => "sum_id"
|
253
|
+
# column_alias_for("count(distinct users.id)") # => "count_distinct_users_id"
|
254
|
+
# column_alias_for("count(*)") # => "count_all"
|
255
|
+
# column_alias_for("count", "id") # => "count_id"
|
249
256
|
def column_alias_for(*keys)
|
250
257
|
connection.table_alias_for(keys.join(' ').downcase.gsub(/\*/, 'all').gsub(/\W+/, ' ').strip.gsub(/ +/, '_'))
|
251
258
|
end
|
@@ -161,7 +161,7 @@ module ActiveRecord
|
|
161
161
|
# == <tt>before_validation*</tt> returning statements
|
162
162
|
#
|
163
163
|
# If the returning value of a +before_validation+ callback can be evaluated to +false+, the process will be aborted and <tt>Base#save</tt> will return +false+.
|
164
|
-
# If
|
164
|
+
# If Base#save! is called it will raise a RecordNotSaved exception.
|
165
165
|
# Nothing will be appended to the errors object.
|
166
166
|
#
|
167
167
|
# == Canceling callbacks
|
@@ -183,14 +183,8 @@ module ActiveRecord
|
|
183
183
|
base.send :alias_method_chain, method, :callbacks
|
184
184
|
end
|
185
185
|
|
186
|
-
|
187
|
-
|
188
|
-
def self.#{method}(*callbacks, &block)
|
189
|
-
callbacks << block if block_given?
|
190
|
-
write_inheritable_array(#{method.to_sym.inspect}, callbacks)
|
191
|
-
end
|
192
|
-
end_eval
|
193
|
-
end
|
186
|
+
base.send :include, ActiveSupport::Callbacks
|
187
|
+
base.define_callbacks *CALLBACKS
|
194
188
|
end
|
195
189
|
|
196
190
|
# Is called when the object was instantiated by one of the finders, like <tt>Base.find</tt>.
|
@@ -235,9 +229,9 @@ module ActiveRecord
|
|
235
229
|
# Is called _after_ <tt>Base.save</tt> on existing objects that have a record.
|
236
230
|
def after_update() end
|
237
231
|
|
238
|
-
def update_with_callbacks #:nodoc:
|
232
|
+
def update_with_callbacks(*args) #:nodoc:
|
239
233
|
return false if callback(:before_update) == false
|
240
|
-
result = update_without_callbacks
|
234
|
+
result = update_without_callbacks(*args)
|
241
235
|
callback(:after_update)
|
242
236
|
result
|
243
237
|
end
|
@@ -301,38 +295,15 @@ module ActiveRecord
|
|
301
295
|
def callback(method)
|
302
296
|
notify(method)
|
303
297
|
|
304
|
-
|
305
|
-
result = case callback
|
306
|
-
when Symbol
|
307
|
-
self.send(callback)
|
308
|
-
when String
|
309
|
-
eval(callback, binding)
|
310
|
-
when Proc, Method
|
311
|
-
callback.call(self)
|
312
|
-
else
|
313
|
-
if callback.respond_to?(method)
|
314
|
-
callback.send(method, self)
|
315
|
-
else
|
316
|
-
raise ActiveRecordError, "Callbacks must be a symbol denoting the method to call, a string to be evaluated, a block to be invoked, or an object responding to the callback method."
|
317
|
-
end
|
318
|
-
end
|
319
|
-
return false if result == false
|
320
|
-
end
|
298
|
+
result = run_callbacks(method) { |result, object| result == false }
|
321
299
|
|
322
|
-
result
|
300
|
+
if result != false && respond_to_without_attributes?(method)
|
301
|
+
result = send(method)
|
302
|
+
end
|
323
303
|
|
324
304
|
return result
|
325
305
|
end
|
326
306
|
|
327
|
-
def callbacks_for(method)
|
328
|
-
self.class.read_inheritable_attribute(method.to_sym) or []
|
329
|
-
end
|
330
|
-
|
331
|
-
def invoke_and_notify(method)
|
332
|
-
notify(method)
|
333
|
-
send(method) if respond_to_without_attributes?(method)
|
334
|
-
end
|
335
|
-
|
336
307
|
def notify(method) #:nodoc:
|
337
308
|
self.class.changed
|
338
309
|
self.class.notify_observers(method, self)
|
@@ -175,7 +175,7 @@ module ActiveRecord
|
|
175
175
|
end
|
176
176
|
|
177
177
|
# Establishes the connection to the database. Accepts a hash as input where
|
178
|
-
# the
|
178
|
+
# the <tt>:adapter</tt> key must be specified with the name of a database adapter (in lower-case)
|
179
179
|
# example for regular databases (MySQL, Postgresql, etc):
|
180
180
|
#
|
181
181
|
# ActiveRecord::Base.establish_connection(
|
@@ -193,7 +193,8 @@ module ActiveRecord
|
|
193
193
|
# :database => "path/to/dbfile"
|
194
194
|
# )
|
195
195
|
#
|
196
|
-
# Also accepts keys as strings (for parsing from
|
196
|
+
# Also accepts keys as strings (for parsing from YAML for example):
|
197
|
+
#
|
197
198
|
# ActiveRecord::Base.establish_connection(
|
198
199
|
# "adapter" => "sqlite",
|
199
200
|
# "database" => "path/to/dbfile"
|
@@ -29,7 +29,7 @@ module ActiveRecord
|
|
29
29
|
end
|
30
30
|
|
31
31
|
# Returns an array of arrays containing the field values.
|
32
|
-
# Order is the same as that returned by
|
32
|
+
# Order is the same as that returned by +columns+.
|
33
33
|
def select_rows(sql, name = nil)
|
34
34
|
raise NotImplementedError, "select_rows is an abstract method"
|
35
35
|
end
|
@@ -93,7 +93,7 @@ module ActiveRecord
|
|
93
93
|
# done if the transaction block raises an exception or returns false.
|
94
94
|
def rollback_db_transaction() end
|
95
95
|
|
96
|
-
# Alias for
|
96
|
+
# Alias for <tt>add_limit_offset!</tt>.
|
97
97
|
def add_limit!(sql, options)
|
98
98
|
add_limit_offset!(sql, options) if options
|
99
99
|
end
|
@@ -44,6 +44,12 @@ module ActiveRecord
|
|
44
44
|
@query_cache_enabled = old
|
45
45
|
end
|
46
46
|
|
47
|
+
# Clears the query cache.
|
48
|
+
#
|
49
|
+
# One reason you may wish to call this method explicitly is between queries
|
50
|
+
# that ask the database to randomize results. Otherwise the cache would see
|
51
|
+
# the same SQL query and repeatedly return the same result each time, silently
|
52
|
+
# undermining the randomness you were expecting.
|
47
53
|
def clear_query_cache
|
48
54
|
@query_cache.clear if @query_cache
|
49
55
|
end
|
@@ -16,13 +16,13 @@ module ActiveRecord
|
|
16
16
|
|
17
17
|
# Instantiates a new column in the table.
|
18
18
|
#
|
19
|
-
# +name+ is the column's name, as
|
20
|
-
# +default+ is the type-casted default value, such as <tt>sales_stage varchar(20) default
|
21
|
-
# +sql_type+ is only used to extract the column's length, if necessary.
|
19
|
+
# +name+ is the column's name, such as <tt>supplier_id</tt> in <tt>supplier_id int(11)</tt>.
|
20
|
+
# +default+ is the type-casted default value, such as +new+ in <tt>sales_stage varchar(20) default 'new'</tt>.
|
21
|
+
# +sql_type+ is only used to extract the column's length, if necessary. For example +60+ in <tt>company_name varchar(60)</tt>.
|
22
22
|
# +null+ determines if this column allows +NULL+ values.
|
23
23
|
def initialize(name, default, sql_type = nil, null = true)
|
24
24
|
@name, @sql_type, @null = name, sql_type, null
|
25
|
-
@limit, @precision, @scale
|
25
|
+
@limit, @precision, @scale = extract_limit(sql_type), extract_precision(sql_type), extract_scale(sql_type)
|
26
26
|
@type = simplified_type(sql_type)
|
27
27
|
@default = extract_default(default)
|
28
28
|
|
@@ -92,7 +92,7 @@ module ActiveRecord
|
|
92
92
|
# Returns the human name of the column name.
|
93
93
|
#
|
94
94
|
# ===== Examples
|
95
|
-
# Column.new('sales_stage', ...).human_name
|
95
|
+
# Column.new('sales_stage', ...).human_name # => 'Sales stage'
|
96
96
|
def human_name
|
97
97
|
Base.human_attribute_name(@name)
|
98
98
|
end
|
@@ -144,7 +144,10 @@ module ActiveRecord
|
|
144
144
|
|
145
145
|
# convert something to a BigDecimal
|
146
146
|
def value_to_decimal(value)
|
147
|
-
|
147
|
+
# Using .class is faster than .is_a? and
|
148
|
+
# subclasses of BigDecimal will be handled
|
149
|
+
# in the else clause
|
150
|
+
if value.class == BigDecimal
|
148
151
|
value
|
149
152
|
elsif value.respond_to?(:to_d)
|
150
153
|
value.to_d
|
@@ -170,11 +173,7 @@ module ActiveRecord
|
|
170
173
|
# Treat 0000-00-00 00:00:00 as nil.
|
171
174
|
return nil if year.nil? || year == 0
|
172
175
|
|
173
|
-
Time.
|
174
|
-
# Over/underflow to DateTime
|
175
|
-
rescue ArgumentError, TypeError
|
176
|
-
zone_offset = Base.default_timezone == :local ? DateTime.local_offset : 0
|
177
|
-
DateTime.civil(year, mon, mday, hour, min, sec, zone_offset) rescue nil
|
176
|
+
Time.time_with_datetime_fallback(Base.default_timezone, year, mon, mday, hour, min, sec, microsec) rescue nil
|
178
177
|
end
|
179
178
|
|
180
179
|
def fast_string_to_date(string)
|
@@ -192,7 +191,7 @@ module ActiveRecord
|
|
192
191
|
end
|
193
192
|
|
194
193
|
def fallback_string_to_date(string)
|
195
|
-
new_date(
|
194
|
+
new_date(*::Date._parse(string, false).values_at(:year, :mon, :mday))
|
196
195
|
end
|
197
196
|
|
198
197
|
def fallback_string_to_time(string)
|
@@ -251,11 +250,11 @@ module ActiveRecord
|
|
251
250
|
end
|
252
251
|
|
253
252
|
class ColumnDefinition < Struct.new(:base, :name, :type, :limit, :precision, :scale, :default, :null) #:nodoc:
|
254
|
-
|
253
|
+
|
255
254
|
def sql_type
|
256
255
|
base.type_to_sql(type.to_sym, limit, precision, scale) rescue type
|
257
256
|
end
|
258
|
-
|
257
|
+
|
259
258
|
def to_sql
|
260
259
|
column_sql = "#{base.quote_column_name(name)} #{sql_type}"
|
261
260
|
add_column_options!(column_sql, :null => null, :default => default) unless type.to_sym == :primary_key
|
@@ -271,7 +270,7 @@ module ActiveRecord
|
|
271
270
|
end
|
272
271
|
|
273
272
|
# Represents a SQL table in an abstract way.
|
274
|
-
# Columns are stored as a ColumnDefinition in the
|
273
|
+
# Columns are stored as a ColumnDefinition in the +columns+ attribute.
|
275
274
|
class TableDefinition
|
276
275
|
attr_accessor :columns
|
277
276
|
|
@@ -310,39 +309,39 @@ module ActiveRecord
|
|
310
309
|
# * <tt>:default</tt> -
|
311
310
|
# The column's default value. Use nil for NULL.
|
312
311
|
# * <tt>:null</tt> -
|
313
|
-
# Allows or disallows +NULL+ values in the column.
|
312
|
+
# Allows or disallows +NULL+ values in the column. This option could
|
314
313
|
# have been named <tt>:null_allowed</tt>.
|
315
314
|
# * <tt>:precision</tt> -
|
316
|
-
# Specifies the precision for a <tt>:decimal</tt> column.
|
315
|
+
# Specifies the precision for a <tt>:decimal</tt> column.
|
317
316
|
# * <tt>:scale</tt> -
|
318
|
-
# Specifies the scale for a <tt>:decimal</tt> column.
|
317
|
+
# Specifies the scale for a <tt>:decimal</tt> column.
|
319
318
|
#
|
320
319
|
# Please be aware of different RDBMS implementations behavior with
|
321
320
|
# <tt>:decimal</tt> columns:
|
322
321
|
# * The SQL standard says the default scale should be 0, <tt>:scale</tt> <=
|
323
322
|
# <tt>:precision</tt>, and makes no comments about the requirements of
|
324
323
|
# <tt>:precision</tt>.
|
325
|
-
# * MySQL: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..30].
|
324
|
+
# * MySQL: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..30].
|
326
325
|
# Default is (10,0).
|
327
|
-
# * PostgreSQL: <tt>:precision</tt> [1..infinity],
|
326
|
+
# * PostgreSQL: <tt>:precision</tt> [1..infinity],
|
328
327
|
# <tt>:scale</tt> [0..infinity]. No default.
|
329
|
-
# * SQLite2: Any <tt>:precision</tt> and <tt>:scale</tt> may be used.
|
328
|
+
# * SQLite2: Any <tt>:precision</tt> and <tt>:scale</tt> may be used.
|
330
329
|
# Internal storage as strings. No default.
|
331
330
|
# * SQLite3: No restrictions on <tt>:precision</tt> and <tt>:scale</tt>,
|
332
331
|
# but the maximum supported <tt>:precision</tt> is 16. No default.
|
333
|
-
# * Oracle: <tt>:precision</tt> [1..38], <tt>:scale</tt> [-84..127].
|
332
|
+
# * Oracle: <tt>:precision</tt> [1..38], <tt>:scale</tt> [-84..127].
|
334
333
|
# Default is (38,0).
|
335
|
-
# * DB2: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..62].
|
334
|
+
# * DB2: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..62].
|
336
335
|
# Default unknown.
|
337
|
-
# * Firebird: <tt>:precision</tt> [1..18], <tt>:scale</tt> [0..18].
|
336
|
+
# * Firebird: <tt>:precision</tt> [1..18], <tt>:scale</tt> [0..18].
|
338
337
|
# Default (9,0). Internal types NUMERIC and DECIMAL have different
|
339
338
|
# storage rules, decimal being better.
|
340
|
-
# * FrontBase?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
|
339
|
+
# * FrontBase?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
|
341
340
|
# Default (38,0). WARNING Max <tt>:precision</tt>/<tt>:scale</tt> for
|
342
341
|
# NUMERIC is 19, and DECIMAL is 38.
|
343
|
-
# * SqlServer?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
|
342
|
+
# * SqlServer?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
|
344
343
|
# Default (38,0).
|
345
|
-
# * Sybase: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
|
344
|
+
# * Sybase: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
|
346
345
|
# Default (38,0).
|
347
346
|
# * OpenBase?: Documentation unclear. Claims storage in <tt>double</tt>.
|
348
347
|
#
|
@@ -351,28 +350,28 @@ module ActiveRecord
|
|
351
350
|
# == Examples
|
352
351
|
# # Assuming td is an instance of TableDefinition
|
353
352
|
# td.column(:granted, :boolean)
|
354
|
-
#
|
353
|
+
# # granted BOOLEAN
|
355
354
|
#
|
356
355
|
# td.column(:picture, :binary, :limit => 2.megabytes)
|
357
|
-
#
|
356
|
+
# # => picture BLOB(2097152)
|
358
357
|
#
|
359
358
|
# td.column(:sales_stage, :string, :limit => 20, :default => 'new', :null => false)
|
360
|
-
#
|
359
|
+
# # => sales_stage VARCHAR(20) DEFAULT 'new' NOT NULL
|
361
360
|
#
|
362
|
-
#
|
363
|
-
#
|
361
|
+
# td.column(:bill_gates_money, :decimal, :precision => 15, :scale => 2)
|
362
|
+
# # => bill_gates_money DECIMAL(15,2)
|
364
363
|
#
|
365
|
-
#
|
366
|
-
#
|
364
|
+
# td.column(:sensor_reading, :decimal, :precision => 30, :scale => 20)
|
365
|
+
# # => sensor_reading DECIMAL(30,20)
|
367
366
|
#
|
368
367
|
# # While <tt>:scale</tt> defaults to zero on most databases, it
|
369
368
|
# # probably wouldn't hurt to include it.
|
370
|
-
#
|
371
|
-
#
|
369
|
+
# td.column(:huge_integer, :decimal, :precision => 30)
|
370
|
+
# # => huge_integer DECIMAL(30)
|
372
371
|
#
|
373
372
|
# == Short-hand examples
|
374
373
|
#
|
375
|
-
# Instead of calling column directly, you can also work with the short-hand definitions for the default types.
|
374
|
+
# Instead of calling +column+ directly, you can also work with the short-hand definitions for the default types.
|
376
375
|
# They use the type as the method name instead of as a parameter and allow for multiple columns to be defined
|
377
376
|
# in a single statement.
|
378
377
|
#
|
@@ -395,12 +394,12 @@ module ActiveRecord
|
|
395
394
|
# t.timestamps
|
396
395
|
# end
|
397
396
|
#
|
398
|
-
# There's a short-hand method for each of the type values declared at the top. And then there's
|
399
|
-
# TableDefinition#timestamps that'll add created_at and updated_at as datetimes.
|
397
|
+
# There's a short-hand method for each of the type values declared at the top. And then there's
|
398
|
+
# TableDefinition#timestamps that'll add created_at and +updated_at+ as datetimes.
|
400
399
|
#
|
401
400
|
# TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type
|
402
|
-
# column if the
|
403
|
-
# used when creating the _type column. So what can be written like this:
|
401
|
+
# column if the <tt>:polymorphic</tt> option is supplied. If <tt>:polymorphic</tt> is a hash of options, these will be
|
402
|
+
# used when creating the <tt>_type</tt> column. So what can be written like this:
|
404
403
|
#
|
405
404
|
# create_table :taggings do |t|
|
406
405
|
# t.integer :tag_id, :tagger_id, :taggable_id
|
@@ -435,13 +434,13 @@ module ActiveRecord
|
|
435
434
|
def #{column_type}(*args)
|
436
435
|
options = args.extract_options!
|
437
436
|
column_names = args
|
438
|
-
|
437
|
+
|
439
438
|
column_names.each { |name| column(name, '#{column_type}', options) }
|
440
439
|
end
|
441
440
|
EOV
|
442
441
|
end
|
443
|
-
|
444
|
-
# Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
|
442
|
+
|
443
|
+
# Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
|
445
444
|
# <tt>:updated_at</tt> to the table.
|
446
445
|
def timestamps
|
447
446
|
column(:created_at, :datetime)
|
@@ -459,7 +458,7 @@ module ActiveRecord
|
|
459
458
|
alias :belongs_to :references
|
460
459
|
|
461
460
|
# Returns a String whose contents are the column definitions
|
462
|
-
# concatenated together.
|
461
|
+
# concatenated together. This string can then be prepended and appended to
|
463
462
|
# to generate the final SQL to create the table.
|
464
463
|
def to_sql
|
465
464
|
@columns * ', '
|
@@ -470,5 +469,193 @@ module ActiveRecord
|
|
470
469
|
@base.native_database_types
|
471
470
|
end
|
472
471
|
end
|
472
|
+
|
473
|
+
# Represents a SQL table in an abstract way for updating a table.
|
474
|
+
# Also see TableDefinition and SchemaStatements#create_table
|
475
|
+
#
|
476
|
+
# Available transformations are:
|
477
|
+
#
|
478
|
+
# change_table :table do |t|
|
479
|
+
# t.column
|
480
|
+
# t.index
|
481
|
+
# t.timestamps
|
482
|
+
# t.change
|
483
|
+
# t.change_default
|
484
|
+
# t.rename
|
485
|
+
# t.references
|
486
|
+
# t.belongs_to
|
487
|
+
# t.string
|
488
|
+
# t.text
|
489
|
+
# t.integer
|
490
|
+
# t.float
|
491
|
+
# t.decimal
|
492
|
+
# t.datetime
|
493
|
+
# t.timestamp
|
494
|
+
# t.time
|
495
|
+
# t.date
|
496
|
+
# t.binary
|
497
|
+
# t.boolean
|
498
|
+
# t.remove
|
499
|
+
# t.remove_references
|
500
|
+
# t.remove_belongs_to
|
501
|
+
# t.remove_index
|
502
|
+
# t.remove_timestamps
|
503
|
+
# end
|
504
|
+
#
|
505
|
+
class Table
|
506
|
+
def initialize(table_name, base)
|
507
|
+
@table_name = table_name
|
508
|
+
@base = base
|
509
|
+
end
|
510
|
+
|
511
|
+
# Adds a new column to the named table.
|
512
|
+
# See TableDefinition#column for details of the options you can use.
|
513
|
+
# ===== Example
|
514
|
+
# ====== Creating a simple column
|
515
|
+
# t.column(:name, :string)
|
516
|
+
def column(column_name, type, options = {})
|
517
|
+
@base.add_column(@table_name, column_name, type, options)
|
518
|
+
end
|
519
|
+
|
520
|
+
# Adds a new index to the table. +column_name+ can be a single Symbol, or
|
521
|
+
# an Array of Symbols. See SchemaStatements#add_index
|
522
|
+
#
|
523
|
+
# ===== Examples
|
524
|
+
# ====== Creating a simple index
|
525
|
+
# t.index(:name)
|
526
|
+
# ====== Creating a unique index
|
527
|
+
# t.index([:branch_id, :party_id], :unique => true)
|
528
|
+
# ====== Creating a named index
|
529
|
+
# t.index([:branch_id, :party_id], :unique => true, :name => 'by_branch_party')
|
530
|
+
def index(column_name, options = {})
|
531
|
+
@base.add_index(@table_name, column_name, options)
|
532
|
+
end
|
533
|
+
|
534
|
+
# Adds timestamps (created_at and updated_at) columns to the table. See SchemaStatements#add_timestamps
|
535
|
+
# ===== Example
|
536
|
+
# t.timestamps
|
537
|
+
def timestamps
|
538
|
+
@base.add_timestamps(@table_name)
|
539
|
+
end
|
540
|
+
|
541
|
+
# Changes the column's definition according to the new options.
|
542
|
+
# See TableDefinition#column for details of the options you can use.
|
543
|
+
# ===== Examples
|
544
|
+
# t.change(:name, :string, :limit => 80)
|
545
|
+
# t.change(:description, :text)
|
546
|
+
def change(column_name, type, options = {})
|
547
|
+
@base.change_column(@table_name, column_name, type, options)
|
548
|
+
end
|
549
|
+
|
550
|
+
# Sets a new default value for a column. See SchemaStatements#change_column_default
|
551
|
+
# ===== Examples
|
552
|
+
# t.change_default(:qualification, 'new')
|
553
|
+
# t.change_default(:authorized, 1)
|
554
|
+
def change_default(column_name, default)
|
555
|
+
@base.change_column_default(@table_name, column_name, default)
|
556
|
+
end
|
557
|
+
|
558
|
+
# Removes the column(s) from the table definition.
|
559
|
+
# ===== Examples
|
560
|
+
# t.remove(:qualification)
|
561
|
+
# t.remove(:qualification, :experience)
|
562
|
+
def remove(*column_names)
|
563
|
+
@base.remove_column(@table_name, column_names)
|
564
|
+
end
|
565
|
+
|
566
|
+
# Removes the given index from the table.
|
567
|
+
#
|
568
|
+
# ===== Examples
|
569
|
+
# ====== Remove the suppliers_name_index in the suppliers table
|
570
|
+
# t.remove_index :name
|
571
|
+
# ====== Remove the index named accounts_branch_id_index in the accounts table
|
572
|
+
# t.remove_index :column => :branch_id
|
573
|
+
# ====== Remove the index named accounts_branch_id_party_id_index in the accounts table
|
574
|
+
# t.remove_index :column => [:branch_id, :party_id]
|
575
|
+
# ====== Remove the index named by_branch_party in the accounts table
|
576
|
+
# t.remove_index :name => :by_branch_party
|
577
|
+
def remove_index(options = {})
|
578
|
+
@base.remove_index(@table_name, options)
|
579
|
+
end
|
580
|
+
|
581
|
+
# Removes the timestamp columns (created_at and updated_at) from the table.
|
582
|
+
# ===== Example
|
583
|
+
# t.remove_timestamps
|
584
|
+
def remove_timestamps
|
585
|
+
@base.remove_timestamps(@table_name)
|
586
|
+
end
|
587
|
+
|
588
|
+
# Renames a column.
|
589
|
+
# ===== Example
|
590
|
+
# t.rename(:description, :name)
|
591
|
+
def rename(column_name, new_column_name)
|
592
|
+
@base.rename_column(@table_name, column_name, new_column_name)
|
593
|
+
end
|
594
|
+
|
595
|
+
# Adds a reference. Optionally adds a +type+ column.
|
596
|
+
# <tt>references</tt> and <tt>belongs_to</tt> are acceptable.
|
597
|
+
# ===== Examples
|
598
|
+
# t.references(:goat)
|
599
|
+
# t.references(:goat, :polymorphic => true)
|
600
|
+
# t.belongs_to(:goat)
|
601
|
+
def references(*args)
|
602
|
+
options = args.extract_options!
|
603
|
+
polymorphic = options.delete(:polymorphic)
|
604
|
+
args.each do |col|
|
605
|
+
@base.add_column(@table_name, "#{col}_id", :integer, options)
|
606
|
+
@base.add_column(@table_name, "#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) unless polymorphic.nil?
|
607
|
+
end
|
608
|
+
end
|
609
|
+
alias :belongs_to :references
|
610
|
+
|
611
|
+
# Removes a reference. Optionally removes a +type+ column.
|
612
|
+
# <tt>remove_references</tt> and <tt>remove_belongs_to</tt> are acceptable.
|
613
|
+
# ===== Examples
|
614
|
+
# t.remove_references(:goat)
|
615
|
+
# t.remove_references(:goat, :polymorphic => true)
|
616
|
+
# t.remove_belongs_to(:goat)
|
617
|
+
def remove_references(*args)
|
618
|
+
options = args.extract_options!
|
619
|
+
polymorphic = options.delete(:polymorphic)
|
620
|
+
args.each do |col|
|
621
|
+
@base.remove_column(@table_name, "#{col}_id")
|
622
|
+
@base.remove_column(@table_name, "#{col}_type") unless polymorphic.nil?
|
623
|
+
end
|
624
|
+
end
|
625
|
+
alias :remove_belongs_to :remove_references
|
626
|
+
|
627
|
+
# Adds a column or columns of a specified type
|
628
|
+
# ===== Examples
|
629
|
+
# t.string(:goat)
|
630
|
+
# t.string(:goat, :sheep)
|
631
|
+
%w( string text integer float decimal datetime timestamp time date binary boolean ).each do |column_type|
|
632
|
+
class_eval <<-EOV
|
633
|
+
def #{column_type}(*args)
|
634
|
+
options = args.extract_options!
|
635
|
+
column_names = args
|
636
|
+
|
637
|
+
column_names.each do |name|
|
638
|
+
column = ColumnDefinition.new(@base, name, '#{column_type}')
|
639
|
+
if options[:limit]
|
640
|
+
column.limit = options[:limit]
|
641
|
+
elsif native['#{column_type}'.to_sym].is_a?(Hash)
|
642
|
+
column.limit = native['#{column_type}'.to_sym][:limit]
|
643
|
+
end
|
644
|
+
column.precision = options[:precision]
|
645
|
+
column.scale = options[:scale]
|
646
|
+
column.default = options[:default]
|
647
|
+
column.null = options[:null]
|
648
|
+
@base.add_column(@table_name, name, column.sql_type, options)
|
649
|
+
end
|
650
|
+
end
|
651
|
+
EOV
|
652
|
+
end
|
653
|
+
|
654
|
+
private
|
655
|
+
def native
|
656
|
+
@base.native_database_types
|
657
|
+
end
|
658
|
+
end
|
659
|
+
|
473
660
|
end
|
474
661
|
end
|