diff options
-rw-r--r-- | actionpack/lib/action_controller/base.rb | 1 | ||||
-rw-r--r-- | actionpack/lib/action_controller/metal/params_wrapper.rb | 160 | ||||
-rw-r--r-- | actionpack/lib/action_view/helpers/form_tag_helper.rb | 2 | ||||
-rw-r--r-- | actionpack/test/controller/params_wrapper_test.rb | 2 | ||||
-rw-r--r-- | activerecord/test/cases/finder_test.rb | 6 | ||||
-rw-r--r-- | activesupport/lib/active_support/core_ext/struct.rb | 6 | ||||
-rw-r--r-- | activesupport/test/core_ext/struct_test.rb | 10 | ||||
-rw-r--r-- | railties/CHANGELOG.md | 2 | ||||
-rw-r--r-- | railties/lib/rails/test_unit/testing.rake | 2 | ||||
-rw-r--r-- | railties/test/application/assets_test.rb | 26 | ||||
-rw-r--r-- | railties/test/application/rake_test.rb | 29 |
11 files changed, 181 insertions, 65 deletions
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 9b3bf99fc3..971c4189c8 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -1,4 +1,5 @@ require "action_controller/log_subscriber" +require "action_controller/metal/params_wrapper" module ActionController # Action Controllers are the core of a web request in \Rails. They are made up of one or more actions that are executed diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb index 09abc999c1..a475d4bdff 100644 --- a/actionpack/lib/action_controller/metal/params_wrapper.rb +++ b/actionpack/lib/action_controller/metal/params_wrapper.rb @@ -1,6 +1,7 @@ require 'active_support/core_ext/hash/slice' require 'active_support/core_ext/hash/except' require 'active_support/core_ext/module/anonymous' +require 'active_support/core_ext/struct' require 'action_dispatch/http/mime_types' module ActionController @@ -72,12 +73,99 @@ module ActionController EXCLUDE_PARAMETERS = %w(authenticity_token _method utf8) + require 'mutex_m' + + class Options < Struct.new(:name, :format, :include, :exclude, :klass, :model) # :nodoc: + include Mutex_m + + def self.from_hash(hash) + name = hash[:name] + format = Array(hash[:format]) + include = hash[:include] && Array(hash[:include]).collect(&:to_s) + exclude = hash[:exclude] && Array(hash[:exclude]).collect(&:to_s) + new name, format, include, exclude, nil, nil + end + + def initialize(name, format, include, exclude, klass, model) # nodoc + super + @include_set = include + @name_set = name + end + + def model + super || synchronize { super || self.model = _default_wrap_model } + end + + def include + return super if @include_set + + m = model + synchronize do + return super if @include_set + + @include_set = true + + unless super || exclude + if m.respond_to?(:attribute_names) && m.attribute_names.any? + self.include = m.attribute_names + end + end + end + end + + def name + return super if @name_set + + m = model + synchronize do + return super if @name_set + + @name_set = true + + unless super || klass.anonymous? + self.name = m ? m.to_s.demodulize.underscore : + klass.controller_name.singularize + end + end + end + + private + # Determine the wrapper model from the controller's name. By convention, + # this could be done by trying to find the defined model that has the + # same singularize name as the controller. For example, +UsersController+ + # will try to find if the +User+ model exists. + # + # This method also does namespace lookup. Foo::Bar::UsersController will + # try to find Foo::Bar::User, Foo::User and finally User. + def _default_wrap_model #:nodoc: + return nil if klass.anonymous? + model_name = klass.name.sub(/Controller$/, '').classify + + begin + if model_klass = model_name.safe_constantize + model_klass + else + namespaces = model_name.split("::") + namespaces.delete_at(-2) + break if namespaces.last == model_name + model_name = namespaces.join("::") + end + end until model_klass + + model_klass + end + end + included do class_attribute :_wrapper_options - self._wrapper_options = { :format => [] } + self._wrapper_options = Options.from_hash(format: []) end module ClassMethods + def _set_wrapper_options(options) + self._wrapper_options = Options.from_hash(options) + end + # Sets the name of the wrapper key, or the model which +ParamsWrapper+ # would use to determine the attribute names from. # @@ -119,68 +207,24 @@ module ActionController model = name_or_model_or_options end - _set_wrapper_defaults(_wrapper_options.slice(:format).merge(options), model) + opts = Options.from_hash _wrapper_options.to_h.slice(:format).merge(options) + opts.model = model + opts.klass = self + + self._wrapper_options = opts end # Sets the default wrapper key or model which will be used to determine # wrapper key and attribute names. Will be called automatically when the # module is inherited. def inherited(klass) - if klass._wrapper_options[:format].present? - klass._set_wrapper_defaults(klass._wrapper_options.slice(:format)) + if klass._wrapper_options.format.any? + params = klass._wrapper_options.dup + params.klass = klass + klass._wrapper_options = params end super end - - protected - - # Determine the wrapper model from the controller's name. By convention, - # this could be done by trying to find the defined model that has the - # same singularize name as the controller. For example, +UsersController+ - # will try to find if the +User+ model exists. - # - # This method also does namespace lookup. Foo::Bar::UsersController will - # try to find Foo::Bar::User, Foo::User and finally User. - def _default_wrap_model #:nodoc: - return nil if self.anonymous? - model_name = self.name.sub(/Controller$/, '').classify - - begin - if model_klass = model_name.safe_constantize - model_klass - else - namespaces = model_name.split("::") - namespaces.delete_at(-2) - break if namespaces.last == model_name - model_name = namespaces.join("::") - end - end until model_klass - - model_klass - end - - def _set_wrapper_defaults(options, model=nil) - options = options.dup - - unless options[:include] || options[:exclude] - model ||= _default_wrap_model - if model.respond_to?(:attribute_names) && model.attribute_names.present? - options[:include] = model.attribute_names - end - end - - unless options[:name] || self.anonymous? - model ||= _default_wrap_model - options[:name] = model ? model.to_s.demodulize.underscore : - controller_name.singularize - end - - options[:include] = Array(options[:include]).collect(&:to_s) if options[:include] - options[:exclude] = Array(options[:exclude]).collect(&:to_s) if options[:exclude] - options[:format] = Array(options[:format]) - - self._wrapper_options = options - end end # Performs parameters wrapping upon the request. Will be called automatically @@ -205,20 +249,20 @@ module ActionController # Returns the wrapper key which will use to stored wrapped parameters. def _wrapper_key - _wrapper_options[:name] + _wrapper_options.name end # Returns the list of enabled formats. def _wrapper_formats - _wrapper_options[:format] + _wrapper_options.format end # Returns the list of parameters which will be selected for wrapped. def _wrap_parameters(parameters) - value = if include_only = _wrapper_options[:include] + value = if include_only = _wrapper_options.include parameters.slice(*include_only) else - exclude = _wrapper_options[:exclude] || [] + exclude = _wrapper_options.exclude || [] parameters.except(*(exclude + EXCLUDE_PARAMETERS)) end diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb index 7f42d6e9c3..e298751062 100644 --- a/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -52,7 +52,7 @@ module ActionView # <%= form_tag('/posts') do -%> # <div><%= submit_tag 'Save' %></div> # <% end -%> - # # => <form action="/posts" method="post"><div><input type="submit" name="submit" value="Save" /></div></form> + # # => <form action="/posts" method="post"><div><input type="submit" name="commit" value="Save" /></div></form> # # <%= form_tag('/posts', remote: true) %> # # => <form action="/posts" method="post" data-remote="true"> diff --git a/actionpack/test/controller/params_wrapper_test.rb b/actionpack/test/controller/params_wrapper_test.rb index 209f021cf7..d87e2b85b0 100644 --- a/actionpack/test/controller/params_wrapper_test.rb +++ b/actionpack/test/controller/params_wrapper_test.rb @@ -4,7 +4,7 @@ module Admin; class User; end; end module ParamsWrapperTestHelp def with_default_wrapper_options(&block) - @controller.class._wrapper_options = {:format => [:json]} + @controller.class._set_wrapper_options({:format => [:json]}) @controller.class.inherited(@controller.class) yield end diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb index f68d7de3ae..7db7953313 100644 --- a/activerecord/test/cases/finder_test.rb +++ b/activerecord/test/cases/finder_test.rb @@ -611,10 +611,8 @@ class FinderTest < ActiveRecord::TestCase end def test_find_by_one_attribute_bang_with_blank_defined - BlankTopic.create(title: "The Blank One") - assert_nothing_raised do - BlankTopic.find_by_title!("The Blank One") - end + blank_topic = BlankTopic.create(title: "The Blank One") + assert_equal blank_topic, BlankTopic.find_by_title!("The Blank One") end def test_find_by_one_attribute_with_conditions diff --git a/activesupport/lib/active_support/core_ext/struct.rb b/activesupport/lib/active_support/core_ext/struct.rb new file mode 100644 index 0000000000..c2c30044f2 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/struct.rb @@ -0,0 +1,6 @@ +# Backport of Struct#to_h from Ruby 2.0 +class Struct # :nodoc: + def to_h + Hash[members.zip(values)] + end +end unless Struct.instance_methods.include?(:to_h) diff --git a/activesupport/test/core_ext/struct_test.rb b/activesupport/test/core_ext/struct_test.rb new file mode 100644 index 0000000000..0dff7b32d2 --- /dev/null +++ b/activesupport/test/core_ext/struct_test.rb @@ -0,0 +1,10 @@ +require 'abstract_unit' +require 'active_support/core_ext/struct' + +class StructExt < ActiveSupport::TestCase + def test_to_h + x = Struct.new(:foo, :bar) + z = x.new(1, 2) + assert_equal({ foo: 1, bar: 2 }, z.to_h) + end +end diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 8538d5fbfa..a0545916ca 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,5 +1,7 @@ ## Rails 4.0.0 (unreleased) ## +* Rake test:uncommitted finds git directory in ancestors *Nicolas Despres* + * Add dummy app Rake tasks when --skip-test-unit and --dummy-path is passed to the plugin generator. Fix #8121 diff --git a/railties/lib/rails/test_unit/testing.rake b/railties/lib/rails/test_unit/testing.rake index cd59fbe599..9ad3a4e6d6 100644 --- a/railties/lib/rails/test_unit/testing.rake +++ b/railties/lib/rails/test_unit/testing.rake @@ -88,7 +88,7 @@ namespace :test do def t.file_list if File.directory?(".svn") changed_since_checkin = silence_stderr { `svn status` }.split.map { |path| path.chomp[7 .. -1] } - elsif File.directory?(".git") + elsif system "git rev-parse --git-dir 2>&1 >/dev/null" changed_since_checkin = silence_stderr { `git ls-files --modified --others --exclude-standard` }.split.map { |path| path.chomp } else abort "Not a Subversion or Git checkout." diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index f86877db34..f98915d1cc 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -83,6 +83,32 @@ module ApplicationTests end end + def test_precompile_does_not_hit_the_database + app_file "app/assets/javascripts/application.js", "alert();" + app_file "app/assets/javascripts/foo/application.js", "alert();" + app_file "app/controllers/user_controller.rb", <<-eoruby + class UserController < ApplicationController; end + eoruby + app_file "app/models/user.rb", <<-eoruby + class User < ActiveRecord::Base; end + eoruby + + ENV['RAILS_ENV'] = 'production' + ENV['DATABASE_URL'] = 'postgresql://baduser:badpass@127.0.0.1/dbname' + + precompile! + + files = Dir["#{app_path}/public/assets/application-*.js"] + files << Dir["#{app_path}/public/assets/foo/application-*.js"].first + files.each do |file| + assert_not_nil file, "Expected application.js asset to be generated, but none found" + assert_equal "alert();".strip, File.read(file).strip + end + ensure + ENV.delete 'RAILS_ENV' + ENV.delete 'DATABASE_URL' + end + test "precompile application.js and application.css and all other non JS/CSS files" do app_file "app/assets/javascripts/application.js", "alert();" app_file "app/assets/stylesheets/application.css", "body{}" diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb index c5a68a5152..c6aea03d8c 100644 --- a/railties/test/application/rake_test.rb +++ b/railties/test/application/rake_test.rb @@ -106,6 +106,35 @@ module ApplicationTests end end + def test_rake_test_uncommitted_always_find_git_in_parent_dir + app_name = File.basename(app_path) + app_dir = File.dirname(app_path) + moved_app_name = app_name + '_moved' + moved_app_path = "#{app_path}/#{moved_app_name}" + + Dir.chdir(app_dir) do + # Go from "./app/" to "./app/app_moved" + FileUtils.mv(app_name, moved_app_name) + FileUtils.mkdir(app_name) + FileUtils.mv(moved_app_name, app_name) + # Initialize the git repository and start the test. + Dir.chdir(app_name) do + `git init` + Dir.chdir(moved_app_name){ `rake db:migrate` } + silence_stderr { Dir.chdir(moved_app_name) { `rake test:uncommitted` } } + assert_equal 0, $?.exitstatus + end + end + end + + def test_rake_test_uncommitted_fails_with_no_scm + Dir.chdir(app_path){ `rake db:migrate` } + Dir.chdir(app_path) do + silence_stderr { `rake test:uncommitted` } + assert_equal 1, $?.exitstatus + end + end + def test_rake_routes_calls_the_route_inspector app_file "config/routes.rb", <<-RUBY AppTemplate::Application.routes.draw do |