activerecord 4.2.4 → 4.2.5.rc1

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 (29) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +99 -0
  3. data/lib/active_record.rb +1 -0
  4. data/lib/active_record/associations/association_scope.rb +1 -1
  5. data/lib/active_record/associations/join_dependency.rb +2 -1
  6. data/lib/active_record/associations/preloader/association.rb +5 -1
  7. data/lib/active_record/attribute_set.rb +4 -0
  8. data/lib/active_record/attribute_set/builder.rb +21 -11
  9. data/lib/active_record/connection_adapters/abstract/database_statements.rb +6 -2
  10. data/lib/active_record/connection_adapters/abstract_adapter.rb +0 -1
  11. data/lib/active_record/connection_adapters/column.rb +1 -1
  12. data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -1
  13. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +1 -1
  14. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +1 -1
  15. data/lib/active_record/connection_adapters/postgresql_adapter.rb +2 -6
  16. data/lib/active_record/core.rb +2 -0
  17. data/lib/active_record/enum.rb +1 -2
  18. data/lib/active_record/errors.rb +4 -3
  19. data/lib/active_record/gem_version.rb +2 -2
  20. data/lib/active_record/legacy_yaml_adapter.rb +30 -0
  21. data/lib/active_record/migration.rb +4 -1
  22. data/lib/active_record/reflection.rb +34 -22
  23. data/lib/active_record/relation/query_methods.rb +1 -1
  24. data/lib/active_record/tasks/database_tasks.rb +1 -1
  25. data/lib/active_record/tasks/mysql_database_tasks.rb +19 -9
  26. data/lib/active_record/tasks/postgresql_database_tasks.rb +19 -8
  27. data/lib/active_record/type/decimal.rb +3 -1
  28. data/lib/active_record/validations/uniqueness.rb +7 -1
  29. metadata +10 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7713b03190184900b6e52a043faf4d62ee785ff0
4
- data.tar.gz: cb0520a2e5d6ce794efda315f397fea372b1aa97
3
+ metadata.gz: 7913ddbd27e5cf0a082228874250fd35f19a040b
4
+ data.tar.gz: 019cbfd87bf649f63413f7498ae755f9b763ad48
5
5
  SHA512:
6
- metadata.gz: 176cf4ae3f750d0b0d85ad9465db4e80cb20e9408839a386b4de279a16f75095b3a3ca8f9d380e09425095d45c48134d1985aa7e8bbcc242b06985077ec3025b
7
- data.tar.gz: aa611ec67a99a849bd0299b77cb89afcb2a655dce4a30f9a5c38d23f94157bb676abbf9c242666a689f7ceb528ca6d04ac65d5f3639773bf5664543eb2365372
6
+ metadata.gz: adbb11cc2cd350a0ff21e982419b3d8ec4db2db257cea4bad55e4ecc7f7b514cce441cdd6b23fd7e68f6e1cedb169d1f33a7dbb4b95b938324169eb64ef829b6
7
+ data.tar.gz: 3a7b9cc225154add28df8298a101b5eeff59131549a29c0033bb955735f685c0d001711cb1f413d592bb487da030353c17bd0da18925a9ed04555214199d848f
@@ -1,3 +1,102 @@
1
+ ## Rails 4.2.5.rc1 (October 30, 2015) ##
2
+
3
+ * Set `scope.reordering_value` to `true` if :reordering values are specified.
4
+
5
+ Fixes #21886.
6
+
7
+ *Hiroaki Izu*
8
+
9
+ * Avoid disabling errors on the PostgreSQL connection when enabling the
10
+ standard_conforming_strings setting. Errors were previously disabled because
11
+ the setting wasn't writable in Postgres 8.1 and didn't exist in earlier
12
+ versions. Now Rails only supports Postgres 8.2+ we're fine to assume the
13
+ setting exists. Disabling errors caused problems when using a connection
14
+ pooling tool like PgBouncer because it's not guaranteed to have the same
15
+ connection between calls to `execute` and it could leave the connection
16
+ with errors disabled.
17
+
18
+ Fixes #22101.
19
+
20
+ *Harry Marr*
21
+
22
+ * Includes HABTM returns correct size now. It's caused by the join dependency
23
+ only instantiates one HABTM object because the join table hasn't a primary key.
24
+
25
+ Fixes #16032.
26
+
27
+ Examples:
28
+
29
+ before:
30
+
31
+ Project.first.salaried_developers.size # => 3
32
+ Project.includes(:salaried_developers).first.salaried_developers.size # => 1
33
+
34
+ after:
35
+
36
+ Project.first.salaried_developers.size # => 3
37
+ Project.includes(:salaried_developers).first.salaried_developers.size # => 3
38
+
39
+ *Bigxiang*
40
+
41
+ * Descriptive error message when fixtures contain a missing column.
42
+
43
+ Closes #21201.
44
+
45
+ *Yves Senn*
46
+
47
+ * `bin/rake db:migrate` uses
48
+ `ActiveRecord::Tasks::DatabaseTasks.migrations_paths` instead of
49
+ `Migrator.migrations_paths`.
50
+
51
+ *Tobias Bielohlawek*
52
+
53
+ * Fix `rewhere` in a `has_many` association.
54
+
55
+ Fixes #21955.
56
+
57
+ *Josh Branchaud*, *Kal*
58
+
59
+ * Added run_cmd class method to ActiveRecord::Tasks::DatabaseTasks for
60
+ drying up Kernel.system() calls within this namespace and to avoid
61
+ shell expansion by using a paramter list instead of string as arguments
62
+ for Kernel.system(). Thanks to Nate Berkopec for supply patch to get
63
+ test units passing.
64
+
65
+ *Bryan Paxton*
66
+
67
+ * Avoid leaking the first relation we call `first` on, per model.
68
+
69
+ Fixes #21921.
70
+
71
+ *Matthew Draper*, *Jean Boussier*
72
+
73
+ * Allow deserialization of Active Record models that were YAML encoded prior
74
+ to Rails 4.2
75
+
76
+ *Sean Griffin*
77
+
78
+ * Correctly apply `unscope` when preloading through associations.
79
+
80
+ *Jimmy Bourassa*
81
+
82
+ * Ensure `select` quotes aliased attributes, even when using `from`.
83
+
84
+ Fixes #21488
85
+
86
+ *Sean Griffin & @johanlunds*
87
+
88
+ * Correct query for PostgreSQL 8.2 compatibility.
89
+
90
+ *Ben Murphy*, *Matthew Draper*
91
+
92
+ * Uniqueness validator raises descriptive error when running on a persisted
93
+ record without primary key.
94
+
95
+ Closes #21304.
96
+
97
+ *Yves Senn*
98
+
99
+
1
100
  ## Rails 4.2.4 (August 24, 2015) ##
2
101
 
3
102
  * Skip statement cache on through association reader.
@@ -43,6 +43,7 @@ module ActiveRecord
43
43
  autoload :Explain
44
44
  autoload :Inheritance
45
45
  autoload :Integration
46
+ autoload :LegacyYamlAdapter
46
47
  autoload :Migration
47
48
  autoload :Migrator, 'active_record/migration'
48
49
  autoload :ModelSchema
@@ -162,10 +162,10 @@ module ActiveRecord
162
162
  scope.includes! item.includes_values
163
163
  end
164
164
 
165
+ scope.unscope!(*item.unscope_values)
165
166
  scope.where_values += item.where_values
166
167
  scope.bind_values += item.bind_values
167
168
  scope.order_values |= item.order_values
168
- scope.unscope!(*item.unscope_values)
169
169
  end
170
170
  end
171
171
 
@@ -151,7 +151,8 @@ module ActiveRecord
151
151
 
152
152
  message_bus.instrument('instantiation.active_record', payload) do
153
153
  result_set.each { |row_hash|
154
- parent = parents[row_hash[primary_key]] ||= join_root.instantiate(row_hash, column_aliases)
154
+ parent_key = primary_key ? row_hash[primary_key] : row_hash
155
+ parent = parents[parent_key] ||= join_root.instantiate(row_hash, column_aliases)
155
156
  construct(parent, join_root, row_hash, result_set, seen, model_cache, aliases)
156
157
  }
157
158
  end
@@ -145,6 +145,10 @@ module ActiveRecord
145
145
  scope.joins! preload_values[:joins] || values[:joins]
146
146
  scope.order! preload_values[:order] || values[:order]
147
147
 
148
+ if preload_values[:reordering] || values[:reordering]
149
+ scope.reordering_value = true
150
+ end
151
+
148
152
  if preload_values[:readonly] || values[:readonly]
149
153
  scope.readonly!
150
154
  end
@@ -153,7 +157,7 @@ module ActiveRecord
153
157
  scope.where!(klass.table_name => { reflection.type => model.base_class.sti_name })
154
158
  end
155
159
 
156
- scope.unscope_values = Array(values[:unscope])
160
+ scope.unscope_values = Array(values[:unscope]) + Array(preload_values[:unscope])
157
161
  klass.default_scoped.merge(scope)
158
162
  end
159
163
  end
@@ -64,6 +64,10 @@ module ActiveRecord
64
64
  end
65
65
  end
66
66
 
67
+ def ==(other)
68
+ attributes == other.attributes
69
+ end
70
+
67
71
  protected
68
72
 
69
73
  attr_reader :attributes
@@ -1,3 +1,5 @@
1
+ require 'active_record/attribute'
2
+
1
3
  module ActiveRecord
2
4
  class AttributeSet # :nodoc:
3
5
  class Builder # :nodoc:
@@ -64,10 +66,29 @@ module ActiveRecord
64
66
  end
65
67
  end
66
68
 
69
+ def ==(other)
70
+ if other.is_a?(LazyAttributeHash)
71
+ materialize == other.materialize
72
+ else
73
+ materialize == other
74
+ end
75
+ end
76
+
67
77
  protected
68
78
 
69
79
  attr_reader :types, :values, :additional_types, :delegate_hash
70
80
 
81
+ def materialize
82
+ unless @materialized
83
+ values.each_key { |key| self[key] }
84
+ types.each_key { |key| self[key] }
85
+ unless frozen?
86
+ @materialized = true
87
+ end
88
+ end
89
+ delegate_hash
90
+ end
91
+
71
92
  private
72
93
 
73
94
  def assign_default_value(name)
@@ -81,16 +102,5 @@ module ActiveRecord
81
102
  delegate_hash[name] = Attribute.uninitialized(name, type)
82
103
  end
83
104
  end
84
-
85
- def materialize
86
- unless @materialized
87
- values.each_key { |key| self[key] }
88
- types.each_key { |key| self[key] }
89
- unless frozen?
90
- @materialized = true
91
- end
92
- end
93
- delegate_hash
94
- end
95
105
  end
96
106
  end
@@ -291,8 +291,12 @@ module ActiveRecord
291
291
 
292
292
  key_list = []
293
293
  value_list = fixture.map do |name, value|
294
- key_list << quote_column_name(name)
295
- quote(value, columns[name])
294
+ if column = columns[name]
295
+ key_list << quote_column_name(name)
296
+ quote(value, column)
297
+ else
298
+ raise Fixture::FixtureError, %(table "#{table_name}" has no column named "#{name}".)
299
+ end
296
300
  end
297
301
 
298
302
  execute "INSERT INTO #{quote_table_name(table_name)} (#{key_list.join(', ')}) VALUES (#{value_list.join(', ')})", 'Fixture Insert'
@@ -457,7 +457,6 @@ module ActiveRecord
457
457
  message = "#{e.class.name}: #{e.message.force_encoding sql.encoding}: #{sql}"
458
458
  end
459
459
 
460
- @logger.error message if @logger
461
460
  exception = translate_exception(e, message)
462
461
  exception.set_backtrace e.backtrace
463
462
  exception
@@ -31,7 +31,7 @@ module ActiveRecord
31
31
  # It will be mapped to one of the standard Rails SQL types in the <tt>type</tt> attribute.
32
32
  # +null+ determines if this column allows +NULL+ values.
33
33
  def initialize(name, default, cast_type, sql_type = nil, null = true)
34
- @name = name
34
+ @name = name.freeze
35
35
  @cast_type = cast_type
36
36
  @sql_type = sql_type
37
37
  @null = null
@@ -1,6 +1,6 @@
1
1
  require 'active_record/connection_adapters/abstract_mysql_adapter'
2
2
 
3
- gem 'mysql2', '~> 0.3.13'
3
+ gem 'mysql2', '>= 0.3.13', '< 0.5'
4
4
  require 'mysql2'
5
5
 
6
6
  module ActiveRecord
@@ -36,7 +36,7 @@ module ActiveRecord
36
36
  WHERE
37
37
  t.typname IN (%s)
38
38
  OR t.typtype IN (%s)
39
- OR t.typinput::varchar = 'array_in'
39
+ OR t.typinput = 'array_in(cstring,oid,integer)'::regprocedure
40
40
  OR t.typelem != 0
41
41
  SQL
42
42
  end
@@ -86,7 +86,7 @@ module ActiveRecord
86
86
  execute "DROP DATABASE IF EXISTS #{quote_table_name(name)}"
87
87
  end
88
88
 
89
- # Returns the list of all tables in the schema search path or a specified schema.
89
+ # Returns the list of all tables in the schema search path.
90
90
  def tables(name = nil)
91
91
  query(<<-SQL, 'SCHEMA').map { |row| row[0] }
92
92
  SELECT tablename
@@ -308,12 +308,8 @@ module ActiveRecord
308
308
  true
309
309
  end
310
310
 
311
- # Enable standard-conforming strings if available.
312
311
  def set_standard_conforming_strings
313
- old, self.client_min_messages = client_min_messages, 'panic'
314
- execute('SET standard_conforming_strings = on', 'SCHEMA') rescue nil
315
- ensure
316
- self.client_min_messages = old
312
+ execute('SET standard_conforming_strings = on', 'SCHEMA')
317
313
  end
318
314
 
319
315
  def supports_ddl_transactions?
@@ -677,7 +673,7 @@ module ActiveRecord
677
673
  self.client_min_messages = @config[:min_messages] || 'warning'
678
674
  self.schema_search_path = @config[:schema_search_path] || @config[:schema_order]
679
675
 
680
- # Use standard-conforming strings if available so we don't have to do the E'...' dance.
676
+ # Use standard-conforming strings so we don't have to do the E'...' dance.
681
677
  set_standard_conforming_strings
682
678
 
683
679
  # If using Active Record's time zone support configure the connection to return
@@ -299,6 +299,7 @@ module ActiveRecord
299
299
  # post.init_with(coder)
300
300
  # post.title # => 'hello world'
301
301
  def init_with(coder)
302
+ coder = LegacyYamlAdapter.convert(self.class, coder)
302
303
  @attributes = coder['attributes']
303
304
 
304
305
  init_internals
@@ -372,6 +373,7 @@ module ActiveRecord
372
373
  coder['raw_attributes'] = attributes_before_type_cast
373
374
  coder['attributes'] = @attributes
374
375
  coder['new_record'] = new_record?
376
+ coder['active_record_yaml_version'] = 0
375
377
  end
376
378
 
377
379
  # Returns true if +comparison_object+ is the same exact object, or +comparison_object+
@@ -18,10 +18,9 @@ module ActiveRecord
18
18
  # conversation.archived? # => true
19
19
  # conversation.status # => "archived"
20
20
  #
21
- # # conversation.update! status: 1
21
+ # # conversation.status = 1
22
22
  # conversation.status = "archived"
23
23
  #
24
- # # conversation.update! status: nil
25
24
  # conversation.status = nil
26
25
  # conversation.status.nil? # => true
27
26
  # conversation.status # => nil
@@ -219,11 +219,12 @@ module ActiveRecord
219
219
  class UnknownPrimaryKey < ActiveRecordError
220
220
  attr_reader :model
221
221
 
222
- def initialize(model)
223
- super("Unknown primary key for table #{model.table_name} in model #{model}.")
222
+ def initialize(model, description = nil)
223
+ message = "Unknown primary key for table #{model.table_name} in model #{model}."
224
+ message += "\n#{description}" if description
225
+ super(message)
224
226
  @model = model
225
227
  end
226
-
227
228
  end
228
229
 
229
230
  # Raised when a relation cannot be mutated because it's already loaded.
@@ -7,8 +7,8 @@ module ActiveRecord
7
7
  module VERSION
8
8
  MAJOR = 4
9
9
  MINOR = 2
10
- TINY = 4
11
- PRE = nil
10
+ TINY = 5
11
+ PRE = "rc1"
12
12
 
13
13
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
14
14
  end
@@ -0,0 +1,30 @@
1
+ module ActiveRecord
2
+ module LegacyYamlAdapter
3
+ def self.convert(klass, coder)
4
+ return coder unless coder.is_a?(Psych::Coder)
5
+
6
+ case coder["active_record_yaml_version"]
7
+ when 0 then coder
8
+ else
9
+ if coder["attributes"].is_a?(AttributeSet)
10
+ coder
11
+ else
12
+ Rails41.convert(klass, coder)
13
+ end
14
+ end
15
+ end
16
+
17
+ module Rails41
18
+ def self.convert(klass, coder)
19
+ attributes = klass.attributes_builder
20
+ .build_from_database(coder["attributes"])
21
+ new_record = coder["attributes"][klass.primary_key].blank?
22
+
23
+ {
24
+ "attributes" => attributes,
25
+ "new_record" => new_record,
26
+ }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -420,7 +420,10 @@ module ActiveRecord
420
420
  new.migrate direction
421
421
  end
422
422
 
423
- # Disable DDL transactions for this migration.
423
+ # Disable the transaction wrapping this migration.
424
+ # You can still create your own transactions even after calling #disable_ddl_transaction!
425
+ #
426
+ # For more details read the {"Transactional Migrations" section above}[rdoc-ref:Migration].
424
427
  def disable_ddl_transaction!
425
428
  @disable_ddl_transaction = true
426
429
  end
@@ -32,6 +32,7 @@ module ActiveRecord
32
32
  end
33
33
 
34
34
  def self.add_reflection(ar, name, reflection)
35
+ ar.clear_reflections_cache
35
36
  ar._reflections = ar._reflections.merge(name.to_s => reflection)
36
37
  end
37
38
 
@@ -67,16 +68,21 @@ module ActiveRecord
67
68
  #
68
69
  # @api public
69
70
  def reflections
70
- ref = {}
71
- _reflections.each do |name, reflection|
72
- parent_name, parent_reflection = reflection.parent_reflection
73
- if parent_name
74
- ref[parent_name] = parent_reflection
75
- else
76
- ref[name] = reflection
71
+ @__reflections ||= begin
72
+ ref = {}
73
+
74
+ _reflections.each do |name, reflection|
75
+ parent_name, parent_reflection = reflection.parent_reflection
76
+
77
+ if parent_name
78
+ ref[parent_name] = parent_reflection
79
+ else
80
+ ref[name] = reflection
81
+ end
77
82
  end
83
+
84
+ ref
78
85
  end
79
- ref
80
86
  end
81
87
 
82
88
  # Returns an array of AssociationReflection objects for all the
@@ -116,6 +122,10 @@ module ActiveRecord
116
122
  def reflect_on_all_autosave_associations
117
123
  reflections.values.select { |reflection| reflection.options[:autosave] }
118
124
  end
125
+
126
+ def clear_reflections_cache #:nodoc:
127
+ @__reflections = nil
128
+ end
119
129
  end
120
130
 
121
131
  # Holds all the methods that are shared between MacroReflection, AssociationReflection
@@ -161,6 +171,20 @@ module ActiveRecord
161
171
 
162
172
  macro
163
173
  end
174
+
175
+ def inverse_of
176
+ return unless inverse_name
177
+
178
+ @inverse_of ||= klass._reflect_on_association inverse_name
179
+ end
180
+
181
+ def check_validity_of_inverse!
182
+ unless polymorphic?
183
+ if has_inverse? && inverse_of.nil?
184
+ raise InverseOfAssociationNotFoundError.new(self)
185
+ end
186
+ end
187
+ end
164
188
  end
165
189
  # Base class for AggregateReflection and AssociationReflection. Objects of
166
190
  # AggregateReflection and AssociationReflection are returned by the Reflection::ClassMethods.
@@ -331,14 +355,6 @@ module ActiveRecord
331
355
  check_validity_of_inverse!
332
356
  end
333
357
 
334
- def check_validity_of_inverse!
335
- unless polymorphic?
336
- if has_inverse? && inverse_of.nil?
337
- raise InverseOfAssociationNotFoundError.new(self)
338
- end
339
- end
340
- end
341
-
342
358
  def check_preloadable!
343
359
  return unless scope
344
360
 
@@ -387,12 +403,6 @@ module ActiveRecord
387
403
  inverse_name
388
404
  end
389
405
 
390
- def inverse_of
391
- return unless inverse_name
392
-
393
- @inverse_of ||= klass._reflect_on_association inverse_name
394
- end
395
-
396
406
  def polymorphic_inverse_of(associated_class)
397
407
  if has_inverse?
398
408
  if inverse_relationship = associated_class._reflect_on_association(options[:inverse_of])
@@ -865,6 +875,8 @@ module ActiveRecord
865
875
  klass.primary_key || raise(UnknownPrimaryKey.new(klass))
866
876
  end
867
877
 
878
+ def inverse_name; delegate_reflection.send(:inverse_name); end
879
+
868
880
  private
869
881
  def derive_class_name
870
882
  # get the class_name of the belongs_to association of the through reflection
@@ -258,7 +258,7 @@ module ActiveRecord
258
258
  def _select!(*fields) # :nodoc:
259
259
  fields.flatten!
260
260
  fields.map! do |field|
261
- klass.attribute_alias?(field) ? klass.attribute_alias(field) : field
261
+ klass.attribute_alias?(field) ? klass.attribute_alias(field).to_sym : field
262
262
  end
263
263
  self.select_values += fields
264
264
  self
@@ -134,7 +134,7 @@ module ActiveRecord
134
134
  version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
135
135
  scope = ENV['SCOPE']
136
136
  verbose_was, Migration.verbose = Migration.verbose, verbose
137
- Migrator.migrate(Migrator.migrations_paths, version) do |migration|
137
+ Migrator.migrate(migrations_paths, version) do |migration|
138
138
  scope.blank? || scope == migration.scope
139
139
  end
140
140
  ensure
@@ -56,21 +56,20 @@ module ActiveRecord
56
56
  end
57
57
 
58
58
  def structure_dump(filename)
59
- args = prepare_command_options('mysqldump')
59
+ args = prepare_command_options
60
60
  args.concat(["--result-file", "#{filename}"])
61
61
  args.concat(["--no-data"])
62
62
  args.concat(["#{configuration['database']}"])
63
- unless Kernel.system(*args)
64
- $stderr.puts "Could not dump the database structure. "\
65
- "Make sure `mysqldump` is in your PATH and check the command output for warnings."
66
- end
63
+
64
+ run_cmd('mysqldump', args, 'dumping')
67
65
  end
68
66
 
69
67
  def structure_load(filename)
70
- args = prepare_command_options('mysql')
68
+ args = prepare_command_options
71
69
  args.concat(['--execute', %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}])
72
70
  args.concat(["--database", "#{configuration['database']}"])
73
- Kernel.system(*args)
71
+
72
+ run_cmd('mysql', args, 'loading')
74
73
  end
75
74
 
76
75
  private
@@ -129,8 +128,8 @@ IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION;
129
128
  $stdin.gets.strip
130
129
  end
131
130
 
132
- def prepare_command_options(command)
133
- args = [command]
131
+ def prepare_command_options
132
+ args = []
134
133
  args.concat(['--user', configuration['username']]) if configuration['username']
135
134
  args << "--password=#{configuration['password']}" if configuration['password']
136
135
  args.concat(['--default-character-set', configuration['encoding']]) if configuration['encoding']
@@ -140,6 +139,17 @@ IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION;
140
139
 
141
140
  args
142
141
  end
142
+
143
+ def run_cmd(cmd, args, action)
144
+ fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
145
+ end
146
+
147
+ def run_cmd_error(cmd, args, action)
148
+ msg = "failed to execute:\n"
149
+ msg << "#{cmd}"
150
+ 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"
151
+ msg
152
+ end
143
153
  end
144
154
  end
145
155
  end
@@ -1,5 +1,3 @@
1
- require 'shellwords'
2
-
3
1
  module ActiveRecord
4
2
  module Tasks # :nodoc:
5
3
  class PostgreSQLDatabaseTasks # :nodoc:
@@ -46,20 +44,22 @@ module ActiveRecord
46
44
 
47
45
  def structure_dump(filename)
48
46
  set_psql_env
47
+ args = ['-i', '-s', '-x', '-O', '-f', filename]
49
48
  search_path = configuration['schema_search_path']
50
49
  unless search_path.blank?
51
- search_path = search_path.split(",").map{|search_path_part| "--schema=#{Shellwords.escape(search_path_part.strip)}" }.join(" ")
50
+ args << search_path.split(',').map do |part|
51
+ "--schema=#{part.strip}"
52
+ end.join(' ')
52
53
  end
53
-
54
- command = "pg_dump -i -s -x -O -f #{Shellwords.escape(filename)} #{search_path} #{Shellwords.escape(configuration['database'])}"
55
- raise 'Error dumping database' unless Kernel.system(command)
56
-
54
+ args << configuration['database']
55
+ run_cmd('pg_dump', args, 'dumping')
57
56
  File.open(filename, "a") { |f| f << "SET search_path TO #{connection.schema_search_path};\n\n" }
58
57
  end
59
58
 
60
59
  def structure_load(filename)
61
60
  set_psql_env
62
- Kernel.system("psql -q -f #{Shellwords.escape(filename)} #{configuration['database']}")
61
+ args = [ '-q', '-f', filename, configuration['database'] ]
62
+ run_cmd('psql', args, 'loading')
63
63
  end
64
64
 
65
65
  private
@@ -85,6 +85,17 @@ module ActiveRecord
85
85
  ENV['PGPASSWORD'] = configuration['password'].to_s if configuration['password']
86
86
  ENV['PGUSER'] = configuration['username'].to_s if configuration['username']
87
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
88
99
  end
89
100
  end
90
101
  end
@@ -14,7 +14,7 @@ module ActiveRecord
14
14
  private
15
15
 
16
16
  def cast_value(value)
17
- case value
17
+ casted_value = case value
18
18
  when ::Float
19
19
  convert_float_to_big_decimal(value)
20
20
  when ::Numeric, ::String
@@ -26,6 +26,8 @@ module ActiveRecord
26
26
  cast_value(value.to_s)
27
27
  end
28
28
  end
29
+
30
+ scale ? casted_value.round(scale) : casted_value
29
31
  end
30
32
 
31
33
  def convert_float_to_big_decimal(value)
@@ -17,7 +17,13 @@ module ActiveRecord
17
17
 
18
18
  begin
19
19
  relation = build_relation(finder_class, table, attribute, value)
20
- relation = relation.and(table[finder_class.primary_key.to_sym].not_eq(record.id)) if record.persisted?
20
+ if record.persisted?
21
+ if finder_class.primary_key
22
+ relation = relation.and(table[finder_class.primary_key.to_sym].not_eq(record.id))
23
+ else
24
+ raise UnknownPrimaryKey.new(finder_class, "Can not validate uniqueness for persisted record without primary key.")
25
+ end
26
+ end
21
27
  relation = scope_relation(record, table, relation)
22
28
  relation = finder_class.unscoped.where(relation)
23
29
  relation = relation.merge(options[:conditions]) if options[:conditions]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.2.4
4
+ version: 4.2.5.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-24 00:00:00.000000000 Z
11
+ date: 2015-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 4.2.4
19
+ version: 4.2.5.rc1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 4.2.4
26
+ version: 4.2.5.rc1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activemodel
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 4.2.4
33
+ version: 4.2.5.rc1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 4.2.4
40
+ version: 4.2.5.rc1
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: arel
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -194,6 +194,7 @@ files:
194
194
  - lib/active_record/gem_version.rb
195
195
  - lib/active_record/inheritance.rb
196
196
  - lib/active_record/integration.rb
197
+ - lib/active_record/legacy_yaml_adapter.rb
197
198
  - lib/active_record/locale/en.yml
198
199
  - lib/active_record/locking/optimistic.rb
199
200
  - lib/active_record/locking/pessimistic.rb
@@ -298,14 +299,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
298
299
  version: 1.9.3
299
300
  required_rubygems_version: !ruby/object:Gem::Requirement
300
301
  requirements:
301
- - - ">="
302
+ - - ">"
302
303
  - !ruby/object:Gem::Version
303
- version: '0'
304
+ version: 1.3.1
304
305
  requirements: []
305
306
  rubyforge_project:
306
- rubygems_version: 2.4.7
307
+ rubygems_version: 2.4.5.1
307
308
  signing_key:
308
309
  specification_version: 4
309
310
  summary: Object-relational mapper framework (part of Rails).
310
311
  test_files: []
311
- has_rdoc: