diff options
38 files changed, 272 insertions, 268 deletions
diff --git a/actioncable/lib/action_cable/channel/base.rb b/actioncable/lib/action_cable/channel/base.rb index 8ab061171e..2e589a2cfa 100644 --- a/actioncable/lib/action_cable/channel/base.rb +++ b/actioncable/lib/action_cable/channel/base.rb @@ -247,7 +247,7 @@ module ActionCable end def processable_action?(action) - self.class.action_methods.include?(action.to_s) + self.class.action_methods.include?(action.to_s) unless subscription_rejected? end def dispatch_action(action, data) diff --git a/actioncable/test/channel/rejection_test.rb b/actioncable/test/channel/rejection_test.rb index 0d2ac1c129..faf35ad048 100644 --- a/actioncable/test/channel/rejection_test.rb +++ b/actioncable/test/channel/rejection_test.rb @@ -7,6 +7,9 @@ class ActionCable::Channel::RejectionTest < ActiveSupport::TestCase def subscribed reject if params[:id] > 0 end + + def secret_action + end end setup do @@ -21,4 +24,16 @@ class ActionCable::Channel::RejectionTest < ActiveSupport::TestCase expected = { "identifier" => "{id: 1}", "type" => "reject_subscription" } assert_equal expected, @connection.last_transmission end + + test "does not execute action if subscription is rejected" do + @connection.expects(:subscriptions).returns mock().tap { |m| m.expects(:remove_subscription).with instance_of(SecretChannel) } + @channel = SecretChannel.new @connection, "{id: 1}", id: 1 + + expected = { "identifier" => "{id: 1}", "type" => "reject_subscription" } + assert_equal expected, @connection.last_transmission + assert_equal 1, @connection.transmissions.size + + @channel.perform_action("action" => :secret_action) + assert_equal 1, @connection.transmissions.size + end end diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 9dab1cc76a..a66a1e8af3 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,3 +1,35 @@ +* Include the content of the flash in the auto-generated etag. This solves the following problem: + + 1. POST /messages + 2. redirect_to messages_url, notice: 'Message was created' + 3. GET /messages/1 + 4. GET /messages + + Step 4 would before still include the flash message, even though it's no longer relevant, + because the etag cache was recorded with the flash in place and didn't change when it was gone. + + *DHH* + +* SSL: Changes redirect behavior for all non-GET and non-HEAD requests + (like POST/PUT/PATCH etc) to `http://` resources to redirect to `https://` + with a [307 status code](http://tools.ietf.org/html/rfc7231#section-6.4.7) instead of [301 status code](http://tools.ietf.org/html/rfc7231#section-6.4.2). + + 307 status code instructs the HTTP clients to preserve the original + request method while redirecting. It has been part of HTTP RFC since + 1999 and is implemented/recognized by most (if not all) user agents. + + # Before + POST http://example.com/articles (i.e. ArticlesContoller#create) + redirects to + GET https://example.com/articles (i.e. ArticlesContoller#index) + + # After + POST http://example.com/articles (i.e. ArticlesContoller#create) + redirects to + POST https://example.com/articles (i.e. ArticlesContoller#create) + + *Chirag Singhal* + * Add `:as` option to `ActionController:TestCase#process` and related methods. Specifying `as: mime_type` allows the `CONTENT_TYPE` header to be specified diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb index fc86a907b3..50f20aa789 100644 --- a/actionpack/lib/action_controller.rb +++ b/actionpack/lib/action_controller.rb @@ -23,6 +23,7 @@ module ActionController autoload :Cookies autoload :DataStreaming autoload :EtagWithTemplateDigest + autoload :EtagWithFlash autoload :Flash autoload :ForceSSL autoload :Head diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb index 68a526eccb..ca8066cd82 100644 --- a/actionpack/lib/action_controller/base.rb +++ b/actionpack/lib/action_controller/base.rb @@ -213,6 +213,7 @@ module ActionController Renderers::All, ConditionalGet, EtagWithTemplateDigest, + EtagWithFlash, Caching, MimeResponds, ImplicitRender, diff --git a/actionpack/lib/action_controller/metal/etag_with_flash.rb b/actionpack/lib/action_controller/metal/etag_with_flash.rb new file mode 100644 index 0000000000..474d75f02e --- /dev/null +++ b/actionpack/lib/action_controller/metal/etag_with_flash.rb @@ -0,0 +1,16 @@ +module ActionController + # When you're using the flash, it's generally used as a conditional on the view. + # This means the content of the view depends on the flash. Which in turn means + # that the etag for a response should be computed with the content of the flash + # in mind. This does that by including the content of the flash as a component + # in the etag that's generated for a response. + module EtagWithFlash + extend ActiveSupport::Concern + + include ActionController::ConditionalGet + + included do + etag { flash unless flash.empty? } + end + end +end diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb index e85ea90b94..06ffa983d1 100644 --- a/actionpack/lib/action_dispatch/http/url.rb +++ b/actionpack/lib/action_dispatch/http/url.rb @@ -192,11 +192,7 @@ module ActionDispatch # Returns the complete URL used for this request. # - # class Request < Rack::Request - # include ActionDispatch::Http::URL - # end - # - # req = Request.new 'HTTP_HOST' => 'example.com' + # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com' # req.url # => "http://example.com" def url protocol + host_with_port + fullpath @@ -204,14 +200,10 @@ module ActionDispatch # Returns 'https://' if this is an SSL request and 'http://' otherwise. # - # class Request < Rack::Request - # include ActionDispatch::Http::URL - # end - # - # req = Request.new 'HTTP_HOST' => 'example.com' + # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com' # req.protocol # => "http://" # - # req = Request.new 'HTTP_HOST' => 'example.com', 'HTTPS' => 'on' + # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com', 'HTTPS' => 'on' # req.protocol # => "https://" def protocol @protocol ||= ssl? ? "https://" : "http://" @@ -219,17 +211,13 @@ module ActionDispatch # Returns the \host and port for this request, such as "example.com:8080". # - # class Request < Rack::Request - # include ActionDispatch::Http::URL - # end - # - # req = Request.new 'HTTP_HOST' => 'example.com' + # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com' # req.raw_host_with_port # => "example.com" # - # req = Request.new 'HTTP_HOST' => 'example.com:80' + # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80' # req.raw_host_with_port # => "example.com:80" # - # req = Request.new 'HTTP_HOST' => 'example.com:8080' + # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080' # req.raw_host_with_port # => "example.com:8080" def raw_host_with_port if forwarded = x_forwarded_host.presence @@ -241,11 +229,7 @@ module ActionDispatch # Returns the host for this request, such as "example.com". # - # class Request < Rack::Request - # include ActionDispatch::Http::URL - # end - # - # req = Request.new 'HTTP_HOST' => 'example.com:8080' + # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080' # req.host # => "example.com" def host raw_host_with_port.sub(/:\d+$/, "".freeze) @@ -255,17 +239,13 @@ module ActionDispatch # "example.com:8080". Port is only included if it is not a default port # (80 or 443) # - # class Request < Rack::Request - # include ActionDispatch::Http::URL - # end - # - # req = Request.new 'HTTP_HOST' => 'example.com' + # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com' # req.host_with_port # => "example.com" # - # req = Request.new 'HTTP_HOST' => 'example.com:80' + # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80' # req.host_with_port # => "example.com" # - # req = Request.new 'HTTP_HOST' => 'example.com:8080' + # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080' # req.host_with_port # => "example.com:8080" def host_with_port "#{host}#{port_string}" @@ -273,14 +253,10 @@ module ActionDispatch # Returns the port number of this request as an integer. # - # class Request < Rack::Request - # include ActionDispatch::Http::URL - # end - # - # req = Request.new 'HTTP_HOST' => 'example.com' + # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com' # req.port # => 80 # - # req = Request.new 'HTTP_HOST' => 'example.com:8080' + # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080' # req.port # => 8080 def port @port ||= begin @@ -294,11 +270,7 @@ module ActionDispatch # Returns the standard \port number for this request's protocol. # - # class Request < Rack::Request - # include ActionDispatch::Http::URL - # end - # - # req = Request.new 'HTTP_HOST' => 'example.com:8080' + # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080' # req.standard_port # => 80 def standard_port case protocol @@ -309,14 +281,10 @@ module ActionDispatch # Returns whether this request is using the standard port # - # class Request < Rack::Request - # include ActionDispatch::Http::URL - # end - # - # req = Request.new 'HTTP_HOST' => 'example.com:80' + # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80' # req.standard_port? # => true # - # req = Request.new 'HTTP_HOST' => 'example.com:8080' + # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080' # req.standard_port? # => false def standard_port? port == standard_port @@ -325,14 +293,10 @@ module ActionDispatch # Returns a number \port suffix like 8080 if the \port number of this request # is not the default HTTP \port 80 or HTTPS \port 443. # - # class Request < Rack::Request - # include ActionDispatch::Http::URL - # end - # - # req = Request.new 'HTTP_HOST' => 'example.com:80' + # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80' # req.optional_port # => nil # - # req = Request.new 'HTTP_HOST' => 'example.com:8080' + # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080' # req.optional_port # => 8080 def optional_port standard_port? ? nil : port @@ -341,14 +305,10 @@ module ActionDispatch # Returns a string \port suffix, including colon, like ":8080" if the \port # number of this request is not the default HTTP \port 80 or HTTPS \port 443. # - # class Request < Rack::Request - # include ActionDispatch::Http::URL - # end - # - # req = Request.new 'HTTP_HOST' => 'example.com:80' + # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:80' # req.port_string # => "" # - # req = Request.new 'HTTP_HOST' => 'example.com:8080' + # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080' # req.port_string # => ":8080" def port_string standard_port? ? "" : ":#{port}" @@ -356,14 +316,10 @@ module ActionDispatch # Returns the requested port, such as 8080, based on SERVER_PORT # - # class Request < Rack::Request - # include ActionDispatch::Http::URL - # end - # - # req = Request.new 'SERVER_PORT' => '80' + # req = ActionDispatch::Request.new 'SERVER_PORT' => '80' # req.server_port # => 80 # - # req = Request.new 'SERVER_PORT' => '8080' + # req = ActionDispatch::Request.new 'SERVER_PORT' => '8080' # req.server_port # => 8080 def server_port get_header("SERVER_PORT").to_i diff --git a/actionpack/lib/action_dispatch/middleware/ssl.rb b/actionpack/lib/action_dispatch/middleware/ssl.rb index 0b81d0ad43..992daab3aa 100644 --- a/actionpack/lib/action_dispatch/middleware/ssl.rb +++ b/actionpack/lib/action_dispatch/middleware/ssl.rb @@ -133,12 +133,20 @@ module ActionDispatch end def redirect_to_https(request) - [ @redirect.fetch(:status, 301), + [ @redirect.fetch(:status, redirection_status(request)), { "Content-Type" => "text/html", "Location" => https_location_for(request) }, @redirect.fetch(:body, []) ] end + def redirection_status(request) + if request.get? || request.head? + 301 # Issue a permanent redirect via a GET request. + else + 307 # Issue a fresh request redirect to preserve the HTTP method. + end + end + def https_location_for(request) host = @redirect[:host] || request.host port = @redirect[:port] || request.port diff --git a/actionpack/test/controller/flash_test.rb b/actionpack/test/controller/flash_test.rb index cabbe2d608..e5f24f1a3a 100644 --- a/actionpack/test/controller/flash_test.rb +++ b/actionpack/test/controller/flash_test.rb @@ -263,6 +263,13 @@ class FlashIntegrationTest < ActionDispatch::IntegrationTest flash[:bar] = "for great justice" head :ok end + + def set_flash_optionally + flash.now.notice = params[:flash] + if stale? etag: "abe" + render inline: "maybe flash" + end + end end def test_flash @@ -310,6 +317,28 @@ class FlashIntegrationTest < ActionDispatch::IntegrationTest end end + def test_flash_factored_into_etag + with_test_route_set do + get "/set_flash_optionally" + no_flash_etag = response.etag + + get "/set_flash_optionally", params: { flash: "hello!" } + hello_flash_etag = response.etag + + assert_not_equal no_flash_etag, hello_flash_etag + + get "/set_flash_optionally", params: { flash: "hello!" } + another_hello_flash_etag = response.etag + + assert_equal another_hello_flash_etag, hello_flash_etag + + get "/set_flash_optionally", params: { flash: "goodbye!" } + goodbye_flash_etag = response.etag + + assert_not_equal another_hello_flash_etag, goodbye_flash_etag + end + end + private # Overwrite get to send SessionSecret in env hash diff --git a/actionpack/test/dispatch/ssl_test.rb b/actionpack/test/dispatch/ssl_test.rb index ccddb90bb5..71b274bf1e 100644 --- a/actionpack/test/dispatch/ssl_test.rb +++ b/actionpack/test/dispatch/ssl_test.rb @@ -38,6 +38,16 @@ class RedirectSSLTest < SSLTest assert_equal redirect[:body].join, @response.body end + def assert_post_redirected(redirect: {}, from: "http://a/b?c=d", + to: from.sub("http", "https")) + + self.app = build_app ssl_options: { redirect: redirect } + + post from + assert_response redirect[:status] || 307 + assert_redirected_to to + end + test "exclude can avoid redirect" do excluding = { exclude: -> request { request.path =~ /healthcheck/ } } @@ -57,6 +67,10 @@ class RedirectSSLTest < SSLTest assert_redirected end + test "http POST is redirected to https with status 307" do + assert_post_redirected + end + test "redirect with non-301 status" do assert_redirected redirect: { status: 307 } end diff --git a/actionview/lib/action_view/helpers/tag_helper.rb b/actionview/lib/action_view/helpers/tag_helper.rb index 4950f272a4..24c6d03cd1 100644 --- a/actionview/lib/action_view/helpers/tag_helper.rb +++ b/actionview/lib/action_view/helpers/tag_helper.rb @@ -86,11 +86,11 @@ module ActionView def tag_option(key, value, escape) if value.is_a?(Array) - value = escape ? safe_join(value, " ") : value.join(" ") + value = escape ? safe_join(value, " ".freeze) : value.join(" ".freeze) else value = escape ? ERB::Util.unwrapped_html_escape(value) : value.to_s end - %(#{key}="#{value.gsub(/"/, '"'.freeze)}") + %(#{key}="#{value.gsub('"'.freeze, '"'.freeze)}") end private diff --git a/activejob/CHANGELOG.md b/activejob/CHANGELOG.md index 585ade7229..9bf397af14 100644 --- a/activejob/CHANGELOG.md +++ b/activejob/CHANGELOG.md @@ -1,10 +1,15 @@ -## Rails 5.1.0.alpha ## +* Added instance variable `@queue` to JobWrapper. + + This will fix issues in [resque-scheduler](https://github.com/resque/resque-scheduler) `#job_to_hash` method, + so we can use `#enqueue_delayed_selection`, `#remove_delayed` method in resque-scheduler smoothly. + + *mu29* * Yield the job instance so you have access to things like `job.arguments` on the custom logic after retries fail. *DHH* -* Added declarative exception handling via `ActiveJob::Base.retry_on` and `ActiveJob::Base.discard_on`. +* Added declarative exception handling via `ActiveJob::Base.retry_on` and `ActiveJob::Base.discard_on`. Examples: @@ -24,4 +29,5 @@ *DHH* + Please check [5-0-stable](https://github.com/rails/rails/blob/5-0-stable/activejob/CHANGELOG.md) for previous changes. diff --git a/activejob/lib/active_job/exceptions.rb b/activejob/lib/active_job/exceptions.rb index f8d76587ad..d236f03d53 100644 --- a/activejob/lib/active_job/exceptions.rb +++ b/activejob/lib/active_job/exceptions.rb @@ -31,12 +31,12 @@ module ActiveJob # retry_on(YetAnotherCustomAppException) do |job, exception| # ExceptionNotifier.caught(exception) # end - # retry_on ActiveRecord::StatementInvalid, wait: 5.seconds, attempts: 3 + # retry_on ActiveRecord::Deadlocked, wait: 5.seconds, attempts: 3 # retry_on Net::OpenTimeout, wait: :exponentially_longer, attempts: 10 # # def perform(*args) # # Might raise CustomAppException, AnotherCustomAppException, or YetAnotherCustomAppException for something domain specific - # # Might raise ActiveRecord::StatementInvalid when a local db deadlock is detected + # # Might raise ActiveRecord::Deadlocked when a local db deadlock is detected # # Might raise Net::OpenTimeout when the remote service is down # end # end diff --git a/activejob/lib/active_job/queue_adapters/resque_adapter.rb b/activejob/lib/active_job/queue_adapters/resque_adapter.rb index 8620401cc1..2df157ef89 100644 --- a/activejob/lib/active_job/queue_adapters/resque_adapter.rb +++ b/activejob/lib/active_job/queue_adapters/resque_adapter.rb @@ -27,6 +27,7 @@ module ActiveJob # Rails.application.config.active_job.queue_adapter = :resque class ResqueAdapter def enqueue(job) #:nodoc: + JobWrapper.instance_variable_set(:@queue, job.queue_name) Resque.enqueue_to job.queue_name, JobWrapper, job.serialize end diff --git a/activejob/test/integration/queuing_test.rb b/activejob/test/integration/queuing_test.rb index 41b6b9cd6b..2669c52a1c 100644 --- a/activejob/test/integration/queuing_test.rb +++ b/activejob/test/integration/queuing_test.rb @@ -43,6 +43,13 @@ class QueuingTest < ActiveSupport::TestCase end end + test "resque JobWrapper should have instance variable queue" do + skip unless adapter_is?(:resque) + job = ::HelloJob.set(wait: 5.seconds).perform_later + hash = Resque.decode(Resque.find_delayed_selection { true }[0]) + assert_equal hash["queue"], job.queue_name + end + test "should not run job enqueued in the future" do begin TestJob.set(wait: 10.minutes).perform_later @id diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index fd2c5dd9bb..4aa1853bde 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,6 +1,4 @@ -* Option to remove standardized column types/arguments spaces in schema dump - with `ActiveRecord::SchemaDumper.standardized_argument_widths` and - `ActiveRecord::SchemaDumper.standardized_type_widths` methods. +* Remove standardized column types/arguments spaces in schema dump. *Tim Petricola* diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 659e512ce2..dc68b01386 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1296,6 +1296,12 @@ module ActiveRecord # If using with the <tt>:through</tt> option, the association on the join model must be # a #belongs_to, and the records which get deleted are the join records, rather than # the associated records. + # + # If using <tt>dependent: :destroy</tt> on a scoped association, only the scoped objects are destroyed. + # For example, if a Post model defines + # <tt>has_many :comments, -> { where published: true }, dependent: :destroy</tt> and <tt>destroy</tt> is + # called on a post, only published comments are destroyed. This means that any unpublished comments in the + # database would still contain a foreign key pointing to the now deleted post. # [:counter_cache] # This option can be used to configure a custom named <tt>:counter_cache.</tt> You only need this option, # when you customized the name of your <tt>:counter_cache</tt> on the #belongs_to association. diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/bit.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/bit.rb index a6b5a89ec0..74bff229ea 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/bit.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/bit.rb @@ -7,7 +7,7 @@ module ActiveRecord :bit end - def cast(value) + def cast_value(value) if ::String === value case value when /^0x/i @@ -16,7 +16,7 @@ module ActiveRecord value # Bit-string notation end else - value + value.to_s end end diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb index be74922453..b65d5b56f1 100644 --- a/activerecord/lib/active_record/schema_dumper.rb +++ b/activerecord/lib/active_record/schema_dumper.rb @@ -16,22 +16,6 @@ module ActiveRecord cattr_accessor :ignore_tables @@ignore_tables = [] - ## - # :singleton-method: - # Define whether column arguments are lined up in dump. - # Acceptable values are true or false. - # This setting is only used if ActiveRecord::Base.schema_format == :ruby - cattr_accessor :standardized_argument_widths - @@standardized_argument_widths = true - - ## - # :singleton-method: - # Define whether columns types are lined up in dump. - # Acceptable values are true or false. - # This setting is only used if ActiveRecord::Base.schema_format == :ruby - cattr_accessor :standardized_type_widths - @@standardized_type_widths = true - class << self def dump(connection=ActiveRecord::Base.connection, stream=STDOUT, config = ActiveRecord::Base) new(connection, generate_options(config)).dump(stream) @@ -162,32 +146,13 @@ HEADER keys = @connection.migration_keys # figure out the lengths for each column based on above keys - lengths = if standardized_argument_widths - keys.map { |key| - column_specs.map { |spec| - spec[key] ? spec[key].length + 2 : 0 - }.max - } - else - [0] * keys.length - end + lengths = [0] * keys.length # the string we're going to sprintf our values against, with standardized column widths - format_string = if standardized_argument_widths - lengths.map { |len| "%-#{len}s" } - else - ["%s"] * keys.length - end + format_string = ["%s"] * keys.length # add column type definition to our format string - if standardized_type_widths - # find the max length for the 'type' column, which is special - type_length = column_specs.map { |column| column[:type].length }.max - - format_string.unshift " t.%-#{type_length}s " - else - format_string.unshift " t.%s " - end + format_string.unshift " t.%s " format_string *= "" diff --git a/activerecord/test/cases/adapters/postgresql/bit_string_test.rb b/activerecord/test/cases/adapters/postgresql/bit_string_test.rb index f646e59848..7712e809a2 100644 --- a/activerecord/test/cases/adapters/postgresql/bit_string_test.rb +++ b/activerecord/test/cases/adapters/postgresql/bit_string_test.rb @@ -65,10 +65,11 @@ class PostgresqlBitStringTest < ActiveRecord::PostgreSQLTestCase end def test_roundtrip - PostgresqlBitString.create! a_bit: "00001010", a_bit_varying: "0101" - record = PostgresqlBitString.first + record = PostgresqlBitString.create!(a_bit: "00001010", a_bit_varying: "0101") assert_equal "00001010", record.a_bit assert_equal "0101", record.a_bit_varying + assert_nil record.another_bit + assert_nil record.another_bit_varying record.a_bit = "11111111" record.a_bit_varying = "0xF" diff --git a/activerecord/test/cases/adapters/postgresql/uuid_test.rb b/activerecord/test/cases/adapters/postgresql/uuid_test.rb index 321b74c1f5..9a59691737 100644 --- a/activerecord/test/cases/adapters/postgresql/uuid_test.rb +++ b/activerecord/test/cases/adapters/postgresql/uuid_test.rb @@ -198,13 +198,13 @@ class PostgresqlUUIDGenerationTest < ActiveRecord::PostgreSQLTestCase def test_schema_dumper_for_uuid_primary_key schema = dump_table_schema "pg_uuids" assert_match(/\bcreate_table "pg_uuids", id: :uuid, default: -> { "uuid_generate_v1\(\)" }/, schema) - assert_match(/t\.uuid "other_uuid", default: -> { "uuid_generate_v4\(\)" }/, schema) + assert_match(/t\.uuid "other_uuid", default: -> { "uuid_generate_v4\(\)" }/, schema) end def test_schema_dumper_for_uuid_primary_key_with_custom_default schema = dump_table_schema "pg_uuids_2" assert_match(/\bcreate_table "pg_uuids_2", id: :uuid, default: -> { "my_uuid_generator\(\)" }/, schema) - assert_match(/t\.uuid "other_uuid_2", default: -> { "my_uuid_generator\(\)" }/, schema) + assert_match(/t\.uuid "other_uuid_2", default: -> { "my_uuid_generator\(\)" }/, schema) end end end diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb index 23cfe46d7f..57b1bc889a 100644 --- a/activerecord/test/cases/schema_dumper_test.rb +++ b/activerecord/test/cases/schema_dumper_test.rb @@ -70,38 +70,35 @@ class SchemaDumperTest < ActiveRecord::TestCase assert_match %r{create_table "CamelCase"}, output end - def assert_line_up(lines, pattern, required = false) + def assert_no_line_up(lines, pattern) return assert(true) if lines.empty? matches = lines.map { |line| line.match(pattern) } - assert matches.all? if required matches.compact! return assert(true) if matches.empty? - assert_equal 1, matches.map { |match| match.offset(0).first }.uniq.length + line_matches = lines.map { |line| [line, line.match(pattern)] }.select { |line, match| match } + assert line_matches.all? { |line, match| + start = match.offset(0).first + line[start - 2..start - 1] == ", " + } end def column_definition_lines(output = standard_dump) output.scan(/^( *)create_table.*?\n(.*?)^\1end/m).map { |m| m.last.split(/\n/) } end - def test_types_line_up + def test_types_no_line_up column_definition_lines.each do |column_set| next if column_set.empty? - lengths = column_set.map do |column| - if match = column.match(/\bt\.\w+\s+(?="\w+?")/) - match[0].length - end - end.compact - - assert_equal 1, lengths.uniq.length + assert column_set.all? { |column| !column.match(/\bt\.\w+\s{2,}/) } end end - def test_arguments_line_up + def test_arguments_no_line_up column_definition_lines.each do |column_set| - assert_line_up(column_set, /default: /) - assert_line_up(column_set, /limit: /) - assert_line_up(column_set, /null: /) + assert_no_line_up(column_set, /default: /) + assert_no_line_up(column_set, /limit: /) + assert_no_line_up(column_set, /null: /) end end @@ -442,81 +439,3 @@ class SchemaDumperDefaultsTest < ActiveRecord::TestCase assert_match %r{t\.time\s+"time_with_default",\s+default: '2000-01-01 07:17:04'}, output end end - -class SchemaDumperNoStandardizedArgumentWidthsTest < ActiveRecord::TestCase - include SchemaDumpingHelper - - setup do - ActiveRecord::SchemaDumper.standardized_argument_widths = false - ActiveRecord::SchemaMigration.create_table - end - - teardown do - ActiveRecord::SchemaDumper.standardized_argument_widths = true - end - - def standard_dump - @@standard_dump ||= perform_schema_dump - end - - def perform_schema_dump - dump_all_table_schema [] - end - - def assert_no_line_up(lines, pattern) - return assert(true) if lines.empty? - matches = lines.map { |line| line.match(pattern) } - matches.compact! - return assert(true) if matches.empty? - line_matches = lines.map { |line| [line, line.match(pattern)] }.select { |line, match| match } - assert line_matches.all? { |line, match| - start = match.offset(0).first - line[start - 2..start - 1] == ", " - } - end - - def column_definition_lines(output = standard_dump) - output.scan(/^( *)create_table.*?\n(.*?)^\1end/m).map { |m| m.last.split(/\n/) } - end - - def test_arguments_no_line_up - column_definition_lines.each do |column_set| - assert_no_line_up(column_set, /default: /) - assert_no_line_up(column_set, /limit: /) - assert_no_line_up(column_set, /null: /) - end - end -end - -class SchemaDumperNoStandardizedTypeWidthsTest < ActiveRecord::TestCase - include SchemaDumpingHelper - - setup do - ActiveRecord::SchemaDumper.standardized_type_widths = false - ActiveRecord::SchemaMigration.create_table - end - - teardown do - ActiveRecord::SchemaDumper.standardized_type_widths = true - end - - def standard_dump - @@standard_dump ||= perform_schema_dump - end - - def perform_schema_dump - dump_all_table_schema [] - end - - def column_definition_lines(output = standard_dump) - output.scan(/^( *)create_table.*?\n(.*?)^\1end/m).map { |m| m.last.split(/\n/) } - end - - def test_types_no_line_up - column_definition_lines.each do |column_set| - next if column_set.empty? - - assert column_set.all? { |column| !column.match(/\bt\.\w+\s{2,}/) } - end - end -end diff --git a/guides/assets/stylesheets/syntaxhighlighter/shCore.css b/guides/assets/stylesheets/syntaxhighlighter/shCore.css index 34f6864a15..7e1e199343 100644 --- a/guides/assets/stylesheets/syntaxhighlighter/shCore.css +++ b/guides/assets/stylesheets/syntaxhighlighter/shCore.css @@ -33,7 +33,7 @@ height: auto !important; left: auto !important; line-height: 1.1em !important; - margin: 0 !important; + margin: 0 0 0.5px 0 !important; outline: 0 !important; overflow: visible !important; padding: 0 !important; diff --git a/guides/bug_report_templates/action_controller_master.rb b/guides/bug_report_templates/action_controller_master.rb index cd0a3be85c..486c7243ad 100644 --- a/guides/bug_report_templates/action_controller_master.rb +++ b/guides/bug_report_templates/action_controller_master.rb @@ -14,7 +14,6 @@ require "action_controller/railtie" class TestApp < Rails::Application config.root = File.dirname(__FILE__) - config.session_store :cookie_store, key: "cookie_store_key" secrets.secret_token = "secret_token" secrets.secret_key_base = "secret_key_base" diff --git a/guides/source/3_1_release_notes.md b/guides/source/3_1_release_notes.md index feee0f9920..fd90cf9886 100644 --- a/guides/source/3_1_release_notes.md +++ b/guides/source/3_1_release_notes.md @@ -99,7 +99,7 @@ gem 'jquery-rails' # config.assets.manifest = YOUR_PATH # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) - # config.assets.precompile `= %w( search.js ) + # config.assets.precompile `= %w( admin.js admin.css ) # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. diff --git a/guides/source/action_cable_overview.md b/guides/source/action_cable_overview.md index 118b0b52b2..4b9a22101a 100644 --- a/guides/source/action_cable_overview.md +++ b/guides/source/action_cable_overview.md @@ -510,10 +510,10 @@ WebNotificationsChannel.broadcast_to( The `WebNotificationsChannel.broadcast_to` call places a message in the current subscription adapter's pubsub queue under a separate broadcasting name for each user. For a user with an ID of 1, the broadcasting name would be -"web_notifications_1". +`web_notifications:1`. The channel has been instructed to stream everything that arrives at -"web_notifications_1" directly to the client by invoking the `received` +`web_notifications:1` directly to the client by invoking the `received` callback. The data passed as argument is the hash sent as the second parameter to the server-side broadcast call, JSON encoded for the trip across the wire, and unpacked for the data argument arriving to `received`. diff --git a/guides/source/active_record_querying.md b/guides/source/active_record_querying.md index 6f941d0e4e..493fd526fb 100644 --- a/guides/source/active_record_querying.md +++ b/guides/source/active_record_querying.md @@ -84,7 +84,7 @@ The methods are: * `distinct` * `where` -All of the above methods return an instance of `ActiveRecord::Relation`. +Finder methods that return a collection, such as `where` and `group`, return an instance of `ActiveRecord::Relation`. Methods that find a single entity, such as `find` and `first`, return a single instance of the model. The primary operation of `Model.find(options)` can be summarized as: @@ -1014,13 +1014,13 @@ There are multiple ways to use the `joins` method. You can just supply the raw SQL specifying the `JOIN` clause to `joins`: ```ruby -Author.joins("INNER JOIN posts ON posts.author_id = author.id AND posts.published = 't'") +Author.joins("INNER JOIN posts ON posts.author_id = authors.id AND posts.published = 't'") ``` This will result in the following SQL: ```sql -SELECT clients.* FROM clients INNER JOIN posts ON posts.author_id = author.id AND posts.published = 't' +SELECT clients.* FROM clients INNER JOIN posts ON posts.author_id = authors.id AND posts.published = 't' ``` #### Using Array/Hash of Named Associations @@ -1251,9 +1251,9 @@ articles, all the articles would still be loaded. By using `joins` (an INNER JOIN), the join conditions **must** match, otherwise no records will be returned. -NOTE: If an association is eager loaded as part of a join, any fields from a custom select clause will not present be on the loaded models. +NOTE: If an association is eager loaded as part of a join, any fields from a custom select clause will not present be on the loaded models. This is because it is ambiguous whether they should appear on the parent record, or the child. - + Scopes ------ diff --git a/guides/source/asset_pipeline.md b/guides/source/asset_pipeline.md index e6631a513c..701304acde 100644 --- a/guides/source/asset_pipeline.md +++ b/guides/source/asset_pipeline.md @@ -485,7 +485,7 @@ which contains these lines: Rails creates both `app/assets/javascripts/application.js` and `app/assets/stylesheets/application.css` regardless of whether the ---skip-sprockets option is used when creating a new rails application. This is +--skip-sprockets option is used when creating a new Rails application. This is so you can easily add asset pipelining later if you like. The directives that work in JavaScript files also work in stylesheets @@ -724,7 +724,7 @@ If you have other manifests or individual stylesheets and JavaScript files to include, you can add them to the `precompile` array in `config/initializers/assets.rb`: ```ruby -Rails.application.config.assets.precompile += ['admin.js', 'admin.css', 'swfObject.js'] +Rails.application.config.assets.precompile += %w( admin.js admin.css ) ``` NOTE. Always specify an expected compiled filename that ends with .js or .css, @@ -1024,7 +1024,7 @@ to tell our CDN (and browser) that the asset is "public", that means any cache can store the request. Also we commonly want to set `max-age` which is how long the cache will store the object before invalidating the cache. The `max-age` value is set to seconds with a maximum possible value of `31536000` which is one -year. You can do this in your rails application by setting +year. You can do this in your Rails application by setting ``` config.public_file_server.headers = { @@ -1109,9 +1109,9 @@ Windows you have a JavaScript runtime installed in your operating system. ### Serving GZipped version of assets -By default, gzipped version of compiled assets will be generated, along -with the non-gzipped version of assets. Gzipped assets help reduce the transmission of -data over the wire. You can configure this by setting the `gzip` flag. +By default, gzipped version of compiled assets will be generated, along with +the non-gzipped version of assets. Gzipped assets help reduce the transmission +of data over the wire. You can configure this by setting the `gzip` flag. ```ruby config.assets.gzip = false # disable gzipped assets generation @@ -1291,7 +1291,7 @@ config.assets.digest = true # Precompile additional assets (application.js, application.css, and all # non-JS/CSS are already added) -# config.assets.precompile += %w( search.js ) +# config.assets.precompile += %w( admin.js admin.css ) ``` Rails 4 and above no longer set default config values for Sprockets in `test.rb`, so diff --git a/guides/source/configuring.md b/guides/source/configuring.md index 3e27dfafa0..7239105b29 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -368,11 +368,9 @@ The MySQL adapter adds one additional configuration option: * `ActiveRecord::ConnectionAdapters::Mysql2Adapter.emulate_booleans` controls whether Active Record will consider all `tinyint(1)` columns as booleans. Defaults to `true`. -The schema dumper adds additional configuration options: +The schema dumper adds one additional configuration option: * `ActiveRecord::SchemaDumper.ignore_tables` accepts an array of tables that should _not_ be included in any generated schema file. This setting is ignored unless `config.active_record.schema_format == :ruby`. -* `ActiveRecord::SchemaDumper.standardized_argument_widths` configures whether colum arguments should be lined up or not in dump. By default this is `true`. This setting is ignored unless `config.active_record.schema_format == :ruby`. -* `ActiveRecord::SchemaDumper.standardized_type_widths` configures whether colum types should be lined up or not in dump. By default this is `true`. This setting is ignored unless `config.active_record.schema_format == :ruby`. ### Configuring Action Controller diff --git a/guides/source/development_dependencies_install.md b/guides/source/development_dependencies_install.md index cc24e6f666..20cd34c182 100644 --- a/guides/source/development_dependencies_install.md +++ b/guides/source/development_dependencies_install.md @@ -288,3 +288,46 @@ NOTE: Using the rake task to create the test databases ensures they have the cor NOTE: You'll see the following warning (or localized warning) during activating HStore extension in PostgreSQL 9.1.x or earlier: "WARNING: => is deprecated as an operator". If you're using another database, check the file `activerecord/test/config.yml` or `activerecord/test/config.example.yml` for default connection information. You can edit `activerecord/test/config.yml` to provide different credentials on your machine if you must, but obviously you should not push any such changes back to Rails. + +### Action Cable Setup + +Action Cable uses Redis as its default subscriptions adapter ([read more](action_cable_overview.html#broadcasting)). Thus, in order to have Action Cable's tests passing you need to install and have Redis running. + +#### Install Redis From Source + +Redis' documentation discourage installations with package managers as those are usually outdated. Installing from source and bringing the server up is straight forward and well documented on [Redis' documentation](http://redis.io/download#installation). + +#### Install Redis From Package Manager + +On OS X, you can run: + +```bash +$ brew install redis +``` + +Follow the instructions given by Homebrew to start these. + +In Ubuntu just run: + +```bash +$ sudo apt-get install redis-server +``` + +On Fedora or CentOS (requires EPEL enabled), just run: + +```bash +$ sudo yum install redis +``` + +If you are running Arch Linux just run: + +```bash +$ sudo pacman -S redis +$ sudo systemctl start redis +``` + +FreeBSD users will have to run the following: + +```bash +# portmaster databases/redis +``` diff --git a/guides/source/engines.md b/guides/source/engines.md index f9a37e45ac..d6118c014f 100644 --- a/guides/source/engines.md +++ b/guides/source/engines.md @@ -1364,7 +1364,7 @@ You can define assets for precompilation in `engine.rb`: ```ruby initializer "blorgh.assets.precompile" do |app| - app.config.assets.precompile += %w(admin.css admin.js) + app.config.assets.precompile += %w( admin.js admin.css ) end ``` diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md index d56b817bad..54421a328c 100644 --- a/guides/source/getting_started.md +++ b/guides/source/getting_started.md @@ -485,7 +485,7 @@ to find a template called `articles/new` within `app/views` for the application. The format for this template can only be `html` and the default handler for HTML is `erb`. Rails uses other handlers for other formats. `builder` handler is used to build XML templates and `coffee` handler uses -CoffeeScript to build JavaScript templates. Because you want to create a new +CoffeeScript to build JavaScript templates. Since you want to create a new HTML form, you will be using the `ERB` language which is designed to embed Ruby in HTML. @@ -528,7 +528,7 @@ method called `form_for`. To use this method, add this code into <% end %> ``` -If you refresh the page now, you'll see the exact same form as in the example. +If you refresh the page now, you'll see the exact same form from our example above. Building forms in Rails is really just that easy! When you call `form_for`, you pass it an identifying object for this diff --git a/guides/source/plugins.md b/guides/source/plugins.md index ff84861b8c..760ff431c0 100644 --- a/guides/source/plugins.md +++ b/guides/source/plugins.md @@ -67,7 +67,7 @@ This will tell you that everything got generated properly and you are ready to s Extending Core Classes ---------------------- -This section will explain how to add a method to String that will be available anywhere in your rails application. +This section will explain how to add a method to String that will be available anywhere in your Rails application. In this example you will add a method to String named `to_squawk`. To begin, create a new test file with a few assertions: diff --git a/guides/source/routing.md b/guides/source/routing.md index 756e0fefd7..937e313663 100644 --- a/guides/source/routing.md +++ b/guides/source/routing.md @@ -553,29 +553,23 @@ In particular, simple routing makes it very easy to map legacy URLs to new Rails ### Bound Parameters -When you set up a regular route, you supply a series of symbols that Rails maps to parts of an incoming HTTP request. Two of these symbols are special: `:controller` maps to the name of a controller in your application, and `:action` maps to the name of an action within that controller. For example, consider this route: +When you set up a regular route, you supply a series of symbols that Rails maps to parts of an incoming HTTP request. For example, consider this route: ```ruby -get ':controller(/:action(/:id))' +get 'photos(/:id)', to: :display ``` -If an incoming request of `/photos/show/1` is processed by this route (because it hasn't matched any previous route in the file), then the result will be to invoke the `show` action of the `PhotosController`, and to make the final parameter `"1"` available as `params[:id]`. This route will also route the incoming request of `/photos` to `PhotosController#index`, since `:action` and `:id` are optional parameters, denoted by parentheses. +If an incoming request of `/photos/1` is processed by this route (because it hasn't matched any previous route in the file), then the result will be to invoke the `display` action of the `PhotosController`, and to make the final parameter `"1"` available as `params[:id]`. This route will also route the incoming request of `/photos` to `PhotosController#display`, since `:id` is an optional parameter, denoted by parentheses. ### Dynamic Segments -You can set up as many dynamic segments within a regular route as you like. Anything other than `:controller` or `:action` will be available to the action as part of `params`. If you set up this route: +You can set up as many dynamic segments within a regular route as you like. Any segment will be available to the action as part of `params`. If you set up this route: ```ruby -get ':controller/:action/:id/:user_id' +get 'photos/:id/:user_id', to: 'photos#show' ``` -An incoming path of `/photos/show/1/2` will be dispatched to the `show` action of the `PhotosController`. `params[:id]` will be `"1"`, and `params[:user_id]` will be `"2"`. - -NOTE: You can't use `:namespace` or `:module` with a `:controller` path segment. If you need to do this then use a constraint on :controller that matches the namespace you require. e.g: - -```ruby -get ':controller(/:action(/:id))', controller: /admin\/[^\/]+/ -``` +An incoming path of `/photos/1/2` will be dispatched to the `show` action of the `PhotosController`. `params[:id]` will be `"1"`, and `params[:user_id]` will be `"2"`. TIP: By default, dynamic segments don't accept dots - this is because the dot is used as a separator for formatted routes. If you need to use a dot within a dynamic segment, add a constraint that overrides this – for example, `id: /[^\/]+/` allows anything except a slash. @@ -584,32 +578,24 @@ TIP: By default, dynamic segments don't accept dots - this is because the dot is You can specify static segments when creating a route by not prepending a colon to a fragment: ```ruby -get ':controller/:action/:id/with_user/:user_id' +get 'photos/:id/with_user/:user_id', to: 'photos#show' ``` -This route would respond to paths such as `/photos/show/1/with_user/2`. In this case, `params` would be `{ controller: 'photos', action: 'show', id: '1', user_id: '2' }`. +This route would respond to paths such as `/photos/1/with_user/2`. In this case, `params` would be `{ controller: 'photos', action: 'show', id: '1', user_id: '2' }`. ### The Query String The `params` will also include any parameters from the query string. For example, with this route: ```ruby -get ':controller/:action/:id' +get 'photos/:id', to: 'photos#show' ``` -An incoming path of `/photos/show/1?user_id=2` will be dispatched to the `show` action of the `Photos` controller. `params` will be `{ controller: 'photos', action: 'show', id: '1', user_id: '2' }`. +An incoming path of `/photos/1?user_id=2` will be dispatched to the `show` action of the `Photos` controller. `params` will be `{ controller: 'photos', action: 'show', id: '1', user_id: '2' }`. ### Defining Defaults -You do not need to explicitly use the `:controller` and `:action` symbols within a route. You can supply them as defaults: - -```ruby -get 'photos/:id', to: 'photos#show' -``` - -With this route, Rails will match an incoming path of `/photos/12` to the `show` action of `PhotosController`. - -You can also define other defaults in a route by supplying a hash for the `:defaults` option. This even applies to parameters that you do not specify as dynamic segments. For example: +You can define defaults in a route by supplying a hash for the `:defaults` option. This even applies to parameters that you do not specify as dynamic segments. For example: ```ruby get 'photos/:id', to: 'photos#show', defaults: { format: 'jpg' } diff --git a/guides/source/security.md b/guides/source/security.md index 2d1bc3b5b3..36eb61be8b 100644 --- a/guides/source/security.md +++ b/guides/source/security.md @@ -965,7 +965,7 @@ When `params[:token]` is one of: `[nil]`, `[nil, nil, ...]` or `['foo', nil]` it will bypass the test for `nil`, but `IS NULL` or `IN ('foo', NULL)` where clauses still will be added to the SQL query. -To keep rails secure by default, `deep_munge` replaces some of the values with +To keep Rails secure by default, `deep_munge` replaces some of the values with `nil`. Below table shows what the parameters look like based on `JSON` sent in request: diff --git a/guides/source/testing.md b/guides/source/testing.md index 26d50bec0c..4ca3236ec1 100644 --- a/guides/source/testing.md +++ b/guides/source/testing.md @@ -37,10 +37,12 @@ controllers/ helpers/ mailers/ test_helper.rb fixtures/ integration/ models/ ``` -The `models` directory is meant to hold tests for your models, the `controllers` directory is meant to hold tests for your controllers and the `integration` directory is meant to hold tests that involve any number of controllers interacting. There is also a directory for testing your mailers and one for testing view helpers. +The `helpers`, `mailers`, and `models` directories are meant to hold tests for view helpers, mailers, and models, respectively. The `controllers` directory is meant to hold tests for controllers, routes, and views. The `integration` directory is meant to hold tests for interactions between controllers. Fixtures are a way of organizing test data; they reside in the `fixtures` directory. +A `jobs` directory will also be created when an associated test is first generated. + The `test_helper.rb` file holds the default configuration for your tests. @@ -1085,7 +1087,7 @@ end Testing Routes -------------- -Like everything else in your Rails application, you can test your routes. +Like everything else in your Rails application, you can test your routes. Route tests reside in `test/controllers/` or are part of controller tests. NOTE: If your application has complex routes, Rails provides a number of useful helpers to test them. diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md index a8afa0ca6e..2372590cec 100644 --- a/guides/source/upgrading_ruby_on_rails.md +++ b/guides/source/upgrading_ruby_on_rails.md @@ -1426,7 +1426,7 @@ config.assets.digest = true # config.assets.manifest = YOUR_PATH # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) -# config.assets.precompile += %w( search.js ) +# config.assets.precompile += %w( admin.js admin.css ) # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. # config.force_ssl = true diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt index 01ef3e6630..2318cf59ff 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/assets.rb.tt @@ -7,5 +7,6 @@ Rails.application.config.assets.version = '1.0' # Rails.application.config.assets.paths << Emoji.images_path # Precompile additional assets. -# application.js, application.css, and all non-JS/CSS in app/assets folder are already added. -# Rails.application.config.assets.precompile += %w( search.js ) +# application.js, application.css, and all non-JS/CSS in the app/assets +# folder are already added. +# Rails.application.config.assets.precompile += %w( admin.js admin.css ) |