activerecord 3.0.0 → 4.0.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.

Files changed (181) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +2102 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +35 -44
  5. data/examples/performance.rb +110 -100
  6. data/lib/active_record/aggregations.rb +59 -75
  7. data/lib/active_record/associations/alias_tracker.rb +76 -0
  8. data/lib/active_record/associations/association.rb +248 -0
  9. data/lib/active_record/associations/association_scope.rb +135 -0
  10. data/lib/active_record/associations/belongs_to_association.rb +60 -59
  11. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +16 -59
  12. data/lib/active_record/associations/builder/association.rb +108 -0
  13. data/lib/active_record/associations/builder/belongs_to.rb +98 -0
  14. data/lib/active_record/associations/builder/collection_association.rb +89 -0
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +39 -0
  16. data/lib/active_record/associations/builder/has_many.rb +15 -0
  17. data/lib/active_record/associations/builder/has_one.rb +25 -0
  18. data/lib/active_record/associations/builder/singular_association.rb +32 -0
  19. data/lib/active_record/associations/collection_association.rb +608 -0
  20. data/lib/active_record/associations/collection_proxy.rb +986 -0
  21. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +40 -112
  22. data/lib/active_record/associations/has_many_association.rb +83 -76
  23. data/lib/active_record/associations/has_many_through_association.rb +147 -66
  24. data/lib/active_record/associations/has_one_association.rb +67 -108
  25. data/lib/active_record/associations/has_one_through_association.rb +21 -25
  26. data/lib/active_record/associations/join_dependency/join_association.rb +174 -0
  27. data/lib/active_record/associations/join_dependency/join_base.rb +24 -0
  28. data/lib/active_record/associations/join_dependency/join_part.rb +78 -0
  29. data/lib/active_record/associations/join_dependency.rb +235 -0
  30. data/lib/active_record/associations/join_helper.rb +45 -0
  31. data/lib/active_record/associations/preloader/association.rb +121 -0
  32. data/lib/active_record/associations/preloader/belongs_to.rb +17 -0
  33. data/lib/active_record/associations/preloader/collection_association.rb +24 -0
  34. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +60 -0
  35. data/lib/active_record/associations/preloader/has_many.rb +17 -0
  36. data/lib/active_record/associations/preloader/has_many_through.rb +19 -0
  37. data/lib/active_record/associations/preloader/has_one.rb +23 -0
  38. data/lib/active_record/associations/preloader/has_one_through.rb +9 -0
  39. data/lib/active_record/associations/preloader/singular_association.rb +21 -0
  40. data/lib/active_record/associations/preloader/through_association.rb +63 -0
  41. data/lib/active_record/associations/preloader.rb +178 -0
  42. data/lib/active_record/associations/singular_association.rb +64 -0
  43. data/lib/active_record/associations/through_association.rb +87 -0
  44. data/lib/active_record/associations.rb +512 -1224
  45. data/lib/active_record/attribute_assignment.rb +201 -0
  46. data/lib/active_record/attribute_methods/before_type_cast.rb +49 -12
  47. data/lib/active_record/attribute_methods/dirty.rb +51 -28
  48. data/lib/active_record/attribute_methods/primary_key.rb +94 -22
  49. data/lib/active_record/attribute_methods/query.rb +5 -4
  50. data/lib/active_record/attribute_methods/read.rb +63 -72
  51. data/lib/active_record/attribute_methods/serialization.rb +162 -0
  52. data/lib/active_record/attribute_methods/time_zone_conversion.rb +39 -41
  53. data/lib/active_record/attribute_methods/write.rb +39 -13
  54. data/lib/active_record/attribute_methods.rb +362 -29
  55. data/lib/active_record/autosave_association.rb +132 -75
  56. data/lib/active_record/base.rb +83 -1627
  57. data/lib/active_record/callbacks.rb +69 -47
  58. data/lib/active_record/coders/yaml_column.rb +38 -0
  59. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +411 -138
  60. data/lib/active_record/connection_adapters/abstract/database_limits.rb +21 -11
  61. data/lib/active_record/connection_adapters/abstract/database_statements.rb +234 -173
  62. data/lib/active_record/connection_adapters/abstract/query_cache.rb +36 -22
  63. data/lib/active_record/connection_adapters/abstract/quoting.rb +82 -25
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +176 -414
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +70 -0
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +562 -232
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +203 -0
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +281 -53
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +782 -0
  70. data/lib/active_record/connection_adapters/column.rb +318 -0
  71. data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
  72. data/lib/active_record/connection_adapters/mysql2_adapter.rb +273 -0
  73. data/lib/active_record/connection_adapters/mysql_adapter.rb +365 -450
  74. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +97 -0
  75. data/lib/active_record/connection_adapters/postgresql/cast.rb +152 -0
  76. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +242 -0
  77. data/lib/active_record/connection_adapters/postgresql/oid.rb +366 -0
  78. data/lib/active_record/connection_adapters/postgresql/quoting.rb +171 -0
  79. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
  80. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +489 -0
  81. data/lib/active_record/connection_adapters/postgresql_adapter.rb +672 -752
  82. data/lib/active_record/connection_adapters/schema_cache.rb +129 -0
  83. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +588 -17
  84. data/lib/active_record/connection_adapters/statement_pool.rb +40 -0
  85. data/lib/active_record/connection_handling.rb +98 -0
  86. data/lib/active_record/core.rb +463 -0
  87. data/lib/active_record/counter_cache.rb +108 -101
  88. data/lib/active_record/dynamic_matchers.rb +131 -0
  89. data/lib/active_record/errors.rb +54 -13
  90. data/lib/active_record/explain.rb +38 -0
  91. data/lib/active_record/explain_registry.rb +30 -0
  92. data/lib/active_record/explain_subscriber.rb +29 -0
  93. data/lib/active_record/fixture_set/file.rb +55 -0
  94. data/lib/active_record/fixtures.rb +703 -785
  95. data/lib/active_record/inheritance.rb +200 -0
  96. data/lib/active_record/integration.rb +60 -0
  97. data/lib/active_record/locale/en.yml +8 -1
  98. data/lib/active_record/locking/optimistic.rb +69 -60
  99. data/lib/active_record/locking/pessimistic.rb +34 -12
  100. data/lib/active_record/log_subscriber.rb +40 -6
  101. data/lib/active_record/migration/command_recorder.rb +164 -0
  102. data/lib/active_record/migration/join_table.rb +15 -0
  103. data/lib/active_record/migration.rb +614 -216
  104. data/lib/active_record/model_schema.rb +345 -0
  105. data/lib/active_record/nested_attributes.rb +248 -119
  106. data/lib/active_record/null_relation.rb +65 -0
  107. data/lib/active_record/persistence.rb +275 -57
  108. data/lib/active_record/query_cache.rb +29 -9
  109. data/lib/active_record/querying.rb +62 -0
  110. data/lib/active_record/railtie.rb +135 -21
  111. data/lib/active_record/railties/console_sandbox.rb +5 -0
  112. data/lib/active_record/railties/controller_runtime.rb +17 -5
  113. data/lib/active_record/railties/databases.rake +249 -359
  114. data/lib/active_record/railties/jdbcmysql_error.rb +16 -0
  115. data/lib/active_record/readonly_attributes.rb +30 -0
  116. data/lib/active_record/reflection.rb +283 -103
  117. data/lib/active_record/relation/batches.rb +38 -34
  118. data/lib/active_record/relation/calculations.rb +252 -139
  119. data/lib/active_record/relation/delegation.rb +125 -0
  120. data/lib/active_record/relation/finder_methods.rb +182 -188
  121. data/lib/active_record/relation/merger.rb +161 -0
  122. data/lib/active_record/relation/predicate_builder.rb +86 -21
  123. data/lib/active_record/relation/query_methods.rb +917 -134
  124. data/lib/active_record/relation/spawn_methods.rb +53 -92
  125. data/lib/active_record/relation.rb +405 -143
  126. data/lib/active_record/result.rb +67 -0
  127. data/lib/active_record/runtime_registry.rb +17 -0
  128. data/lib/active_record/sanitization.rb +168 -0
  129. data/lib/active_record/schema.rb +20 -14
  130. data/lib/active_record/schema_dumper.rb +55 -46
  131. data/lib/active_record/schema_migration.rb +39 -0
  132. data/lib/active_record/scoping/default.rb +146 -0
  133. data/lib/active_record/scoping/named.rb +175 -0
  134. data/lib/active_record/scoping.rb +82 -0
  135. data/lib/active_record/serialization.rb +8 -46
  136. data/lib/active_record/serializers/xml_serializer.rb +21 -68
  137. data/lib/active_record/statement_cache.rb +26 -0
  138. data/lib/active_record/store.rb +156 -0
  139. data/lib/active_record/tasks/database_tasks.rb +203 -0
  140. data/lib/active_record/tasks/firebird_database_tasks.rb +56 -0
  141. data/lib/active_record/tasks/mysql_database_tasks.rb +143 -0
  142. data/lib/active_record/tasks/oracle_database_tasks.rb +45 -0
  143. data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
  144. data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
  145. data/lib/active_record/tasks/sqlserver_database_tasks.rb +48 -0
  146. data/lib/active_record/test_case.rb +57 -28
  147. data/lib/active_record/timestamp.rb +49 -18
  148. data/lib/active_record/transactions.rb +106 -63
  149. data/lib/active_record/translation.rb +22 -0
  150. data/lib/active_record/validations/associated.rb +25 -24
  151. data/lib/active_record/validations/presence.rb +65 -0
  152. data/lib/active_record/validations/uniqueness.rb +123 -83
  153. data/lib/active_record/validations.rb +29 -29
  154. data/lib/active_record/version.rb +7 -5
  155. data/lib/active_record.rb +83 -34
  156. data/lib/rails/generators/active_record/migration/migration_generator.rb +46 -9
  157. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +19 -0
  158. data/lib/rails/generators/active_record/migration/templates/migration.rb +30 -8
  159. data/lib/rails/generators/active_record/model/model_generator.rb +15 -5
  160. data/lib/rails/generators/active_record/model/templates/model.rb +7 -2
  161. data/lib/rails/generators/active_record/model/templates/module.rb +3 -1
  162. data/lib/rails/generators/active_record.rb +4 -8
  163. metadata +163 -121
  164. data/CHANGELOG +0 -6023
  165. data/examples/associations.png +0 -0
  166. data/lib/active_record/association_preload.rb +0 -403
  167. data/lib/active_record/associations/association_collection.rb +0 -562
  168. data/lib/active_record/associations/association_proxy.rb +0 -295
  169. data/lib/active_record/associations/through_association_scope.rb +0 -154
  170. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -113
  171. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -401
  172. data/lib/active_record/dynamic_finder_match.rb +0 -53
  173. data/lib/active_record/dynamic_scope_match.rb +0 -32
  174. data/lib/active_record/named_scope.rb +0 -138
  175. data/lib/active_record/observer.rb +0 -140
  176. data/lib/active_record/session_store.rb +0 -340
  177. data/lib/rails/generators/active_record/model/templates/migration.rb +0 -16
  178. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  179. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -2
  180. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -24
  181. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -16
@@ -1,401 +0,0 @@
1
- require 'active_record/connection_adapters/abstract_adapter'
2
- require 'active_support/core_ext/kernel/requires'
3
-
4
- module ActiveRecord
5
- module ConnectionAdapters #:nodoc:
6
- class SQLiteColumn < Column #:nodoc:
7
- class << self
8
- def string_to_binary(value)
9
- value.gsub(/\0|\%/n) do |b|
10
- case b
11
- when "\0" then "%00"
12
- when "%" then "%25"
13
- end
14
- end
15
- end
16
-
17
- def binary_to_string(value)
18
- if value.respond_to?(:force_encoding) && value.encoding != Encoding::ASCII_8BIT
19
- value = value.force_encoding(Encoding::ASCII_8BIT)
20
- end
21
-
22
- value.gsub(/%00|%25/n) do |b|
23
- case b
24
- when "%00" then "\0"
25
- when "%25" then "%"
26
- end
27
- end
28
- end
29
- end
30
- end
31
-
32
- # The SQLite adapter works with both the 2.x and 3.x series of SQLite with the sqlite-ruby
33
- # drivers (available both as gems and from http://rubyforge.org/projects/sqlite-ruby/).
34
- #
35
- # Options:
36
- #
37
- # * <tt>:database</tt> - Path to the database file.
38
- class SQLiteAdapter < AbstractAdapter
39
- class Version
40
- include Comparable
41
-
42
- def initialize(version_string)
43
- @version = version_string.split('.').map { |v| v.to_i }
44
- end
45
-
46
- def <=>(version_string)
47
- @version <=> version_string.split('.').map { |v| v.to_i }
48
- end
49
- end
50
-
51
- def initialize(connection, logger, config)
52
- super(connection, logger)
53
- @config = config
54
- end
55
-
56
- def adapter_name #:nodoc:
57
- 'SQLite'
58
- end
59
-
60
- def supports_ddl_transactions?
61
- sqlite_version >= '2.0.0'
62
- end
63
-
64
- def supports_migrations? #:nodoc:
65
- true
66
- end
67
-
68
- def supports_primary_key? #:nodoc:
69
- true
70
- end
71
-
72
- def requires_reloading?
73
- true
74
- end
75
-
76
- def supports_add_column?
77
- sqlite_version >= '3.1.6'
78
- end
79
-
80
- def disconnect!
81
- super
82
- @connection.close rescue nil
83
- end
84
-
85
- def supports_count_distinct? #:nodoc:
86
- sqlite_version >= '3.2.6'
87
- end
88
-
89
- def supports_autoincrement? #:nodoc:
90
- sqlite_version >= '3.1.0'
91
- end
92
-
93
- def native_database_types #:nodoc:
94
- {
95
- :primary_key => default_primary_key_type,
96
- :string => { :name => "varchar", :limit => 255 },
97
- :text => { :name => "text" },
98
- :integer => { :name => "integer" },
99
- :float => { :name => "float" },
100
- :decimal => { :name => "decimal" },
101
- :datetime => { :name => "datetime" },
102
- :timestamp => { :name => "datetime" },
103
- :time => { :name => "time" },
104
- :date => { :name => "date" },
105
- :binary => { :name => "blob" },
106
- :boolean => { :name => "boolean" }
107
- }
108
- end
109
-
110
-
111
- # QUOTING ==================================================
112
-
113
- def quote_string(s) #:nodoc:
114
- @connection.class.quote(s)
115
- end
116
-
117
- def quote_column_name(name) #:nodoc:
118
- %Q("#{name}")
119
- end
120
-
121
- # Quote date/time values for use in SQL input. Includes microseconds
122
- # if the value is a Time responding to usec.
123
- def quoted_date(value) #:nodoc:
124
- if value.acts_like?(:time) && value.respond_to?(:usec)
125
- "#{super}.#{sprintf("%06d", value.usec)}"
126
- else
127
- super
128
- end
129
- end
130
-
131
-
132
- # DATABASE STATEMENTS ======================================
133
-
134
- def execute(sql, name = nil) #:nodoc:
135
- log(sql, name) { @connection.execute(sql) }
136
- end
137
-
138
- def update_sql(sql, name = nil) #:nodoc:
139
- super
140
- @connection.changes
141
- end
142
-
143
- def delete_sql(sql, name = nil) #:nodoc:
144
- sql += " WHERE 1=1" unless sql =~ /WHERE/i
145
- super sql, name
146
- end
147
-
148
- def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) #:nodoc:
149
- super || @connection.last_insert_row_id
150
- end
151
- alias :create :insert_sql
152
-
153
- def select_rows(sql, name = nil)
154
- execute(sql, name).map do |row|
155
- (0...(row.size / 2)).map { |i| row[i] }
156
- end
157
- end
158
-
159
- def begin_db_transaction #:nodoc:
160
- @connection.transaction
161
- end
162
-
163
- def commit_db_transaction #:nodoc:
164
- @connection.commit
165
- end
166
-
167
- def rollback_db_transaction #:nodoc:
168
- @connection.rollback
169
- end
170
-
171
- # SCHEMA STATEMENTS ========================================
172
-
173
- def tables(name = nil) #:nodoc:
174
- sql = <<-SQL
175
- SELECT name
176
- FROM sqlite_master
177
- WHERE type = 'table' AND NOT name = 'sqlite_sequence'
178
- SQL
179
-
180
- execute(sql, name).map do |row|
181
- row['name']
182
- end
183
- end
184
-
185
- def columns(table_name, name = nil) #:nodoc:
186
- table_structure(table_name).map do |field|
187
- SQLiteColumn.new(field['name'], field['dflt_value'], field['type'], field['notnull'].to_i == 0)
188
- end
189
- end
190
-
191
- def indexes(table_name, name = nil) #:nodoc:
192
- execute("PRAGMA index_list(#{quote_table_name(table_name)})", name).map do |row|
193
- IndexDefinition.new(
194
- table_name,
195
- row['name'],
196
- row['unique'].to_i != 0,
197
- execute("PRAGMA index_info('#{row['name']}')").map { |col|
198
- col['name']
199
- })
200
- end
201
- end
202
-
203
- def primary_key(table_name) #:nodoc:
204
- column = table_structure(table_name).find { |field|
205
- field['pk'].to_i == 1
206
- }
207
- column && column['name']
208
- end
209
-
210
- def remove_index!(table_name, index_name) #:nodoc:
211
- execute "DROP INDEX #{quote_column_name(index_name)}"
212
- end
213
-
214
- def rename_table(name, new_name)
215
- execute "ALTER TABLE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}"
216
- end
217
-
218
- # See: http://www.sqlite.org/lang_altertable.html
219
- # SQLite has an additional restriction on the ALTER TABLE statement
220
- def valid_alter_table_options( type, options)
221
- type.to_sym != :primary_key
222
- end
223
-
224
- def add_column(table_name, column_name, type, options = {}) #:nodoc:
225
- if supports_add_column? && valid_alter_table_options( type, options )
226
- super(table_name, column_name, type, options)
227
- else
228
- alter_table(table_name) do |definition|
229
- definition.column(column_name, type, options)
230
- end
231
- end
232
- end
233
-
234
- def remove_column(table_name, *column_names) #:nodoc:
235
- raise ArgumentError.new("You must specify at least one column name. Example: remove_column(:people, :first_name)") if column_names.empty?
236
- column_names.flatten.each do |column_name|
237
- alter_table(table_name) do |definition|
238
- definition.columns.delete(definition[column_name])
239
- end
240
- end
241
- end
242
- alias :remove_columns :remove_column
243
-
244
- def change_column_default(table_name, column_name, default) #:nodoc:
245
- alter_table(table_name) do |definition|
246
- definition[column_name].default = default
247
- end
248
- end
249
-
250
- def change_column_null(table_name, column_name, null, default = nil)
251
- unless null || default.nil?
252
- execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
253
- end
254
- alter_table(table_name) do |definition|
255
- definition[column_name].null = null
256
- end
257
- end
258
-
259
- def change_column(table_name, column_name, type, options = {}) #:nodoc:
260
- alter_table(table_name) do |definition|
261
- include_default = options_include_default?(options)
262
- definition[column_name].instance_eval do
263
- self.type = type
264
- self.limit = options[:limit] if options.include?(:limit)
265
- self.default = options[:default] if include_default
266
- self.null = options[:null] if options.include?(:null)
267
- end
268
- end
269
- end
270
-
271
- def rename_column(table_name, column_name, new_column_name) #:nodoc:
272
- unless columns(table_name).detect{|c| c.name == column_name.to_s }
273
- raise ActiveRecord::ActiveRecordError, "Missing column #{table_name}.#{column_name}"
274
- end
275
- alter_table(table_name, :rename => {column_name.to_s => new_column_name.to_s})
276
- end
277
-
278
- def empty_insert_statement_value
279
- "VALUES(NULL)"
280
- end
281
-
282
- protected
283
- def select(sql, name = nil) #:nodoc:
284
- execute(sql, name).map do |row|
285
- record = {}
286
- row.each do |key, value|
287
- record[key.sub(/^"?\w+"?\./, '')] = value if key.is_a?(String)
288
- end
289
- record
290
- end
291
- end
292
-
293
- def table_structure(table_name)
294
- structure = @connection.table_info(quote_table_name(table_name))
295
- raise(ActiveRecord::StatementInvalid, "Could not find table '#{table_name}'") if structure.empty?
296
- structure
297
- end
298
-
299
- def alter_table(table_name, options = {}) #:nodoc:
300
- altered_table_name = "altered_#{table_name}"
301
- caller = lambda {|definition| yield definition if block_given?}
302
-
303
- transaction do
304
- move_table(table_name, altered_table_name,
305
- options.merge(:temporary => true))
306
- move_table(altered_table_name, table_name, &caller)
307
- end
308
- end
309
-
310
- def move_table(from, to, options = {}, &block) #:nodoc:
311
- copy_table(from, to, options, &block)
312
- drop_table(from)
313
- end
314
-
315
- def copy_table(from, to, options = {}) #:nodoc:
316
- options = options.merge(:id => (!columns(from).detect{|c| c.name == 'id'}.nil? && 'id' == primary_key(from).to_s))
317
- create_table(to, options) do |definition|
318
- @definition = definition
319
- columns(from).each do |column|
320
- column_name = options[:rename] ?
321
- (options[:rename][column.name] ||
322
- options[:rename][column.name.to_sym] ||
323
- column.name) : column.name
324
-
325
- @definition.column(column_name, column.type,
326
- :limit => column.limit, :default => column.default,
327
- :null => column.null)
328
- end
329
- @definition.primary_key(primary_key(from)) if primary_key(from)
330
- yield @definition if block_given?
331
- end
332
-
333
- copy_table_indexes(from, to, options[:rename] || {})
334
- copy_table_contents(from, to,
335
- @definition.columns.map {|column| column.name},
336
- options[:rename] || {})
337
- end
338
-
339
- def copy_table_indexes(from, to, rename = {}) #:nodoc:
340
- indexes(from).each do |index|
341
- name = index.name
342
- if to == "altered_#{from}"
343
- name = "temp_#{name}"
344
- elsif from == "altered_#{to}"
345
- name = name[5..-1]
346
- end
347
-
348
- to_column_names = columns(to).map { |c| c.name }
349
- columns = index.columns.map {|c| rename[c] || c }.select do |column|
350
- to_column_names.include?(column)
351
- end
352
-
353
- unless columns.empty?
354
- # index name can't be the same
355
- opts = { :name => name.gsub(/_(#{from})_/, "_#{to}_") }
356
- opts[:unique] = true if index.unique
357
- add_index(to, columns, opts)
358
- end
359
- end
360
- end
361
-
362
- def copy_table_contents(from, to, columns, rename = {}) #:nodoc:
363
- column_mappings = Hash[*columns.map {|name| [name, name]}.flatten]
364
- rename.inject(column_mappings) {|map, a| map[a.last] = a.first; map}
365
- from_columns = columns(from).collect {|col| col.name}
366
- columns = columns.find_all{|col| from_columns.include?(column_mappings[col])}
367
- quoted_columns = columns.map { |col| quote_column_name(col) } * ','
368
-
369
- quoted_to = quote_table_name(to)
370
- @connection.execute "SELECT * FROM #{quote_table_name(from)}" do |row|
371
- sql = "INSERT INTO #{quoted_to} (#{quoted_columns}) VALUES ("
372
- sql << columns.map {|col| quote row[column_mappings[col]]} * ', '
373
- sql << ')'
374
- @connection.execute sql
375
- end
376
- end
377
-
378
- def sqlite_version
379
- @sqlite_version ||= SQLiteAdapter::Version.new(select_value('select sqlite_version(*)'))
380
- end
381
-
382
- def default_primary_key_type
383
- if supports_autoincrement?
384
- 'INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL'
385
- else
386
- 'INTEGER PRIMARY KEY NOT NULL'
387
- end
388
- end
389
-
390
- def translate_exception(exception, message)
391
- case exception.message
392
- when /column(s)? .* (is|are) not unique/
393
- RecordNotUnique.new(message, exception)
394
- else
395
- super
396
- end
397
- end
398
-
399
- end
400
- end
401
- end
@@ -1,53 +0,0 @@
1
- module ActiveRecord
2
-
3
- # = Active Record Dynamic Finder Match
4
- #
5
- # Refer to ActiveRecord::Base documentation for Dynamic attribute-based finders for detailed info
6
- #
7
- class DynamicFinderMatch
8
- def self.match(method)
9
- df_match = self.new(method)
10
- df_match.finder ? df_match : nil
11
- end
12
-
13
- def initialize(method)
14
- @finder = :first
15
- @bang = false
16
- @instantiator = nil
17
-
18
- case method.to_s
19
- when /^find_(all_by|last_by|by)_([_a-zA-Z]\w*)$/
20
- @finder = :last if $1 == 'last_by'
21
- @finder = :all if $1 == 'all_by'
22
- names = $2
23
- when /^find_by_([_a-zA-Z]\w*)\!$/
24
- @bang = true
25
- names = $1
26
- when /^find_or_(initialize|create)_by_([_a-zA-Z]\w*)$/
27
- @instantiator = $1 == 'initialize' ? :new : :create
28
- names = $2
29
- else
30
- @finder = nil
31
- end
32
- @attribute_names = names && names.split('_and_')
33
- end
34
-
35
- attr_reader :finder, :attribute_names, :instantiator
36
-
37
- def finder?
38
- !@finder.nil? && @instantiator.nil?
39
- end
40
-
41
- def instantiator?
42
- @finder == :first && !@instantiator.nil?
43
- end
44
-
45
- def creator?
46
- @finder == :first && @instantiator == :create
47
- end
48
-
49
- def bang?
50
- @bang
51
- end
52
- end
53
- end
@@ -1,32 +0,0 @@
1
- module ActiveRecord
2
-
3
- # = Active Record Dynamic Scope Match
4
- #
5
- # Provides dynamic attribute-based scopes such as <tt>scoped_by_price(4.99)</tt>
6
- # if, for example, the <tt>Product</tt> has an attribute with that name. You can
7
- # chain more <tt>scoped_by_* </tt> methods after the other. It acts like a named
8
- # scope except that it's dynamic.
9
- class DynamicScopeMatch
10
- def self.match(method)
11
- ds_match = self.new(method)
12
- ds_match.scope ? ds_match : nil
13
- end
14
-
15
- def initialize(method)
16
- @scope = true
17
- case method.to_s
18
- when /^scoped_by_([_a-zA-Z]\w*)$/
19
- names = $1
20
- else
21
- @scope = nil
22
- end
23
- @attribute_names = names && names.split('_and_')
24
- end
25
-
26
- attr_reader :scope, :attribute_names
27
-
28
- def scope?
29
- !@scope.nil?
30
- end
31
- end
32
- end
@@ -1,138 +0,0 @@
1
- require 'active_support/core_ext/array'
2
- require 'active_support/core_ext/hash/except'
3
- require 'active_support/core_ext/kernel/singleton_class'
4
- require 'active_support/core_ext/object/blank'
5
-
6
- module ActiveRecord
7
- # = Active Record Named \Scopes
8
- module NamedScope
9
- extend ActiveSupport::Concern
10
-
11
- module ClassMethods
12
- # Returns an anonymous \scope.
13
- #
14
- # posts = Post.scoped
15
- # posts.size # Fires "select count(*) from posts" and returns the count
16
- # posts.each {|p| puts p.name } # Fires "select * from posts" and loads post objects
17
- #
18
- # fruits = Fruit.scoped
19
- # fruits = fruits.where(:colour => 'red') if options[:red_only]
20
- # fruits = fruits.limit(10) if limited?
21
- #
22
- # Anonymous \scopes tend to be useful when procedurally generating complex
23
- # queries, where passing intermediate values (\scopes) around as first-class
24
- # objects is convenient.
25
- #
26
- # You can define a \scope that applies to all finders using
27
- # ActiveRecord::Base.default_scope.
28
- def scoped(options = nil)
29
- if options
30
- scoped.apply_finder_options(options)
31
- else
32
- current_scoped_methods ? relation.merge(current_scoped_methods) : relation.clone
33
- end
34
- end
35
-
36
- def scopes
37
- read_inheritable_attribute(:scopes) || write_inheritable_attribute(:scopes, {})
38
- end
39
-
40
- # Adds a class method for retrieving and querying objects. A \scope represents a narrowing of a database query,
41
- # such as <tt>where(:color => :red).select('shirts.*').includes(:washing_instructions)</tt>.
42
- #
43
- # class Shirt < ActiveRecord::Base
44
- # scope :red, where(:color => 'red')
45
- # scope :dry_clean_only, joins(:washing_instructions).where('washing_instructions.dry_clean_only = ?', true)
46
- # end
47
- #
48
- # The above calls to <tt>scope</tt> define class methods Shirt.red and Shirt.dry_clean_only. Shirt.red,
49
- # in effect, represents the query <tt>Shirt.where(:color => 'red')</tt>.
50
- #
51
- # Unlike <tt>Shirt.find(...)</tt>, however, the object returned by Shirt.red is not an Array; it
52
- # resembles the association object constructed by a <tt>has_many</tt> declaration. For instance,
53
- # you can invoke <tt>Shirt.red.first</tt>, <tt>Shirt.red.count</tt>, <tt>Shirt.red.where(:size => 'small')</tt>.
54
- # Also, just as with the association objects, named \scopes act like an Array, implementing Enumerable;
55
- # <tt>Shirt.red.each(&block)</tt>, <tt>Shirt.red.first</tt>, and <tt>Shirt.red.inject(memo, &block)</tt>
56
- # all behave as if Shirt.red really was an Array.
57
- #
58
- # These named \scopes are composable. For instance, <tt>Shirt.red.dry_clean_only</tt> will produce
59
- # all shirts that are both red and dry clean only.
60
- # Nested finds and calculations also work with these compositions: <tt>Shirt.red.dry_clean_only.count</tt>
61
- # returns the number of garments for which these criteria obtain. Similarly with
62
- # <tt>Shirt.red.dry_clean_only.average(:thread_count)</tt>.
63
- #
64
- # All \scopes are available as class methods on the ActiveRecord::Base descendant upon which
65
- # the \scopes were defined. But they are also available to <tt>has_many</tt> associations. If,
66
- #
67
- # class Person < ActiveRecord::Base
68
- # has_many :shirts
69
- # end
70
- #
71
- # then <tt>elton.shirts.red.dry_clean_only</tt> will return all of Elton's red, dry clean
72
- # only shirts.
73
- #
74
- # Named \scopes can also be procedural:
75
- #
76
- # class Shirt < ActiveRecord::Base
77
- # scope :colored, lambda {|color| where(:color => color) }
78
- # end
79
- #
80
- # In this example, <tt>Shirt.colored('puce')</tt> finds all puce shirts.
81
- #
82
- # Named \scopes can also have extensions, just as with <tt>has_many</tt> declarations:
83
- #
84
- # class Shirt < ActiveRecord::Base
85
- # scope :red, where(:color => 'red') do
86
- # def dom_id
87
- # 'red_shirts'
88
- # end
89
- # end
90
- # end
91
- #
92
- # Scopes can also be used while creating/building a record.
93
- #
94
- # class Article < ActiveRecord::Base
95
- # scope :published, where(:published => true)
96
- # end
97
- #
98
- # Article.published.new.published # => true
99
- # Article.published.create.published # => true
100
- def scope(name, scope_options = {}, &block)
101
- name = name.to_sym
102
- valid_scope_name?(name)
103
-
104
- extension = Module.new(&block) if block_given?
105
-
106
- scopes[name] = lambda do |*args|
107
- options = scope_options.is_a?(Proc) ? scope_options.call(*args) : scope_options
108
-
109
- relation = if options.is_a?(Hash)
110
- scoped.apply_finder_options(options)
111
- elsif options
112
- scoped.merge(options)
113
- else
114
- scoped
115
- end
116
-
117
- extension ? relation.extending(extension) : relation
118
- end
119
-
120
- singleton_class.send(:redefine_method, name, &scopes[name])
121
- end
122
-
123
- def named_scope(*args, &block)
124
- ActiveSupport::Deprecation.warn("Base.named_scope has been deprecated, please use Base.scope instead", caller)
125
- scope(*args, &block)
126
- end
127
-
128
- protected
129
-
130
- def valid_scope_name?(name)
131
- if !scopes[name] && respond_to?(name, true)
132
- logger.warn "Creating scope :#{name}. " \
133
- "Overwriting existing method #{self.name}.#{name}."
134
- end
135
- end
136
- end
137
- end
138
- end