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
This commit is contained in:
commit
ee46f1d5d2
@ -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
|
||||
|
@ -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,12 +45,12 @@ 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)
|
||||
@ -58,6 +58,8 @@ def initialize(name, default, oid_type, sql_type = nil, null = true)
|
||||
@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
|
||||
|
@ -574,7 +574,7 @@ def scope_chain
|
||||
# Add to it the scope from this reflection (if any)
|
||||
scope_chain.first << scope if scope
|
||||
|
||||
through_scope_chain = through_reflection.scope_chain
|
||||
through_scope_chain = through_reflection.scope_chain.map(&:dup)
|
||||
|
||||
if options[:source_type]
|
||||
through_scope_chain.first <<
|
||||
|
@ -19,17 +19,16 @@ module Calculations
|
||||
#
|
||||
# Person.group(:city).count
|
||||
# # => { 'Rome' => 5, 'Paris' => 3 }
|
||||
def count(column_name = nil, options = {})
|
||||
column_name, options = nil, column_name if column_name.is_a?(Hash)
|
||||
calculate(:count, column_name, options)
|
||||
def count(column_name = nil)
|
||||
calculate(:count, column_name)
|
||||
end
|
||||
|
||||
# Calculates the average value on a given column. Returns +nil+ if there's
|
||||
# no row. See +calculate+ for examples with options.
|
||||
#
|
||||
# Person.average(:age) # => 35.8
|
||||
def average(column_name, options = {})
|
||||
calculate(:average, column_name, options)
|
||||
def average(column_name)
|
||||
calculate(:average, column_name)
|
||||
end
|
||||
|
||||
# Calculates the minimum value on a given column. The value is returned
|
||||
@ -37,8 +36,8 @@ def average(column_name, options = {})
|
||||
# +calculate+ for examples with options.
|
||||
#
|
||||
# Person.minimum(:age) # => 7
|
||||
def minimum(column_name, options = {})
|
||||
calculate(:minimum, column_name, options)
|
||||
def minimum(column_name)
|
||||
calculate(:minimum, column_name)
|
||||
end
|
||||
|
||||
# Calculates the maximum value on a given column. The value is returned
|
||||
@ -46,8 +45,8 @@ def minimum(column_name, options = {})
|
||||
# +calculate+ for examples with options.
|
||||
#
|
||||
# Person.maximum(:age) # => 93
|
||||
def maximum(column_name, options = {})
|
||||
calculate(:maximum, column_name, options)
|
||||
def maximum(column_name)
|
||||
calculate(:maximum, column_name)
|
||||
end
|
||||
|
||||
# Calculates the sum of values on a given column. The value is returned
|
||||
@ -90,15 +89,15 @@ def sum(*args)
|
||||
# Person.group(:last_name).having("min(age) > 17").minimum(:age)
|
||||
#
|
||||
# Person.sum("2 * age")
|
||||
def calculate(operation, column_name, options = {})
|
||||
def calculate(operation, column_name)
|
||||
if column_name.is_a?(Symbol) && attribute_alias?(column_name)
|
||||
column_name = attribute_alias(column_name)
|
||||
end
|
||||
|
||||
if has_include?(column_name)
|
||||
construct_relation_for_association_calculations.calculate(operation, column_name, options)
|
||||
construct_relation_for_association_calculations.calculate(operation, column_name)
|
||||
else
|
||||
perform_calculation(operation, column_name, options)
|
||||
perform_calculation(operation, column_name)
|
||||
end
|
||||
end
|
||||
|
||||
@ -181,7 +180,7 @@ def has_include?(column_name)
|
||||
eager_loading? || (includes_values.present? && (column_name || references_eager_loaded_tables?))
|
||||
end
|
||||
|
||||
def perform_calculation(operation, column_name, options = {})
|
||||
def perform_calculation(operation, column_name)
|
||||
operation = operation.to_s.downcase
|
||||
|
||||
# If #count is used with #distinct / #uniq it is considered distinct. (eg. relation.distinct.count)
|
||||
|
@ -242,10 +242,9 @@ def raise_record_not_found_exception!(ids, result_size, expected_size) #:nodoc:
|
||||
|
||||
def find_with_associations
|
||||
join_dependency = construct_join_dependency
|
||||
relation = except :select
|
||||
|
||||
aliases = join_dependency.aliases
|
||||
relation = relation.select aliases.columns
|
||||
relation = select aliases.columns
|
||||
relation = apply_join_dependency(relation, join_dependency)
|
||||
|
||||
if block_given?
|
||||
|
@ -127,7 +127,17 @@ def replace_bind_variables(statement, values) #:nodoc:
|
||||
raise_if_bind_arity_mismatch(statement, statement.count('?'), values.size)
|
||||
bound = values.dup
|
||||
c = connection
|
||||
statement.gsub('?') { quote_bound_value(bound.shift, c) }
|
||||
statement.gsub('?') do
|
||||
replace_bind_variable(bound.shift, c)
|
||||
end
|
||||
end
|
||||
|
||||
def replace_bind_variable(value, c = connection) #:nodoc:
|
||||
if ActiveRecord::Relation === value
|
||||
value.to_sql
|
||||
else
|
||||
quote_bound_value(value, c)
|
||||
end
|
||||
end
|
||||
|
||||
def replace_named_bind_variables(statement, bind_vars) #:nodoc:
|
||||
@ -135,7 +145,7 @@ def replace_named_bind_variables(statement, bind_vars) #:nodoc:
|
||||
if $1 == ':' # skip postgresql casts
|
||||
$& # return the whole match
|
||||
elsif bind_vars.include?(match = $2.to_sym)
|
||||
quote_bound_value(bind_vars[match])
|
||||
replace_bind_variable(bind_vars[match])
|
||||
else
|
||||
raise PreparedStatementInvalid, "missing value for :#{match} in #{statement}"
|
||||
end
|
||||
|
@ -123,6 +123,7 @@ def table(table, stream)
|
||||
tbl.print %Q(, primary_key: "#{pk}")
|
||||
elsif pkcol.sql_type == 'uuid'
|
||||
tbl.print ", id: :uuid"
|
||||
tbl.print %Q(, default: "#{pkcol.default_function}") if pkcol.default_function
|
||||
end
|
||||
else
|
||||
tbl.print ", id: false"
|
||||
|
@ -24,7 +24,7 @@ def setup
|
||||
@connection.reconnect!
|
||||
|
||||
@connection.transaction do
|
||||
@connection.create_table('pg_uuids', id: :uuid) do |t|
|
||||
@connection.create_table('pg_uuids', id: :uuid, default: 'uuid_generate_v1()') do |t|
|
||||
t.string 'name'
|
||||
t.uuid 'other_uuid', default: 'uuid_generate_v4()'
|
||||
end
|
||||
@ -60,7 +60,7 @@ def test_pk_and_sequence_for_uuid_primary_key
|
||||
def test_schema_dumper_for_uuid_primary_key
|
||||
schema = StringIO.new
|
||||
ActiveRecord::SchemaDumper.dump(@connection, schema)
|
||||
assert_match(/\bcreate_table "pg_uuids", id: :uuid\b/, schema.string)
|
||||
assert_match(/\bcreate_table "pg_uuids", id: :uuid, default: "uuid_generate_v1\(\)"/, schema.string)
|
||||
assert_match(/t\.uuid "other_uuid", default: "uuid_generate_v4\(\)"/, schema.string)
|
||||
end
|
||||
end
|
||||
|
@ -603,6 +603,18 @@ def test_child_instance_should_be_shared_with_replaced_via_method_parent
|
||||
assert_equal face.description, new_man.polymorphic_face.description, "Description of face should be the same after changes to replaced-parent-owned instance"
|
||||
end
|
||||
|
||||
def test_inversed_instance_should_not_be_reloaded_after_stale_state_changed
|
||||
new_man = Man.new
|
||||
face = Face.new
|
||||
new_man.face = face
|
||||
|
||||
old_inversed_man = face.man
|
||||
new_man.save!
|
||||
new_inversed_man = face.man
|
||||
|
||||
assert_equal old_inversed_man.object_id, new_inversed_man.object_id
|
||||
end
|
||||
|
||||
def test_should_not_try_to_set_inverse_instances_when_the_inverse_is_a_has_many
|
||||
i = interests(:llama_wrangling)
|
||||
m = i.polymorphic_man
|
||||
|
@ -253,7 +253,8 @@ def test_serialized_fixtures
|
||||
end
|
||||
|
||||
def test_fixtures_are_set_up_with_database_env_variable
|
||||
ENV.stubs(:[]).with("DATABASE_URL").returns("sqlite3:///:memory:")
|
||||
db_url_tmp = ENV['DATABASE_URL']
|
||||
ENV['DATABASE_URL'] = "sqlite3:///:memory:"
|
||||
ActiveRecord::Base.stubs(:configurations).returns({})
|
||||
test_case = Class.new(ActiveRecord::TestCase) do
|
||||
fixtures :accounts
|
||||
@ -266,6 +267,8 @@ def test_fixtures
|
||||
result = test_case.new(:test_fixtures).run
|
||||
|
||||
assert result.passed?, "Expected #{result.name} to pass:\n#{result}"
|
||||
ensure
|
||||
ENV['DATABASE_URL'] = db_url_tmp
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -18,6 +18,11 @@
|
||||
require 'models/tag'
|
||||
require 'models/sponsor'
|
||||
require 'models/edge'
|
||||
require 'models/hotel'
|
||||
require 'models/chef'
|
||||
require 'models/department'
|
||||
require 'models/cake_designer'
|
||||
require 'models/drink_designer'
|
||||
|
||||
class ReflectionTest < ActiveRecord::TestCase
|
||||
include ActiveRecord::Reflection
|
||||
@ -227,6 +232,17 @@ def test_scope_chain
|
||||
assert_equal expected, actual
|
||||
end
|
||||
|
||||
def test_scope_chain_does_not_interfere_with_hmt_with_polymorphic_case
|
||||
@hotel = Hotel.create!
|
||||
@department = @hotel.departments.create!
|
||||
@department.chefs.create!(employable: CakeDesigner.create!)
|
||||
@department.chefs.create!(employable: DrinkDesigner.create!)
|
||||
|
||||
assert_equal 1, @hotel.cake_designers.size
|
||||
assert_equal 1, @hotel.drink_designers.size
|
||||
assert_equal 2, @hotel.chefs.size
|
||||
end
|
||||
|
||||
def test_nested?
|
||||
assert !Author.reflect_on_association(:comments).nested?
|
||||
assert Author.reflect_on_association(:tags).nested?
|
||||
|
@ -9,10 +9,11 @@ class DelegationTest < ActiveRecord::TestCase
|
||||
def assert_responds(target, method)
|
||||
assert target.respond_to?(method)
|
||||
assert_nothing_raised do
|
||||
case target.to_a.method(method).arity
|
||||
when 0
|
||||
method_arity = target.to_a.method(method).arity
|
||||
|
||||
if method_arity.zero?
|
||||
target.send(method)
|
||||
when -1
|
||||
elsif method_arity < 0
|
||||
if method == :shuffle!
|
||||
target.send(method)
|
||||
else
|
||||
|
@ -295,7 +295,7 @@ def test_null_relation_content_size_methods
|
||||
def test_null_relation_calculations_methods
|
||||
assert_no_queries do
|
||||
assert_equal 0, Developer.none.count
|
||||
assert_equal 0, Developer.none.calculate(:count, nil, {})
|
||||
assert_equal 0, Developer.none.calculate(:count, nil)
|
||||
assert_equal nil, Developer.none.calculate(:average, 'salary')
|
||||
end
|
||||
end
|
||||
@ -486,6 +486,14 @@ def test_default_scoping_finder_methods
|
||||
assert_equal Developer.where(name: 'David').map(&:id).sort, developers
|
||||
end
|
||||
|
||||
def test_includes_with_select
|
||||
query = Post.select('comments_count AS ranking').order('ranking').includes(:comments)
|
||||
.where(comments: { id: 1 })
|
||||
|
||||
assert_equal ['comments_count AS ranking'], query.select_values
|
||||
assert_equal 1, query.to_a.size
|
||||
end
|
||||
|
||||
def test_loading_with_one_association
|
||||
posts = Post.preload(:comments)
|
||||
post = posts.find { |p| p.id == 1 }
|
||||
@ -626,6 +634,11 @@ def test_find_all_using_where_with_relation
|
||||
relation = Author.where(:id => Author.where(:id => david.id))
|
||||
assert_equal [david], relation.to_a
|
||||
}
|
||||
|
||||
assert_queries(1) {
|
||||
relation = Author.where('id in (?)', Author.where(id: david).select(:id))
|
||||
assert_equal [david], relation.to_a
|
||||
}
|
||||
end
|
||||
|
||||
def test_find_all_using_where_with_relation_and_alternate_primary_key
|
||||
|
@ -31,4 +31,10 @@ def test_sanitize_sql_array_handles_bind_variables
|
||||
assert_equal "name=#{quoted_bambi_and_thumper}", Binary.send(:sanitize_sql_array, ["name=?", "Bambi\nand\nThumper"])
|
||||
assert_equal "name=#{quoted_bambi_and_thumper}", Binary.send(:sanitize_sql_array, ["name=?", "Bambi\nand\nThumper".mb_chars])
|
||||
end
|
||||
|
||||
def test_sanitize_sql_array_handles_relations
|
||||
assert_match(/\(\bselect\b.*?\bwhere\b.*?\)/i,
|
||||
Binary.send(:sanitize_sql_array, ["id in (?)", Binary.where(id: 1)]),
|
||||
"should sanitize `Relation` as subquery")
|
||||
end
|
||||
end
|
||||
|
@ -421,7 +421,9 @@ def test_rollback_when_saving_a_frozen_record
|
||||
topic = Topic.new(:title => 'test')
|
||||
topic.freeze
|
||||
e = assert_raise(RuntimeError) { topic.save }
|
||||
assert_equal "can't modify frozen Hash", e.message
|
||||
assert_match(/frozen/i, e.message) # Not good enough, but we can't do much
|
||||
# about it since there is no specific error
|
||||
# for frozen objects.
|
||||
assert !topic.persisted?, 'not persisted'
|
||||
assert_nil topic.id
|
||||
assert topic.frozen?, 'not frozen'
|
||||
|
2
activerecord/test/fixtures/sponsors.yml
vendored
2
activerecord/test/fixtures/sponsors.yml
vendored
@ -8,5 +8,5 @@ boring_club_sponsor_for_groucho:
|
||||
sponsorable_type: Member
|
||||
crazy_club_sponsor_for_groucho:
|
||||
sponsor_club: crazy_club
|
||||
sponsorable_id: 2
|
||||
sponsorable_id: 3
|
||||
sponsorable_type: Member
|
||||
|
3
activerecord/test/models/cake_designer.rb
Normal file
3
activerecord/test/models/cake_designer.rb
Normal file
@ -0,0 +1,3 @@
|
||||
class CakeDesigner < ActiveRecord::Base
|
||||
has_one :chef, as: :employable
|
||||
end
|
3
activerecord/test/models/chef.rb
Normal file
3
activerecord/test/models/chef.rb
Normal file
@ -0,0 +1,3 @@
|
||||
class Chef < ActiveRecord::Base
|
||||
belongs_to :employable, polymorphic: true
|
||||
end
|
4
activerecord/test/models/department.rb
Normal file
4
activerecord/test/models/department.rb
Normal file
@ -0,0 +1,4 @@
|
||||
class Department < ActiveRecord::Base
|
||||
has_many :chefs
|
||||
belongs_to :hotel
|
||||
end
|
3
activerecord/test/models/drink_designer.rb
Normal file
3
activerecord/test/models/drink_designer.rb
Normal file
@ -0,0 +1,3 @@
|
||||
class DrinkDesigner < ActiveRecord::Base
|
||||
has_one :chef, as: :employable
|
||||
end
|
6
activerecord/test/models/hotel.rb
Normal file
6
activerecord/test/models/hotel.rb
Normal file
@ -0,0 +1,6 @@
|
||||
class Hotel < ActiveRecord::Base
|
||||
has_many :departments
|
||||
has_many :chefs, through: :departments
|
||||
has_many :cake_designers, source_type: 'CakeDesigner', source: :employable, through: :chefs
|
||||
has_many :drink_designers, source_type: 'DrinkDesigner', source: :employable, through: :chefs
|
||||
end
|
@ -787,6 +787,22 @@ def create_table(*args, &block)
|
||||
t.string 'from'
|
||||
end
|
||||
|
||||
create_table :hotels, force: true do |t|
|
||||
end
|
||||
create_table :departments, force: true do |t|
|
||||
t.integer :hotel_id
|
||||
end
|
||||
create_table :cake_designers, force: true do |t|
|
||||
end
|
||||
create_table :drink_designers, force: true do |t|
|
||||
end
|
||||
create_table :chefs, force: true do |t|
|
||||
t.integer :employable_id
|
||||
t.string :employable_type
|
||||
t.integer :department_id
|
||||
end
|
||||
|
||||
|
||||
except 'SQLite' do
|
||||
# fk_test_has_fk should be before fk_test_has_pk
|
||||
create_table :fk_test_has_fk, :force => true do |t|
|
||||
|
@ -1,9 +1,6 @@
|
||||
ActiveRecord::Schema.define do
|
||||
# For sqlite 3.1.0+, make a table with an autoincrement column
|
||||
if supports_autoincrement?
|
||||
create_table :table_with_autoincrement, :force => true do |t|
|
||||
t.column :name, :string
|
||||
end
|
||||
create_table :table_with_autoincrement, :force => true do |t|
|
||||
t.column :name, :string
|
||||
end
|
||||
|
||||
execute "DROP TABLE fk_test_has_fk" rescue nil
|
||||
|
@ -1,10 +1,3 @@
|
||||
* Add `flatten` and `flatten!` methods to Duration objects.
|
||||
|
||||
Example:
|
||||
Date.today + (1.month + 1.month).flatten == Date.today + 2.months
|
||||
|
||||
*Ionatan Wiznia*
|
||||
|
||||
* `require_dependency` accepts objects that respond to `to_path`, in
|
||||
particular `Pathname` instances.
|
||||
|
||||
|
@ -118,7 +118,10 @@ def class_attribute(*attrs)
|
||||
end
|
||||
|
||||
private
|
||||
def singleton_class?
|
||||
ancestors.first != self
|
||||
|
||||
unless respond_to?(:singleton_class?)
|
||||
def singleton_class?
|
||||
ancestors.first != self
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -8,6 +8,7 @@
|
||||
require 'active_support/core_ext/module/anonymous'
|
||||
require 'active_support/core_ext/module/qualified_const'
|
||||
require 'active_support/core_ext/object/blank'
|
||||
require 'active_support/core_ext/kernel/reporting'
|
||||
require 'active_support/core_ext/load_error'
|
||||
require 'active_support/core_ext/name_error'
|
||||
require 'active_support/core_ext/string/starts_ends_with'
|
||||
|
@ -81,18 +81,6 @@ def as_json(options = nil) #:nodoc:
|
||||
to_i
|
||||
end
|
||||
|
||||
# Flattens all the +parts+ of the duration, and returns a
|
||||
# new duration object.
|
||||
def flatten
|
||||
Duration.new(@value, flatten_parts)
|
||||
end
|
||||
|
||||
# Flattens all the +parts+ of this duration.
|
||||
def flatten!
|
||||
@parts = flatten_parts
|
||||
self
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def sum(sign, time = ::Time.current) #:nodoc:
|
||||
@ -109,14 +97,6 @@ def sum(sign, time = ::Time.current) #:nodoc:
|
||||
end
|
||||
end
|
||||
|
||||
def flatten_parts
|
||||
@parts.inject({}) do |result, (name, value)|
|
||||
result[name] ||= 0
|
||||
result[name] += value
|
||||
result
|
||||
end.to_a
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def method_missing(method, *args, &block) #:nodoc:
|
||||
|
@ -108,7 +108,7 @@ module NumberHelper
|
||||
|
||||
DECIMAL_UNITS = { 0 => :unit, 1 => :ten, 2 => :hundred, 3 => :thousand, 6 => :million, 9 => :billion, 12 => :trillion, 15 => :quadrillion,
|
||||
-1 => :deci, -2 => :centi, -3 => :mili, -6 => :micro, -9 => :nano, -12 => :pico, -15 => :femto }
|
||||
|
||||
INVERTED_DECIMAL_UNITS = DECIMAL_UNITS.invert
|
||||
STORAGE_UNITS = [:byte, :kb, :mb, :gb, :tb]
|
||||
|
||||
# Formats a +number+ into a US phone number (e.g., (555)
|
||||
@ -561,8 +561,6 @@ def number_to_human(number, options = {})
|
||||
#for backwards compatibility with those that didn't add strip_insignificant_zeros to their locale files
|
||||
options[:strip_insignificant_zeros] = true if not options.key?(:strip_insignificant_zeros)
|
||||
|
||||
inverted_du = DECIMAL_UNITS.invert
|
||||
|
||||
units = options.delete :units
|
||||
unit_exponents = case units
|
||||
when Hash
|
||||
@ -573,7 +571,7 @@ def number_to_human(number, options = {})
|
||||
translate_number_value_with_default("human.decimal_units.units", :locale => options[:locale], :raise => true)
|
||||
else
|
||||
raise ArgumentError, ":units must be a Hash or String translation scope."
|
||||
end.keys.map{|e_name| inverted_du[e_name] }.sort_by{|e| -e}
|
||||
end.keys.map!{|e_name| INVERTED_DECIMAL_UNITS[e_name] }.sort_by!{|e| -e}
|
||||
|
||||
number_exponent = number != 0 ? Math.log10(number.abs).floor : 0
|
||||
display_exponent = unit_exponents.find{ |e| number_exponent >= e } || 0
|
||||
|
@ -145,21 +145,6 @@ def test_to_json
|
||||
assert_equal '172800', 2.days.to_json
|
||||
end
|
||||
|
||||
def test_flatten
|
||||
a = 2.months
|
||||
b = (1.month + 1.month).flatten
|
||||
|
||||
assert_equal a.parts, b.parts
|
||||
end
|
||||
|
||||
def test_flatten!
|
||||
a = (1.month + 1.month)
|
||||
b = a.flatten
|
||||
a.flatten!
|
||||
|
||||
assert_equal a.parts, b.parts
|
||||
end
|
||||
|
||||
protected
|
||||
def with_env_tz(new_tz = 'US/Eastern')
|
||||
old_tz, ENV['TZ'] = ENV['TZ'], new_tz
|
||||
|
@ -72,17 +72,4 @@ def test_thread_variable_frozen_after_set
|
||||
end
|
||||
end
|
||||
|
||||
def test_thread_variable_security
|
||||
rubinius_skip "$SAFE is not supported on Rubinius."
|
||||
|
||||
t = Thread.new { sleep }
|
||||
|
||||
assert_raises(SecurityError) do
|
||||
Thread.new { $SAFE = 4; t.thread_variable_get(:foo) }.join
|
||||
end
|
||||
|
||||
assert_raises(SecurityError) do
|
||||
Thread.new { $SAFE = 4; t.thread_variable_set(:foo, :baz) }.join
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -209,7 +209,7 @@ class PeopleController < ActionController::Base
|
||||
# Request reply.
|
||||
def update
|
||||
person = current_account.people.find(params[:id])
|
||||
person.update_attributes!(person_params)
|
||||
person.update!(person_params)
|
||||
redirect_to person
|
||||
end
|
||||
|
||||
|
@ -269,7 +269,7 @@ Rails will render the `_product_ruler` partial (with no data passed to it) betwe
|
||||
|
||||
### Layouts
|
||||
|
||||
Layouts can be used to render a common view template around the results of Rails controller actions. Typically, every Rails has a couple of overall layouts that most pages are rendered within. For example, a site might have a layout for a logged in user, and a layout for the marketing or sales side of the site. The logged in user layout might include top-level navigation that should be present across many controller actions. The sales layout for a SaaS app might include top-level navigation for things like "Pricing" and "Contact Us." You would expect each layout to have a different look and feel. You can read more details about Layouts in the [Layouts and Rendering in Rails](layouts_and_rendering.html) guide.
|
||||
Layouts can be used to render a common view template around the results of Rails controller actions. Typically, every Rails application has a couple of overall layouts that most pages are rendered within. For example, a site might have a layout for a logged in user, and a layout for the marketing or sales side of the site. The logged in user layout might include top-level navigation that should be present across many controller actions. The sales layout for a SaaS app might include top-level navigation for things like "Pricing" and "Contact Us." You would expect each layout to have a different look and feel. You can read more details about Layouts in the [Layouts and Rendering in Rails](layouts_and_rendering.html) guide.
|
||||
|
||||
Partial Layouts
|
||||
---------------
|
||||
|
@ -116,7 +116,7 @@ to Active Record instances:
|
||||
locking](http://api.rubyonrails.org/classes/ActiveRecord/Locking.html) to
|
||||
a model.
|
||||
* `type` - Specifies that the model uses [Single Table
|
||||
Inheritance](http://api.rubyonrails.org/classes/ActiveRecord/Base.html).
|
||||
Inheritance](http://api.rubyonrails.org/classes/ActiveRecord/Base.html#label-Single+table+inheritance).
|
||||
* `(association_name)_type` - Stores the type for
|
||||
[polymorphic associations](association_basics.html#polymorphic-associations).
|
||||
* `(table_name)_count` - Used to cache the number of belonging objects on
|
||||
|
@ -438,8 +438,6 @@ provide a personalized message or use `presence: true` instead. When
|
||||
`:in` or `:within` have a lower limit of 1, you should either provide a
|
||||
personalized message or call `presence` prior to `length`.
|
||||
|
||||
The `size` helper is an alias for `length`.
|
||||
|
||||
### `numericality`
|
||||
|
||||
This helper validates that your attributes have only numeric values. By
|
||||
@ -528,7 +526,7 @@ If you validate the presence of an object associated via a `has_one` or
|
||||
Since `false.blank?` is true, if you want to validate the presence of a boolean
|
||||
field you should use `validates :field_name, inclusion: { in: [true, false] }`.
|
||||
|
||||
The default error message is _"can't be empty"_.
|
||||
The default error message is _"can't be blank"_.
|
||||
|
||||
### `absence`
|
||||
|
||||
|
@ -3699,21 +3699,6 @@ Time.utc(1582, 10, 3) + 5.days
|
||||
# => Mon Oct 18 00:00:00 UTC 1582
|
||||
```
|
||||
|
||||
When addinng or substracting durations, the resulting duration will be equivalent to subsequent calls to since or advance, so:
|
||||
|
||||
```ruby
|
||||
Date.new(2013,1,28) + 1.month + 1.month
|
||||
# => Thu, 28 Mar 2013
|
||||
```
|
||||
|
||||
If you want to add durations and then use them as just one call to since or advance, you can use the flatten or flatten! method:
|
||||
|
||||
```ruby
|
||||
Date.new(2013,1,31) + (1.month + 1.month).flatten
|
||||
# => Sun, 31 Mar 2013
|
||||
```
|
||||
|
||||
|
||||
Extensions to `File`
|
||||
--------------------
|
||||
|
||||
|
@ -1490,8 +1490,8 @@ So first, we'll wire up the Post show template
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<%= link_to 'Edit Post', edit_post_path(@post) %> |
|
||||
<%= link_to 'Back to Posts', posts_path %>
|
||||
<%= link_to 'Back', posts_path %>
|
||||
| <%= link_to 'Edit', edit_post_path(@post) %>
|
||||
```
|
||||
|
||||
This adds a form on the `Post` show page that creates a new comment by
|
||||
|
@ -1,3 +1,7 @@
|
||||
* Added `--model-name` scaffld\_controller\_generator option.
|
||||
|
||||
*yalab*
|
||||
|
||||
* Expose MiddlewareStack#unshift to environment configuration.
|
||||
|
||||
*Ben Pickles*
|
||||
|
@ -1,6 +1,7 @@
|
||||
require 'fileutils'
|
||||
require 'optparse'
|
||||
require 'action_dispatch'
|
||||
require 'rails'
|
||||
|
||||
module Rails
|
||||
class Server < ::Rack::Server
|
||||
@ -32,7 +33,7 @@ def parse!(args)
|
||||
|
||||
opt_parser.parse! args
|
||||
|
||||
options[:log_stdout] = options[:daemonize].blank? && options[:environment] == "development"
|
||||
options[:log_stdout] = options[:daemonize].blank? && (options[:environment] || Rails.env) == "development"
|
||||
options[:server] = args.shift
|
||||
options
|
||||
end
|
||||
|
@ -25,7 +25,7 @@ end
|
||||
# gem 'unicorn'
|
||||
|
||||
# Use Capistrano for deployment
|
||||
# gem 'capistrano', group: :development
|
||||
# gem 'capistrano-rails', group: :development
|
||||
|
||||
<% unless defined?(JRUBY_VERSION) -%>
|
||||
# Use debugger
|
||||
|
@ -13,7 +13,7 @@ class ScaffoldControllerGenerator < NamedBase # :nodoc:
|
||||
argument :attributes, type: :array, default: [], banner: "field:type field:type"
|
||||
|
||||
def create_controller_files
|
||||
template "controller.rb", File.join('app/controllers', class_path, "#{controller_file_name}_controller.rb")
|
||||
template "controller.rb", File.join('app/controllers', controller_class_path, "#{controller_file_name}_controller.rb")
|
||||
end
|
||||
|
||||
hook_for :template_engine, :test_framework, as: :scaffold
|
||||
|
@ -9,11 +9,19 @@ module ResourceHelpers # :nodoc:
|
||||
|
||||
def self.included(base) #:nodoc:
|
||||
base.class_option :force_plural, type: :boolean, desc: "Forces the use of a plural ModelName"
|
||||
base.class_option :model_name, type: :string, desc: "ModelName to be used"
|
||||
end
|
||||
|
||||
# Set controller variables on initialization.
|
||||
def initialize(*args) #:nodoc:
|
||||
super
|
||||
if options[:model_name]
|
||||
controller_name = name
|
||||
self.name = options[:model_name]
|
||||
assign_names!(self.name)
|
||||
else
|
||||
controller_name = name
|
||||
end
|
||||
|
||||
if name == name.pluralize && name.singularize != name.pluralize && !options[:force_plural]
|
||||
unless ResourceHelpers.skip_warn
|
||||
@ -24,19 +32,26 @@ def initialize(*args) #:nodoc:
|
||||
assign_names!(name)
|
||||
end
|
||||
|
||||
@controller_name = name.pluralize
|
||||
assign_controller_names!(controller_name.pluralize)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
attr_reader :controller_name
|
||||
attr_reader :controller_name, :controller_file_name
|
||||
|
||||
def controller_class_path
|
||||
class_path
|
||||
if options[:model_name]
|
||||
@controller_class_path
|
||||
else
|
||||
class_path
|
||||
end
|
||||
end
|
||||
|
||||
def controller_file_name
|
||||
@controller_file_name ||= file_name.pluralize
|
||||
def assign_controller_names!(name)
|
||||
@controller_name = name
|
||||
@controller_class_path = name.include?('/') ? name.split('/') : name.split('::')
|
||||
@controller_class_path.map! { |m| m.underscore }
|
||||
@controller_file_name = @controller_class_path.pop
|
||||
end
|
||||
|
||||
def controller_file_path
|
||||
|
@ -27,26 +27,62 @@ def test_server_option_without_environment
|
||||
end
|
||||
|
||||
def test_environment_with_rails_env
|
||||
with_rails_env 'production' do
|
||||
server = Rails::Server.new
|
||||
assert_equal 'production', server.options[:environment]
|
||||
with_rack_env nil do
|
||||
with_rails_env 'production' do
|
||||
server = Rails::Server.new
|
||||
assert_equal 'production', server.options[:environment]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_environment_with_rack_env
|
||||
with_rack_env 'production' do
|
||||
server = Rails::Server.new
|
||||
assert_equal 'production', server.options[:environment]
|
||||
with_rails_env nil do
|
||||
with_rack_env 'production' do
|
||||
server = Rails::Server.new
|
||||
assert_equal 'production', server.options[:environment]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_log_stdout
|
||||
args = ["-e", "development"]
|
||||
options = Rails::Server::Options.new.parse!(args)
|
||||
assert_equal true, options[:log_stdout]
|
||||
with_rack_env nil do
|
||||
with_rails_env nil do
|
||||
args = []
|
||||
options = Rails::Server::Options.new.parse!(args)
|
||||
assert_equal true, options[:log_stdout]
|
||||
|
||||
args = ["-e", "production"]
|
||||
options = Rails::Server::Options.new.parse!(args)
|
||||
assert_equal false, options[:log_stdout]
|
||||
args = ["-e", "development"]
|
||||
options = Rails::Server::Options.new.parse!(args)
|
||||
assert_equal true, options[:log_stdout]
|
||||
|
||||
args = ["-e", "production"]
|
||||
options = Rails::Server::Options.new.parse!(args)
|
||||
assert_equal false, options[:log_stdout]
|
||||
|
||||
with_rack_env 'development' do
|
||||
args = []
|
||||
options = Rails::Server::Options.new.parse!(args)
|
||||
assert_equal true, options[:log_stdout]
|
||||
end
|
||||
|
||||
with_rack_env 'production' do
|
||||
args = []
|
||||
options = Rails::Server::Options.new.parse!(args)
|
||||
assert_equal false, options[:log_stdout]
|
||||
end
|
||||
|
||||
with_rails_env 'development' do
|
||||
args = []
|
||||
options = Rails::Server::Options.new.parse!(args)
|
||||
assert_equal true, options[:log_stdout]
|
||||
end
|
||||
|
||||
with_rails_env 'production' do
|
||||
args = []
|
||||
options = Rails::Server::Options.new.parse!(args)
|
||||
assert_equal false, options[:log_stdout]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,7 +1,10 @@
|
||||
require 'rails'
|
||||
|
||||
module EnvHelpers
|
||||
private
|
||||
|
||||
def with_rails_env(env)
|
||||
Rails.instance_variable_set :@_env, nil
|
||||
switch_env 'RAILS_ENV', env do
|
||||
switch_env 'RACK_ENV', nil do
|
||||
yield
|
||||
@ -10,6 +13,7 @@ def with_rails_env(env)
|
||||
end
|
||||
|
||||
def with_rack_env(env)
|
||||
Rails.instance_variable_set :@_env, nil
|
||||
switch_env 'RACK_ENV', env do
|
||||
switch_env 'RAILS_ENV', nil do
|
||||
yield
|
||||
|
@ -117,6 +117,25 @@ def test_hide_namespace
|
||||
assert Rails::Generators.hidden_namespaces.include?('hidden')
|
||||
end
|
||||
|
||||
def test_scaffold_plural_names_with_model_name_option
|
||||
g = generator ['Admin::Foo'], model_name: 'User'
|
||||
assert_name g, 'user', :singular_name
|
||||
assert_name g, 'User', :name
|
||||
assert_name g, 'user', :file_path
|
||||
assert_name g, 'User', :class_name
|
||||
assert_name g, 'user', :file_name
|
||||
assert_name g, 'User', :human_name
|
||||
assert_name g, 'users', :plural_name
|
||||
assert_name g, 'user', :i18n_scope
|
||||
assert_name g, 'users', :table_name
|
||||
assert_name g, 'Admin::Foos', :controller_name
|
||||
assert_name g, %w(admin), :controller_class_path
|
||||
assert_name g, 'Admin::Foos', :controller_class_name
|
||||
assert_name g, 'admin/foos', :controller_file_path
|
||||
assert_name g, 'foos', :controller_file_name
|
||||
assert_name g, 'admin.foos', :controller_i18n_scope
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def assert_name(generator, value, method)
|
||||
|
@ -166,4 +166,13 @@ def test_new_hash_style
|
||||
assert_match(/render action: 'new'/, content)
|
||||
end
|
||||
end
|
||||
|
||||
def test_model_name_option
|
||||
run_generator ["Admin::User", "--model-name=User"]
|
||||
assert_file "app/controllers/admin/users_controller.rb" do |content|
|
||||
assert_instance_method :index, content do |m|
|
||||
assert_match("@users = User.all", m)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user