diff options
22 files changed, 97 insertions, 140 deletions
diff --git a/actionpack/test/lib/controller/fake_models.rb b/actionpack/test/lib/controller/fake_models.rb index 38abb16d08..08af187311 100644 --- a/actionpack/test/lib/controller/fake_models.rb +++ b/actionpack/test/lib/controller/fake_models.rb @@ -96,88 +96,6 @@ class Comment attr_accessor :body end -class Tag - extend ActiveModel::Naming - include ActiveModel::Conversion - - attr_reader :id - attr_reader :post_id - def initialize(id = nil, post_id = nil); @id, @post_id = id, post_id end - def to_key; id ? [id] : nil end - def save; @id = 1; @post_id = 1 end - def persisted?; @id.present? end - def to_param; @id; end - def value - @id.nil? ? "new #{self.class.name.downcase}" : "#{self.class.name.downcase} ##{@id}" - end - - attr_accessor :relevances - def relevances_attributes=(attributes); end - -end - -class CommentRelevance - extend ActiveModel::Naming - include ActiveModel::Conversion - - attr_reader :id - attr_reader :comment_id - def initialize(id = nil, comment_id = nil); @id, @comment_id = id, comment_id end - def to_key; id ? [id] : nil end - def save; @id = 1; @comment_id = 1 end - def persisted?; @id.present? end - def to_param; @id; end - def value - @id.nil? ? "new #{self.class.name.downcase}" : "#{self.class.name.downcase} ##{@id}" - end -end - -class Sheep - extend ActiveModel::Naming - include ActiveModel::Conversion - - attr_reader :id - def to_key; id ? [id] : nil end - def save; @id = 1 end - def new_record?; @id.nil? end - def name - @id.nil? ? 'new sheep' : "sheep ##{@id}" - end -end - - -class TagRelevance - extend ActiveModel::Naming - include ActiveModel::Conversion - - attr_reader :id - attr_reader :tag_id - def initialize(id = nil, tag_id = nil); @id, @tag_id = id, tag_id end - def to_key; id ? [id] : nil end - def save; @id = 1; @tag_id = 1 end - def persisted?; @id.present? end - def to_param; @id; end - def value - @id.nil? ? "new #{self.class.name.downcase}" : "#{self.class.name.downcase} ##{@id}" - end -end - -class Author < Comment - attr_accessor :post - def post_attributes=(attributes); end -end - -class HashBackedAuthor < Hash - extend ActiveModel::Naming - include ActiveModel::Conversion - - def persisted?; false; end - - def name - "hash backed author" - end -end - module Blog def self.use_relative_model_naming? true @@ -193,21 +111,8 @@ module Blog end end -class ArelLike - def to_ary - true - end - def each - a = Array.new(2) { |id| Comment.new(id + 1) } - a.each { |i| yield i } - end -end - class RenderJsonTestException < Exception def to_json(options = nil) return { :error => self.class.name, :message => self.to_s }.to_json end end - -class Car < Struct.new(:color) -end diff --git a/actionview/lib/action_view/helpers/form_helper.rb b/actionview/lib/action_view/helpers/form_helper.rb index ead7871fc5..38d969ed0c 100644 --- a/actionview/lib/action_view/helpers/form_helper.rb +++ b/actionview/lib/action_view/helpers/form_helper.rb @@ -1173,7 +1173,7 @@ module ActionView # methods in the +FormHelper+ module. This class, however, allows you to # call methods with the model object you are building the form for. # - # You can create your own custom FormBuilder templates by subclasses this + # You can create your own custom FormBuilder templates by subclassing this # class. For example: # # class MyFormBuilder < ActionView::Helpers::FormBuilder diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 0b7fbe5a48..2d19e44abc 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,10 @@ +* `NullRelation#pluck` takes a list of columns + + The method signature in `NullRelation` was updated to mimic that in + `Calculations`. + + *Derek Prior* + * `scope_chain` should not be mutated for other reflections. Currently `scope_chain` uses same array for building different @@ -335,13 +342,13 @@ * Reset @column_defaults when assigning `locking_column`. We had a potential problem. For example: - class Post < ActiveRecord::Base - self.column_defaults # if we call this unintentionally before setting locking_column ... - self.locking_column = 'my_locking_column' - end + class Post < ActiveRecord::Base + self.column_defaults # if we call this unintentionally before setting locking_column ... + self.locking_column = 'my_locking_column' + end - Post.column_defaults["my_locking_column"] - => nil # expected value is 0 ! + Post.column_defaults["my_locking_column"] + => nil # expected value is 0 ! *kennyj* @@ -588,7 +595,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* diff --git a/activerecord/lib/active_record/associations/join_dependency/join_base.rb b/activerecord/lib/active_record/associations/join_dependency/join_base.rb index 48de12bcd5..adc9f63aec 100644 --- a/activerecord/lib/active_record/associations/join_dependency/join_base.rb +++ b/activerecord/lib/active_record/associations/join_dependency/join_base.rb @@ -18,7 +18,7 @@ module ActiveRecord end def table - Arel::Table.new(table_name, arel_engine) + base_klass.arel_table end def aliased_table_name diff --git a/activerecord/lib/active_record/associations/join_dependency/join_part.rb b/activerecord/lib/active_record/associations/join_dependency/join_part.rb index d39ce94c99..e6da4d3c9e 100644 --- a/activerecord/lib/active_record/associations/join_dependency/join_part.rb +++ b/activerecord/lib/active_record/associations/join_dependency/join_part.rb @@ -19,7 +19,7 @@ module ActiveRecord # association. attr_reader :base_klass, :children - delegate :table_name, :column_names, :primary_key, :arel_engine, :to => :base_klass + delegate :table_name, :column_names, :primary_key, :to => :base_klass def initialize(base_klass, parent) @base_klass = base_klass diff --git a/activerecord/lib/active_record/associations/preloader/through_association.rb b/activerecord/lib/active_record/associations/preloader/through_association.rb index 3166df57eb..2a8530af62 100644 --- a/activerecord/lib/active_record/associations/preloader/through_association.rb +++ b/activerecord/lib/active_record/associations/preloader/through_association.rb @@ -29,29 +29,30 @@ module ActiveRecord 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 diff --git a/activerecord/lib/active_record/null_relation.rb b/activerecord/lib/active_record/null_relation.rb index 1f3d377e53..080b20134d 100644 --- a/activerecord/lib/active_record/null_relation.rb +++ b/activerecord/lib/active_record/null_relation.rb @@ -6,7 +6,7 @@ module ActiveRecord @records = [] end - def pluck(_column_name) + def pluck(*column_names) [] end diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 8583286de5..fe75a32545 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -261,7 +261,7 @@ module ActiveRecord end def construct_relation_for_association_find(join_dependency) - relation = except(:select).select(join_dependency.columns + select_values) + relation = select(join_dependency.columns) apply_join_dependency(relation, join_dependency) end diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index ec43ded690..860bd424b7 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -274,7 +274,7 @@ class RelationTest < ActiveRecord::TestCase def test_none_chained_to_methods_firing_queries_straight_to_db assert_no_queries do - assert_equal [], Developer.none.pluck(:id) # => uses select_all + assert_equal [], Developer.none.pluck(:id, :name) assert_equal 0, Developer.none.delete_all assert_equal 0, Developer.none.update_all(:name => 'David') assert_equal 0, Developer.none.delete(1) diff --git a/activerecord/test/fixtures/sponsors.yml b/activerecord/test/fixtures/sponsors.yml index bfc6b238b1..2da541c539 100644 --- a/activerecord/test/fixtures/sponsors.yml +++ b/activerecord/test/fixtures/sponsors.yml @@ -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 diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index f1dd7c312d..246d94882b 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -22,14 +22,14 @@ You can do this: - class JokeSubscriber < ActiveSupport::Subscriber - # This is much easier to read! - attach_to "active_record" + class JokeSubscriber < ActiveSupport::Subscriber + # This is much easier to read! + attach_to "active_record" - def sql(event) - puts "A rabbi and a priest walk into a bar..." + def sql(event) + puts "A rabbi and a priest walk into a bar..." + end end - end This should make it easier to read and understand these subscribers. diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb index df13fef0a4..19d4ff51d7 100644 --- a/activesupport/lib/active_support/dependencies.rb +++ b/activesupport/lib/active_support/dependencies.rb @@ -8,6 +8,7 @@ require 'active_support/core_ext/module/introspection' 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' diff --git a/activesupport/lib/active_support/number_helper.rb b/activesupport/lib/active_support/number_helper.rb index c9c0eff2bf..e0151baa36 100644 --- a/activesupport/lib/active_support/number_helper.rb +++ b/activesupport/lib/active_support/number_helper.rb @@ -108,7 +108,7 @@ module ActiveSupport 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 @@ module ActiveSupport #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 @@ module ActiveSupport 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 diff --git a/guides/source/action_controller_overview.md b/guides/source/action_controller_overview.md index 8dfecd0190..cd4a1a0792 100644 --- a/guides/source/action_controller_overview.md +++ b/guides/source/action_controller_overview.md @@ -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 diff --git a/guides/source/active_record_callbacks.md b/guides/source/active_record_callbacks.md index aa2ce99f6d..5cc6ca5798 100644 --- a/guides/source/active_record_callbacks.md +++ b/guides/source/active_record_callbacks.md @@ -204,7 +204,7 @@ As you start registering new callbacks for your models, they will be queued for The whole callback chain is wrapped in a transaction. If any _before_ callback method returns exactly `false` or raises an exception, the execution chain gets halted and a ROLLBACK is issued; _after_ callbacks can only accomplish that by raising an exception. -WARNING. Raising an arbitrary exception may break code that expects `save` and its friends not to fail like that. The `ActiveRecord::Rollback` exception is thought precisely to tell Active Record a rollback is going on. That one is internally captured but not reraised. +WARNING. Any exception that is not `ActiveRecord::Rollback` will be re-raised by Rails after the callback chain is halted. Raising an exception other than `ActiveRecord::Rollback` may break code that does not expect methods like `save` and `update_attributes` (which normally try to return `true` or `false`) to raise an exception. Relational Callbacks -------------------- diff --git a/guides/source/active_record_validations.md b/guides/source/active_record_validations.md index 797b996357..0df52a655f 100644 --- a/guides/source/active_record_validations.md +++ b/guides/source/active_record_validations.md @@ -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 diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 4e6bf899af..1d01c8d0e5 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,7 @@ +* Added `--model-name` option to `ScaffoldControllerGenerator`. + + *yalab* + * Expose MiddlewareStack#unshift to environment configuration. *Ben Pickles* diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile index edc76e6c34..4048930c8d 100644 --- a/railties/lib/rails/generators/rails/app/templates/Gemfile +++ b/railties/lib/rails/generators/rails/app/templates/Gemfile @@ -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 diff --git a/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb b/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb index 4f36b612ae..6bf0a33a5f 100644 --- a/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb +++ b/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb @@ -13,7 +13,7 @@ module Rails 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 diff --git a/railties/lib/rails/generators/resource_helpers.rb b/railties/lib/rails/generators/resource_helpers.rb index 7fd5c00768..a01eb57651 100644 --- a/railties/lib/rails/generators/resource_helpers.rb +++ b/railties/lib/rails/generators/resource_helpers.rb @@ -9,11 +9,19 @@ module Rails 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 @@ module Rails 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 diff --git a/railties/test/generators/named_base_test.rb b/railties/test/generators/named_base_test.rb index 2bc2c33a72..ac5cfff229 100644 --- a/railties/test/generators/named_base_test.rb +++ b/railties/test/generators/named_base_test.rb @@ -117,6 +117,25 @@ class NamedBaseTest < Rails::Generators::TestCase 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) diff --git a/railties/test/generators/scaffold_controller_generator_test.rb b/railties/test/generators/scaffold_controller_generator_test.rb index 013cb78252..26e56a162c 100644 --- a/railties/test/generators/scaffold_controller_generator_test.rb +++ b/railties/test/generators/scaffold_controller_generator_test.rb @@ -166,4 +166,13 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase 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 |