diff --git a/actionpack/lib/action_controller/metal/conditional_get.rb b/actionpack/lib/action_controller/metal/conditional_get.rb index b210ee3423..febbc72861 100644 --- a/actionpack/lib/action_controller/metal/conditional_get.rb +++ b/actionpack/lib/action_controller/metal/conditional_get.rb @@ -51,7 +51,7 @@ module ActionController # # def show # @article = Article.find(params[:id]) - # fresh_when(etag: @article, last_modified: @article.created_at, public: true) + # fresh_when(etag: @article, last_modified: @article.updated_at, public: true) # end # # This will render the show template if the request isn't sending a matching ETag or @@ -115,7 +115,7 @@ module ActionController # def show # @article = Article.find(params[:id]) # - # if stale?(etag: @article, last_modified: @article.created_at) + # if stale?(etag: @article, last_modified: @article.updated_at) # @statistics = @article.really_expensive_call # respond_to do |format| # # all the supported formats diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb index 74b3a7c2a9..fe8a2ac9ba 100644 --- a/activesupport/lib/active_support/inflector/methods.rb +++ b/activesupport/lib/active_support/inflector/methods.rb @@ -22,49 +22,49 @@ module ActiveSupport # pluralized using rules defined for that language. By default, # this parameter is set to :en. # - # 'post'.pluralize # => "posts" - # 'octopus'.pluralize # => "octopi" - # 'sheep'.pluralize # => "sheep" - # 'words'.pluralize # => "words" - # 'CamelOctopus'.pluralize # => "CamelOctopi" - # 'ley'.pluralize(:es) # => "leyes" + # pluralize('post') # => "posts" + # pluralize('octopus') # => "octopi" + # pluralize('sheep') # => "sheep" + # pluralize('words') # => "words" + # pluralize('CamelOctopus') # => "CamelOctopi" + # pluralize('ley', :es) # => "leyes" def pluralize(word, locale = :en) apply_inflections(word, inflections(locale).plurals) end - # The reverse of +pluralize+, returns the singular form of a word in a + # The reverse of #pluralize, returns the singular form of a word in a # string. # # If passed an optional +locale+ parameter, the word will be # singularized using rules defined for that language. By default, # this parameter is set to :en. # - # 'posts'.singularize # => "post" - # 'octopi'.singularize # => "octopus" - # 'sheep'.singularize # => "sheep" - # 'word'.singularize # => "word" - # 'CamelOctopi'.singularize # => "CamelOctopus" - # 'leyes'.singularize(:es) # => "ley" + # singularize('posts') # => "post" + # singularize('octopi') # => "octopus" + # singularize('sheep') # => "sheep" + # singularize('word') # => "word" + # singularize('CamelOctopi') # => "CamelOctopus" + # singularize('leyes', :es) # => "ley" def singularize(word, locale = :en) apply_inflections(word, inflections(locale).singulars) end - # By default, +camelize+ converts strings to UpperCamelCase. If the argument - # to +camelize+ is set to :lower then +camelize+ produces + # Converts strings to UpperCamelCase. + # If the +uppercase_first_letter+ parameter is set to false, then produces # lowerCamelCase. # - # +camelize+ will also convert '/' to '::' which is useful for converting + # Also converts '/' to '::' which is useful for converting # paths to namespaces. # - # 'active_model'.camelize # => "ActiveModel" - # 'active_model'.camelize(:lower) # => "activeModel" - # 'active_model/errors'.camelize # => "ActiveModel::Errors" - # 'active_model/errors'.camelize(:lower) # => "activeModel::Errors" + # camelize('active_model') # => "ActiveModel" + # camelize('active_model', false) # => "activeModel" + # camelize('active_model/errors') # => "ActiveModel::Errors" + # camelize('active_model/errors', false) # => "activeModel::Errors" # # As a rule of thumb you can think of +camelize+ as the inverse of - # +underscore+, though there are cases where that does not hold: + # #underscore, though there are cases where that does not hold: # - # 'SSLError'.underscore.camelize # => "SslError" + # camelize(underscore('SSLError')) # => "SslError" def camelize(term, uppercase_first_letter = true) string = term.to_s if uppercase_first_letter @@ -81,13 +81,13 @@ module ActiveSupport # # Changes '::' to '/' to convert namespaces to paths. # - # 'ActiveModel'.underscore # => "active_model" - # 'ActiveModel::Errors'.underscore # => "active_model/errors" + # underscore('ActiveModel') # => "active_model" + # underscore('ActiveModel::Errors') # => "active_model/errors" # # As a rule of thumb you can think of +underscore+ as the inverse of - # +camelize+, though there are cases where that does not hold: + # #camelize, though there are cases where that does not hold: # - # 'SSLError'.underscore.camelize # => "SslError" + # camelize(underscore('SSLError')) # => "SslError" def underscore(camel_cased_word) return camel_cased_word unless camel_cased_word =~ /[A-Z-]|::/ word = camel_cased_word.to_s.gsub(/::/, '/') @@ -101,14 +101,14 @@ module ActiveSupport # Tweaks an attribute name for display to end users. # - # Specifically, +humanize+ performs these transformations: + # Specifically, performs these transformations: # - # * Applies human inflection rules to the argument. - # * Deletes leading underscores, if any. - # * Removes a "_id" suffix if present. - # * Replaces underscores with spaces, if any. - # * Downcases all words except acronyms. - # * Capitalizes the first word. + # * Applies human inflection rules to the argument. + # * Deletes leading underscores, if any. + # * Removes a "_id" suffix if present. + # * Replaces underscores with spaces, if any. + # * Downcases all words except acronyms. + # * Capitalizes the first word. # # The capitalization of the first word can be turned off by setting the # +:capitalize+ option to false (default is true). @@ -148,34 +148,34 @@ module ActiveSupport # # +titleize+ is also aliased as +titlecase+. # - # 'man from the boondocks'.titleize # => "Man From The Boondocks" - # 'x-men: the last stand'.titleize # => "X Men: The Last Stand" - # 'TheManWithoutAPast'.titleize # => "The Man Without A Past" - # 'raiders_of_the_lost_ark'.titleize # => "Raiders Of The Lost Ark" + # titleize('man from the boondocks') # => "Man From The Boondocks" + # titleize('x-men: the last stand') # => "X Men: The Last Stand" + # titleize('TheManWithoutAPast') # => "The Man Without A Past" + # titleize('raiders_of_the_lost_ark') # => "Raiders Of The Lost Ark" def titleize(word) humanize(underscore(word)).gsub(/\b(? "raw_scaled_scorers" - # 'egg_and_ham'.tableize # => "egg_and_hams" - # 'fancyCategory'.tableize # => "fancy_categories" + # tableize('RawScaledScorer') # => "raw_scaled_scorers" + # tableize('egg_and_ham') # => "egg_and_hams" + # tableize('fancyCategory') # => "fancy_categories" def tableize(class_name) pluralize(underscore(class_name)) end - # Create a class name from a plural table name like Rails does for table + # Creates a class name from a plural table name like Rails does for table # names to models. Note that this returns a string and not a Class (To - # convert to an actual class follow +classify+ with +constantize+). + # convert to an actual class follow +classify+ with #constantize). # - # 'egg_and_hams'.classify # => "EggAndHam" - # 'posts'.classify # => "Post" + # classify('egg_and_hams') # => "EggAndHam" + # classify('posts') # => "Post" # # Singular names are not handled correctly: # - # 'calculus'.classify # => "Calculu" + # classify('calculus') # => "Calculu" def classify(table_name) # strip out any leading schema name camelize(singularize(table_name.to_s.sub(/.*\./, ''))) @@ -183,19 +183,19 @@ module ActiveSupport # Replaces underscores with dashes in the string. # - # 'puni_puni'.dasherize # => "puni-puni" + # dasherize('puni_puni') # => "puni-puni" def dasherize(underscored_word) underscored_word.tr('_', '-') end # Removes the module part from the expression in the string. # - # 'ActiveRecord::CoreExtensions::String::Inflections'.demodulize # => "Inflections" - # 'Inflections'.demodulize # => "Inflections" - # '::Inflections'.demodulize # => "Inflections" - # ''.demodulize # => "" + # demodulize('ActiveRecord::CoreExtensions::String::Inflections') # => "Inflections" + # demodulize('Inflections') # => "Inflections" + # demodulize('::Inflections') # => "Inflections" + # demodulize('') # => "" # - # See also +deconstantize+. + # See also #deconstantize. def demodulize(path) path = path.to_s if i = path.rindex('::') @@ -207,13 +207,13 @@ module ActiveSupport # Removes the rightmost segment from the constant expression in the string. # - # 'Net::HTTP'.deconstantize # => "Net" - # '::Net::HTTP'.deconstantize # => "::Net" - # 'String'.deconstantize # => "" - # '::String'.deconstantize # => "" - # ''.deconstantize # => "" + # deconstantize('Net::HTTP') # => "Net" + # deconstantize('::Net::HTTP') # => "::Net" + # deconstantize('String') # => "" + # deconstantize('::String') # => "" + # deconstantize('') # => "" # - # See also +demodulize+. + # See also #demodulize. def deconstantize(path) path.to_s[0, path.rindex('::') || 0] # implementation based on the one in facets' Module#spacename end @@ -222,9 +222,9 @@ module ActiveSupport # +separate_class_name_and_id_with_underscore+ sets whether # the method should put '_' between the name and 'id'. # - # 'Message'.foreign_key # => "message_id" - # 'Message'.foreign_key(false) # => "messageid" - # 'Admin::Post'.foreign_key # => "post_id" + # foreign_key('Message') # => "message_id" + # foreign_key('Message', false) # => "messageid" + # foreign_key('Admin::Post') # => "post_id" def foreign_key(class_name, separate_class_name_and_id_with_underscore = true) underscore(demodulize(class_name)) + (separate_class_name_and_id_with_underscore ? "_id" : "id") end @@ -280,8 +280,8 @@ module ActiveSupport # Tries to find a constant with the name specified in the argument string. # - # 'Module'.safe_constantize # => Module - # 'Test::Unit'.safe_constantize # => Test::Unit + # safe_constantize('Module') # => Module + # safe_constantize('Test::Unit') # => Test::Unit # # The name is assumed to be the one of a top-level constant, no matter # whether it starts with "::" or not. No lexical context is taken into @@ -290,16 +290,16 @@ module ActiveSupport # C = 'outside' # module M # C = 'inside' - # C # => 'inside' - # 'C'.safe_constantize # => 'outside', same as ::C + # C # => 'inside' + # safe_constantize('C') # => 'outside', same as ::C # end # # +nil+ is returned when the name is not in CamelCase or the constant (or # part of it) is unknown. # - # 'blargle'.safe_constantize # => nil - # 'UnknownModule'.safe_constantize # => nil - # 'UnknownModule::Foo::Bar'.safe_constantize # => nil + # safe_constantize('blargle') # => nil + # safe_constantize('UnknownModule') # => nil + # safe_constantize('UnknownModule::Foo::Bar') # => nil def safe_constantize(camel_cased_word) constantize(camel_cased_word) rescue NameError => e diff --git a/activesupport/lib/active_support/inflector/transliterate.rb b/activesupport/lib/active_support/inflector/transliterate.rb index 1cde417fc5..edea142e82 100644 --- a/activesupport/lib/active_support/inflector/transliterate.rb +++ b/activesupport/lib/active_support/inflector/transliterate.rb @@ -67,17 +67,8 @@ module ActiveSupport # Replaces special characters in a string so that it may be used as part of # a 'pretty' URL. # - # class Person - # def to_param - # "#{id}-#{name.parameterize}" - # end - # end - # - # @person = Person.find(1) - # # => # - # - # <%= link_to(@person.name, person_path(@person)) %> - # # => Donald E. Knuth + # parameterize("Donald E. Knuth") # => "donald-e-knuth" + # parameterize("^trés|Jolie-- ") # => "tres-jolie" def parameterize(string, sep = '-') # replace accented chars with their ascii equivalents parameterized_string = transliterate(string) @@ -92,6 +83,5 @@ module ActiveSupport end parameterized_string.downcase end - end end diff --git a/guides/source/active_job_basics.md b/guides/source/active_job_basics.md index 53588bdd1d..4d1625b28d 100644 --- a/guides/source/active_job_basics.md +++ b/guides/source/active_job_basics.md @@ -78,7 +78,8 @@ end Enqueue a job like so: ```ruby -# Enqueue a job to be performed as soon the queueing system is free. +# Enqueue a job to be performed as soon the queueing system is +# free. MyJob.perform_later record ``` @@ -114,8 +115,9 @@ You can easily set your queueing backend: # config/application.rb module YourApp class Application < Rails::Application - # Be sure to have the adapter's gem in your Gemfile and follow - # the adapter's specific installation and deployment instructions. + # Be sure to have the adapter's gem in your Gemfile + # and follow the adapter's specific installation + # and deployment instructions. config.active_job.queue_adapter = :sidekiq end end @@ -153,8 +155,8 @@ class GuestsCleanupJob < ActiveJob::Base end # Now your job will run on queue production_low_priority on your -# production environment and on staging_low_priority on your staging -# environment +# production environment and on staging_low_priority +# on your staging environment ``` The default queue name prefix delimiter is '\_'. This can be changed by setting @@ -176,8 +178,8 @@ class GuestsCleanupJob < ActiveJob::Base end # Now your job will run on queue production.low_priority on your -# production environment and on staging.low_priority on your staging -# environment +# production environment and on staging.low_priority +# on your staging environment ``` If you want more control on what queue a job will be run you can pass a `:queue` @@ -295,7 +297,7 @@ end ``` This works with any class that mixes in `GlobalID::Identification`, which -by default has been mixed into Active Model classes. +by default has been mixed into Active Record classes. Exceptions diff --git a/guides/source/configuring.md b/guides/source/configuring.md index cc3d840271..9c0f2ddc8a 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -692,7 +692,7 @@ development: pool: 5 ``` -Prepared Statements are enabled by default on PostgreSQL. You can be disable prepared statements by setting `prepared_statements` to `false`: +Prepared Statements are enabled by default on PostgreSQL. You can disable prepared statements by setting `prepared_statements` to `false`: ```yaml production: diff --git a/guides/source/testing.md b/guides/source/testing.md index 8456a8c4a8..94cfcf12b7 100644 --- a/guides/source/testing.md +++ b/guides/source/testing.md @@ -528,6 +528,19 @@ All of request types have equivalent methods that you can use. In a typical C.R. NOTE: Functional tests do not verify whether the specified request type is accepted by the action, we're more concerned with the result. Request tests exist for this use case to make your tests more purposeful. +### Testing XHR (AJAX) requests + +`xhr` accepts method (listed in the section above), action name and parameters: + +```ruby +test "ajax request responds with no layout" do + xhr :get, :show, id: articles(:first).id + + assert_template :index + assert_template layout: nil +end +``` + ### The Four Hashes of the Apocalypse After a request has been made and processed, you will have 4 Hash objects ready for use: @@ -740,10 +753,8 @@ class ArticlesControllerTest < ActionController::TestCase # called after every single test def teardown - # as we are re-initializing @article before every test - # setting it to nil here is not essential but I hope - # you understand how you can use the teardown method - @article = nil + # when controller is using cache it may be a good idea to reset it afterwards + Rails.cache.clear end test "should show article" do @@ -769,6 +780,41 @@ end Similar to other callbacks in Rails, the `setup` and `teardown` methods can also be used by passing a block, lambda, or method name as a symbol to call. +### Test helpers + +To avoid code duplication, you can add your own test helpers. +Sign in helper can be a good example: + +```ruby +test/test_helper.rb + +module SignInHelper + def sign_in(user) + session[:user_id] = user.id + end +end + +class ActionController::TestCase + include SignInHelper +end +``` + +```ruby +require 'test_helper' + +class ProfileControllerTest < ActionController::TestCase + + test "should show profile" do + # helper is now reusable from any controller test case + sign_in users(:david) + + get :show + assert_response :success + assert_equal users(:david), assigns(:user) + end +end +``` + Testing Routes -------------- @@ -1050,9 +1096,10 @@ require 'test_helper' class UserMailerTest < ActionMailer::TestCase test "invite" do # Send the email, then test that it got queued - email = UserMailer.create_invite('me@example.com', - 'friend@example.com', Time.now).deliver_now - assert_not ActionMailer::Base.deliveries.empty? + assert_emails 1 do + email = UserMailer.create_invite('me@example.com', + 'friend@example.com', Time.now).deliver_now + end # Test the body of the sent email contains what we expect it to assert_equal ['me@example.com'], email.from