diff options
82 files changed, 1203 insertions, 775 deletions
diff --git a/.travis.yml b/.travis.yml index 6c870d8797..2237ca85d9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,7 @@ env: - "GEM=ar:sqlite3" - "GEM=ar:postgresql" - "GEM=aj:integration" + - "GEM=guides" rvm: - 2.2.2 - ruby-head diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 3c522ce707..7022c04a9a 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -155,7 +155,7 @@ module ActionMailer # Note that <tt>deliver_later</tt> will execute your method from the background job. # # You never instantiate your mailer class. Rather, you just call the method you defined on the class itself. - # All instance method are expected to return a message object to be sent. + # All instance methods are expected to return a message object to be sent. # # = Multipart Emails # diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb index a7bd3622ee..4cb634477e 100644 --- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb +++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb @@ -258,7 +258,7 @@ module ActionController #:nodoc: # Returns true or false if a request is verified. Checks: # - # * is it a GET or HEAD request? Gets should be safe and idempotent + # * Is it a GET or HEAD request? Gets should be safe and idempotent # * Does the form_authenticity_token match the given token value from the params? # * Does the X-CSRF-Token header match the form_authenticity_token def verified_request? diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index fe83c01562..3c62c055e5 100644 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -228,7 +228,7 @@ module ActionDispatch alias_method :uuid, :request_id - def x_request_id # :nodoc + def x_request_id # :nodoc: @env[HTTP_X_REQUEST_ID] end @@ -259,7 +259,7 @@ module ActionDispatch end end - # returns true if request content mime type is + # Returns true if the request's content MIME type is # +application/x-www-form-urlencoded+ or +multipart/form-data+. def form_data? FORM_DATA_MEDIA_TYPES.include?(content_mime_type.to_s) diff --git a/actionpack/lib/action_dispatch/journey/route.rb b/actionpack/lib/action_dispatch/journey/route.rb index 4698ff8cc7..cbc985640a 100644 --- a/actionpack/lib/action_dispatch/journey/route.rb +++ b/actionpack/lib/action_dispatch/journey/route.rb @@ -11,7 +11,7 @@ module ActionDispatch ## # +path+ is a path constraint. # +constraints+ is a hash of constraints to be applied to this route. - def initialize(name, app, path, constraints, defaults = {}) + def initialize(name, app, path, constraints, required_defaults, defaults) @name = name @app = app @path = path @@ -19,6 +19,7 @@ module ActionDispatch @constraints = constraints @defaults = defaults @required_defaults = nil + @_required_defaults = required_defaults || [] @required_parts = nil @parts = nil @decorated_ast = nil @@ -73,7 +74,7 @@ module ActionDispatch end def required_default?(key) - (constraints[:required_defaults] || []).include?(key) + @_required_defaults.include?(key) end def required_defaults @@ -92,8 +93,6 @@ module ActionDispatch def matches?(request) constraints.all? do |method, value| - next true unless request.respond_to?(method) - case value when Regexp, String value === request.send(method).to_s diff --git a/actionpack/lib/action_dispatch/journey/routes.rb b/actionpack/lib/action_dispatch/journey/routes.rb index 6325dfa3dd..5990964b57 100644 --- a/actionpack/lib/action_dispatch/journey/routes.rb +++ b/actionpack/lib/action_dispatch/journey/routes.rb @@ -63,8 +63,8 @@ module ActionDispatch end # Add a route to the routing table. - def add_route(app, path, conditions, defaults, name = nil) - route = Route.new(name, app, path, conditions, defaults) + def add_route(app, path, conditions, required_defaults, defaults, name = nil) + route = Route.new(name, app, path, conditions, required_defaults, defaults) route.precedence = routes.length routes << route diff --git a/actionpack/lib/action_dispatch/request/session.rb b/actionpack/lib/action_dispatch/request/session.rb index 9a1a05e971..773d41de88 100644 --- a/actionpack/lib/action_dispatch/request/session.rb +++ b/actionpack/lib/action_dispatch/request/session.rb @@ -86,11 +86,14 @@ module ActionDispatch load_for_write! end + # Returns value of the key stored in the session or + # nil if the given key is not found in the session. def [](key) load_for_read! @delegate[key.to_s] end + # Returns true if the session has the given key or false. def has_key?(key) load_for_read! @delegate.key?(key.to_s) @@ -98,39 +101,69 @@ module ActionDispatch alias :key? :has_key? alias :include? :has_key? + # Returns keys of the session as Array. def keys @delegate.keys end + # Returns values of the session as Array. def values @delegate.values end + # Writes given value to given key of the session. def []=(key, value) load_for_write! @delegate[key.to_s] = value end + # Clears the session. def clear load_for_write! @delegate.clear end + # Returns the session as Hash. def to_hash load_for_read! @delegate.dup.delete_if { |_,v| v.nil? } end + # Updates the session with given Hash. + # + # session.to_hash + # # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2"} + # + # session.update({ "foo" => "bar" }) + # # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2", "foo" => "bar"} + # + # session.to_hash + # # => {"session_id"=>"e29b9ea315edf98aad94cc78c34cc9b2", "foo" => "bar"} def update(hash) load_for_write! @delegate.update stringify_keys(hash) end + # Deletes given key from the session. def delete(key) load_for_write! @delegate.delete key.to_s end + # Returns value of given key from the session, or raises +KeyError+ + # if can't find given key in case of not setted dafault value. + # Returns default value if specified. + # + # session.fetch(:foo) + # # => KeyError: key not found: "foo" + # + # session.fetch(:foo, :bar) + # # => :bar + # + # session.fetch(:foo) do + # :bar + # end + # # => :bar def fetch(key, default=Unspecified, &block) load_for_read! if default == Unspecified diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index d0d8ded515..cf35e85b40 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -511,10 +511,11 @@ module ActionDispatch path = conditions.delete :path_info ast = conditions.delete :parsed_path_info + required_defaults = conditions.delete :required_defaults path = build_path(path, ast, requirements, anchor) - conditions = build_conditions(conditions, path.names.map(&:to_sym)) + conditions = build_conditions(conditions) - route = @set.add_route(app, path, conditions, defaults, name) + route = @set.add_route(app, path, conditions, required_defaults, defaults, name) named_routes[name] = route if name route end @@ -550,7 +551,7 @@ module ActionDispatch end private :build_path - def build_conditions(current_conditions, path_values) + def build_conditions(current_conditions) conditions = current_conditions.dup # Rack-Mount requires that :request_method be a regular expression. @@ -563,8 +564,7 @@ module ActionDispatch end conditions.keep_if do |k, _| - k == :action || k == :controller || k == :required_defaults || - request_class.public_method_defined?(k) || path_values.include?(k) + request_class.public_method_defined?(k) end end private :build_conditions diff --git a/actionpack/test/journey/route_test.rb b/actionpack/test/journey/route_test.rb index 0980df06e8..eff96a0abc 100644 --- a/actionpack/test/journey/route_test.rb +++ b/actionpack/test/journey/route_test.rb @@ -7,7 +7,7 @@ module ActionDispatch app = Object.new path = Path::Pattern.from_string '/:controller(/:action(/:id(.:format)))' defaults = {} - route = Route.new("name", app, path, {}, defaults) + route = Route.new("name", app, path, {}, [], defaults) assert_equal app, route.app assert_equal path, route.path @@ -18,7 +18,7 @@ module ActionDispatch app = Object.new path = Path::Pattern.from_string '/:controller(/:action(/:id(.:format)))' defaults = {} - route = Route.new("name", app, path, {}, defaults) + route = Route.new("name", app, path, {}, [], defaults) route.ast.grep(Nodes::Terminal).each do |node| assert_equal route, node.memo @@ -29,27 +29,27 @@ module ActionDispatch strexp = Router::Strexp.build(':name', { name: /love/ }, ['/']) path = Path::Pattern.new strexp defaults = { name: 'tender' } - route = Route.new('name', nil, path, nil, defaults) + route = Route.new('name', nil, path, nil, [], defaults) assert_equal(/love/, route.requirements[:name]) end def test_ip_address path = Path::Pattern.from_string '/messages/:id(.:format)' - route = Route.new("name", nil, path, {:ip => '192.168.1.1'}, + route = Route.new("name", nil, path, {:ip => '192.168.1.1'}, [], { :controller => 'foo', :action => 'bar' }) assert_equal '192.168.1.1', route.ip end def test_default_ip path = Path::Pattern.from_string '/messages/:id(.:format)' - route = Route.new("name", nil, path, {}, + route = Route.new("name", nil, path, {}, [], { :controller => 'foo', :action => 'bar' }) assert_equal(//, route.ip) end def test_format_with_star path = Path::Pattern.from_string '/:controller/*extra' - route = Route.new("name", nil, path, {}, + route = Route.new("name", nil, path, {}, [], { :controller => 'foo', :action => 'bar' }) assert_equal '/foo/himom', route.format({ :controller => 'foo', @@ -59,7 +59,7 @@ module ActionDispatch def test_connects_all_match path = Path::Pattern.from_string '/:controller(/:action(/:id(.:format)))' - route = Route.new("name", nil, path, {:action => 'bar'}, { :controller => 'foo' }) + route = Route.new("name", nil, path, {:action => 'bar'}, [], { :controller => 'foo' }) assert_equal '/foo/bar/10', route.format({ :controller => 'foo', @@ -70,34 +70,34 @@ module ActionDispatch def test_extras_are_not_included_if_optional path = Path::Pattern.from_string '/page/:id(/:action)' - route = Route.new("name", nil, path, { }, { :action => 'show' }) + route = Route.new("name", nil, path, { }, [], { :action => 'show' }) assert_equal '/page/10', route.format({ :id => 10 }) end def test_extras_are_not_included_if_optional_with_parameter path = Path::Pattern.from_string '(/sections/:section)/pages/:id' - route = Route.new("name", nil, path, { }, { :action => 'show' }) + route = Route.new("name", nil, path, { }, [], { :action => 'show' }) assert_equal '/pages/10', route.format({:id => 10}) end def test_extras_are_not_included_if_optional_parameter_is_nil path = Path::Pattern.from_string '(/sections/:section)/pages/:id' - route = Route.new("name", nil, path, { }, { :action => 'show' }) + route = Route.new("name", nil, path, { }, [], { :action => 'show' }) assert_equal '/pages/10', route.format({:id => 10, :section => nil}) end def test_score - constraints = {:required_defaults => [:controller, :action]} + constraints = {} defaults = {:controller=>"pages", :action=>"show"} path = Path::Pattern.from_string "/page/:id(/:action)(.:format)" - specific = Route.new "name", nil, path, constraints, defaults + specific = Route.new "name", nil, path, constraints, [:controller, :action], defaults path = Path::Pattern.from_string "/:controller(/:action(/:id))(.:format)" - generic = Route.new "name", nil, path, constraints + generic = Route.new "name", nil, path, constraints, [], {} knowledge = {:id=>20, :controller=>"pages", :action=>"show"} diff --git a/actionpack/test/journey/router_test.rb b/actionpack/test/journey/router_test.rb index a134e343cc..802fb93c69 100644 --- a/actionpack/test/journey/router_test.rb +++ b/actionpack/test/journey/router_test.rb @@ -35,7 +35,7 @@ module ActionDispatch exp = Router::Strexp.build '/foo-bar-baz', {}, ['/.?'] path = Path::Pattern.new exp - routes.add_route nil, path, {}, {:id => nil}, {} + routes.add_route nil, path, {}, [], {:id => nil}, {} env = rails_env 'PATH_INFO' => '/foo-bar-baz' called = false @@ -52,7 +52,7 @@ module ActionDispatch exp = Router::Strexp.build '/%E3%81%BB%E3%81%92', {}, ['/.?'] path = Path::Pattern.new exp - routes.add_route nil, path, {}, {:id => nil}, {} + routes.add_route nil, path, {}, [], {:id => nil}, {} env = rails_env 'PATH_INFO' => '/%E3%81%BB%E3%81%92' called = false @@ -71,7 +71,7 @@ module ActionDispatch exp = Router::Strexp.build '/foo(/:id)', {}, ['/.?'] path = Path::Pattern.new exp - routes.add_route nil, path, requirements, {:id => nil}, {} + routes.add_route nil, path, requirements, [], {:id => nil}, {} env = rails_env({'PATH_INFO' => '/foo/10'}, klass) router.recognize(env) do |r, params| @@ -91,7 +91,7 @@ module ActionDispatch exp = Router::Strexp.build '/foo(/:id)', {}, ['/.?'] path = Path::Pattern.new exp - router.routes.add_route nil, path, requirements, {:id => nil}, {} + router.routes.add_route nil, path, requirements, [], {:id => nil}, {} env = rails_env({'PATH_INFO' => '/foo/10'}, klass) router.recognize(env) do |r, params| @@ -118,7 +118,7 @@ module ActionDispatch exp = Router::Strexp.build '/bar', {}, ['/.?'] path = Path::Pattern.new exp - routes.add_route nil, path, {}, {}, {} + routes.add_route nil, path, {}, [], {}, {} env = rails_env({'PATH_INFO' => '/foo', 'custom.path_info' => '/bar'}, CustomPathRequest) @@ -192,7 +192,7 @@ module ActionDispatch route_name = "gorby_thunderhorse" pattern = Router::Strexp.build("/foo/:id", { :id => /\d+/ }, ['/', '.', '?'], false) path = Path::Pattern.new pattern - @router.routes.add_route nil, path, {}, {}, route_name + @router.routes.add_route nil, path, {}, [], {}, route_name error = assert_raises(ActionController::UrlGenerationError) do @formatter.generate(route_name, { }, { }) @@ -234,7 +234,7 @@ module ActionDispatch def test_defaults_merge_correctly path = Path::Pattern.from_string '/foo(/:id)' - @router.routes.add_route nil, path, {}, {:id => nil}, {} + @router.routes.add_route nil, path, {}, [], {:id => nil}, {} env = rails_env 'PATH_INFO' => '/foo/10' @router.recognize(env) do |r, params| @@ -317,7 +317,7 @@ module ActionDispatch def test_nil_path_parts_are_ignored path = Path::Pattern.from_string "/:controller(/:action(.:format))" - @router.routes.add_route @app, path, {}, {}, {} + @router.routes.add_route @app, path, {}, [], {}, {} params = { :controller => "tasks", :format => nil } extras = { :action => 'lol' } @@ -332,7 +332,7 @@ module ActionDispatch str = Router::Strexp.build("/", Hash[params], ['/', '.', '?'], true) path = Path::Pattern.new str - @router.routes.add_route @app, path, {}, {}, {} + @router.routes.add_route @app, path, {}, [], {}, {} path, _ = @formatter.generate(nil, Hash[params], {}) assert_equal '/', path @@ -340,7 +340,7 @@ module ActionDispatch def test_generate_calls_param_proc path = Path::Pattern.from_string '/:controller(/:action)' - @router.routes.add_route @app, path, {}, {}, {} + @router.routes.add_route @app, path, {}, [], {}, {} parameterized = [] params = [ [:controller, "tasks"], @@ -357,7 +357,7 @@ module ActionDispatch def test_generate_id path = Path::Pattern.from_string '/:controller(/:action)' - @router.routes.add_route @app, path, {}, {}, {} + @router.routes.add_route @app, path, {}, [], {}, {} path, params = @formatter.generate( nil, {:id=>1, :controller=>"tasks", :action=>"show"}, {}) @@ -367,7 +367,7 @@ module ActionDispatch def test_generate_escapes path = Path::Pattern.from_string '/:controller(/:action)' - @router.routes.add_route @app, path, {}, {}, {} + @router.routes.add_route @app, path, {}, [], {}, {} path, _ = @formatter.generate(nil, { :controller => "tasks", @@ -378,7 +378,7 @@ module ActionDispatch def test_generate_escapes_with_namespaced_controller path = Path::Pattern.from_string '/:controller(/:action)' - @router.routes.add_route @app, path, {}, {}, {} + @router.routes.add_route @app, path, {}, [], {}, {} path, _ = @formatter.generate( nil, { :controller => "admin/tasks", @@ -389,7 +389,7 @@ module ActionDispatch def test_generate_extra_params path = Path::Pattern.from_string '/:controller(/:action)' - @router.routes.add_route @app, path, {}, {}, {} + @router.routes.add_route @app, path, {}, [], {}, {} path, params = @formatter.generate( nil, { :id => 1, @@ -403,7 +403,7 @@ module ActionDispatch def test_generate_missing_keys_no_matches_different_format_keys path = Path::Pattern.from_string '/:controller/:action/:name' - @router.routes.add_route @app, path, {}, {}, {} + @router.routes.add_route @app, path, {}, [], {}, {} primarty_parameters = { :id => 1, :controller => "tasks", @@ -430,7 +430,7 @@ module ActionDispatch def test_generate_uses_recall_if_needed path = Path::Pattern.from_string '/:controller(/:action(/:id))' - @router.routes.add_route @app, path, {}, {}, {} + @router.routes.add_route @app, path, {}, [], {}, {} path, params = @formatter.generate( nil, @@ -442,7 +442,7 @@ module ActionDispatch def test_generate_with_name path = Path::Pattern.from_string '/:controller(/:action)' - @router.routes.add_route @app, path, {}, {}, "tasks" + @router.routes.add_route @app, path, {}, [], {}, "tasks" path, params = @formatter.generate( "tasks", @@ -460,7 +460,7 @@ module ActionDispatch define_method("test_recognize_#{expected.keys.map(&:to_s).join('_')}") do path = Path::Pattern.from_string "/:controller(/:action(/:id))" app = Object.new - route = @router.routes.add_route(app, path, {}, {}, {}) + route = @router.routes.add_route(app, path, {}, [], {}, {}) env = rails_env 'PATH_INFO' => request_path called = false @@ -482,7 +482,7 @@ module ActionDispatch define_method("test_recognize_#{name}") do path = Path::Pattern.from_string '/:segment/*splat' app = Object.new - route = @router.routes.add_route(app, path, {}, {}, {}) + route = @router.routes.add_route(app, path, {}, [], {}, {}) env = rails_env 'PATH_INFO' => request_path called = false @@ -505,7 +505,7 @@ module ActionDispatch ) path = Path::Pattern.new strexp app = Object.new - route = @router.routes.add_route(app, path, {}, {}, {}) + route = @router.routes.add_route(app, path, {}, [], {}, {}) env = rails_env 'PATH_INFO' => '/admin/users/show/10' called = false @@ -526,7 +526,7 @@ module ActionDispatch def test_recognize_literal path = Path::Pattern.from_string "/books(/:action(.:format))" app = Object.new - route = @router.routes.add_route(app, path, {}, {:controller => 'books'}) + route = @router.routes.add_route(app, path, {}, [], {:controller => 'books'}) env = rails_env 'PATH_INFO' => '/books/list.rss' expected = { :controller => 'books', :action => 'list', :format => 'rss' } @@ -544,7 +544,7 @@ module ActionDispatch path = Path::Pattern.from_string "/books(/:action(.:format))" app = Object.new conditions = { request_method: 'HEAD' } - @router.routes.add_route(app, path, conditions, {}) + @router.routes.add_route(app, path, conditions, [], {}) env = rails_env( 'PATH_INFO' => '/books/list.rss', @@ -565,7 +565,7 @@ module ActionDispatch conditions = { :request_method => 'GET' } - @router.routes.add_route(app, path, conditions, {}) + @router.routes.add_route(app, path, conditions, [], {}) env = rails_env 'PATH_INFO' => '/books/list.rss', "REQUEST_METHOD" => "HEAD" @@ -582,7 +582,7 @@ module ActionDispatch path = Path::Pattern.from_string "/books(/:action(.:format))" app = Object.new conditions = { request_method: 'GET' } - @router.routes.add_route(app, path, conditions, {}) + @router.routes.add_route(app, path, conditions, [], {}) env = rails_env 'PATH_INFO' => '/books/list.rss', "REQUEST_METHOD" => "POST" @@ -597,7 +597,7 @@ module ActionDispatch conditions = conditions.dup conditions[:request_method] = 'POST' - post = @router.routes.add_route(app, path, conditions, {}) + post = @router.routes.add_route(app, path, conditions, [], {}) called = false @router.recognize(env) do |r, params| @@ -617,7 +617,7 @@ module ActionDispatch else path = Path::Pattern.new path end - router.routes.add_route @app, path, {}, {}, {} + router.routes.add_route @app, path, {}, [], {}, {} end end diff --git a/actionpack/test/journey/routes_test.rb b/actionpack/test/journey/routes_test.rb index 2a1c1c337e..b9dac8751c 100644 --- a/actionpack/test/journey/routes_test.rb +++ b/actionpack/test/journey/routes_test.rb @@ -13,7 +13,7 @@ module ActionDispatch path = Path::Pattern.new exp requirements = { :hello => /world/ } - routes.add_route nil, path, requirements, {:id => nil}, {} + routes.add_route nil, path, requirements, [], {:id => nil}, {} assert_not routes.empty? assert_equal 1, routes.length @@ -26,9 +26,9 @@ module ActionDispatch routes = Routes.new path = Path::Pattern.from_string '/hello' - routes.add_route nil, path, {}, {}, {} + routes.add_route nil, path, {}, [], {}, {} ast = routes.ast - routes.add_route nil, path, {}, {}, {} + routes.add_route nil, path, {}, [], {}, {} assert_not_equal ast, routes.ast end @@ -36,16 +36,16 @@ module ActionDispatch routes = Routes.new path = Path::Pattern.from_string '/hello' - routes.add_route nil, path, {}, {}, {} + routes.add_route nil, path, {}, [], {}, {} sim = routes.simulator - routes.add_route nil, path, {}, {}, {} + routes.add_route nil, path, {}, [], {}, {} assert_not_equal sim, routes.simulator end def test_partition_route path = Path::Pattern.from_string '/hello' - anchored_route = @routes.add_route nil, path, {}, {}, {} + anchored_route = @routes.add_route nil, path, {}, [], {}, {} assert_equal [anchored_route], @routes.anchored_routes assert_equal [], @routes.custom_routes @@ -54,7 +54,7 @@ module ActionDispatch ) path = Path::Pattern.new strexp - custom_route = @routes.add_route nil, path, {}, {}, {} + custom_route = @routes.add_route nil, path, {}, [], {}, {} assert_equal [custom_route], @routes.custom_routes assert_equal [anchored_route], @routes.anchored_routes end @@ -65,8 +65,8 @@ module ActionDispatch one = Path::Pattern.from_string '/hello' two = Path::Pattern.from_string '/aaron' - routes.add_route nil, one, {}, {}, 'aaron' - routes.add_route nil, two, {}, {}, 'aaron' + routes.add_route nil, one, {}, [], {}, 'aaron' + routes.add_route nil, two, {}, [], {}, 'aaron' assert_equal '/hello', routes.named_routes['aaron'].path.spec.to_s end diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md index 201e118971..7b6008d5ed 100644 --- a/actionview/CHANGELOG.md +++ b/actionview/CHANGELOG.md @@ -1,3 +1,8 @@ +* Raise an ArgumentError when a false value for `include_blank` is passed to a + required select field (to comply with the HTML5 spec). + + *Grey Baker* + * Do not put partial name to `local_assigns` when rendering without an object or a collection. diff --git a/actionview/lib/action_view/helpers/cache_helper.rb b/actionview/lib/action_view/helpers/cache_helper.rb index 251764a8de..72e2aa1807 100644 --- a/actionview/lib/action_view/helpers/cache_helper.rb +++ b/actionview/lib/action_view/helpers/cache_helper.rb @@ -39,7 +39,7 @@ module ActionView # This will include both records as part of the cache key and updating either of them will # expire the cache. # - # ==== Template digest + # ==== \Template digest # # The template digest that's added to the cache key is computed by taking an md5 of the # contents of the entire template file. This ensures that your caches will automatically @@ -75,7 +75,7 @@ module ActionView # render(topics) => render("topics/topic") # render(message.topics) => render("topics/topic") # - # It's not possible to derive all render calls like that, though. + # It's not possible to derive all render calls like that, though. # Here are a few examples of things that can't be derived: # # render group_of_attachments @@ -98,14 +98,14 @@ module ActionView # <%# Template Dependency: todolists/todolist %> # <%= render_sortable_todolists @project.todolists %> # - # The pattern used to match these is /# Template Dependency: ([^ ]+)/, + # The pattern used to match these is <tt>/# Template Dependency: (\S+)/</tt>, # so it's important that you type it out just so. # You can only declare one template dependency per line. # # === External dependencies # - # If you use a helper method, for example, inside a cached block and - # you then update that helper, you'll have to bump the cache as well. + # If you use a helper method, for example, inside a cached block and + # you then update that helper, you'll have to bump the cache as well. # It doesn't really matter how you do it, but the md5 of the template file # must change. One recommendation is to simply be explicit in a comment, like: # @@ -130,8 +130,8 @@ module ActionView # The collection can then automatically use any cached renders for that # template by reading them at once instead of one by one. # - # See ActionView::Template::Handlers::ERB.resource_cache_call_pattern for - # more information on what cache calls make a template eligible for this + # See ActionView::Template::Handlers::ERB.resource_cache_call_pattern for + # more information on what cache calls make a template eligible for this # collection caching. # # The automatic cache multi read can be turned off like so: diff --git a/actionview/lib/action_view/helpers/date_helper.rb b/actionview/lib/action_view/helpers/date_helper.rb index 46ce7cf0be..394e20ff2b 100644 --- a/actionview/lib/action_view/helpers/date_helper.rb +++ b/actionview/lib/action_view/helpers/date_helper.rb @@ -488,7 +488,7 @@ module ActionView # selected. The <tt>datetime</tt> can be either a +Time+ or +DateTime+ object or an integer. # Override the field name using the <tt>:field_name</tt> option, 'minute' by default. # - # my_time = Time.now + 6.hours + # my_time = Time.now + 10.minutes # # # Generates a select field for minutes that defaults to the minutes for the time in my_time. # select_minute(my_time) diff --git a/actionview/lib/action_view/helpers/number_helper.rb b/actionview/lib/action_view/helpers/number_helper.rb index ca8d30e4ef..13effa592d 100644 --- a/actionview/lib/action_view/helpers/number_helper.rb +++ b/actionview/lib/action_view/helpers/number_helper.rb @@ -279,7 +279,7 @@ module ActionView # See <tt>number_to_human_size</tt> if you want to print a file # size. # - # You can also define you own unit-quantifier names if you want + # You can also define your own unit-quantifier names if you want # to use other decimal units (eg.: 1500 becomes "1.5 # kilometers", 0.150 becomes "150 milliliters", etc). You may # define a wide range of unit quantifiers, even fractional ones diff --git a/actionview/lib/action_view/helpers/tags/base.rb b/actionview/lib/action_view/helpers/tags/base.rb index acc6443a96..d57f26ba4f 100644 --- a/actionview/lib/action_view/helpers/tags/base.rb +++ b/actionview/lib/action_view/helpers/tags/base.rb @@ -120,7 +120,12 @@ module ActionView def select_content_tag(option_tags, options, html_options) html_options = html_options.stringify_keys add_default_name_and_id(html_options) - options[:include_blank] ||= true unless options[:prompt] || select_not_required?(html_options) + + if placeholder_required?(html_options) + raise ArgumentError, "include_blank cannot be false for a required field." if options[:include_blank] == false + options[:include_blank] ||= true unless options[:prompt] + end + value = options.fetch(:selected) { value(object) } select = content_tag("select", add_options(option_tags, options, value), html_options) @@ -131,8 +136,9 @@ module ActionView end end - def select_not_required?(html_options) - !html_options["required"] || html_options["multiple"] || html_options["size"].to_i > 1 + def placeholder_required?(html_options) + # See https://html.spec.whatwg.org/multipage/forms.html#attr-select-required + html_options["required"] && !html_options["multiple"] && html_options.fetch("size", 1).to_i == 1 end def add_options(option_tags, options, value = nil) diff --git a/actionview/test/template/form_options_helper_test.rb b/actionview/test/template/form_options_helper_test.rb index d25fa3706f..d7daba8bf3 100644 --- a/actionview/test/template/form_options_helper_test.rb +++ b/actionview/test/template/form_options_helper_test.rb @@ -645,6 +645,13 @@ class FormOptionsHelperTest < ActionView::TestCase ) end + def test_select_with_include_blank_false_and_required + @post = Post.new + @post.category = "<mus>" + e = assert_raises(ArgumentError) { select("post", "category", %w( abe <mus> hest), { include_blank: false }, required: 'required') } + assert_match(/include_blank cannot be false for a required field./, e.message) + end + def test_select_with_blank_as_string @post = Post.new @post.category = "<mus>" diff --git a/activemodel/lib/active_model/serialization.rb b/activemodel/lib/active_model/serialization.rb index c06a64c75f..f95849eb84 100644 --- a/activemodel/lib/active_model/serialization.rb +++ b/activemodel/lib/active_model/serialization.rb @@ -94,6 +94,37 @@ module ActiveModel # person.serializable_hash(except: :name) # => {"age"=>22} # person.serializable_hash(methods: :capitalized_name) # # => {"name"=>"bob", "age"=>22, "capitalized_name"=>"Bob"} + # + # Example with <tt>:include</tt> option + # + # class User + # include ActiveModel::Serializers::JSON + # attr_accessor :name, :notes # Emulate has_many :notes + # def attributes + # {'name' => nil} + # end + # end + # + # class Note + # include ActiveModel::Serializers::JSON + # attr_accessor :title, :text + # def attributes + # {'title' => nil, 'text' => nil} + # end + # end + # + # note = Note.new + # note.title = 'Battle of Austerlitz' + # note.text = 'Some text here' + # + # user = User.new + # user.name = 'Napoleon' + # user.notes = [note] + # + # user.serializable_hash + # # => {"name" => "Napoleon"} + # user.serializable_hash(include: { notes: { only: 'title' }}) + # # => {"name" => "Napoleon", "notes" => [{"title"=>"Battle of Austerlitz"}]} def serializable_hash(options = nil) options ||= {} diff --git a/activemodel/test/cases/validations/i18n_validation_test.rb b/activemodel/test/cases/validations/i18n_validation_test.rb index be17575402..70b93a202b 100644 --- a/activemodel/test/cases/validations/i18n_validation_test.rb +++ b/activemodel/test/cases/validations/i18n_validation_test.rb @@ -98,7 +98,7 @@ class I18nValidationTest < ActiveModel::TestCase # validates_length_of :within too short w/ mocha COMMON_CASES.each do |name, validation_options, generate_message_options| - test "validates_length_of for :withing on generated message when too short #{name}" do + test "validates_length_of for :within on generated message when too short #{name}" do Person.validates_length_of :title, validation_options.merge(within: 3..5) @mock_generator.expect(:call, nil, [:title, :too_short, generate_message_options.merge(count: 3)]) @person.errors.stub(:generate_message, @mock_generator) do diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index f6a0777faf..02b2096ef6 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,8 @@ +* Deprecate the PG `:point` type in favor of a new one which will return + `Point` objects instead of an `Array` + + *Sean Griffin* + * Ensure symbols passed to `ActiveRecord::Relation#select` are always treated as columns. diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index ed19819d63..dd7dcb9cdd 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -662,7 +662,7 @@ module ActiveRecord # [<tt>:foreign_key</tt>] # Add an appropriate foreign key. Defaults to false. # [<tt>:polymorphic</tt>] - # Wether an additional +_type+ column should be added. Defaults to false. + # Whether an additional +_type+ column should be added. Defaults to false. # # ====== Create a user_id integer column # diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb index 92349e2f9b..68752cdd80 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb @@ -12,6 +12,7 @@ require 'active_record/connection_adapters/postgresql/oid/json' require 'active_record/connection_adapters/postgresql/oid/jsonb' require 'active_record/connection_adapters/postgresql/oid/money' require 'active_record/connection_adapters/postgresql/oid/point' +require 'active_record/connection_adapters/postgresql/oid/rails_5_1_point' require 'active_record/connection_adapters/postgresql/oid/range' require 'active_record/connection_adapters/postgresql/oid/specialized_string' require 'active_record/connection_adapters/postgresql/oid/uuid' diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb new file mode 100644 index 0000000000..7427a25ad5 --- /dev/null +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb @@ -0,0 +1,50 @@ +module ActiveRecord + Point = Struct.new(:x, :y) + + module ConnectionAdapters + module PostgreSQL + module OID # :nodoc: + class Rails51Point < Type::Value # :nodoc: + include Type::Helpers::Mutable + + def type + :point + end + + def cast(value) + case value + when ::String + if value[0] == '(' && value[-1] == ')' + value = value[1...-1] + end + x, y = value.split(",") + build_point(x, y) + when ::Array + build_point(*value) + else + value + end + end + + def serialize(value) + if value.is_a?(ActiveRecord::Point) + "(#{number_for_point(value.x)},#{number_for_point(value.y)})" + else + super + end + end + + private + + def number_for_point(number) + number.to_s.gsub(/\.0$/, '') + end + + def build_point(x, y) + ActiveRecord::Point.new(Float(x), Float(y)) + end + end + end + end + end +end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 93fa3984e6..2c43c46a3d 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -838,6 +838,8 @@ module ActiveRecord ActiveRecord::Type.register(:jsonb, OID::Jsonb, adapter: :postgresql) ActiveRecord::Type.register(:money, OID::Money, adapter: :postgresql) ActiveRecord::Type.register(:point, OID::Point, adapter: :postgresql) + ActiveRecord::Type.register(:legacy_point, OID::Point, adapter: :postgresql) + ActiveRecord::Type.register(:rails_5_1_point, OID::Rails51Point, adapter: :postgresql) ActiveRecord::Type.register(:uuid, OID::Uuid, adapter: :postgresql) ActiveRecord::Type.register(:vector, OID::Vector, adapter: :postgresql) ActiveRecord::Type.register(:xml, OID::Xml, adapter: :postgresql) diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb index eed1853841..738fab2bd9 100644 --- a/activerecord/lib/active_record/fixtures.rb +++ b/activerecord/lib/active_record/fixtures.rb @@ -615,7 +615,6 @@ module ActiveRecord # a list of rows to insert to that table. def table_rows now = config.default_timezone == :utc ? Time.now.utc : Time.now - now = now.to_s(:db) # allow a standard key to be used for doing defaults in YAML fixtures.delete('DEFAULTS') diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb index 3674f672cb..5a6f42ba09 100644 --- a/activerecord/lib/active_record/model_schema.rb +++ b/activerecord/lib/active_record/model_schema.rb @@ -310,6 +310,7 @@ module ActiveRecord def load_schema! @columns_hash = connection.schema_cache.columns_hash(table_name) @columns_hash.each do |name, column| + warn_if_deprecated_type(column) define_attribute( name, connection.lookup_cast_type_from_column(column), @@ -356,6 +357,28 @@ module ActiveRecord base.table_name end end + + def warn_if_deprecated_type(column) + return if attributes_to_define_after_schema_loads.key?(column.name) + if column.respond_to?(:oid) && column.sql_type.start_with?("point") + if column.array? + array_arguments = ", array: true" + else + array_arguments = "" + end + ActiveSupport::Deprecation.warn(<<-WARNING.strip_heredoc) + The behavior of the `:point` type will be changing in Rails 5.1 to + return a `Point` object, rather than an `Array`. If you'd like to + keep the old behavior, you can add this line to #{self.name}: + + attribute :#{column.name}, :legacy_point#{array_arguments} + + If you'd like the new behavior today, you can add this line: + + attribute :#{column.name}, :rails_5_1_point#{array_arguments} + WARNING + end + end end end end diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index 311dacb449..6f2def0df1 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -196,9 +196,9 @@ module ActiveRecord # automatically released. The following example demonstrates the problem: # # Model.connection.transaction do # BEGIN - # Model.connection.transaction(requires_new: true) do # CREATE SAVEPOINT active_record_1 + # Model.connection.transaction(requires_new: true) do # CREATE SAVEPOINT active_record_1 # Model.connection.create_table(...) # active_record_1 now automatically released - # end # RELEASE savepoint active_record_1 + # end # RELEASE SAVEPOINT active_record_1 # # ^^^^ BOOM! database error! # end # diff --git a/activerecord/test/cases/adapters/postgresql/geometric_test.rb b/activerecord/test/cases/adapters/postgresql/geometric_test.rb index 41e9572907..7057848eb0 100644 --- a/activerecord/test/cases/adapters/postgresql/geometric_test.rb +++ b/activerecord/test/cases/adapters/postgresql/geometric_test.rb @@ -6,7 +6,15 @@ class PostgresqlPointTest < ActiveRecord::TestCase include ConnectionHelper include SchemaDumpingHelper - class PostgresqlPoint < ActiveRecord::Base; end + class PostgresqlPoint < ActiveRecord::Base + attribute :x, :rails_5_1_point + attribute :y, :rails_5_1_point + attribute :z, :rails_5_1_point + attribute :array_of_points, :rails_5_1_point, array: true + attribute :legacy_x, :legacy_point + attribute :legacy_y, :legacy_point + attribute :legacy_z, :legacy_point + end def setup @connection = ActiveRecord::Base.connection @@ -14,11 +22,27 @@ class PostgresqlPointTest < ActiveRecord::TestCase t.point :x t.point :y, default: [12.2, 13.3] t.point :z, default: "(14.4,15.5)" + t.point :array_of_points, array: true + t.point :legacy_x + t.point :legacy_y, default: [12.2, 13.3] + t.point :legacy_z, default: "(14.4,15.5)" + end + @connection.create_table('deprecated_points') do |t| + t.point :x end end teardown do @connection.drop_table 'postgresql_points', if_exists: true + @connection.drop_table 'deprecated_points', if_exists: true + end + + class DeprecatedPoint < ActiveRecord::Base; end + + def test_deprecated_legacy_type + assert_deprecated do + DeprecatedPoint.new + end end def test_column @@ -32,11 +56,11 @@ class PostgresqlPointTest < ActiveRecord::TestCase end def test_default - assert_equal [12.2, 13.3], PostgresqlPoint.column_defaults['y'] - assert_equal [12.2, 13.3], PostgresqlPoint.new.y + assert_equal ActiveRecord::Point.new(12.2, 13.3), PostgresqlPoint.column_defaults['y'] + assert_equal ActiveRecord::Point.new(12.2, 13.3), PostgresqlPoint.new.y - assert_equal [14.4, 15.5], PostgresqlPoint.column_defaults['z'] - assert_equal [14.4, 15.5], PostgresqlPoint.new.z + assert_equal ActiveRecord::Point.new(14.4, 15.5), PostgresqlPoint.column_defaults['z'] + assert_equal ActiveRecord::Point.new(14.4, 15.5), PostgresqlPoint.new.z end def test_schema_dumping @@ -49,22 +73,95 @@ class PostgresqlPointTest < ActiveRecord::TestCase def test_roundtrip PostgresqlPoint.create! x: [10, 25.2] record = PostgresqlPoint.first - assert_equal [10, 25.2], record.x + assert_equal ActiveRecord::Point.new(10, 25.2), record.x - record.x = [1.1, 2.2] + record.x = ActiveRecord::Point.new(1.1, 2.2) record.save! assert record.reload - assert_equal [1.1, 2.2], record.x + assert_equal ActiveRecord::Point.new(1.1, 2.2), record.x end def test_mutation - p = PostgresqlPoint.create! x: [10, 20] + p = PostgresqlPoint.create! x: ActiveRecord::Point.new(10, 20) + + p.x.y = 25 + p.save! + p.reload + + assert_equal ActiveRecord::Point.new(10.0, 25.0), p.x + assert_not p.changed? + end + + def test_array_assignment + p = PostgresqlPoint.new(x: [1, 2]) + + assert_equal ActiveRecord::Point.new(1, 2), p.x + end + + def test_string_assignment + p = PostgresqlPoint.new(x: "(1, 2)") + + assert_equal ActiveRecord::Point.new(1, 2), p.x + end + + def test_array_of_points_round_trip + expected_value = [ + ActiveRecord::Point.new(1, 2), + ActiveRecord::Point.new(2, 3), + ActiveRecord::Point.new(3, 4), + ] + p = PostgresqlPoint.new(array_of_points: expected_value) + + assert_equal expected_value, p.array_of_points + p.save! + p.reload + assert_equal expected_value, p.array_of_points + end + + def test_legacy_column + column = PostgresqlPoint.columns_hash["legacy_x"] + assert_equal :point, column.type + assert_equal "point", column.sql_type + assert_not column.array? + + type = PostgresqlPoint.type_for_attribute("legacy_x") + assert_not type.binary? + end + + def test_legacy_default + assert_equal [12.2, 13.3], PostgresqlPoint.column_defaults['legacy_y'] + assert_equal [12.2, 13.3], PostgresqlPoint.new.legacy_y + + assert_equal [14.4, 15.5], PostgresqlPoint.column_defaults['legacy_z'] + assert_equal [14.4, 15.5], PostgresqlPoint.new.legacy_z + end + + def test_legacy_schema_dumping + output = dump_table_schema("postgresql_points") + assert_match %r{t\.point\s+"legacy_x"$}, output + assert_match %r{t\.point\s+"legacy_y",\s+default: \[12\.2, 13\.3\]$}, output + assert_match %r{t\.point\s+"legacy_z",\s+default: \[14\.4, 15\.5\]$}, output + end + + def test_legacy_roundtrip + PostgresqlPoint.create! legacy_x: [10, 25.2] + record = PostgresqlPoint.first + assert_equal [10, 25.2], record.legacy_x + + record.legacy_x = [1.1, 2.2] + record.save! + assert record.reload + assert_equal [1.1, 2.2], record.legacy_x + end + + def test_legacy_mutation + p = PostgresqlPoint.create! legacy_x: [10, 20] - p.x[1] = 25 + p.legacy_x[1] = 25 p.save! p.reload - assert_equal [10.0, 25.0], p.x + assert_equal [10.0, 25.0], p.legacy_x assert_not p.changed? end end diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 7658c8ba26..6ebbdbc3db 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -14,7 +14,7 @@ Before: - if (slack_url = Rails.application.secrets.slack_url).present?) + if (slack_url = Rails.application.secrets.slack_url).present? # Do something worthwhile else # Raise as important secret password is not specified diff --git a/activesupport/lib/active_support/backtrace_cleaner.rb b/activesupport/lib/active_support/backtrace_cleaner.rb index d06f22ad5c..e161ec4cca 100644 --- a/activesupport/lib/active_support/backtrace_cleaner.rb +++ b/activesupport/lib/active_support/backtrace_cleaner.rb @@ -25,7 +25,7 @@ module ActiveSupport # of the backtrace, you can call <tt>BacktraceCleaner#remove_filters!</tt> # These two methods will give you a completely untouched backtrace. # - # Inspired by the Quiet Backtrace gem by Thoughtbot. + # Inspired by the Quiet Backtrace gem by thoughtbot. class BacktraceCleaner def initialize @filters, @silencers = [], [] diff --git a/activesupport/lib/active_support/core_ext/uri.rb b/activesupport/lib/active_support/core_ext/uri.rb index bfe0832b37..0b2ff817c3 100644 --- a/activesupport/lib/active_support/core_ext/uri.rb +++ b/activesupport/lib/active_support/core_ext/uri.rb @@ -12,7 +12,7 @@ unless str == parser.unescape(parser.escape(str)) # YK: My initial experiments say yes, but let's be sure please enc = str.encoding enc = Encoding::UTF_8 if enc == Encoding::US_ASCII - str.gsub(escaped) { [$&[1, 2].hex].pack('C') }.force_encoding(enc) + str.gsub(escaped) { |match| [match[1, 2].hex].pack('C') }.force_encoding(enc) end end end diff --git a/activesupport/lib/active_support/deprecation/behaviors.rb b/activesupport/lib/active_support/deprecation/behaviors.rb index 0cdc7e96f7..28d2d78643 100644 --- a/activesupport/lib/active_support/deprecation/behaviors.rb +++ b/activesupport/lib/active_support/deprecation/behaviors.rb @@ -39,8 +39,8 @@ module ActiveSupport } # Behavior module allows to determine how to display deprecation messages. - # You can set any behaviors from +DEFAULT_BEHAVIORS+ constant or create - # custom behavior. Available behaviors: + # You can create a custom behavior or set any from the +DEFAULT_BEHAVIORS+ + # constant. Available behaviors are: # # [+raise+] Raise <tt>ActiveSupport::DeprecationException</tt>. # [+stderr+] Log all deprecation warnings to +$stderr+. @@ -49,7 +49,7 @@ module ActiveSupport # [+silence+] Do nothing. # # Setting behaviors only affects deprecations that happen after boot time. - # For more information you can read documentation for +behavior=+ method. + # For more information you can read the documentation of the +behavior=+ method. module Behavior # Whether to print a backtrace along with the warning. attr_accessor :debug diff --git a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb index c6d2b5e795..9b264cbb79 100644 --- a/activesupport/lib/active_support/deprecation/proxy_wrappers.rb +++ b/activesupport/lib/active_support/deprecation/proxy_wrappers.rb @@ -127,7 +127,7 @@ module ActiveSupport @deprecator = deprecator end - # Returns class of a new constant. + # Returns the class of the new constant. # # PLANETS_POST_2006 = %w(mercury venus earth mars jupiter saturn uranus neptune) # PLANETS = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('PLANETS', 'PLANETS_POST_2006') diff --git a/activesupport/lib/active_support/test_case.rb b/activesupport/lib/active_support/test_case.rb index d9a668c0ea..ae6f00b861 100644 --- a/activesupport/lib/active_support/test_case.rb +++ b/activesupport/lib/active_support/test_case.rb @@ -9,6 +9,7 @@ require 'active_support/testing/isolation' require 'active_support/testing/constant_lookup' require 'active_support/testing/time_helpers' require 'active_support/testing/file_fixtures' +require 'active_support/testing/composite_filter' require 'active_support/core_ext/kernel/reporting' module ActiveSupport @@ -38,6 +39,15 @@ module ActiveSupport def test_order ActiveSupport.test_order ||= :random end + + def run(reporter, options = {}) + if options[:patterns] && options[:patterns].any? { |p| p =~ /:\d+/ } + options[:filter] = \ + Testing::CompositeFilter.new(self, options[:filter], options[:patterns]) + end + + super + end end alias_method :method_name, :name diff --git a/activesupport/lib/active_support/testing/composite_filter.rb b/activesupport/lib/active_support/testing/composite_filter.rb new file mode 100644 index 0000000000..bde723e30b --- /dev/null +++ b/activesupport/lib/active_support/testing/composite_filter.rb @@ -0,0 +1,54 @@ +require 'method_source' + +module ActiveSupport + module Testing + class CompositeFilter # :nodoc: + def initialize(runnable, filter, patterns) + @runnable = runnable + @filters = [ derive_regexp(filter), *derive_line_filters(patterns) ].compact + end + + def ===(method) + @filters.any? { |filter| filter === method } + end + + private + def derive_regexp(filter) + filter =~ %r%/(.*)/% ? Regexp.new($1) : filter + end + + def derive_line_filters(patterns) + patterns.map do |file_and_line| + file, line = file_and_line.split(':') + Filter.new(@runnable, file, line) if file + end + end + + class Filter # :nodoc: + def initialize(runnable, file, line) + @runnable, @file = runnable, File.expand_path(file) + @line = line.to_i if line + end + + def ===(method) + return unless @runnable.method_defined?(method) + + if @line + test_file, test_range = definition_for(@runnable.instance_method(method)) + test_file == @file && test_range.include?(@line) + else + @runnable.instance_method(method).source_location.first == @file + end + end + + private + def definition_for(method) + file, start_line = method.source_location + end_line = method.source.count("\n") + start_line - 1 + + return file, start_line..end_line + end + end + end + end +end diff --git a/activesupport/lib/active_support/testing/time_helpers.rb b/activesupport/lib/active_support/testing/time_helpers.rb index 3478b09423..fca0947c5b 100644 --- a/activesupport/lib/active_support/testing/time_helpers.rb +++ b/activesupport/lib/active_support/testing/time_helpers.rb @@ -39,7 +39,7 @@ module ActiveSupport end end - # Contain helpers that help you test passage of time. + # Contains helpers that help you test passage of time. module TimeHelpers # Changes current time to the time in the future or in the past by a given time difference by # stubbing +Time.now+, +Date.today+, and +DateTime.now+. diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb index b0d7f3299f..412c72d27c 100644 --- a/activesupport/lib/active_support/time_with_zone.rb +++ b/activesupport/lib/active_support/time_with_zone.rb @@ -1,3 +1,4 @@ +require 'active_support/duration' require 'active_support/values/time_zone' require 'active_support/core_ext/object/acts_like' diff --git a/activesupport/test/abstract_unit.rb b/activesupport/test/abstract_unit.rb index 7ffcae6007..9b88a2dcc1 100644 --- a/activesupport/test/abstract_unit.rb +++ b/activesupport/test/abstract_unit.rb @@ -37,4 +37,5 @@ def jruby_skip(message = '') skip message if defined?(JRUBY_VERSION) end +require 'minitest/mock' require 'mocha/setup' # FIXME: stop using mocha diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb index dce4e9b051..8e22d4ed2f 100644 --- a/activesupport/test/caching_test.rb +++ b/activesupport/test/caching_test.rb @@ -288,8 +288,9 @@ module CacheStoreBehavior @cache.write('foo', 'bar', :expires_in => 10) @cache.write('fu', 'baz') @cache.write('fud', 'biz') - Time.stubs(:now).returns(time + 11) - assert_equal({"fu" => "baz"}, @cache.read_multi('foo', 'fu')) + Time.stub(:now, time + 11) do + assert_equal({"fu" => "baz"}, @cache.read_multi('foo', 'fu')) + end end def test_fetch_multi @@ -387,66 +388,74 @@ module CacheStoreBehavior def test_expires_in time = Time.local(2008, 4, 24) - Time.stubs(:now).returns(time) - @cache.write('foo', 'bar') - assert_equal 'bar', @cache.read('foo') + Time.stub(:now, time) do + @cache.write('foo', 'bar') + assert_equal 'bar', @cache.read('foo') + end - Time.stubs(:now).returns(time + 30) - assert_equal 'bar', @cache.read('foo') + Time.stub(:now, time + 30) do + assert_equal 'bar', @cache.read('foo') + end - Time.stubs(:now).returns(time + 61) - assert_nil @cache.read('foo') + Time.stub(:now, time + 61) do + assert_nil @cache.read('foo') + end end def test_race_condition_protection_skipped_if_not_defined @cache.write('foo', 'bar') time = @cache.send(:read_entry, 'foo', {}).expires_at - Time.stubs(:now).returns(Time.at(time)) - result = @cache.fetch('foo') do - assert_equal nil, @cache.read('foo') - 'baz' + Time.stub(:now, Time.at(time)) do + result = @cache.fetch('foo') do + assert_equal nil, @cache.read('foo') + 'baz' + end + assert_equal 'baz', result end - assert_equal 'baz', result end def test_race_condition_protection_is_limited time = Time.now @cache.write('foo', 'bar', :expires_in => 60) - Time.stubs(:now).returns(time + 71) - result = @cache.fetch('foo', :race_condition_ttl => 10) do - assert_equal nil, @cache.read('foo') - "baz" + Time.stub(:now, time + 71) do + result = @cache.fetch('foo', :race_condition_ttl => 10) do + assert_equal nil, @cache.read('foo') + "baz" + end + assert_equal "baz", result end - assert_equal "baz", result end def test_race_condition_protection_is_safe time = Time.now @cache.write('foo', 'bar', :expires_in => 60) - Time.stubs(:now).returns(time + 61) - begin - @cache.fetch('foo', :race_condition_ttl => 10) do - assert_equal 'bar', @cache.read('foo') - raise ArgumentError.new + Time.stub(:now, time + 61) do + begin + @cache.fetch('foo', :race_condition_ttl => 10) do + assert_equal 'bar', @cache.read('foo') + raise ArgumentError.new + end + rescue ArgumentError end - rescue ArgumentError + assert_equal "bar", @cache.read('foo') + end + Time.stub(:now, time + 91) do + assert_nil @cache.read('foo') end - assert_equal "bar", @cache.read('foo') - Time.stubs(:now).returns(time + 91) - assert_nil @cache.read('foo') end def test_race_condition_protection time = Time.now @cache.write('foo', 'bar', :expires_in => 60) - Time.stubs(:now).returns(time + 61) - result = @cache.fetch('foo', :race_condition_ttl => 10) do - assert_equal 'bar', @cache.read('foo') - "baz" + Time.stub(:now, time + 61) do + result = @cache.fetch('foo', :race_condition_ttl => 10) do + assert_equal 'bar', @cache.read('foo') + "baz" + end + assert_equal "baz", result end - assert_equal "baz", result end def test_crazy_key_characters @@ -775,11 +784,12 @@ class FileStoreTest < ActiveSupport::TestCase @cache.write('foo', 'bar', expires_in: 10) @cache.write('baz', 'qux') @cache.write('quux', 'corge', expires_in: 20) - Time.stubs(:now).returns(time + 15) - @cache.cleanup - assert_not @cache.exist?('foo') - assert @cache.exist?('baz') - assert @cache.exist?('quux') + Time.stub(:now, time + 15) do + @cache.cleanup + assert_not @cache.exist?('foo') + assert @cache.exist?('baz') + assert @cache.exist?('quux') + end end def test_write_with_unless_exist @@ -1056,9 +1066,9 @@ class CacheEntryTest < ActiveSupport::TestCase assert !entry.expired?, 'entry not expired' entry = ActiveSupport::Cache::Entry.new("value", :expires_in => 60) assert !entry.expired?, 'entry not expired' - time = Time.now + 61 - Time.stubs(:now).returns(time) - assert entry.expired?, 'entry is expired' + Time.stub(:now, Time.now + 61) do + assert entry.expired?, 'entry is expired' + end end def test_compress_values diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb index e89be25b53..0fc3f765f5 100644 --- a/activesupport/test/core_ext/date_ext_test.rb +++ b/activesupport/test/core_ext/date_ext_test.rb @@ -191,8 +191,9 @@ class DateExtCalculationsTest < ActiveSupport::TestCase def test_yesterday_constructor_when_zone_is_set with_env_tz 'UTC' do with_tz_default ActiveSupport::TimeZone['Eastern Time (US & Canada)'] do # UTC -5 - Time.stubs(:now).returns Time.local(2000, 1, 1) - assert_equal Date.new(1999, 12, 30), Date.yesterday + Time.stub(:now, Time.local(2000, 1, 1)) do + assert_equal Date.new(1999, 12, 30), Date.yesterday + end end end end @@ -212,8 +213,9 @@ class DateExtCalculationsTest < ActiveSupport::TestCase def test_tomorrow_constructor_when_zone_is_set with_env_tz 'UTC' do with_tz_default ActiveSupport::TimeZone['Europe/Paris'] do # UTC +1 - Time.stubs(:now).returns Time.local(1999, 12, 31, 23) - assert_equal Date.new(2000, 1, 2), Date.tomorrow + Time.stub(:now, Time.local(1999, 12, 31, 23)) do + assert_equal Date.new(2000, 1, 2), Date.tomorrow + end end end end @@ -317,23 +319,26 @@ class DateExtCalculationsTest < ActiveSupport::TestCase end def test_past - Date.stubs(:current).returns(Date.new(2000, 1, 1)) - assert_equal true, Date.new(1999, 12, 31).past? - assert_equal false, Date.new(2000,1,1).past? - assert_equal false, Date.new(2000,1,2).past? + Date.stub(:current, Date.new(2000, 1, 1)) do + assert_equal true, Date.new(1999, 12, 31).past? + assert_equal false, Date.new(2000,1,1).past? + assert_equal false, Date.new(2000,1,2).past? + end end def test_future - Date.stubs(:current).returns(Date.new(2000, 1, 1)) - assert_equal false, Date.new(1999, 12, 31).future? - assert_equal false, Date.new(2000,1,1).future? - assert_equal true, Date.new(2000,1,2).future? + Date.stub(:current, Date.new(2000, 1, 1)) do + assert_equal false, Date.new(1999, 12, 31).future? + assert_equal false, Date.new(2000,1,1).future? + assert_equal true, Date.new(2000,1,2).future? + end end def test_current_returns_date_today_when_zone_not_set with_env_tz 'US/Central' do - Time.stubs(:now).returns Time.local(1999, 12, 31, 23) - assert_equal Date.today, Date.current + Time.stub(:now, Time.local(1999, 12, 31, 23)) do + assert_equal Date.today, Date.current + end end end diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb index 74319ecd09..58d79f0541 100644 --- a/activesupport/test/core_ext/date_time_ext_test.rb +++ b/activesupport/test/core_ext/date_time_ext_test.rb @@ -204,61 +204,69 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase end def test_today_with_offset - Date.stubs(:current).returns(Date.new(2000, 1, 1)) - assert_equal false, DateTime.civil(1999,12,31,23,59,59, Rational(-18000, 86400)).today? - assert_equal true, DateTime.civil(2000,1,1,0,0,0, Rational(-18000, 86400)).today? - assert_equal true, DateTime.civil(2000,1,1,23,59,59, Rational(-18000, 86400)).today? - assert_equal false, DateTime.civil(2000,1,2,0,0,0, Rational(-18000, 86400)).today? + Date.stub(:current, Date.new(2000, 1, 1)) do + assert_equal false, DateTime.civil(1999,12,31,23,59,59, Rational(-18000, 86400)).today? + assert_equal true, DateTime.civil(2000,1,1,0,0,0, Rational(-18000, 86400)).today? + assert_equal true, DateTime.civil(2000,1,1,23,59,59, Rational(-18000, 86400)).today? + assert_equal false, DateTime.civil(2000,1,2,0,0,0, Rational(-18000, 86400)).today? + end end def test_today_without_offset - Date.stubs(:current).returns(Date.new(2000, 1, 1)) - assert_equal false, DateTime.civil(1999,12,31,23,59,59).today? - assert_equal true, DateTime.civil(2000,1,1,0).today? - assert_equal true, DateTime.civil(2000,1,1,23,59,59).today? - assert_equal false, DateTime.civil(2000,1,2,0).today? + Date.stub(:current, Date.new(2000, 1, 1)) do + assert_equal false, DateTime.civil(1999,12,31,23,59,59).today? + assert_equal true, DateTime.civil(2000,1,1,0).today? + assert_equal true, DateTime.civil(2000,1,1,23,59,59).today? + assert_equal false, DateTime.civil(2000,1,2,0).today? + end end def test_past_with_offset - DateTime.stubs(:current).returns(DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400))) - assert_equal true, DateTime.civil(2005,2,10,15,30,44, Rational(-18000, 86400)).past? - assert_equal false, DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400)).past? - assert_equal false, DateTime.civil(2005,2,10,15,30,46, Rational(-18000, 86400)).past? + DateTime.stub(:current, DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400))) do + assert_equal true, DateTime.civil(2005,2,10,15,30,44, Rational(-18000, 86400)).past? + assert_equal false, DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400)).past? + assert_equal false, DateTime.civil(2005,2,10,15,30,46, Rational(-18000, 86400)).past? + end end def test_past_without_offset - DateTime.stubs(:current).returns(DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400))) - assert_equal true, DateTime.civil(2005,2,10,20,30,44).past? - assert_equal false, DateTime.civil(2005,2,10,20,30,45).past? - assert_equal false, DateTime.civil(2005,2,10,20,30,46).past? + DateTime.stub(:current, DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400))) do + assert_equal true, DateTime.civil(2005,2,10,20,30,44).past? + assert_equal false, DateTime.civil(2005,2,10,20,30,45).past? + assert_equal false, DateTime.civil(2005,2,10,20,30,46).past? + end end def test_future_with_offset - DateTime.stubs(:current).returns(DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400))) - assert_equal false, DateTime.civil(2005,2,10,15,30,44, Rational(-18000, 86400)).future? - assert_equal false, DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400)).future? - assert_equal true, DateTime.civil(2005,2,10,15,30,46, Rational(-18000, 86400)).future? + DateTime.stub(:current, DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400))) do + assert_equal false, DateTime.civil(2005,2,10,15,30,44, Rational(-18000, 86400)).future? + assert_equal false, DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400)).future? + assert_equal true, DateTime.civil(2005,2,10,15,30,46, Rational(-18000, 86400)).future? + end end def test_future_without_offset - DateTime.stubs(:current).returns(DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400))) - assert_equal false, DateTime.civil(2005,2,10,20,30,44).future? - assert_equal false, DateTime.civil(2005,2,10,20,30,45).future? - assert_equal true, DateTime.civil(2005,2,10,20,30,46).future? + DateTime.stub(:current, DateTime.civil(2005,2,10,15,30,45, Rational(-18000, 86400))) do + assert_equal false, DateTime.civil(2005,2,10,20,30,44).future? + assert_equal false, DateTime.civil(2005,2,10,20,30,45).future? + assert_equal true, DateTime.civil(2005,2,10,20,30,46).future? + end end def test_current_returns_date_today_when_zone_is_not_set with_env_tz 'US/Eastern' do - Time.stubs(:now).returns Time.local(1999, 12, 31, 23, 59, 59) - assert_equal DateTime.new(1999, 12, 31, 23, 59, 59, Rational(-18000, 86400)), DateTime.current + Time.stub(:now, Time.local(1999, 12, 31, 23, 59, 59)) do + assert_equal DateTime.new(1999, 12, 31, 23, 59, 59, Rational(-18000, 86400)), DateTime.current + end end end def test_current_returns_time_zone_today_when_zone_is_set Time.zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] with_env_tz 'US/Eastern' do - Time.stubs(:now).returns Time.local(1999, 12, 31, 23, 59, 59) - assert_equal DateTime.new(1999, 12, 31, 23, 59, 59, Rational(-18000, 86400)), DateTime.current + Time.stub(:now, Time.local(1999, 12, 31, 23, 59, 59)) do + assert_equal DateTime.new(1999, 12, 31, 23, 59, 59, Rational(-18000, 86400)), DateTime.current + end end ensure Time.zone = nil diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb index c283b546e6..9e97acaffb 100644 --- a/activesupport/test/core_ext/duration_test.rb +++ b/activesupport/test/core_ext/duration_test.rb @@ -140,28 +140,30 @@ class DurationTest < ActiveSupport::TestCase def test_since_and_ago_anchored_to_time_now_when_time_zone_is_not_set Time.zone = nil with_env_tz 'US/Eastern' do - Time.stubs(:now).returns Time.local(2000) - # since - assert_not_instance_of ActiveSupport::TimeWithZone, 5.seconds.since - assert_equal Time.local(2000,1,1,0,0,5), 5.seconds.since - # ago - assert_not_instance_of ActiveSupport::TimeWithZone, 5.seconds.ago - assert_equal Time.local(1999,12,31,23,59,55), 5.seconds.ago + Time.stub(:now, Time.local(2000)) do + # since + assert_not_instance_of ActiveSupport::TimeWithZone, 5.seconds.since + assert_equal Time.local(2000,1,1,0,0,5), 5.seconds.since + # ago + assert_not_instance_of ActiveSupport::TimeWithZone, 5.seconds.ago + assert_equal Time.local(1999,12,31,23,59,55), 5.seconds.ago + end end end def test_since_and_ago_anchored_to_time_zone_now_when_time_zone_is_set Time.zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] with_env_tz 'US/Eastern' do - Time.stubs(:now).returns Time.local(2000) - # since - assert_instance_of ActiveSupport::TimeWithZone, 5.seconds.since - assert_equal Time.utc(2000,1,1,0,0,5), 5.seconds.since.time - assert_equal 'Eastern Time (US & Canada)', 5.seconds.since.time_zone.name - # ago - assert_instance_of ActiveSupport::TimeWithZone, 5.seconds.ago - assert_equal Time.utc(1999,12,31,23,59,55), 5.seconds.ago.time - assert_equal 'Eastern Time (US & Canada)', 5.seconds.ago.time_zone.name + Time.stub(:now, Time.local(2000)) do + # since + assert_instance_of ActiveSupport::TimeWithZone, 5.seconds.since + assert_equal Time.utc(2000,1,1,0,0,5), 5.seconds.since.time + assert_equal 'Eastern Time (US & Canada)', 5.seconds.since.time_zone.name + # ago + assert_instance_of ActiveSupport::TimeWithZone, 5.seconds.ago + assert_equal Time.utc(1999,12,31,23,59,55), 5.seconds.ago.time + assert_equal 'Eastern Time (US & Canada)', 5.seconds.ago.time_zone.name + end end ensure Time.zone = nil diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index cb24147ab3..3a5d6df06d 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -435,117 +435,123 @@ class StringConversionsTest < ActiveSupport::TestCase def test_standard_time_string_to_time_when_current_time_is_standard_time with_env_tz "US/Eastern" do - Time.stubs(:now).returns(Time.local(2012, 1, 1)) - assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00".to_time - assert_equal Time.utc(2012, 1, 1, 10, 0), "2012-01-01 10:00".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 13, 0), "2012-01-01 10:00 -0800".to_time - assert_equal Time.utc(2012, 1, 1, 18, 0), "2012-01-01 10:00 -0800".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00 -0500".to_time - assert_equal Time.utc(2012, 1, 1, 15, 0), "2012-01-01 10:00 -0500".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 5, 0), "2012-01-01 10:00 UTC".to_time - assert_equal Time.utc(2012, 1, 1, 10, 0), "2012-01-01 10:00 UTC".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 13, 0), "2012-01-01 10:00 PST".to_time - assert_equal Time.utc(2012, 1, 1, 18, 0), "2012-01-01 10:00 PST".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00 EST".to_time - assert_equal Time.utc(2012, 1, 1, 15, 0), "2012-01-01 10:00 EST".to_time(:utc) + Time.stub(:now, Time.local(2012, 1, 1)) do + assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00".to_time + assert_equal Time.utc(2012, 1, 1, 10, 0), "2012-01-01 10:00".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 13, 0), "2012-01-01 10:00 -0800".to_time + assert_equal Time.utc(2012, 1, 1, 18, 0), "2012-01-01 10:00 -0800".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00 -0500".to_time + assert_equal Time.utc(2012, 1, 1, 15, 0), "2012-01-01 10:00 -0500".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 5, 0), "2012-01-01 10:00 UTC".to_time + assert_equal Time.utc(2012, 1, 1, 10, 0), "2012-01-01 10:00 UTC".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 13, 0), "2012-01-01 10:00 PST".to_time + assert_equal Time.utc(2012, 1, 1, 18, 0), "2012-01-01 10:00 PST".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00 EST".to_time + assert_equal Time.utc(2012, 1, 1, 15, 0), "2012-01-01 10:00 EST".to_time(:utc) + end end end def test_standard_time_string_to_time_when_current_time_is_daylight_savings with_env_tz "US/Eastern" do - Time.stubs(:now).returns(Time.local(2012, 7, 1)) - assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00".to_time - assert_equal Time.utc(2012, 1, 1, 10, 0), "2012-01-01 10:00".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 13, 0), "2012-01-01 10:00 -0800".to_time - assert_equal Time.utc(2012, 1, 1, 18, 0), "2012-01-01 10:00 -0800".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00 -0500".to_time - assert_equal Time.utc(2012, 1, 1, 15, 0), "2012-01-01 10:00 -0500".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 5, 0), "2012-01-01 10:00 UTC".to_time - assert_equal Time.utc(2012, 1, 1, 10, 0), "2012-01-01 10:00 UTC".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 13, 0), "2012-01-01 10:00 PST".to_time - assert_equal Time.utc(2012, 1, 1, 18, 0), "2012-01-01 10:00 PST".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00 EST".to_time - assert_equal Time.utc(2012, 1, 1, 15, 0), "2012-01-01 10:00 EST".to_time(:utc) + Time.stub(:now, Time.local(2012, 7, 1)) do + assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00".to_time + assert_equal Time.utc(2012, 1, 1, 10, 0), "2012-01-01 10:00".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 13, 0), "2012-01-01 10:00 -0800".to_time + assert_equal Time.utc(2012, 1, 1, 18, 0), "2012-01-01 10:00 -0800".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00 -0500".to_time + assert_equal Time.utc(2012, 1, 1, 15, 0), "2012-01-01 10:00 -0500".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 5, 0), "2012-01-01 10:00 UTC".to_time + assert_equal Time.utc(2012, 1, 1, 10, 0), "2012-01-01 10:00 UTC".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 13, 0), "2012-01-01 10:00 PST".to_time + assert_equal Time.utc(2012, 1, 1, 18, 0), "2012-01-01 10:00 PST".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 10, 0), "2012-01-01 10:00 EST".to_time + assert_equal Time.utc(2012, 1, 1, 15, 0), "2012-01-01 10:00 EST".to_time(:utc) + end end end def test_daylight_savings_string_to_time_when_current_time_is_standard_time with_env_tz "US/Eastern" do - Time.stubs(:now).returns(Time.local(2012, 1, 1)) - assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00".to_time - assert_equal Time.utc(2012, 7, 1, 10, 0), "2012-07-01 10:00".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 13, 0), "2012-07-01 10:00 -0700".to_time - assert_equal Time.utc(2012, 7, 1, 17, 0), "2012-07-01 10:00 -0700".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00 -0400".to_time - assert_equal Time.utc(2012, 7, 1, 14, 0), "2012-07-01 10:00 -0400".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 6, 0), "2012-07-01 10:00 UTC".to_time - assert_equal Time.utc(2012, 7, 1, 10, 0), "2012-07-01 10:00 UTC".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 13, 0), "2012-07-01 10:00 PDT".to_time - assert_equal Time.utc(2012, 7, 1, 17, 0), "2012-07-01 10:00 PDT".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00 EDT".to_time - assert_equal Time.utc(2012, 7, 1, 14, 0), "2012-07-01 10:00 EDT".to_time(:utc) + Time.stub(:now, Time.local(2012, 1, 1)) do + assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00".to_time + assert_equal Time.utc(2012, 7, 1, 10, 0), "2012-07-01 10:00".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 13, 0), "2012-07-01 10:00 -0700".to_time + assert_equal Time.utc(2012, 7, 1, 17, 0), "2012-07-01 10:00 -0700".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00 -0400".to_time + assert_equal Time.utc(2012, 7, 1, 14, 0), "2012-07-01 10:00 -0400".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 6, 0), "2012-07-01 10:00 UTC".to_time + assert_equal Time.utc(2012, 7, 1, 10, 0), "2012-07-01 10:00 UTC".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 13, 0), "2012-07-01 10:00 PDT".to_time + assert_equal Time.utc(2012, 7, 1, 17, 0), "2012-07-01 10:00 PDT".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00 EDT".to_time + assert_equal Time.utc(2012, 7, 1, 14, 0), "2012-07-01 10:00 EDT".to_time(:utc) + end end end def test_daylight_savings_string_to_time_when_current_time_is_daylight_savings with_env_tz "US/Eastern" do - Time.stubs(:now).returns(Time.local(2012, 7, 1)) - assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00".to_time - assert_equal Time.utc(2012, 7, 1, 10, 0), "2012-07-01 10:00".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 13, 0), "2012-07-01 10:00 -0700".to_time - assert_equal Time.utc(2012, 7, 1, 17, 0), "2012-07-01 10:00 -0700".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00 -0400".to_time - assert_equal Time.utc(2012, 7, 1, 14, 0), "2012-07-01 10:00 -0400".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 6, 0), "2012-07-01 10:00 UTC".to_time - assert_equal Time.utc(2012, 7, 1, 10, 0), "2012-07-01 10:00 UTC".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 13, 0), "2012-07-01 10:00 PDT".to_time - assert_equal Time.utc(2012, 7, 1, 17, 0), "2012-07-01 10:00 PDT".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00 EDT".to_time - assert_equal Time.utc(2012, 7, 1, 14, 0), "2012-07-01 10:00 EDT".to_time(:utc) + Time.stub(:now, Time.local(2012, 7, 1)) do + assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00".to_time + assert_equal Time.utc(2012, 7, 1, 10, 0), "2012-07-01 10:00".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 13, 0), "2012-07-01 10:00 -0700".to_time + assert_equal Time.utc(2012, 7, 1, 17, 0), "2012-07-01 10:00 -0700".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00 -0400".to_time + assert_equal Time.utc(2012, 7, 1, 14, 0), "2012-07-01 10:00 -0400".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 6, 0), "2012-07-01 10:00 UTC".to_time + assert_equal Time.utc(2012, 7, 1, 10, 0), "2012-07-01 10:00 UTC".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 13, 0), "2012-07-01 10:00 PDT".to_time + assert_equal Time.utc(2012, 7, 1, 17, 0), "2012-07-01 10:00 PDT".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 10, 0), "2012-07-01 10:00 EDT".to_time + assert_equal Time.utc(2012, 7, 1, 14, 0), "2012-07-01 10:00 EDT".to_time(:utc) + end end end def test_partial_string_to_time_when_current_time_is_standard_time with_env_tz "US/Eastern" do - Time.stubs(:now).returns(Time.local(2012, 1, 1)) - assert_equal Time.local(2012, 1, 1, 10, 0), "10:00".to_time - assert_equal Time.utc(2012, 1, 1, 10, 0), "10:00".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 6, 0), "10:00 -0100".to_time - assert_equal Time.utc(2012, 1, 1, 11, 0), "10:00 -0100".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 10, 0), "10:00 -0500".to_time - assert_equal Time.utc(2012, 1, 1, 15, 0), "10:00 -0500".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 5, 0), "10:00 UTC".to_time - assert_equal Time.utc(2012, 1, 1, 10, 0), "10:00 UTC".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 13, 0), "10:00 PST".to_time - assert_equal Time.utc(2012, 1, 1, 18, 0), "10:00 PST".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 12, 0), "10:00 PDT".to_time - assert_equal Time.utc(2012, 1, 1, 17, 0), "10:00 PDT".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 10, 0), "10:00 EST".to_time - assert_equal Time.utc(2012, 1, 1, 15, 0), "10:00 EST".to_time(:utc) - assert_equal Time.local(2012, 1, 1, 9, 0), "10:00 EDT".to_time - assert_equal Time.utc(2012, 1, 1, 14, 0), "10:00 EDT".to_time(:utc) + Time.stub(:now, Time.local(2012, 1, 1)) do + assert_equal Time.local(2012, 1, 1, 10, 0), "10:00".to_time + assert_equal Time.utc(2012, 1, 1, 10, 0), "10:00".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 6, 0), "10:00 -0100".to_time + assert_equal Time.utc(2012, 1, 1, 11, 0), "10:00 -0100".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 10, 0), "10:00 -0500".to_time + assert_equal Time.utc(2012, 1, 1, 15, 0), "10:00 -0500".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 5, 0), "10:00 UTC".to_time + assert_equal Time.utc(2012, 1, 1, 10, 0), "10:00 UTC".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 13, 0), "10:00 PST".to_time + assert_equal Time.utc(2012, 1, 1, 18, 0), "10:00 PST".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 12, 0), "10:00 PDT".to_time + assert_equal Time.utc(2012, 1, 1, 17, 0), "10:00 PDT".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 10, 0), "10:00 EST".to_time + assert_equal Time.utc(2012, 1, 1, 15, 0), "10:00 EST".to_time(:utc) + assert_equal Time.local(2012, 1, 1, 9, 0), "10:00 EDT".to_time + assert_equal Time.utc(2012, 1, 1, 14, 0), "10:00 EDT".to_time(:utc) + end end end def test_partial_string_to_time_when_current_time_is_daylight_savings with_env_tz "US/Eastern" do - Time.stubs(:now).returns(Time.local(2012, 7, 1)) - assert_equal Time.local(2012, 7, 1, 10, 0), "10:00".to_time - assert_equal Time.utc(2012, 7, 1, 10, 0), "10:00".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 7, 0), "10:00 -0100".to_time - assert_equal Time.utc(2012, 7, 1, 11, 0), "10:00 -0100".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 11, 0), "10:00 -0500".to_time - assert_equal Time.utc(2012, 7, 1, 15, 0), "10:00 -0500".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 6, 0), "10:00 UTC".to_time - assert_equal Time.utc(2012, 7, 1, 10, 0), "10:00 UTC".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 14, 0), "10:00 PST".to_time - assert_equal Time.utc(2012, 7, 1, 18, 0), "10:00 PST".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 13, 0), "10:00 PDT".to_time - assert_equal Time.utc(2012, 7, 1, 17, 0), "10:00 PDT".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 11, 0), "10:00 EST".to_time - assert_equal Time.utc(2012, 7, 1, 15, 0), "10:00 EST".to_time(:utc) - assert_equal Time.local(2012, 7, 1, 10, 0), "10:00 EDT".to_time - assert_equal Time.utc(2012, 7, 1, 14, 0), "10:00 EDT".to_time(:utc) + Time.stub(:now, Time.local(2012, 7, 1)) do + assert_equal Time.local(2012, 7, 1, 10, 0), "10:00".to_time + assert_equal Time.utc(2012, 7, 1, 10, 0), "10:00".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 7, 0), "10:00 -0100".to_time + assert_equal Time.utc(2012, 7, 1, 11, 0), "10:00 -0100".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 11, 0), "10:00 -0500".to_time + assert_equal Time.utc(2012, 7, 1, 15, 0), "10:00 -0500".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 6, 0), "10:00 UTC".to_time + assert_equal Time.utc(2012, 7, 1, 10, 0), "10:00 UTC".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 14, 0), "10:00 PST".to_time + assert_equal Time.utc(2012, 7, 1, 18, 0), "10:00 PST".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 13, 0), "10:00 PDT".to_time + assert_equal Time.utc(2012, 7, 1, 17, 0), "10:00 PDT".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 11, 0), "10:00 EST".to_time + assert_equal Time.utc(2012, 7, 1, 15, 0), "10:00 EST".to_time(:utc) + assert_equal Time.local(2012, 7, 1, 10, 0), "10:00 EDT".to_time + assert_equal Time.utc(2012, 7, 1, 14, 0), "10:00 EDT".to_time(:utc) + end end end diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb index 62868d146b..e1ac5b3d8d 100644 --- a/activesupport/test/core_ext/time_ext_test.rb +++ b/activesupport/test/core_ext/time_ext_test.rb @@ -605,13 +605,15 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase end def test_days_in_month_feb_in_common_year_without_year_arg - Time.stubs(:now).returns(Time.utc(2007)) - assert_equal 28, Time.days_in_month(2) + Time.stub(:now, Time.utc(2007)) do + assert_equal 28, Time.days_in_month(2) + end end def test_days_in_month_feb_in_leap_year_without_year_arg - Time.stubs(:now).returns(Time.utc(2008)) - assert_equal 29, Time.days_in_month(2) + Time.stub(:now, Time.utc(2008)) do + assert_equal 29, Time.days_in_month(2) + end end def test_last_month_on_31st @@ -623,68 +625,74 @@ class TimeExtCalculationsTest < ActiveSupport::TestCase end def test_today_with_time_local - Date.stubs(:current).returns(Date.new(2000, 1, 1)) - assert_equal false, Time.local(1999,12,31,23,59,59).today? - assert_equal true, Time.local(2000,1,1,0).today? - assert_equal true, Time.local(2000,1,1,23,59,59).today? - assert_equal false, Time.local(2000,1,2,0).today? + Date.stub(:current, Date.new(2000, 1, 1)) do + assert_equal false, Time.local(1999,12,31,23,59,59).today? + assert_equal true, Time.local(2000,1,1,0).today? + assert_equal true, Time.local(2000,1,1,23,59,59).today? + assert_equal false, Time.local(2000,1,2,0).today? + end end def test_today_with_time_utc - Date.stubs(:current).returns(Date.new(2000, 1, 1)) - assert_equal false, Time.utc(1999,12,31,23,59,59).today? - assert_equal true, Time.utc(2000,1,1,0).today? - assert_equal true, Time.utc(2000,1,1,23,59,59).today? - assert_equal false, Time.utc(2000,1,2,0).today? + Date.stub(:current, Date.new(2000, 1, 1)) do + assert_equal false, Time.utc(1999,12,31,23,59,59).today? + assert_equal true, Time.utc(2000,1,1,0).today? + assert_equal true, Time.utc(2000,1,1,23,59,59).today? + assert_equal false, Time.utc(2000,1,2,0).today? + end end def test_past_with_time_current_as_time_local with_env_tz 'US/Eastern' do - Time.stubs(:current).returns(Time.local(2005,2,10,15,30,45)) - assert_equal true, Time.local(2005,2,10,15,30,44).past? - assert_equal false, Time.local(2005,2,10,15,30,45).past? - assert_equal false, Time.local(2005,2,10,15,30,46).past? - assert_equal true, Time.utc(2005,2,10,20,30,44).past? - assert_equal false, Time.utc(2005,2,10,20,30,45).past? - assert_equal false, Time.utc(2005,2,10,20,30,46).past? + Time.stub(:current, Time.local(2005,2,10,15,30,45)) do + assert_equal true, Time.local(2005,2,10,15,30,44).past? + assert_equal false, Time.local(2005,2,10,15,30,45).past? + assert_equal false, Time.local(2005,2,10,15,30,46).past? + assert_equal true, Time.utc(2005,2,10,20,30,44).past? + assert_equal false, Time.utc(2005,2,10,20,30,45).past? + assert_equal false, Time.utc(2005,2,10,20,30,46).past? + end end end def test_past_with_time_current_as_time_with_zone with_env_tz 'US/Eastern' do twz = Time.utc(2005,2,10,15,30,45).in_time_zone('Central Time (US & Canada)') - Time.stubs(:current).returns(twz) - assert_equal true, Time.local(2005,2,10,10,30,44).past? - assert_equal false, Time.local(2005,2,10,10,30,45).past? - assert_equal false, Time.local(2005,2,10,10,30,46).past? - assert_equal true, Time.utc(2005,2,10,15,30,44).past? - assert_equal false, Time.utc(2005,2,10,15,30,45).past? - assert_equal false, Time.utc(2005,2,10,15,30,46).past? + Time.stub(:current, twz) do + assert_equal true, Time.local(2005,2,10,10,30,44).past? + assert_equal false, Time.local(2005,2,10,10,30,45).past? + assert_equal false, Time.local(2005,2,10,10,30,46).past? + assert_equal true, Time.utc(2005,2,10,15,30,44).past? + assert_equal false, Time.utc(2005,2,10,15,30,45).past? + assert_equal false, Time.utc(2005,2,10,15,30,46).past? + end end end def test_future_with_time_current_as_time_local with_env_tz 'US/Eastern' do - Time.stubs(:current).returns(Time.local(2005,2,10,15,30,45)) - assert_equal false, Time.local(2005,2,10,15,30,44).future? - assert_equal false, Time.local(2005,2,10,15,30,45).future? - assert_equal true, Time.local(2005,2,10,15,30,46).future? - assert_equal false, Time.utc(2005,2,10,20,30,44).future? - assert_equal false, Time.utc(2005,2,10,20,30,45).future? - assert_equal true, Time.utc(2005,2,10,20,30,46).future? + Time.stub(:current, Time.local(2005,2,10,15,30,45)) do + assert_equal false, Time.local(2005,2,10,15,30,44).future? + assert_equal false, Time.local(2005,2,10,15,30,45).future? + assert_equal true, Time.local(2005,2,10,15,30,46).future? + assert_equal false, Time.utc(2005,2,10,20,30,44).future? + assert_equal false, Time.utc(2005,2,10,20,30,45).future? + assert_equal true, Time.utc(2005,2,10,20,30,46).future? + end end end def test_future_with_time_current_as_time_with_zone with_env_tz 'US/Eastern' do twz = Time.utc(2005,2,10,15,30,45).in_time_zone('Central Time (US & Canada)') - Time.stubs(:current).returns(twz) - assert_equal false, Time.local(2005,2,10,10,30,44).future? - assert_equal false, Time.local(2005,2,10,10,30,45).future? - assert_equal true, Time.local(2005,2,10,10,30,46).future? - assert_equal false, Time.utc(2005,2,10,15,30,44).future? - assert_equal false, Time.utc(2005,2,10,15,30,45).future? - assert_equal true, Time.utc(2005,2,10,15,30,46).future? + Time.stub(:current, twz) do + assert_equal false, Time.local(2005,2,10,10,30,44).future? + assert_equal false, Time.local(2005,2,10,10,30,45).future? + assert_equal true, Time.local(2005,2,10,10,30,46).future? + assert_equal false, Time.utc(2005,2,10,15,30,44).future? + assert_equal false, Time.utc(2005,2,10,15,30,45).future? + assert_equal true, Time.utc(2005,2,10,15,30,46).future? + end end end diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb index 79d78c02cd..5b48bf328c 100644 --- a/activesupport/test/core_ext/time_with_zone_test.rb +++ b/activesupport/test/core_ext/time_with_zone_test.rb @@ -205,45 +205,50 @@ class TimeWithZoneTest < ActiveSupport::TestCase end def test_today - Date.stubs(:current).returns(Date.new(2000, 1, 1)) - assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.utc(1999,12,31,23,59,59) ).today? - assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.utc(2000,1,1,0) ).today? - assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.utc(2000,1,1,23,59,59) ).today? - assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.utc(2000,1,2,0) ).today? + Date.stub(:current, Date.new(2000, 1, 1)) do + assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.utc(1999,12,31,23,59,59) ).today? + assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.utc(2000,1,1,0) ).today? + assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.utc(2000,1,1,23,59,59) ).today? + assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.utc(2000,1,2,0) ).today? + end end def test_past_with_time_current_as_time_local with_env_tz 'US/Eastern' do - Time.stubs(:current).returns(Time.local(2005,2,10,15,30,45)) - assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,44)).past? - assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,45)).past? - assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,46)).past? + Time.stub(:current, Time.local(2005,2,10,15,30,45)) do + assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,44)).past? + assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,45)).past? + assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,46)).past? + end end end def test_past_with_time_current_as_time_with_zone twz = ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,45) ) - Time.stubs(:current).returns(twz) - assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,44)).past? - assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,45)).past? - assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,46)).past? + Time.stub(:current, twz) do + assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,44)).past? + assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,45)).past? + assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,46)).past? + end end def test_future_with_time_current_as_time_local with_env_tz 'US/Eastern' do - Time.stubs(:current).returns(Time.local(2005,2,10,15,30,45)) - assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,44)).future? - assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,45)).future? - assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,46)).future? + Time.stub(:current, Time.local(2005,2,10,15,30,45)) do + assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,44)).future? + assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,45)).future? + assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,46)).future? + end end end def test_future_with_time_current_as_time_with_zone twz = ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,45) ) - Time.stubs(:current).returns(twz) - assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,44)).future? - assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,45)).future? - assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,46)).future? + Time.stub(:current, twz) do + assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,44)).future? + assert_equal false, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,45)).future? + assert_equal true, ActiveSupport::TimeWithZone.new( nil, @time_zone, Time.local(2005,2,10,15,30,46)).future? + end end def test_eql? @@ -1033,19 +1038,21 @@ class TimeWithZoneMethodsForTimeAndDateTimeTest < ActiveSupport::TestCase def test_current_returns_time_now_when_zone_not_set with_env_tz 'US/Eastern' do - Time.stubs(:now).returns Time.local(2000) - assert_equal false, Time.current.is_a?(ActiveSupport::TimeWithZone) - assert_equal Time.local(2000), Time.current + Time.stub(:now, Time.local(2000)) do + assert_equal false, Time.current.is_a?(ActiveSupport::TimeWithZone) + assert_equal Time.local(2000), Time.current + end end end def test_current_returns_time_zone_now_when_zone_set Time.zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] with_env_tz 'US/Eastern' do - Time.stubs(:now).returns Time.local(2000) - assert_equal true, Time.current.is_a?(ActiveSupport::TimeWithZone) - assert_equal 'Eastern Time (US & Canada)', Time.current.time_zone.name - assert_equal Time.utc(2000), Time.current.time + Time.stub(:now, Time.local(2000)) do + assert_equal true, Time.current.is_a?(ActiveSupport::TimeWithZone) + assert_equal 'Eastern Time (US & Canada)', Time.current.time_zone.name + assert_equal Time.utc(2000), Time.current.time + end end end diff --git a/activesupport/test/time_travel_test.rb b/activesupport/test/time_travel_test.rb index 869bc09991..59c3e52c2f 100644 --- a/activesupport/test/time_travel_test.rb +++ b/activesupport/test/time_travel_test.rb @@ -3,80 +3,88 @@ require 'active_support/core_ext/date_time' require 'active_support/core_ext/numeric/time' class TimeTravelTest < ActiveSupport::TestCase - setup do - Time.stubs now: Time.now - end - teardown do travel_back end def test_time_helper_travel - expected_time = Time.now + 1.day - travel 1.day - - assert_equal expected_time.to_s(:db), Time.now.to_s(:db) - assert_equal expected_time.to_date, Date.today - assert_equal expected_time.to_datetime.to_s(:db), DateTime.now.to_s(:db) - end - - def test_time_helper_travel_with_block - expected_time = Time.now + 1.day + Time.stub(:now, Time.now) do + expected_time = Time.now + 1.day + travel 1.day - travel 1.day do assert_equal expected_time.to_s(:db), Time.now.to_s(:db) assert_equal expected_time.to_date, Date.today assert_equal expected_time.to_datetime.to_s(:db), DateTime.now.to_s(:db) end - - assert_not_equal expected_time.to_s(:db), Time.now.to_s(:db) - assert_not_equal expected_time.to_date, Date.today - assert_not_equal expected_time.to_datetime.to_s(:db), DateTime.now.to_s(:db) end - def test_time_helper_travel_to - expected_time = Time.new(2004, 11, 24, 01, 04, 44) - travel_to expected_time - - assert_equal expected_time, Time.now - assert_equal Date.new(2004, 11, 24), Date.today - assert_equal expected_time.to_datetime, DateTime.now + def test_time_helper_travel_with_block + Time.stub(:now, Time.now) do + expected_time = Time.now + 1.day + + travel 1.day do + assert_equal expected_time.to_s(:db), Time.now.to_s(:db) + assert_equal expected_time.to_date, Date.today + assert_equal expected_time.to_datetime.to_s(:db), DateTime.now.to_s(:db) + end + + assert_not_equal expected_time.to_s(:db), Time.now.to_s(:db) + assert_not_equal expected_time.to_date, Date.today + assert_not_equal expected_time.to_datetime.to_s(:db), DateTime.now.to_s(:db) + end end - def test_time_helper_travel_to_with_block - expected_time = Time.new(2004, 11, 24, 01, 04, 44) + def test_time_helper_travel_to + Time.stub(:now, Time.now) do + expected_time = Time.new(2004, 11, 24, 01, 04, 44) + travel_to expected_time - travel_to expected_time do assert_equal expected_time, Time.now assert_equal Date.new(2004, 11, 24), Date.today assert_equal expected_time.to_datetime, DateTime.now end + end - assert_not_equal expected_time, Time.now - assert_not_equal Date.new(2004, 11, 24), Date.today - assert_not_equal expected_time.to_datetime, DateTime.now + def test_time_helper_travel_to_with_block + Time.stub(:now, Time.now) do + expected_time = Time.new(2004, 11, 24, 01, 04, 44) + + travel_to expected_time do + assert_equal expected_time, Time.now + assert_equal Date.new(2004, 11, 24), Date.today + assert_equal expected_time.to_datetime, DateTime.now + end + + assert_not_equal expected_time, Time.now + assert_not_equal Date.new(2004, 11, 24), Date.today + assert_not_equal expected_time.to_datetime, DateTime.now + end end def test_time_helper_travel_back - expected_time = Time.new(2004, 11, 24, 01, 04, 44) + Time.stub(:now, Time.now) do + expected_time = Time.new(2004, 11, 24, 01, 04, 44) - travel_to expected_time - assert_equal expected_time, Time.now - assert_equal Date.new(2004, 11, 24), Date.today - assert_equal expected_time.to_datetime, DateTime.now - travel_back + travel_to expected_time + assert_equal expected_time, Time.now + assert_equal Date.new(2004, 11, 24), Date.today + assert_equal expected_time.to_datetime, DateTime.now + travel_back - assert_not_equal expected_time, Time.now - assert_not_equal Date.new(2004, 11, 24), Date.today - assert_not_equal expected_time.to_datetime, DateTime.now + assert_not_equal expected_time, Time.now + assert_not_equal Date.new(2004, 11, 24), Date.today + assert_not_equal expected_time.to_datetime, DateTime.now + end end def test_travel_to_will_reset_the_usec_to_avoid_mysql_rouding - travel_to Time.utc(2014, 10, 10, 10, 10, 50, 999999) do - assert_equal 50, Time.now.sec - assert_equal 0, Time.now.usec - assert_equal 50, DateTime.now.sec - assert_equal 0, DateTime.now.usec + Time.stub(:now, Time.now) do + travel_to Time.utc(2014, 10, 10, 10, 10, 50, 999999) do + assert_equal 50, Time.now.sec + assert_equal 0, Time.now.usec + assert_equal 50, DateTime.now.sec + assert_equal 0, DateTime.now.usec + end end end end diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb index 5e0474f449..34bb0e2995 100644 --- a/activesupport/test/time_zone_test.rb +++ b/activesupport/test/time_zone_test.rb @@ -252,9 +252,10 @@ class TimeZoneTest < ActiveSupport::TestCase def test_parse_with_incomplete_date zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] - zone.stubs(:now).returns zone.local(1999,12,31) - twz = zone.parse('19:00:00') - assert_equal Time.utc(1999,12,31,19), twz.time + zone.stub(:now, zone.local(1999,12,31)) do + twz = zone.parse('19:00:00') + assert_equal Time.utc(1999,12,31,19), twz.time + end end def test_parse_with_day_omitted @@ -284,9 +285,10 @@ class TimeZoneTest < ActiveSupport::TestCase def test_parse_with_missing_time_components zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] - zone.stubs(:now).returns zone.local(1999, 12, 31, 12, 59, 59) - twz = zone.parse('2012-12-01') - assert_equal Time.utc(2012, 12, 1), twz.time + zone.stub(:now, zone.local(1999, 12, 31, 12, 59, 59)) do + twz = zone.parse('2012-12-01') + assert_equal Time.utc(2012, 12, 1), twz.time + end end def test_parse_with_javascript_date diff --git a/ci/travis.rb b/ci/travis.rb index b62f90a59e..52fef05fbf 100755 --- a/ci/travis.rb +++ b/ci/travis.rb @@ -16,13 +16,14 @@ end class Build MAP = { 'railties' => 'railties', - 'ap' => 'actionpack', - 'am' => 'actionmailer', - 'amo' => 'activemodel', - 'as' => 'activesupport', - 'ar' => 'activerecord', - 'av' => 'actionview', - 'aj' => 'activejob' + 'ap' => 'actionpack', + 'am' => 'actionmailer', + 'amo' => 'activemodel', + 'as' => 'activesupport', + 'ar' => 'activerecord', + 'av' => 'actionview', + 'aj' => 'activejob', + 'guides' => 'guides' } attr_reader :component, :options @@ -36,7 +37,11 @@ class Build self.options.update(options) Dir.chdir(dir) do announce(heading) - rake(*tasks) + if guides? + run_bug_report_templates + else + rake(*tasks) + end end end @@ -71,6 +76,10 @@ class Build gem == 'activerecord' end + def guides? + gem == 'guides' + end + def isolated? options[:isolated] end @@ -96,6 +105,12 @@ class Build end true end + + def run_bug_report_templates + Dir.glob('bug_report_templates/*.rb').all? do |file| + system(Gem.ruby, '-w', file) + end + end end if ENV['GEM']=='aj:integration' @@ -110,6 +125,7 @@ ENV['GEM'].split(',').each do |gem| next if ENV['TRAVIS_PULL_REQUEST'] && ENV['TRAVIS_PULL_REQUEST'] != 'false' && isolated next if gem == 'railties' && isolated next if gem == 'aj:integration' && isolated + next if gem == 'guides' && isolated build = Build.new(gem, :isolated => isolated) results[build.key] = build.run! diff --git a/guides/bug_report_templates/action_controller_gem.rb b/guides/bug_report_templates/action_controller_gem.rb index 032e6bfe11..11561c55f9 100644 --- a/guides/bug_report_templates/action_controller_gem.rb +++ b/guides/bug_report_templates/action_controller_gem.rb @@ -1,7 +1,16 @@ -# Activate the gem you are reporting the issue against. -gem 'rails', '4.2.0' +begin + require 'bundler/inline' +rescue LoadError => e + $stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler' + raise e +end + +gemfile(true) do + source 'https://rubygems.org' + # Activate the gem you are reporting the issue against. + gem 'rails', '4.2.0' +end -require 'rails' require 'rack/test' require 'action_controller/railtie' diff --git a/guides/bug_report_templates/action_controller_master.rb b/guides/bug_report_templates/action_controller_master.rb index 9be8130884..66887398b9 100644 --- a/guides/bug_report_templates/action_controller_master.rb +++ b/guides/bug_report_templates/action_controller_master.rb @@ -1,17 +1,16 @@ -unless File.exist?('Gemfile') - File.write('Gemfile', <<-GEMFILE) - source 'https://rubygems.org' - gem 'rails', github: 'rails/rails' - gem 'arel', github: 'rails/arel' - GEMFILE - - system 'bundle' +begin + require 'bundler/inline' +rescue LoadError => e + $stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler' + raise e end -require 'bundler' -Bundler.setup(:default) +gemfile(true) do + source 'https://rubygems.org' + gem 'rails', github: 'rails/rails' + gem 'arel', github: 'rails/arel' +end -require 'rails' require 'action_controller/railtie' class TestApp < Rails::Application diff --git a/guides/bug_report_templates/active_record_gem.rb b/guides/bug_report_templates/active_record_gem.rb index b295d9d21f..09d6e7b331 100644 --- a/guides/bug_report_templates/active_record_gem.rb +++ b/guides/bug_report_templates/active_record_gem.rb @@ -1,5 +1,17 @@ -# Activate the gem you are reporting the issue against. -gem 'activerecord', '4.2.0' +begin + require 'bundler/inline' +rescue LoadError => e + $stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler' + raise e +end + +gemfile(true) do + source 'https://rubygems.org' + # Activate the gem you are reporting the issue against. + gem 'activerecord', '4.2.0' + gem 'sqlite3' +end + require 'active_record' require 'minitest/autorun' require 'logger' diff --git a/guides/bug_report_templates/active_record_master.rb b/guides/bug_report_templates/active_record_master.rb index 9557f0b7c5..270dbe7df7 100644 --- a/guides/bug_report_templates/active_record_master.rb +++ b/guides/bug_report_templates/active_record_master.rb @@ -1,16 +1,16 @@ -unless File.exist?('Gemfile') - File.write('Gemfile', <<-GEMFILE) - source 'https://rubygems.org' - gem 'rails', github: 'rails/rails' - gem 'arel', github: 'rails/arel' - gem 'sqlite3' - GEMFILE - - system 'bundle' +begin + require 'bundler/inline' +rescue LoadError => e + $stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler' + raise e end -require 'bundler' -Bundler.setup(:default) +gemfile(true) do + source 'https://rubygems.org' + gem 'rails', github: 'rails/rails' + gem 'arel', github: 'rails/arel' + gem 'sqlite3' +end require 'active_record' require 'minitest/autorun' diff --git a/guides/bug_report_templates/generic_gem.rb b/guides/bug_report_templates/generic_gem.rb index 3e3f8593d4..a4fe51156d 100644 --- a/guides/bug_report_templates/generic_gem.rb +++ b/guides/bug_report_templates/generic_gem.rb @@ -1,6 +1,16 @@ -# Activate the gems you are reporting the issue against. -gem 'activesupport', '4.2.0' -require 'active_support' +begin + require 'bundler/inline' +rescue LoadError => e + $stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler' + raise e +end + +gemfile(true) do + source 'https://rubygems.org' + # Activate the gem you are reporting the issue against. + gem 'activesupport', '4.2.0' +end + require 'active_support/core_ext/object/blank' require 'minitest/autorun' diff --git a/guides/bug_report_templates/generic_master.rb b/guides/bug_report_templates/generic_master.rb index d930482d4e..b6b4562751 100644 --- a/guides/bug_report_templates/generic_master.rb +++ b/guides/bug_report_templates/generic_master.rb @@ -1,15 +1,15 @@ -unless File.exist?('Gemfile') - File.write('Gemfile', <<-GEMFILE) - source 'https://rubygems.org' - gem 'rails', github: 'rails/rails' - gem 'arel', github: 'rails/arel' - GEMFILE - - system 'bundle' +begin + require 'bundler/inline' +rescue LoadError => e + $stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler' + raise e end -require 'bundler' -Bundler.setup(:default) +gemfile(true) do + source 'https://rubygems.org' + gem 'rails', github: 'rails/rails' + gem 'arel', github: 'rails/arel' +end require 'active_support' require 'active_support/core_ext/object/blank' diff --git a/guides/source/action_view_overview.md b/guides/source/action_view_overview.md index 950bb5e358..09fac41491 100644 --- a/guides/source/action_view_overview.md +++ b/guides/source/action_view_overview.md @@ -214,7 +214,8 @@ By default `ActionView::Partials::PartialRenderer` has its object in a local var <%= render partial: "product" %> ``` -within product we'll get `@product` in the local variable `product`, as if we had written: +within `_product` partial we'll get `@product` in the local variable `product`, +as if we had written: ```erb <%= render partial: "product", locals: { product: @product } %> @@ -706,7 +707,7 @@ Returns a select tag with options for each of the minutes 0 through 59 with the ```ruby # Generates a select field for minutes that defaults to the minutes for the time provided. -select_minute(Time.now + 6.hours) +select_minute(Time.now + 10.minutes) ``` #### select_month diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md index e6475f2bb5..01bf928407 100644 --- a/guides/source/active_support_core_extensions.md +++ b/guides/source/active_support_core_extensions.md @@ -1936,6 +1936,8 @@ as well as adding or subtracting their results from a Time object. For example: (4.months + 5.years).from_now ``` +NOTE: Defined in `active_support/core_ext/numeric/time.rb` + ### Formatting Enables the formatting of numbers in a variety of ways. @@ -2893,7 +2895,7 @@ The method `transform_values` accepts a block and returns a hash that has applie ``` There's also the bang variant `transform_values!` that applies the block operations to values in the very receiver. -NOTE: Defined in `active_support/core_text/hash/transform_values.rb`. +NOTE: Defined in `active_support/core_ext/hash/transform_values.rb`. ### Slicing diff --git a/guides/source/active_support_instrumentation.md b/guides/source/active_support_instrumentation.md index 1b14bedfbf..373dbbb9aa 100644 --- a/guides/source/active_support_instrumentation.md +++ b/guides/source/active_support_instrumentation.md @@ -252,6 +252,20 @@ INFO. The adapters will add their own data as well. | `:name` | Record's class | | `:connection_id` | `self.object_id` | +### instantiation.active_record + +| Key | Value | +| ---------------- | ----------------------------------------- | +| `:record_count` | Number of records that instantiated | +| `:class_name` | Record's class | + +```ruby +{ + record_count: 1, + class_name: "User" +} +``` + Action Mailer ------------- diff --git a/guides/source/association_basics.md b/guides/source/association_basics.md index 3f63c31cce..05dd0d2a04 100644 --- a/guides/source/association_basics.md +++ b/guides/source/association_basics.md @@ -1473,7 +1473,8 @@ The `collection.clear` method removes all objects from the collection according @customer.orders.clear ``` -WARNING: Objects will be delete if they're associated with `dependent: :destroy`, just like `dependent: :delete_all`. +WARNING: Objects will be deleted if they're associated with `dependent: :destroy`, +just like `dependent: :delete_all`. ##### `collection.empty?` @@ -1512,7 +1513,7 @@ The `collection.where` method finds objects within the collection based on the c ##### `collection.exists?(...)` -The `collection.exists?` method checks whether an object meeting the supplied +The `collection.exists?` method checks whether an object meeting the supplied conditions exists in the collection. It uses the same syntax and options as [`ActiveRecord::Base.exists?`](http://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-exists-3F). diff --git a/guides/source/command_line.md b/guides/source/command_line.md index 315d8c14b6..0f5a9e4e39 100644 --- a/guides/source/command_line.md +++ b/guides/source/command_line.md @@ -64,10 +64,10 @@ $ cd commandsapp $ bin/rails server => Booting WEBrick => Rails 5.0.0 application starting in development on http://localhost:3000 -=> Call with -d to detach +=> Run `rails server -h` for more startup options => Ctrl-C to shutdown server [2013-08-07 02:00:01] INFO WEBrick 1.3.1 -[2013-08-07 02:00:01] INFO ruby 2.0.0 (2013-06-27) [x86_64-darwin11.2.0] +[2013-08-07 02:00:01] INFO ruby 2.2.2 (2015-06-27) [x86_64-darwin11.2.0] [2013-08-07 02:00:01] INFO WEBrick::HTTPServer#start: pid=69680 port=3000 ``` diff --git a/guides/source/configuring.md b/guides/source/configuring.md index b3a1ae6779..bb6c395c96 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -161,8 +161,6 @@ pipeline is enabled. It is set to true by default. * `config.assets.cache_store` defines the cache store that Sprockets will use. The default is the Rails file store. -* `config.assets.version` is an option string that is used in MD5 hash generation. This can be changed to force all files to be recompiled. - * `config.assets.compile` is a boolean that can be used to turn on live Sprockets compilation in production. * `config.assets.logger` accepts a logger conforming to the interface of Log4r or the default Ruby `Logger` class. Defaults to the same configured at `config.logger`. Setting `config.assets.logger` to false will turn off served assets logging. @@ -188,7 +186,8 @@ The full set of methods that can be used in this block are as follows: * `javascript_engine` configures the engine to be used (for eg. coffee) when generating assets. Defaults to `:js`. * `orm` defines which orm to use. Defaults to `false` and will use Active Record by default. * `resource_controller` defines which generator to use for generating a controller when using `rails generate resource`. Defaults to `:controller`. -* `resource_route` defines whether inject resource route definition in routes or not. Defaults to `true`. +* `resource_route` defines whether a resource route definition should be generated + or not. Defaults to `true`. * `scaffold_controller` different from `resource_controller`, defines which generator to use for generating a _scaffolded_ controller when using `rails generate scaffold`. Defaults to `:scaffold_controller`. * `stylesheets` turns on the hook for stylesheets in generators. Used in Rails for when the `scaffold` generator is run, but this hook can be used in other generates as well. Defaults to `true`. * `stylesheet_engine` configures the stylesheet engine (for eg. sass) to be used when generating assets. Defaults to `:css`. @@ -517,7 +516,8 @@ There are a number of settings available on `config.action_mailer`: config.action_mailer.show_previews = false ``` -* `config.action_mailer.deliver_later_queue_name`. specifies the queue name for mailers. By default this is `mailers`. +* `config.action_mailer.deliver_later_queue_name` specifies the queue name for + mailers. By default this is `mailers`. ### Configuring Active Support diff --git a/guides/source/development_dependencies_install.md b/guides/source/development_dependencies_install.md index 4b10d005eb..295e48f493 100644 --- a/guides/source/development_dependencies_install.md +++ b/guides/source/development_dependencies_install.md @@ -28,7 +28,7 @@ In case you can't use the Rails development box, see section below, these are th Ruby on Rails uses Git for source code control. The [Git homepage](http://git-scm.com/) has installation instructions. There are a variety of resources on the net that will help you get familiar with Git: * [Try Git course](http://try.github.io/) is an interactive course that will teach you the basics. -* The [official Documentation](http://git-scm.com/documentation) is pretty comprehensive and also contains some videos with the basics of Git +* The [official Documentation](http://git-scm.com/documentation) is pretty comprehensive and also contains some videos with the basics of Git. * [Everyday Git](http://schacon.github.io/git/everyday.html) will teach you just enough about Git to get by. * The [PeepCode screencast](https://peepcode.com/products/git) on Git is easier to follow. * [GitHub](http://help.github.com) offers links to a variety of Git resources. diff --git a/guides/source/engines.md b/guides/source/engines.md index a89ed1984f..3b1588b75a 100644 --- a/guides/source/engines.md +++ b/guides/source/engines.md @@ -689,8 +689,8 @@ haven't been copied over already. The first run for this command will output something such as this: ```bash -Copied migration [timestamp_1]_create_blorgh_articles.rb from blorgh -Copied migration [timestamp_2]_create_blorgh_comments.rb from blorgh +Copied migration [timestamp_1]_create_blorgh_articles.blorgh.rb from blorgh +Copied migration [timestamp_2]_create_blorgh_comments.blorgh.rb from blorgh ``` The first timestamp (`[timestamp_1]`) will be the current time, and the second @@ -822,9 +822,9 @@ Notice that only _one_ migration was copied over here. This is because the first two migrations were copied over the first time this command was run. ``` -NOTE Migration [timestamp]_create_blorgh_articles.rb from blorgh has been skipped. Migration with the same name already exists. -NOTE Migration [timestamp]_create_blorgh_comments.rb from blorgh has been skipped. Migration with the same name already exists. -Copied migration [timestamp]_add_author_id_to_blorgh_articles.rb from blorgh +NOTE Migration [timestamp]_create_blorgh_articles.blorgh.rb from blorgh has been skipped. Migration with the same name already exists. +NOTE Migration [timestamp]_create_blorgh_comments.blorgh.rb from blorgh has been skipped. Migration with the same name already exists. +Copied migration [timestamp]_add_author_id_to_blorgh_articles.blorgh.rb from blorgh ``` Run the migration using: diff --git a/guides/source/form_helpers.md b/guides/source/form_helpers.md index 853227e2a1..8f7d97844e 100644 --- a/guides/source/form_helpers.md +++ b/guides/source/form_helpers.md @@ -291,8 +291,8 @@ You can create a similar binding without actually creating `<form>` tags with th ```erb <%= form_for @person, url: {action: "create"} do |person_form| %> <%= person_form.text_field :name %> - <%= fields_for @person.contact_detail do |contact_details_form| %> - <%= contact_details_form.text_field :phone_number %> + <%= fields_for @person.contact_detail do |contact_detail_form| %> + <%= contact_detail_form.text_field :phone_number %> <% end %> <% end %> ``` @@ -441,7 +441,7 @@ Whenever Rails sees that the internal value of an option being generated matches TIP: The second argument to `options_for_select` must be exactly equal to the desired internal value. In particular if the value is the integer `2` you cannot pass `"2"` to `options_for_select` - you must pass `2`. Be aware of values extracted from the `params` hash as they are all strings. -WARNING: when `:include_blank` or `:prompt` are not present, `:include_blank` is forced true if the select attribute `required` is true, display `size` is one and `multiple` is not true. +WARNING: When `:include_blank` or `:prompt` are not present, `:include_blank` is forced true if the select attribute `required` is true, display `size` is one and `multiple` is not true. You can add arbitrary attributes to the options using hashes: diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md index 8cdb25c0c6..e64a788ac2 100644 --- a/guides/source/getting_started.md +++ b/guides/source/getting_started.md @@ -1240,7 +1240,9 @@ article we want to show the form back to the user. We reuse the `article_params` method that we defined earlier for the create action. -TIP: It is not necessary to pass all the attributes to `update`. For example, if `@article.update(title: 'A new title')` were called, Rails would only update the `title` attribute, leaving all other attributes untouched. +TIP: It is not necessary to pass all the attributes to `update`. For example, +if `@article.update(title: 'A new title')` was called, Rails would only update +the `title` attribute, leaving all other attributes untouched. Finally, we want to show a link to the `edit` action in the list of all the articles, so let's add that now to `app/views/articles/index.html.erb` to make diff --git a/guides/source/i18n.md b/guides/source/i18n.md index 51eaf4ba5a..9f0ed1a85b 100644 --- a/guides/source/i18n.md +++ b/guides/source/i18n.md @@ -500,7 +500,10 @@ You can make use of this feature, e.g. when working with a large amount of stati ### Organization of Locale Files -When you are using the default SimpleStore shipped with the i18n library, dictionaries are stored in plain-text files on the disc. Putting translations for all parts of your application in one file per locale could be hard to manage. You can store these files in a hierarchy which makes sense to you. +When you are using the default SimpleStore shipped with the i18n library, +dictionaries are stored in plain-text files on the disk. Putting translations +for all parts of your application in one file per locale could be hard to +manage. You can store these files in a hierarchy which makes sense to you. For example, your `config/locales` directory could look like this: diff --git a/guides/source/routing.md b/guides/source/routing.md index b1e4c8ad86..52f11f92bd 100644 --- a/guides/source/routing.md +++ b/guides/source/routing.md @@ -809,13 +809,16 @@ As long as `Sprockets` responds to `call` and returns a `[status, headers, body] NOTE: For the curious, `'articles#index'` actually expands out to `ArticlesController.action(:index)`, which returns a valid Rack application. -If you specify a rack application as the endpoint for a matcher remember that the route will be unchanged in the receiving application. With the following route your rack application should expect the route to be '/admin': +If you specify a Rack application as the endpoint for a matcher, remember that +the route will be unchanged in the receiving application. With the following +route your Rack application should expect the route to be '/admin': ```ruby match '/admin', to: AdminApp, via: :all ``` -If you would prefer to have your rack application receive requests at the root path instead use mount: +If you would prefer to have your Rack application receive requests at the root +path instead, use mount: ```ruby mount AdminApp, at: '/admin' diff --git a/railties/lib/rails/commands/test.rb b/railties/lib/rails/commands/test.rb index 598e224a6f..fe5307788a 100644 --- a/railties/lib/rails/commands/test.rb +++ b/railties/lib/rails/commands/test.rb @@ -1,5 +1,5 @@ -require "rails/test_unit/runner" +require "rails/test_unit/minitest_plugin" $: << File.expand_path("../../test", APP_PATH) -Rails::TestRunner.run(ARGV) +exit Minitest.run(ARGV) diff --git a/railties/lib/rails/console/app.rb b/railties/lib/rails/console/app.rb index 2a69c26deb..ac5836a588 100644 --- a/railties/lib/rails/console/app.rb +++ b/railties/lib/rails/console/app.rb @@ -18,6 +18,11 @@ module Rails app = Rails.application session = ActionDispatch::Integration::Session.new(app) yield session if block_given? + + # This makes app.url_for and app.foo_path available in the console + session.extend(app.routes.url_helpers) + session.extend(app.routes.mounted_helpers) + session end diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb index a7da92168d..79088bbe3c 100644 --- a/railties/lib/rails/generators.rb +++ b/railties/lib/rails/generators.rb @@ -33,6 +33,7 @@ module Rails scaffold_controller: '-c', stylesheets: '-y', stylesheet_engine: '-se', + scaffold_stylesheet: '-ss', template_engine: '-e', test_framework: '-t' }, @@ -56,6 +57,7 @@ module Rails scaffold_controller: :scaffold_controller, stylesheets: true, stylesheet_engine: :css, + scaffold_stylesheet: true, test_framework: false, template_engine: :erb } diff --git a/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb b/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb index e89789e72b..17c32bfdb3 100644 --- a/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb +++ b/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb @@ -10,10 +10,11 @@ module Rails class_option :stylesheet_engine, desc: "Engine for Stylesheets" class_option :assets, type: :boolean class_option :resource_route, type: :boolean + class_option :scaffold_stylesheet, type: :boolean def handle_skip @options = @options.merge(stylesheets: false) unless options[:assets] - @options = @options.merge(stylesheet_engine: false) unless options[:stylesheets] + @options = @options.merge(stylesheet_engine: false) unless options[:stylesheets] && options[:scaffold_stylesheet] end hook_for :scaffold_controller, required: true diff --git a/railties/lib/rails/test_help.rb b/railties/lib/rails/test_help.rb index a83e39faee..3b444b0932 100644 --- a/railties/lib/rails/test_help.rb +++ b/railties/lib/rails/test_help.rb @@ -3,13 +3,17 @@ abort("Abort testing: Your Rails environment is running in production mode!") if Rails.env.production? require "rails/test_unit/minitest_plugin" -require 'active_support/testing/autorun' require 'active_support/test_case' require 'action_controller' require 'action_controller/test_case' require 'action_dispatch/testing/integration' require 'rails/generators/test_case' +unless Minitest.run_with_rails_extension + Minitest.run_with_autorun = true + require 'active_support/testing/autorun' +end + if defined?(ActiveRecord::Base) ActiveRecord::Migration.maintain_test_schema! diff --git a/railties/lib/rails/test_unit/minitest_plugin.rb b/railties/lib/rails/test_unit/minitest_plugin.rb index 70ce9d3360..421f032d81 100644 --- a/railties/lib/rails/test_unit/minitest_plugin.rb +++ b/railties/lib/rails/test_unit/minitest_plugin.rb @@ -1,14 +1,51 @@ -require "minitest" +require "active_support/core_ext/module/attribute_accessors" require "rails/test_unit/reporter" +require "rails/test_unit/test_requirer" -def Minitest.plugin_rails_init(options) - self.reporter << Rails::TestUnitReporter.new(options[:io], options) - if $rails_test_runner && (method = $rails_test_runner.find_method) - options[:filter] = method +module Minitest + def self.plugin_rails_options(opts, options) + opts.separator "" + opts.separator "Usage: bin/rails test [options] [files or directories]" + opts.separator "You can run a single test by appending a line number to a filename:" + opts.separator "" + opts.separator " bin/rails test test/models/user_test.rb:27" + opts.separator "" + opts.separator "You can run multiple files and directories at the same time:" + opts.separator "" + opts.separator " bin/rails test test/controllers test/integration/login_test.rb" + opts.separator "" + + opts.separator "Rails options:" + opts.on("-e", "--environment [ENV]", + "Run tests in the ENV environment") do |env| + options[:environment] = env.strip + end + + opts.on("-b", "--backtrace", + "Show the complete backtrace") do + options[:full_backtrace] = true + end + + options[:patterns] = opts.order! end - if !($rails_test_runner && $rails_test_runner.show_backtrace?) - Minitest.backtrace_filter = Rails.backtrace_cleaner + def self.plugin_rails_init(options) + self.run_with_rails_extension = true + + ENV["RAILS_ENV"] = options[:environment] || "test" + + Rails::TestRequirer.require_files options[:patterns] unless run_with_autorun + + unless options[:full_backtrace] || ENV["BACKTRACE"] + # Plugin can run without Rails loaded, check before filtering. + Minitest.backtrace_filter = Rails.backtrace_cleaner if Rails.respond_to?(:backtrace_cleaner) + end + + self.reporter << Rails::TestUnitReporter.new(options[:io], options) end + + mattr_accessor(:run_with_autorun) { false } + mattr_accessor(:run_with_rails_extension) { false } end + Minitest.extensions << 'rails' diff --git a/railties/lib/rails/test_unit/reporter.rb b/railties/lib/rails/test_unit/reporter.rb index 64e99626eb..bfdc9754d4 100644 --- a/railties/lib/rails/test_unit/reporter.rb +++ b/railties/lib/rails/test_unit/reporter.rb @@ -15,8 +15,12 @@ module Rails filtered_results.reject!(&:skipped?) unless options[:verbose] filtered_results.map do |result| location, line = result.method(result.name).source_location - "bin/rails test #{location}:#{line}" + "bin/rails test #{relative_path_for(location)}:#{line}" end.join "\n" end + + def relative_path_for(file) + file.sub(/^#{Rails.root}\/?/, '') + end end end diff --git a/railties/lib/rails/test_unit/runner.rb b/railties/lib/rails/test_unit/runner.rb deleted file mode 100644 index 5573fa6904..0000000000 --- a/railties/lib/rails/test_unit/runner.rb +++ /dev/null @@ -1,137 +0,0 @@ -require "optparse" -require "rake/file_list" -require "method_source" - -module Rails - class TestRunner - class Options - def self.parse(args) - options = { backtrace: !ENV["BACKTRACE"].nil?, name: nil, environment: "test" } - - opt_parser = ::OptionParser.new do |opts| - opts.banner = "Usage: bin/rails test [options] [file or directory]" - - opts.separator "" - opts.on("-e", "--environment [ENV]", - "Run tests in the ENV environment") do |env| - options[:environment] = env.strip - end - opts.separator "" - opts.separator "Filter options:" - opts.separator "" - opts.separator <<-DESC - You can run a single test by appending the line number to filename: - - bin/rails test test/models/user_test.rb:27 - - DESC - - opts.on("-n", "--name [NAME]", - "Only run tests matching NAME") do |name| - options[:name] = name - end - opts.on("-p", "--pattern [PATTERN]", - "Only run tests matching PATTERN") do |pattern| - options[:name] = "/#{pattern}/" - end - - opts.separator "" - opts.separator "Output options:" - - opts.on("-b", "--backtrace", - "Show the complete backtrace") do - options[:backtrace] = true - end - - opts.separator "" - opts.separator "Common options:" - - opts.on_tail("-h", "--help", "Show this message") do - puts opts - exit - end - end - - opt_parser.order!(args) - - options[:patterns] = [] - while arg = args.shift - if (file_and_line = arg.split(':')).size > 1 - options[:filename], options[:line] = file_and_line - options[:filename] = File.expand_path options[:filename] - options[:line] &&= options[:line].to_i - else - arg = arg.gsub(':', '') - if Dir.exist?("#{arg}") - options[:patterns] << File.expand_path("#{arg}/**/*_test.rb") - elsif File.file?(arg) - options[:patterns] << File.expand_path(arg) - end - end - end - options - end - end - - def initialize(options = {}) - @options = options - end - - def self.run(arguments) - options = Rails::TestRunner::Options.parse(arguments) - Rails::TestRunner.new(options).run - end - - def run - $rails_test_runner = self - ENV["RAILS_ENV"] = @options[:environment] - run_tests - end - - def find_method - return @options[:name] if @options[:name] - return unless @options[:line] - method = test_methods.find do |location, test_method, start_line, end_line| - location == @options[:filename] && - (start_line..end_line).include?(@options[:line].to_i) - end - method[1] if method - end - - def show_backtrace? - @options[:backtrace] - end - - def test_files - return [@options[:filename]] if @options[:filename] - if @options[:patterns] && @options[:patterns].count > 0 - pattern = @options[:patterns] - else - pattern = "test/**/*_test.rb" - end - Rake::FileList[pattern] - end - - private - def run_tests - test_files.to_a.each do |file| - require File.expand_path file - end - end - - def test_methods - methods_map = [] - suites = Minitest::Runnable.runnables.shuffle - suites.each do |suite_class| - suite_class.runnable_methods.each do |test_method| - method = suite_class.instance_method(test_method) - location = method.source_location - start_line = location.last - end_line = method.source.split("\n").size + start_line - 1 - methods_map << [File.expand_path(location.first), test_method, start_line, end_line] - end - end - methods_map - end - end -end diff --git a/railties/lib/rails/test_unit/test_requirer.rb b/railties/lib/rails/test_unit/test_requirer.rb new file mode 100644 index 0000000000..84c2256729 --- /dev/null +++ b/railties/lib/rails/test_unit/test_requirer.rb @@ -0,0 +1,28 @@ +require 'active_support/core_ext/object/blank' +require 'rake/file_list' + +module Rails + class TestRequirer # :nodoc: + class << self + def require_files(patterns) + patterns = expand_patterns(patterns) + + Rake::FileList[patterns.compact.presence || 'test/**/*_test.rb'].to_a.each do |file| + require File.expand_path(file) + end + end + + private + def expand_patterns(patterns) + patterns.map do |arg| + arg = arg.gsub(/:(\d+)?$/, '') + if Dir.exist?(arg) + "#{arg}/**/*_test.rb" + elsif File.file?(arg) + arg + end + end + end + end + end +end diff --git a/railties/lib/rails/test_unit/testing.rake b/railties/lib/rails/test_unit/testing.rake index 0f26621b59..dda492f974 100644 --- a/railties/lib/rails/test_unit/testing.rake +++ b/railties/lib/rails/test_unit/testing.rake @@ -1,12 +1,13 @@ -require "rails/test_unit/runner" +gem 'minitest' +require 'minitest' +require 'rails/test_unit/minitest_plugin' task default: :test desc "Runs all tests in test folder" task :test do $: << "test" - args = ARGV[0] == "test" ? ARGV[1..-1] : [] - Rails::TestRunner.run(args) + Minitest.run(['test']) end namespace :test do @@ -23,22 +24,22 @@ namespace :test do ["models", "helpers", "controllers", "mailers", "integration", "jobs"].each do |name| task name => "test:prepare" do $: << "test" - Rails::TestRunner.run(["test/#{name}"]) + Minitest.run(["test/#{name}"]) end end task :generators => "test:prepare" do $: << "test" - Rails::TestRunner.run(["test/lib/generators"]) + Minitest.run(["test/lib/generators"]) end task :units => "test:prepare" do $: << "test" - Rails::TestRunner.run(["test/models", "test/helpers", "test/unit"]) + Minitest.run(["test/models", "test/helpers", "test/unit"]) end task :functionals => "test:prepare" do $: << "test" - Rails::TestRunner.run(["test/controllers", "test/mailers", "test/functional"]) + Minitest.run(["test/controllers", "test/mailers", "test/functional"]) end end diff --git a/railties/test/application/console_test.rb b/railties/test/application/console_test.rb index 31bc003dcb..7bf123d12b 100644 --- a/railties/test/application/console_test.rb +++ b/railties/test/application/console_test.rb @@ -29,6 +29,18 @@ class ConsoleTest < ActiveSupport::TestCase assert_instance_of ActionDispatch::Integration::Session, console_session end + def test_app_can_access_path_helper_method + app_file 'config/routes.rb', <<-RUBY + Rails.application.routes.draw do + get 'foo', to: 'foo#index' + end + RUBY + + load_environment + console_session = irb_context.app + assert_equal '/foo', console_session.foo_path + end + def test_new_session_should_return_integration_session load_environment session = irb_context.new_session diff --git a/railties/test/application/multiple_applications_test.rb b/railties/test/application/multiple_applications_test.rb index cddc79cc85..f2770a9cb4 100644 --- a/railties/test/application/multiple_applications_test.rb +++ b/railties/test/application/multiple_applications_test.rb @@ -118,7 +118,7 @@ module ApplicationTests assert_equal 0, run_count, "Without loading the initializers, the count should be 0" # Set config.eager_load to false so that an eager_load warning doesn't pop up - AppTemplate::Application.new { config.eager_load = false }.initialize! + AppTemplate::Application.create { config.eager_load = false }.initialize! assert_equal 3, run_count, "There should have been three initializers that incremented the count" end diff --git a/railties/test/application/test_runner_test.rb b/railties/test/application/test_runner_test.rb index c122b315c0..bbaab42a7f 100644 --- a/railties/test/application/test_runner_test.rb +++ b/railties/test/application/test_runner_test.rb @@ -1,9 +1,10 @@ require 'isolation/abstract_unit' require 'active_support/core_ext/string/strip' +require 'env_helpers' module ApplicationTests class TestRunnerTest < ActiveSupport::TestCase - include ActiveSupport::Testing::Isolation + include ActiveSupport::Testing::Isolation, EnvHelpers def setup build_app @@ -14,20 +15,6 @@ module ApplicationTests teardown_app end - def test_run_in_test_environment - app_file 'test/unit/env_test.rb', <<-RUBY - require 'test_helper' - - class EnvTest < ActiveSupport::TestCase - def test_env - puts "Current Environment: \#{Rails.env}" - end - end - RUBY - - assert_match "Current Environment: test", run_test_command('test/unit/env_test.rb') - end - def test_run_single_file create_test_file :models, 'foo' create_test_file :models, 'bar' @@ -187,7 +174,7 @@ module ApplicationTests end RUBY - run_test_command('-p rikka test/unit/chu_2_koi_test.rb').tap do |output| + run_test_command('-n /rikka/ test/unit/chu_2_koi_test.rb').tap do |output| assert_match "Rikka", output assert_no_match "Sanae", output end @@ -229,24 +216,128 @@ module ApplicationTests assert_match "development", run_test_command('test/unit/env_test.rb') end + def test_run_in_test_environment_by_default + create_env_test + + assert_match "Current Environment: test", run_test_command('test/unit/env_test.rb') + end + def test_run_different_environment - env = "development" - app_file 'test/unit/env_test.rb', <<-RUBY + create_env_test + + assert_match "Current Environment: development", + run_test_command("-e development test/unit/env_test.rb") + end + + def test_generated_scaffold_works_with_rails_test + create_scaffold + assert_match "0 failures, 0 errors, 0 skips", run_test_command('') + end + + def test_run_multiple_folders + create_test_file :models, 'account' + create_test_file :controllers, 'accounts_controller' + + run_test_command('test/models test/controllers').tap do |output| + assert_match 'AccountTest', output + assert_match 'AccountsControllerTest', output + assert_match '2 runs, 2 assertions, 0 failures, 0 errors, 0 skips', output + end + end + + def test_run_with_ruby_command + app_file 'test/models/post_test.rb', <<-RUBY require 'test_helper' - class EnvTest < ActiveSupport::TestCase - def test_env - puts Rails.env + class PostTest < ActiveSupport::TestCase + test 'declarative syntax works' do + puts 'PostTest' + assert true end end RUBY - assert_match env, run_test_command("-e #{env} test/unit/env_test.rb") + Dir.chdir(app_path) do + `ruby -Itest test/models/post_test.rb`.tap do |output| + assert_match 'PostTest', output + assert_no_match 'is already defined in', output + end + end end - def test_generated_scaffold_works_with_rails_test - create_scaffold - assert_match "0 failures, 0 errors, 0 skips", run_test_command('') + def test_mix_files_and_line_filters + create_test_file :models, 'account' + app_file 'test/models/post_test.rb', <<-RUBY + require 'test_helper' + + class PostTest < ActiveSupport::TestCase + def test_post + puts 'PostTest' + assert true + end + + def test_line_filter_does_not_run_this + assert true + end + end + RUBY + + run_test_command('test/models/account_test.rb test/models/post_test.rb:4').tap do |output| + assert_match 'AccountTest', output + assert_match 'PostTest', output + assert_match '2 runs, 2 assertions', output + end + end + + def test_multiple_line_filters + create_test_file :models, 'account' + create_test_file :models, 'post' + + run_test_command('test/models/account_test.rb:4 test/models/post_test.rb:4').tap do |output| + assert_match 'AccountTest', output + assert_match 'PostTest', output + end + end + + def test_line_filter_without_line_runs_all_tests + create_test_file :models, 'account' + + run_test_command('test/models/account_test.rb:').tap do |output| + assert_match 'AccountTest', output + end + end + + def test_shows_filtered_backtrace_by_default + create_backtrace_test + + assert_match 'Rails::BacktraceCleaner', run_test_command('test/unit/backtrace_test.rb') + end + + def test_backtrace_option + create_backtrace_test + + assert_match 'Minitest::BacktraceFilter', run_test_command('test/unit/backtrace_test.rb -b') + assert_match 'Minitest::BacktraceFilter', + run_test_command('test/unit/backtrace_test.rb --backtrace') + end + + def test_show_full_backtrace_using_backtrace_environment_variable + create_backtrace_test + + switch_env 'BACKTRACE', 'true' do + assert_match 'Minitest::BacktraceFilter', run_test_command('test/unit/backtrace_test.rb') + end + end + + def test_run_app_without_rails_loaded + # Simulate a real Rails app boot. + app_file 'config/boot.rb', <<-RUBY + ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) + + require 'bundler/setup' # Set up gems listed in the Gemfile. + RUBY + + assert_match '0 runs, 0 assertions', run_test_command('') end private @@ -284,6 +375,18 @@ module ApplicationTests RUBY end + def create_backtrace_test + app_file 'test/unit/backtrace_test.rb', <<-RUBY + require 'test_helper' + + class BacktraceTest < ActiveSupport::TestCase + def test_backtrace + puts Minitest.backtrace_filter + end + end + RUBY + end + def create_schema app_file 'db/schema.rb', '' end @@ -301,6 +404,18 @@ module ApplicationTests RUBY end + def create_env_test + app_file 'test/unit/env_test.rb', <<-RUBY + require 'test_helper' + + class EnvTest < ActiveSupport::TestCase + def test_env + puts "Current Environment: \#{Rails.env}" + end + end + RUBY + end + def create_scaffold script 'generate scaffold user name:string' Dir.chdir(app_path) { File.exist?('app/models/user.rb') } diff --git a/railties/test/application/test_test.rb b/railties/test/application/test_test.rb index bb30940a74..0e997f4ba7 100644 --- a/railties/test/application/test_test.rb +++ b/railties/test/application/test_test.rb @@ -64,8 +64,8 @@ module ApplicationTests RUBY output = run_test_file('unit/failing_test.rb', env: { "BACKTRACE" => "1" }) - assert_match %r{/app/test/unit/failing_test\.rb}, output - assert_match %r{/app/test/unit/failing_test\.rb:4}, output + assert_match %r{test/unit/failing_test\.rb}, output + assert_match %r{test/unit/failing_test\.rb:4}, output end test "ruby schema migrations" do diff --git a/railties/test/generators/scaffold_generator_test.rb b/railties/test/generators/scaffold_generator_test.rb index 8f43747b9e..8d7fea8741 100644 --- a/railties/test/generators/scaffold_generator_test.rb +++ b/railties/test/generators/scaffold_generator_test.rb @@ -282,6 +282,20 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase assert_no_file "app/assets/stylesheets/posts.css" end + def test_scaffold_generator_no_scaffold_stylesheet_with_switch_no_scaffold_stylesheet + run_generator [ "posts", "--no-scaffold-stylesheet" ] + assert_no_file "app/assets/stylesheets/scaffold.css" + assert_file "app/assets/javascripts/posts.js" + assert_file "app/assets/stylesheets/posts.css" + end + + def test_scaffold_generator_no_scaffold_stylesheet_with_switch_scaffold_stylesheet_false + run_generator [ "posts", "--scaffold-stylesheet=false" ] + assert_no_file "app/assets/stylesheets/scaffold.css" + assert_file "app/assets/javascripts/posts.js" + assert_file "app/assets/stylesheets/posts.css" + end + def test_scaffold_generator_with_switch_resource_route_false run_generator [ "posts", "--resource-route=false" ] assert_file "config/routes.rb" do |route| diff --git a/railties/test/test_unit/runner_test.rb b/railties/test/test_unit/runner_test.rb deleted file mode 100644 index 9ea8b2c114..0000000000 --- a/railties/test/test_unit/runner_test.rb +++ /dev/null @@ -1,111 +0,0 @@ -require 'abstract_unit' -require 'env_helpers' -require 'rails/test_unit/runner' - -class TestUnitTestRunnerTest < ActiveSupport::TestCase - include EnvHelpers - - setup do - @options = Rails::TestRunner::Options - end - - test "shows the filtered backtrace by default" do - options = @options.parse([]) - assert_not options[:backtrace] - end - - test "has --backtrace (-b) option to show the full backtrace" do - options = @options.parse(["-b"]) - assert options[:backtrace] - - options = @options.parse(["--backtrace"]) - assert options[:backtrace] - end - - test "show full backtrace using BACKTRACE environment variable" do - switch_env "BACKTRACE", "true" do - options = @options.parse([]) - assert options[:backtrace] - end - end - - test "tests run in the test environment by default" do - options = @options.parse([]) - assert_equal "test", options[:environment] - end - - test "can run in a specific environment" do - options = @options.parse(["-e development"]) - assert_equal "development", options[:environment] - end - - test "parse the filename and line" do - file = "test/test_unit/runner_test.rb" - absolute_file = File.expand_path __FILE__ - options = @options.parse(["#{file}:20"]) - assert_equal absolute_file, options[:filename] - assert_equal 20, options[:line] - - options = @options.parse(["#{file}:"]) - assert_equal [absolute_file], options[:patterns] - assert_nil options[:line] - - options = @options.parse([file]) - assert_equal [absolute_file], options[:patterns] - assert_nil options[:line] - end - - test "find_method on same file" do - options = @options.parse(["#{__FILE__}:#{__LINE__}"]) - runner = Rails::TestRunner.new(options) - assert_equal "test_find_method_on_same_file", runner.find_method - end - - test "find_method on a different file" do - options = @options.parse(["foobar.rb:#{__LINE__}"]) - runner = Rails::TestRunner.new(options) - assert_nil runner.find_method - end - - test "run all tests in a directory" do - options = @options.parse([__dir__]) - - assert_equal ["#{__dir__}/**/*_test.rb"], options[:patterns] - assert_nil options[:filename] - assert_nil options[:line] - end - - test "run multiple folders" do - application_dir = File.expand_path("#{__dir__}/../application") - - options = @options.parse([__dir__, application_dir]) - - assert_equal ["#{__dir__}/**/*_test.rb", "#{application_dir}/**/*_test.rb"], options[:patterns] - assert_nil options[:filename] - assert_nil options[:line] - - runner = Rails::TestRunner.new(options) - assert runner.test_files.size > 0 - end - - test "run multiple files and run one file by line" do - line = __LINE__ - absolute_file = File.expand_path(__FILE__) - options = @options.parse([__dir__, "#{__FILE__}:#{line}"]) - - assert_equal ["#{__dir__}/**/*_test.rb"], options[:patterns] - assert_equal absolute_file, options[:filename] - assert_equal line, options[:line] - - runner = Rails::TestRunner.new(options) - assert_equal [absolute_file], runner.test_files, 'Only returns the file that running by line' - end - - test "running multiple files passing line number" do - line = __LINE__ - options = @options.parse(["foobar.rb:8", "#{__FILE__}:#{line}"]) - - assert_equal File.expand_path(__FILE__), options[:filename], 'Returns the last file' - assert_equal line, options[:line] - end -end |