Permalink
Browse files

Merge branch 'master' into joindep

* master: (44 commits)
  grammar fix (reverted in e9a1ecd)
  Revert "fixed a doc bug in the CHANGELOG.md s/does no longer depend on/no longer depends on/"
  Add missed require making `enable_warnings` available
  Prepare generated Gemfile for Capistrano 3
  Added --model-name option scaffold_controller_generator.
  read the association instead of sending
  we should have unique sponsorable ids in the fixtures at least
  simplify populating the ordering hash
  the preloader for the RHS has all the preloaded records, so ask it
  only calculate offset index once. #12537
  Remove size alias for length validation
  Fix `singleton_class?`
  Minor Refactoring to `NumberHelper#number_to_human`
  `$SAFE = 4;` has been removed with Ruby 2.1
  scope_chain should not be mutated for other reflections
  Remove `default_primary_key_type`  and extract contains of `native_database_types` to a constant since they aren't conditional now in SQLite3Adapter. Makes it more like other adapters.
  cleanup changelog entry format. [ci skip]
  Extract a function to determine if the default value is a function
  Push default_function to superclass to avoid method check
  Dump the default function when the primary key is uuid
  ...

Conflicts:
	activerecord/lib/active_record/relation/finder_methods.rb
  • Loading branch information...
2 parents 704bf0e + e3e3851 commit ee46f1d5d2a8825de2d4973fb0301f2d85986e73 @tenderlove tenderlove committed Oct 15, 2013
Showing with 365 additions and 203 deletions.
  1. +2 −2 actionview/lib/action_view/helpers/date_helper.rb
  2. +1 −1 actionview/lib/action_view/helpers/url_helper.rb
  3. +51 −1 activerecord/CHANGELOG.md
  4. +6 −2 activerecord/lib/active_record/associations/association.rb
  5. +1 −3 activerecord/lib/active_record/associations/collection_association.rb
  6. +2 −2 activerecord/lib/active_record/associations/collection_proxy.rb
  7. +3 −3 activerecord/lib/active_record/associations/preloader.rb
  8. +12 −11 activerecord/lib/active_record/associations/preloader/through_association.rb
  9. +12 −11 activerecord/lib/active_record/connection_adapters/column.rb
  10. +9 −3 activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
  11. +16 −27 activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
  12. +1 −1 activerecord/lib/active_record/null_relation.rb
  13. +1 −0 activerecord/lib/active_record/railties/databases.rake
  14. +1 −1 activerecord/lib/active_record/reflection.rb
  15. +12 −13 activerecord/lib/active_record/relation/calculations.rb
  16. +1 −2 activerecord/lib/active_record/relation/finder_methods.rb
  17. +12 −2 activerecord/lib/active_record/sanitization.rb
  18. +1 −0 activerecord/lib/active_record/schema_dumper.rb
  19. +2 −2 activerecord/test/cases/adapters/postgresql/uuid_test.rb
  20. +12 −0 activerecord/test/cases/associations/inverse_associations_test.rb
  21. +4 −1 activerecord/test/cases/fixtures_test.rb
  22. +16 −0 activerecord/test/cases/reflection_test.rb
  23. +4 −3 activerecord/test/cases/relation/delegation_test.rb
  24. +14 −1 activerecord/test/cases/relations_test.rb
  25. +6 −0 activerecord/test/cases/sanitize_test.rb
  26. +3 −1 activerecord/test/cases/transactions_test.rb
  27. +1 −1 activerecord/test/fixtures/sponsors.yml
  28. +3 −0 activerecord/test/models/cake_designer.rb
  29. +3 −0 activerecord/test/models/chef.rb
  30. +4 −0 activerecord/test/models/department.rb
  31. +3 −0 activerecord/test/models/drink_designer.rb
  32. +6 −0 activerecord/test/models/hotel.rb
  33. +16 −0 activerecord/test/schema/schema.rb
  34. +2 −5 activerecord/test/schema/sqlite_specific_schema.rb
  35. +0 −7 activesupport/CHANGELOG.md
  36. +5 −2 activesupport/lib/active_support/core_ext/class/attribute.rb
  37. +1 −0 activesupport/lib/active_support/dependencies.rb
  38. +0 −20 activesupport/lib/active_support/duration.rb
  39. +2 −4 activesupport/lib/active_support/number_helper.rb
  40. +0 −15 activesupport/test/core_ext/duration_test.rb
  41. +0 −13 activesupport/test/core_ext/thread_test.rb
  42. +1 −1 guides/source/action_controller_overview.md
  43. +1 −1 guides/source/action_view_overview.md
  44. +1 −1 guides/source/active_record_basics.md
  45. +1 −3 guides/source/active_record_validations.md
  46. +0 −15 guides/source/active_support_core_extensions.md
  47. +2 −2 guides/source/getting_started.md
  48. +4 −0 railties/CHANGELOG.md
  49. +2 −1 railties/lib/rails/commands/server.rb
  50. +1 −1 railties/lib/rails/generators/rails/app/templates/Gemfile
  51. +1 −1 railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb
  52. +20 −5 railties/lib/rails/generators/resource_helpers.rb
  53. +48 −12 railties/test/commands/server_test.rb
  54. +4 −0 railties/test/env_helpers.rb
  55. +19 −0 railties/test/generators/named_base_test.rb
  56. +9 −0 railties/test/generators/scaffold_controller_generator_test.rb
@@ -531,7 +531,7 @@ def select_hour(datetime, options = {}, html_options = {})
# my_date = Time.now + 2.days
#
# # Generates a select field for days that defaults to the day for the date in my_date.
- # select_day(my_time)
+ # select_day(my_date)
#
# # Generates a select field for days that defaults to the number given.
# select_day(5)
@@ -541,7 +541,7 @@ def select_hour(datetime, options = {}, html_options = {})
#
# # Generates a select field for days that defaults to the day for the date in my_date
# # that is named 'due' rather than 'day'.
- # select_day(my_time, field_name: 'due')
+ # select_day(my_date, field_name: 'due')
#
# # Generates a select field for days with a custom prompt. Use <tt>prompt: true</tt> for a
# # generic prompt.
@@ -455,7 +455,7 @@ def mail_to(email_address, name = nil, html_options = {}, &block)
html_options, name = name, nil if block_given?
html_options = (html_options || {}).stringify_keys
- extras = %w{ cc bcc body subject }.map { |item|
+ extras = %w{ cc bcc body subject }.map! { |item|
option = html_options.delete(item) || next
"#{item}=#{Rack::Utils.escape_path(option)}"
}.compact
View
@@ -1,3 +1,47 @@
+* `scope_chain` should not be mutated for other reflections.
+
+ Currently `scope_chain` uses same array for building different
+ `scope_chain` for different associations. During processing
+ these arrays are sometimes mutated and because of in-place
+ mutation the changed `scope_chain` impacts other reflections.
+
+ Fix is to dup the value before adding to the `scope_chain`.
+
+ Fixes #3882.
+
+ *Neeraj Singh*
+
+* Prevent the inversed association from being reloaded on save.
+
+ Fixes #9499.
+
+ *Dmitry Polushkin*
+
+* Generate subquery for `Relation` if it passed as array condition for `where`
+ method.
+
+ Example:
+
+ # Before
+ Blog.where('id in (?)', Blog.where(id: 1))
+ # => SELECT "blogs".* FROM "blogs" WHERE "blogs"."id" = 1
+ # => SELECT "blogs".* FROM "blogs" WHERE (id IN (1))
+
+ # After
+ Blog.where('id in (?)', Blog.where(id: 1).select(:id))
+ # => SELECT "blogs".* FROM "blogs"
+ # WHERE "blogs"."id" IN (SELECT "blogs"."id" FROM "blogs" WHERE "blogs"."id" = 1)
+
+ Fixes #12415.
+
+ *Paul Nikitochkin*
+
+* For missed association exception message
+ which is raised in `ActiveRecord::Associations::Preloader` class
+ added owner record class name in order to simplify to find problem code.
+
+ *Paul Nikitochkin*
+
* `has_and_belongs_to_many` is now transparently implemented in terms of
`has_many :through`. Behavior should remain the same, if not, it is a bug.
@@ -199,6 +243,12 @@
*Yves Senn*
+* Fixes bug when using includes combined with select, the select statement was overwritten.
+
+ Fixes #11773
+
+ *Edo Balvers*
+
* Load fixtures from linked folders.
*Kassio Borges*
@@ -538,7 +588,7 @@
*Neeraj Singh*
-* Fixture setup does no longer depend on `ActiveRecord::Base.configurations`.
+* Fixture setup no longer depends on `ActiveRecord::Base.configurations`.
This is relevant when `ENV["DATABASE_URL"]` is used in place of a `database.yml`.
*Yves Senn*
@@ -17,6 +17,7 @@ module Associations
# HasManyThroughAssociation + ThroughAssociation
class Association #:nodoc:
attr_reader :owner, :target, :reflection
+ attr_accessor :inversed
delegate :options, :to => :reflection
@@ -42,6 +43,7 @@ def reset
@loaded = false
@target = nil
@stale_state = nil
+ @inversed = false
end
# Reloads the \target and returns +self+ on success.
@@ -59,8 +61,9 @@ def loaded?
# Asserts the \target has been loaded setting the \loaded flag to +true+.
def loaded!
- @loaded = true
+ @loaded = true
@stale_state = stale_state
+ @inversed = false
end
# The target is stale if the target no longer points to the record(s) that the
@@ -70,7 +73,7 @@ def loaded!
#
# Note that if the target has not been loaded, it is not considered stale.
def stale_target?
- loaded? && @stale_state != stale_state
+ !inversed && loaded? && @stale_state != stale_state
end
# Sets the target of this association to <tt>\target</tt>, and the \loaded flag to +true+.
@@ -104,6 +107,7 @@ def set_inverse_instance(record)
if record && invertible_for?(record)
inverse = record.association(inverse_reflection_for(record).name)
inverse.target = owner
+ inverse.inversed = true
end
end
@@ -195,9 +195,7 @@ def destroy_all
# Count all records using SQL. Construct options and pass them with
# scope to the target class's +count+.
- def count(column_name = nil, count_options = {})
- column_name, count_options = nil, column_name if column_name.is_a?(Hash)
-
+ def count(column_name = nil)
relation = scope
if association_scope.distinct_value
# This is needed because 'SELECT count(DISTINCT *)..' is not valid SQL.
@@ -669,8 +669,8 @@ def distinct
# # #<Pet id: 2, name: "Spook", person_id: 1>,
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
# # ]
- def count(column_name = nil, options = {})
- @association.count(column_name, options)
+ def count(column_name = nil)
+ @association.count(column_name)
end
# Returns the size of the collection. If the collection hasn't been loaded,
@@ -153,13 +153,13 @@ def records_by_reflection(association, records)
records.group_by do |record|
reflection = record.class.reflect_on_association(association)
- reflection || raise_config_error(association)
+ reflection || raise_config_error(record, association)
end
end
- def raise_config_error(association)
+ def raise_config_error(record, association)
raise ActiveRecord::ConfigurationError,
- "Association named '#{association}' was not found; " \
+ "Association named '#{association}' was not found on #{record.class.name}; " \
"perhaps you misspelled it?"
end
@@ -15,7 +15,7 @@ def associated_records_by_owner(preloader)
through_reflection.name,
through_scope)
- through_records = owners.map do |owner, h|
+ through_records = owners.map do |owner|
association = owner.association through_reflection.name
[owner, Array(association.reader)]
@@ -29,29 +29,30 @@ def associated_records_by_owner(preloader)
source_reflection.name,
reflection_scope)
+ @preloaded_records = preloaders.flat_map(&:preloaded_records)
+
middle_to_pl = preloaders.each_with_object({}) do |pl,h|
pl.owners.each { |middle|
h[middle] = pl
}
end
+ record_offset = {}
+ @preloaded_records.each_with_index do |record,i|
+ record_offset[record] = i
+ end
+
through_records.each_with_object({}) { |(lhs,center),records_by_owner|
pl_to_middle = center.group_by { |record| middle_to_pl[record] }
records_by_owner[lhs] = pl_to_middle.flat_map do |pl, middles|
rhs_records = middles.flat_map { |r|
- r.send(source_reflection.name)
+ association = r.association source_reflection.name
+
+ association.reader
}.compact
- loaded_records = pl.preloaded_records
- i = 0
- record_index = loaded_records.each_with_object({}) { |r,indexes|
- indexes[r] = i
- i += 1
- }
- records = rhs_records.sort_by { |rhs| record_index[rhs] }
- @preloaded_records.concat rhs_records
- records
+ rhs_records.sort_by { |rhs| record_offset[rhs] }
end
}
end
@@ -13,7 +13,7 @@ module Format
ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/
end
- attr_reader :name, :default, :type, :limit, :null, :sql_type, :precision, :scale
+ attr_reader :name, :default, :type, :limit, :null, :sql_type, :precision, :scale, :default_function
attr_accessor :primary, :coder
alias :encoded? :coder
@@ -27,16 +27,17 @@ module Format
# It will be mapped to one of the standard Rails SQL types in the <tt>type</tt> attribute.
# +null+ determines if this column allows +NULL+ values.
def initialize(name, default, sql_type = nil, null = true)
- @name = name
- @sql_type = sql_type
- @null = null
- @limit = extract_limit(sql_type)
- @precision = extract_precision(sql_type)
- @scale = extract_scale(sql_type)
- @type = simplified_type(sql_type)
- @default = extract_default(default)
- @primary = nil
- @coder = nil
+ @name = name
+ @sql_type = sql_type
+ @null = null
+ @limit = extract_limit(sql_type)
+ @precision = extract_precision(sql_type)
+ @scale = extract_scale(sql_type)
+ @type = simplified_type(sql_type)
+ @default = extract_default(default)
+ @default_function = nil
+ @primary = nil
+ @coder = nil
end
# Returns +true+ if the column is either of type string or text.
@@ -45,19 +45,21 @@ def postgresql_connection(config)
module ConnectionAdapters
# PostgreSQL-specific extensions to column definitions in a table.
class PostgreSQLColumn < Column #:nodoc:
- attr_accessor :array, :default_function
+ attr_accessor :array
# Instantiates a new PostgreSQL column definition in a table.
def initialize(name, default, oid_type, sql_type = nil, null = true)
@oid_type = oid_type
default_value = self.class.extract_value_from_default(default)
- @default_function = default if !default_value && default && default =~ /.+\(.*\)/
+
if sql_type =~ /\[\]$/
@array = true
super(name, default_value, sql_type[0..sql_type.length - 3], null)
else
@array = false
super(name, default_value, sql_type, null)
end
+
+ @default_function = default if has_default_function?(default_value, default)
end
# :stopdoc:
@@ -148,6 +150,10 @@ def type_cast(value)
private
+ def has_default_function?(default_value, default)
+ !default_value && (%r{\w+(.*)} === default)
+ end
+
def extract_limit(sql_type)
case sql_type
when /^bigint/i; 8
@@ -442,7 +448,7 @@ def adapter_name
def prepare_column_options(column, types)
spec = super
spec[:array] = 'true' if column.respond_to?(:array) && column.array
- spec[:default] = "\"#{column.default_function}\"" if column.respond_to?(:default_function) && column.default_function
+ spec[:default] = "\"#{column.default_function}\"" if column.default_function
spec
end
@@ -55,6 +55,21 @@ def binary_to_string(value)
class SQLite3Adapter < AbstractAdapter
include Savepoints
+ NATIVE_DATABASE_TYPES = {
+ primary_key: 'INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL',
+ string: { name: "varchar", limit: 255 },
+ text: { name: "text" },
+ integer: { name: "integer" },
+ float: { name: "float" },
+ decimal: { name: "decimal" },
+ datetime: { name: "datetime" },
+ timestamp: { name: "datetime" },
+ time: { name: "time" },
+ date: { name: "date" },
+ binary: { name: "blob" },
+ boolean: { name: "boolean" }
+ }
+
class Version
include Comparable
@@ -183,11 +198,6 @@ def supports_count_distinct? #:nodoc:
true
end
- # Returns true
- def supports_autoincrement? #:nodoc:
- true
- end
-
def supports_index_sort_order?
true
end
@@ -200,20 +210,7 @@ def allowed_index_name_length
end
def native_database_types #:nodoc:
- {
- :primary_key => default_primary_key_type,
- :string => { :name => "varchar", :limit => 255 },
- :text => { :name => "text" },
- :integer => { :name => "integer" },
- :float => { :name => "float" },
- :decimal => { :name => "decimal" },
- :datetime => { :name => "datetime" },
- :timestamp => { :name => "datetime" },
- :time => { :name => "time" },
- :date => { :name => "date" },
- :binary => { :name => "blob" },
- :boolean => { :name => "boolean" }
- }
+ NATIVE_DATABASE_TYPES
end
# Returns the current database encoding format as a string, eg: 'UTF-8'
@@ -596,14 +593,6 @@ def sqlite_version
@sqlite_version ||= SQLite3Adapter::Version.new(select_value('select sqlite_version(*)'))
end
- def default_primary_key_type
- if supports_autoincrement?
- 'INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL'
- else
- 'INTEGER PRIMARY KEY NOT NULL'
- end
- end
-
def translate_exception(exception, message)
case exception.message
when /column(s)? .* (is|are) not unique/
@@ -50,7 +50,7 @@ def sum(*)
0
end
- def calculate(_operation, _column_name, _options = {})
+ def calculate(_operation, _column_name)
if _operation == :count
0
else
@@ -287,6 +287,7 @@ db_namespace = namespace :db do
if ActiveRecord::Base.connection.supports_migrations?
File.open(filename, "a") do |f|
f.puts ActiveRecord::Base.connection.dump_schema_information
+ f.print "\n"
end
end
db_namespace['structure:dump'].reenable
Oops, something went wrong.

0 comments on commit ee46f1d

Please sign in to comment.