activerecord 3.1.10 → 4.2.11

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.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (237) hide show
  1. checksums.yaml +6 -6
  2. data/CHANGELOG.md +1837 -338
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +39 -43
  5. data/examples/performance.rb +51 -20
  6. data/examples/simple.rb +4 -4
  7. data/lib/active_record/aggregations.rb +57 -43
  8. data/lib/active_record/association_relation.rb +35 -0
  9. data/lib/active_record/associations/alias_tracker.rb +47 -39
  10. data/lib/active_record/associations/association.rb +71 -85
  11. data/lib/active_record/associations/association_scope.rb +138 -89
  12. data/lib/active_record/associations/belongs_to_association.rb +65 -25
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +9 -3
  14. data/lib/active_record/associations/builder/association.rb +125 -29
  15. data/lib/active_record/associations/builder/belongs_to.rb +91 -60
  16. data/lib/active_record/associations/builder/collection_association.rb +69 -49
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +113 -42
  18. data/lib/active_record/associations/builder/has_many.rb +8 -64
  19. data/lib/active_record/associations/builder/has_one.rb +12 -52
  20. data/lib/active_record/associations/builder/singular_association.rb +22 -29
  21. data/lib/active_record/associations/collection_association.rb +294 -187
  22. data/lib/active_record/associations/collection_proxy.rb +961 -94
  23. data/lib/active_record/associations/foreign_association.rb +11 -0
  24. data/lib/active_record/associations/has_many_association.rb +118 -23
  25. data/lib/active_record/associations/has_many_through_association.rb +115 -45
  26. data/lib/active_record/associations/has_one_association.rb +57 -24
  27. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  28. data/lib/active_record/associations/join_dependency/join_association.rb +76 -102
  29. data/lib/active_record/associations/join_dependency/join_base.rb +7 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +30 -37
  31. data/lib/active_record/associations/join_dependency.rb +230 -156
  32. data/lib/active_record/associations/preloader/association.rb +96 -55
  33. data/lib/active_record/associations/preloader/collection_association.rb +3 -3
  34. data/lib/active_record/associations/preloader/has_many_through.rb +7 -3
  35. data/lib/active_record/associations/preloader/has_one.rb +1 -1
  36. data/lib/active_record/associations/preloader/singular_association.rb +3 -3
  37. data/lib/active_record/associations/preloader/through_association.rb +61 -32
  38. data/lib/active_record/associations/preloader.rb +113 -87
  39. data/lib/active_record/associations/singular_association.rb +29 -13
  40. data/lib/active_record/associations/through_association.rb +37 -19
  41. data/lib/active_record/associations.rb +505 -371
  42. data/lib/active_record/attribute.rb +163 -0
  43. data/lib/active_record/attribute_assignment.rb +212 -0
  44. data/lib/active_record/attribute_decorators.rb +66 -0
  45. data/lib/active_record/attribute_methods/before_type_cast.rb +52 -7
  46. data/lib/active_record/attribute_methods/dirty.rb +141 -51
  47. data/lib/active_record/attribute_methods/primary_key.rb +87 -36
  48. data/lib/active_record/attribute_methods/query.rb +5 -4
  49. data/lib/active_record/attribute_methods/read.rb +74 -117
  50. data/lib/active_record/attribute_methods/serialization.rb +70 -0
  51. data/lib/active_record/attribute_methods/time_zone_conversion.rb +49 -47
  52. data/lib/active_record/attribute_methods/write.rb +60 -21
  53. data/lib/active_record/attribute_methods.rb +409 -48
  54. data/lib/active_record/attribute_set/builder.rb +106 -0
  55. data/lib/active_record/attribute_set.rb +81 -0
  56. data/lib/active_record/attributes.rb +147 -0
  57. data/lib/active_record/autosave_association.rb +279 -232
  58. data/lib/active_record/base.rb +84 -1969
  59. data/lib/active_record/callbacks.rb +66 -28
  60. data/lib/active_record/coders/json.rb +13 -0
  61. data/lib/active_record/coders/yaml_column.rb +18 -21
  62. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +422 -243
  63. data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
  64. data/lib/active_record/connection_adapters/abstract/database_statements.rb +170 -194
  65. data/lib/active_record/connection_adapters/abstract/query_cache.rb +32 -19
  66. data/lib/active_record/connection_adapters/abstract/quoting.rb +79 -57
  67. data/lib/active_record/connection_adapters/abstract/savepoints.rb +21 -0
  68. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +125 -0
  69. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +273 -170
  70. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +50 -0
  71. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +731 -254
  72. data/lib/active_record/connection_adapters/abstract/transaction.rb +215 -0
  73. data/lib/active_record/connection_adapters/abstract_adapter.rb +339 -95
  74. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +946 -0
  75. data/lib/active_record/connection_adapters/column.rb +33 -221
  76. data/lib/active_record/connection_adapters/connection_specification.rb +275 -0
  77. data/lib/active_record/connection_adapters/mysql2_adapter.rb +140 -602
  78. data/lib/active_record/connection_adapters/mysql_adapter.rb +254 -756
  79. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +93 -0
  80. data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
  81. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +232 -0
  82. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +100 -0
  83. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
  84. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +15 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +46 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +11 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +36 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +19 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +21 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +13 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +11 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +35 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +43 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +79 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +19 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +11 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +109 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +36 -0
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +108 -0
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +152 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +596 -0
  112. data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
  113. data/lib/active_record/connection_adapters/postgresql_adapter.rb +445 -902
  114. data/lib/active_record/connection_adapters/schema_cache.rb +94 -0
  115. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +578 -25
  116. data/lib/active_record/connection_handling.rb +132 -0
  117. data/lib/active_record/core.rb +579 -0
  118. data/lib/active_record/counter_cache.rb +159 -102
  119. data/lib/active_record/dynamic_matchers.rb +140 -0
  120. data/lib/active_record/enum.rb +197 -0
  121. data/lib/active_record/errors.rb +102 -34
  122. data/lib/active_record/explain.rb +38 -0
  123. data/lib/active_record/explain_registry.rb +30 -0
  124. data/lib/active_record/explain_subscriber.rb +29 -0
  125. data/lib/active_record/fixture_set/file.rb +56 -0
  126. data/lib/active_record/fixtures.rb +318 -260
  127. data/lib/active_record/gem_version.rb +15 -0
  128. data/lib/active_record/inheritance.rb +247 -0
  129. data/lib/active_record/integration.rb +113 -0
  130. data/lib/active_record/legacy_yaml_adapter.rb +30 -0
  131. data/lib/active_record/locale/en.yml +8 -1
  132. data/lib/active_record/locking/optimistic.rb +80 -52
  133. data/lib/active_record/locking/pessimistic.rb +27 -5
  134. data/lib/active_record/log_subscriber.rb +25 -18
  135. data/lib/active_record/migration/command_recorder.rb +130 -38
  136. data/lib/active_record/migration/join_table.rb +15 -0
  137. data/lib/active_record/migration.rb +532 -201
  138. data/lib/active_record/model_schema.rb +342 -0
  139. data/lib/active_record/nested_attributes.rb +229 -139
  140. data/lib/active_record/no_touching.rb +52 -0
  141. data/lib/active_record/null_relation.rb +81 -0
  142. data/lib/active_record/persistence.rb +304 -99
  143. data/lib/active_record/query_cache.rb +25 -43
  144. data/lib/active_record/querying.rb +68 -0
  145. data/lib/active_record/railtie.rb +86 -45
  146. data/lib/active_record/railties/console_sandbox.rb +3 -4
  147. data/lib/active_record/railties/controller_runtime.rb +7 -4
  148. data/lib/active_record/railties/databases.rake +198 -377
  149. data/lib/active_record/railties/jdbcmysql_error.rb +2 -2
  150. data/lib/active_record/readonly_attributes.rb +23 -0
  151. data/lib/active_record/reflection.rb +516 -165
  152. data/lib/active_record/relation/batches.rb +96 -45
  153. data/lib/active_record/relation/calculations.rb +221 -144
  154. data/lib/active_record/relation/delegation.rb +140 -0
  155. data/lib/active_record/relation/finder_methods.rb +362 -243
  156. data/lib/active_record/relation/merger.rb +193 -0
  157. data/lib/active_record/relation/predicate_builder/array_handler.rb +48 -0
  158. data/lib/active_record/relation/predicate_builder/relation_handler.rb +13 -0
  159. data/lib/active_record/relation/predicate_builder.rb +135 -41
  160. data/lib/active_record/relation/query_methods.rb +982 -155
  161. data/lib/active_record/relation/spawn_methods.rb +50 -110
  162. data/lib/active_record/relation.rb +371 -180
  163. data/lib/active_record/result.rb +109 -12
  164. data/lib/active_record/runtime_registry.rb +22 -0
  165. data/lib/active_record/sanitization.rb +191 -0
  166. data/lib/active_record/schema.rb +19 -13
  167. data/lib/active_record/schema_dumper.rb +111 -61
  168. data/lib/active_record/schema_migration.rb +53 -0
  169. data/lib/active_record/scoping/default.rb +135 -0
  170. data/lib/active_record/scoping/named.rb +164 -0
  171. data/lib/active_record/scoping.rb +87 -0
  172. data/lib/active_record/serialization.rb +7 -45
  173. data/lib/active_record/serializers/xml_serializer.rb +14 -65
  174. data/lib/active_record/statement_cache.rb +111 -0
  175. data/lib/active_record/store.rb +205 -0
  176. data/lib/active_record/tasks/database_tasks.rb +299 -0
  177. data/lib/active_record/tasks/mysql_database_tasks.rb +159 -0
  178. data/lib/active_record/tasks/postgresql_database_tasks.rb +101 -0
  179. data/lib/active_record/tasks/sqlite_database_tasks.rb +55 -0
  180. data/lib/active_record/timestamp.rb +35 -14
  181. data/lib/active_record/transactions.rb +141 -74
  182. data/lib/active_record/translation.rb +22 -0
  183. data/lib/active_record/type/big_integer.rb +13 -0
  184. data/lib/active_record/type/binary.rb +50 -0
  185. data/lib/active_record/type/boolean.rb +31 -0
  186. data/lib/active_record/type/date.rb +50 -0
  187. data/lib/active_record/type/date_time.rb +54 -0
  188. data/lib/active_record/type/decimal.rb +64 -0
  189. data/lib/active_record/type/decimal_without_scale.rb +11 -0
  190. data/lib/active_record/type/decorator.rb +14 -0
  191. data/lib/active_record/type/float.rb +19 -0
  192. data/lib/active_record/type/hash_lookup_type_map.rb +23 -0
  193. data/lib/active_record/type/integer.rb +59 -0
  194. data/lib/active_record/type/mutable.rb +16 -0
  195. data/lib/active_record/type/numeric.rb +36 -0
  196. data/lib/active_record/type/serialized.rb +62 -0
  197. data/lib/active_record/type/string.rb +40 -0
  198. data/lib/active_record/type/text.rb +11 -0
  199. data/lib/active_record/type/time.rb +26 -0
  200. data/lib/active_record/type/time_value.rb +38 -0
  201. data/lib/active_record/type/type_map.rb +64 -0
  202. data/lib/active_record/type/unsigned_integer.rb +15 -0
  203. data/lib/active_record/type/value.rb +110 -0
  204. data/lib/active_record/type.rb +23 -0
  205. data/lib/active_record/validations/associated.rb +27 -18
  206. data/lib/active_record/validations/presence.rb +67 -0
  207. data/lib/active_record/validations/uniqueness.rb +125 -66
  208. data/lib/active_record/validations.rb +37 -30
  209. data/lib/active_record/version.rb +5 -7
  210. data/lib/active_record.rb +80 -25
  211. data/lib/rails/generators/active_record/migration/migration_generator.rb +54 -9
  212. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +19 -0
  213. data/lib/rails/generators/active_record/migration/templates/migration.rb +25 -11
  214. data/lib/rails/generators/active_record/migration.rb +11 -8
  215. data/lib/rails/generators/active_record/model/model_generator.rb +17 -4
  216. data/lib/rails/generators/active_record/model/templates/model.rb +5 -2
  217. data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
  218. data/lib/rails/generators/active_record.rb +3 -11
  219. metadata +132 -53
  220. data/examples/associations.png +0 -0
  221. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -62
  222. data/lib/active_record/associations/join_helper.rb +0 -55
  223. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
  224. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -135
  225. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -556
  226. data/lib/active_record/dynamic_finder_match.rb +0 -56
  227. data/lib/active_record/dynamic_scope_match.rb +0 -23
  228. data/lib/active_record/identity_map.rb +0 -163
  229. data/lib/active_record/named_scope.rb +0 -200
  230. data/lib/active_record/observer.rb +0 -121
  231. data/lib/active_record/session_store.rb +0 -358
  232. data/lib/active_record/test_case.rb +0 -69
  233. data/lib/rails/generators/active_record/model/templates/migration.rb +0 -17
  234. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  235. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  236. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  237. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -16
@@ -0,0 +1,159 @@
1
+ module ActiveRecord
2
+ module Tasks # :nodoc:
3
+ class MySQLDatabaseTasks # :nodoc:
4
+ DEFAULT_CHARSET = ENV['CHARSET'] || 'utf8'
5
+ DEFAULT_COLLATION = ENV['COLLATION'] || 'utf8_unicode_ci'
6
+ ACCESS_DENIED_ERROR = 1045
7
+
8
+ delegate :connection, :establish_connection, to: ActiveRecord::Base
9
+
10
+ def initialize(configuration)
11
+ @configuration = configuration
12
+ end
13
+
14
+ def create
15
+ establish_connection configuration_without_database
16
+ connection.create_database configuration['database'], creation_options
17
+ establish_connection configuration
18
+ rescue ActiveRecord::StatementInvalid => error
19
+ if /database exists/ === error.message
20
+ raise DatabaseAlreadyExists
21
+ else
22
+ raise
23
+ end
24
+ rescue error_class => error
25
+ if error.respond_to?(:errno) && error.errno == ACCESS_DENIED_ERROR
26
+ $stdout.print error.error
27
+ establish_connection root_configuration_without_database
28
+ connection.create_database configuration['database'], creation_options
29
+ if configuration['username'] != 'root'
30
+ connection.execute grant_statement.gsub(/\s+/, ' ').strip
31
+ end
32
+ establish_connection configuration
33
+ else
34
+ $stderr.puts error.inspect
35
+ $stderr.puts "Couldn't create database for #{configuration.inspect}, #{creation_options.inspect}"
36
+ $stderr.puts "(If you set the charset manually, make sure you have a matching collation)" if configuration['encoding']
37
+ end
38
+ end
39
+
40
+ def drop
41
+ establish_connection configuration
42
+ connection.drop_database configuration['database']
43
+ end
44
+
45
+ def purge
46
+ establish_connection configuration
47
+ connection.recreate_database configuration['database'], creation_options
48
+ end
49
+
50
+ def charset
51
+ connection.charset
52
+ end
53
+
54
+ def collation
55
+ connection.collation
56
+ end
57
+
58
+ def structure_dump(filename)
59
+ args = prepare_command_options
60
+ args.concat(["--result-file", "#{filename}"])
61
+ args.concat(["--no-data"])
62
+ args.concat(["#{configuration['database']}"])
63
+
64
+ run_cmd('mysqldump', args, 'dumping')
65
+ end
66
+
67
+ def structure_load(filename)
68
+ args = prepare_command_options
69
+ args.concat(['--execute', %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}])
70
+ args.concat(["--database", "#{configuration['database']}"])
71
+
72
+ run_cmd('mysql', args, 'loading')
73
+ end
74
+
75
+ private
76
+
77
+ def configuration
78
+ @configuration
79
+ end
80
+
81
+ def configuration_without_database
82
+ configuration.merge('database' => nil)
83
+ end
84
+
85
+ def creation_options
86
+ Hash.new.tap do |options|
87
+ options[:charset] = configuration['encoding'] if configuration.include? 'encoding'
88
+ options[:collation] = configuration['collation'] if configuration.include? 'collation'
89
+
90
+ # Set default charset only when collation isn't set.
91
+ options[:charset] ||= DEFAULT_CHARSET unless options[:collation]
92
+
93
+ # Set default collation only when charset is also default.
94
+ options[:collation] ||= DEFAULT_COLLATION if options[:charset] == DEFAULT_CHARSET
95
+ end
96
+ end
97
+
98
+ def error_class
99
+ if configuration['adapter'] =~ /jdbc/
100
+ require 'active_record/railties/jdbcmysql_error'
101
+ ArJdbcMySQL::Error
102
+ elsif defined?(Mysql2)
103
+ Mysql2::Error
104
+ elsif defined?(Mysql)
105
+ Mysql::Error
106
+ else
107
+ StandardError
108
+ end
109
+ end
110
+
111
+ def grant_statement
112
+ <<-SQL
113
+ GRANT ALL PRIVILEGES ON #{configuration['database']}.*
114
+ TO '#{configuration['username']}'@'localhost'
115
+ IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION;
116
+ SQL
117
+ end
118
+
119
+ def root_configuration_without_database
120
+ configuration_without_database.merge(
121
+ 'username' => 'root',
122
+ 'password' => root_password
123
+ )
124
+ end
125
+
126
+ def root_password
127
+ $stdout.print "Please provide the root password for your MySQL installation\n>"
128
+ $stdin.gets.strip
129
+ end
130
+
131
+ def prepare_command_options
132
+ {
133
+ 'host' => '--host',
134
+ 'port' => '--port',
135
+ 'socket' => '--socket',
136
+ 'username' => '--user',
137
+ 'password' => '--password',
138
+ 'encoding' => '--default-character-set',
139
+ 'sslca' => '--ssl-ca',
140
+ 'sslcert' => '--ssl-cert',
141
+ 'sslcapath' => '--ssl-capath',
142
+ 'sslcipher' => '--ssl-cipher',
143
+ 'sslkey' => '--ssl-key'
144
+ }.map { |opt, arg| "#{arg}=#{configuration[opt]}" if configuration[opt] }.compact
145
+ end
146
+
147
+ def run_cmd(cmd, args, action)
148
+ fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
149
+ end
150
+
151
+ def run_cmd_error(cmd, args, action)
152
+ msg = "failed to execute:\n"
153
+ msg << "#{cmd}"
154
+ msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
155
+ msg
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,101 @@
1
+ module ActiveRecord
2
+ module Tasks # :nodoc:
3
+ class PostgreSQLDatabaseTasks # :nodoc:
4
+ DEFAULT_ENCODING = ENV['CHARSET'] || 'utf8'
5
+
6
+ delegate :connection, :establish_connection, :clear_active_connections!,
7
+ to: ActiveRecord::Base
8
+
9
+ def initialize(configuration)
10
+ @configuration = configuration
11
+ end
12
+
13
+ def create(master_established = false)
14
+ establish_master_connection unless master_established
15
+ connection.create_database configuration['database'],
16
+ configuration.merge('encoding' => encoding)
17
+ establish_connection configuration
18
+ rescue ActiveRecord::StatementInvalid => error
19
+ if /database .* already exists/ === error.message
20
+ raise DatabaseAlreadyExists
21
+ else
22
+ raise
23
+ end
24
+ end
25
+
26
+ def drop
27
+ establish_master_connection
28
+ connection.drop_database configuration['database']
29
+ end
30
+
31
+ def charset
32
+ connection.encoding
33
+ end
34
+
35
+ def collation
36
+ connection.collation
37
+ end
38
+
39
+ def purge
40
+ clear_active_connections!
41
+ drop
42
+ create true
43
+ end
44
+
45
+ def structure_dump(filename)
46
+ set_psql_env
47
+ args = ['-s', '-x', '-O', '-f', filename]
48
+ search_path = configuration['schema_search_path']
49
+ unless search_path.blank?
50
+ args += search_path.split(',').map do |part|
51
+ "--schema=#{part.strip}"
52
+ end
53
+ end
54
+ args << configuration['database']
55
+ run_cmd('pg_dump', args, 'dumping')
56
+ File.open(filename, "a") { |f| f << "SET search_path TO #{connection.schema_search_path};\n\n" }
57
+ end
58
+
59
+ def structure_load(filename)
60
+ set_psql_env
61
+ args = [ '-q', '-f', filename, configuration['database'] ]
62
+ run_cmd('psql', args, 'loading')
63
+ end
64
+
65
+ private
66
+
67
+ def configuration
68
+ @configuration
69
+ end
70
+
71
+ def encoding
72
+ configuration['encoding'] || DEFAULT_ENCODING
73
+ end
74
+
75
+ def establish_master_connection
76
+ establish_connection configuration.merge(
77
+ 'database' => 'postgres',
78
+ 'schema_search_path' => 'public'
79
+ )
80
+ end
81
+
82
+ def set_psql_env
83
+ ENV['PGHOST'] = configuration['host'] if configuration['host']
84
+ ENV['PGPORT'] = configuration['port'].to_s if configuration['port']
85
+ ENV['PGPASSWORD'] = configuration['password'].to_s if configuration['password']
86
+ ENV['PGUSER'] = configuration['username'].to_s if configuration['username']
87
+ end
88
+
89
+ def run_cmd(cmd, args, action)
90
+ fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
91
+ end
92
+
93
+ def run_cmd_error(cmd, args, action)
94
+ msg = "failed to execute:\n"
95
+ msg << "#{cmd} #{args.join(' ')}\n\n"
96
+ msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
97
+ msg
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,55 @@
1
+ module ActiveRecord
2
+ module Tasks # :nodoc:
3
+ class SQLiteDatabaseTasks # :nodoc:
4
+ delegate :connection, :establish_connection, to: ActiveRecord::Base
5
+
6
+ def initialize(configuration, root = ActiveRecord::Tasks::DatabaseTasks.root)
7
+ @configuration, @root = configuration, root
8
+ end
9
+
10
+ def create
11
+ raise DatabaseAlreadyExists if File.exist?(configuration['database'])
12
+
13
+ establish_connection configuration
14
+ connection
15
+ end
16
+
17
+ def drop
18
+ require 'pathname'
19
+ path = Pathname.new configuration['database']
20
+ file = path.absolute? ? path.to_s : File.join(root, path)
21
+
22
+ FileUtils.rm(file) if File.exist?(file)
23
+ end
24
+
25
+ def purge
26
+ drop
27
+ create
28
+ end
29
+
30
+ def charset
31
+ connection.encoding
32
+ end
33
+
34
+ def structure_dump(filename)
35
+ dbfile = configuration['database']
36
+ `sqlite3 #{dbfile} .schema > #{filename}`
37
+ end
38
+
39
+ def structure_load(filename)
40
+ dbfile = configuration['database']
41
+ `sqlite3 #{dbfile} < "#{filename}"`
42
+ end
43
+
44
+ private
45
+
46
+ def configuration
47
+ @configuration
48
+ end
49
+
50
+ def root
51
+ @root
52
+ end
53
+ end
54
+ end
55
+ end
@@ -1,5 +1,3 @@
1
- require 'active_support/core_ext/class/attribute'
2
-
3
1
  module ActiveRecord
4
2
  # = Active Record Timestamp
5
3
  #
@@ -11,9 +9,9 @@ module ActiveRecord
11
9
  #
12
10
  # config.active_record.record_timestamps = false
13
11
  #
14
- # Timestamps are in the local timezone by default but you can use UTC by setting:
12
+ # Timestamps are in UTC by default but you can use the local timezone by setting:
15
13
  #
16
- # config.active_record.default_timezone = :utc
14
+ # config.active_record.default_timezone = :local
17
15
  #
18
16
  # == Time Zone aware attributes
19
17
  #
@@ -33,25 +31,33 @@ module ActiveRecord
33
31
  extend ActiveSupport::Concern
34
32
 
35
33
  included do
36
- class_attribute :record_timestamps, :instance_writer => false
34
+ class_attribute :record_timestamps
37
35
  self.record_timestamps = true
38
36
  end
39
37
 
38
+ def initialize_dup(other) # :nodoc:
39
+ super
40
+ clear_timestamp_attributes
41
+ end
42
+
40
43
  private
41
44
 
42
- def create #:nodoc:
45
+ def _create_record
43
46
  if self.record_timestamps
44
47
  current_time = current_time_from_proper_timezone
45
48
 
46
49
  all_timestamp_attributes.each do |column|
47
- write_attribute(column.to_s, current_time) if respond_to?(column) && self.send(column).nil?
50
+ column = column.to_s
51
+ if has_attribute?(column) && !attribute_present?(column)
52
+ write_attribute(column, current_time)
53
+ end
48
54
  end
49
55
  end
50
56
 
51
57
  super
52
58
  end
53
59
 
54
- def update(*args) #:nodoc:
60
+ def _update_record(*args)
55
61
  if should_record_timestamps?
56
62
  current_time = current_time_from_proper_timezone
57
63
 
@@ -65,7 +71,7 @@ module ActiveRecord
65
71
  end
66
72
 
67
73
  def should_record_timestamps?
68
- self.record_timestamps && (!partial_updates? || changed? || (attributes.keys & self.class.serialized_attributes.keys).present?)
74
+ self.record_timestamps && (!partial_writes? || changed?)
69
75
  end
70
76
 
71
77
  def timestamp_attributes_for_create_in_model
@@ -80,21 +86,36 @@ module ActiveRecord
80
86
  timestamp_attributes_for_create_in_model + timestamp_attributes_for_update_in_model
81
87
  end
82
88
 
83
- def timestamp_attributes_for_update #:nodoc:
89
+ def timestamp_attributes_for_update
84
90
  [:updated_at, :updated_on]
85
91
  end
86
92
 
87
- def timestamp_attributes_for_create #:nodoc:
93
+ def timestamp_attributes_for_create
88
94
  [:created_at, :created_on]
89
95
  end
90
96
 
91
- def all_timestamp_attributes #:nodoc:
97
+ def all_timestamp_attributes
92
98
  timestamp_attributes_for_create + timestamp_attributes_for_update
93
99
  end
94
100
 
95
- def current_time_from_proper_timezone #:nodoc:
101
+ def max_updated_column_timestamp(timestamp_names = timestamp_attributes_for_update)
102
+ timestamp_names
103
+ .map { |attr| self[attr] }
104
+ .compact
105
+ .map(&:to_time)
106
+ .max
107
+ end
108
+
109
+ def current_time_from_proper_timezone
96
110
  self.class.default_timezone == :utc ? Time.now.utc : Time.now
97
111
  end
112
+
113
+ # Clear attributes and changed_attributes
114
+ def clear_timestamp_attributes
115
+ all_timestamp_attributes_in_model.each do |attribute_name|
116
+ self[attribute_name] = nil
117
+ clear_attribute_changes([attribute_name])
118
+ end
119
+ end
98
120
  end
99
121
  end
100
-