Skip to content

Commit

Permalink
Merge branch 'master' into joindep
Browse files Browse the repository at this point in the history
* 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
tenderlove committed Oct 15, 2013
2 parents 704bf0e + e3e3851 commit ee46f1d
Show file tree
Hide file tree
Showing 56 changed files with 365 additions and 203 deletions.
4 changes: 2 additions & 2 deletions actionview/lib/action_view/helpers/date_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion actionview/lib/action_view/helpers/url_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
52 changes: 51 additions & 1 deletion activerecord/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.

Expand Down Expand Up @@ -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*
Expand Down Expand Up @@ -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*
Expand Down
8 changes: 6 additions & 2 deletions activerecord/lib/active_record/associations/association.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ module Associations
# HasManyThroughAssociation + ThroughAssociation
class Association #:nodoc:
attr_reader :owner, :target, :reflection
attr_accessor :inversed

delegate :options, :to => :reflection

Expand All @@ -42,6 +43,7 @@ def reset
@loaded = false
@target = nil
@stale_state = nil
@inversed = false
end

# Reloads the \target and returns +self+ on success.
Expand All @@ -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
Expand All @@ -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+.
Expand Down Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 3 additions & 3 deletions activerecord/lib/active_record/associations/preloader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -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
Expand Down
23 changes: 12 additions & 11 deletions activerecord/lib/active_record/connection_adapters/column.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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'
Expand Down Expand Up @@ -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/
Expand Down
2 changes: 1 addition & 1 deletion activerecord/lib/active_record/null_relation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def sum(*)
0
end

def calculate(_operation, _column_name, _options = {})
def calculate(_operation, _column_name)
if _operation == :count
0
else
Expand Down
1 change: 1 addition & 0 deletions activerecord/lib/active_record/railties/databases.rake
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit ee46f1d

Please sign in to comment.