diff options
64 files changed, 408 insertions, 160 deletions
diff --git a/RELEASING_RAILS.md b/RELEASING_RAILS.md index 287dd4fa12..7fa180cc43 100644 --- a/RELEASING_RAILS.md +++ b/RELEASING_RAILS.md @@ -109,13 +109,14 @@ browser. This will stop you from looking silly when you push an RC to rubygems.org and then realize it is broken. -### Release to RubyGems and NPM. - -IMPORTANT: The Action Cable client and Action View's UJS adapter are released -as NPM packages, so you must have Node.js installed, have an NPM account -(npmjs.com), and be a package owner for `actioncable` and `rails-ujs` (you can -check this via `npm owner ls actioncable` and `npm owner ls rails-ujs`) in -order to do a full release. Do not release until you're set up with NPM! +### Release to RubyGems and npm. + +IMPORTANT: Several gems have JavaScript components that are released as npm +packages, so you must have Node.js installed, have an npm account (npmjs.com), +and be a package owner for `@rails/actioncable`, `@rails/actiontext`, +`@rails/activestorage`, and `@rails/ujs`. You can check this by making sure your +npm user (`npm whoami`) is listed as an owner (`npm owner ls <pkg>`) of each +package. Do not release until you're set up with npm! The release task will sign the release tag. If you haven't got commit signing set up, use https://git-scm.com/book/tr/v2/Git-Tools-Signing-Your-Work as a diff --git a/actioncable/README.md b/actioncable/README.md index a2783d6f45..84cf817d74 100644 --- a/actioncable/README.md +++ b/actioncable/README.md @@ -504,7 +504,7 @@ WebSocket functionality. ### Installation ``` -npm install actioncable --save +npm install @rails/actioncable --save ``` ### Usage @@ -516,7 +516,7 @@ provided. In JavaScript... ```javascript -ActionCable = require('actioncable') +ActionCable = require('@rails/actioncable') var cable = ActionCable.createConsumer('wss://RAILS-API-PATH.com/cable') @@ -528,7 +528,7 @@ cable.subscriptions.create('AppearanceChannel', { and in CoffeeScript... ```coffeescript -ActionCable = require('actioncable') +ActionCable = require('@rails/actioncable') cable = ActionCable.createConsumer('wss://RAILS-API-PATH.com/cable') diff --git a/actioncable/lib/rails/generators/channel/templates/javascript/consumer.js.tt b/actioncable/lib/rails/generators/channel/templates/javascript/consumer.js.tt index 76ca3d0f2f..eec7e54b8a 100644 --- a/actioncable/lib/rails/generators/channel/templates/javascript/consumer.js.tt +++ b/actioncable/lib/rails/generators/channel/templates/javascript/consumer.js.tt @@ -1,6 +1,6 @@ // Action Cable provides the framework to deal with WebSockets in Rails. // You can generate new channels where WebSocket features live using the `rails generate channel` command. -import ActionCable from "actioncable" +import ActionCable from "@rails/actioncable" export default ActionCable.createConsumer() diff --git a/actioncable/package.json b/actioncable/package.json index db78c1a09a..69a97939fb 100644 --- a/actioncable/package.json +++ b/actioncable/package.json @@ -1,5 +1,5 @@ { - "name": "actioncable", + "name": "@rails/actioncable", "version": "6.0.0-alpha", "description": "WebSocket framework for Ruby on Rails.", "main": "app/assets/javascripts/action_cable.js", diff --git a/actionmailbox/README.md b/actionmailbox/README.md index f0bde03961..c70f73b40f 100644 --- a/actionmailbox/README.md +++ b/actionmailbox/README.md @@ -1,6 +1,6 @@ # Action Mailbox -Action Mailbox routes incoming emails to controller-like mailboxes for processing in Rails. It ships with ingresses for Amazon SES, Mailgun, Mandrill, and SendGrid. You can also handle inbound mails directly via the built-in Postfix ingress. +Action Mailbox routes incoming emails to controller-like mailboxes for processing in Rails. It ships with ingresses for Amazon SES, Mailgun, Mandrill, Postmark, and SendGrid. You can also handle inbound mails directly via the built-in Postfix ingress. The inbound emails are turned into `InboundEmail` records using Active Record and feature lifecycle tracking, storage of the original email on cloud storage via Active Storage, and responsible data handling with on-by-default incineration. diff --git a/actionmailbox/app/controllers/action_mailbox/ingresses/amazon/inbound_emails_controller.rb b/actionmailbox/app/controllers/action_mailbox/ingresses/amazon/inbound_emails_controller.rb index cf45ac8408..e0a187054e 100644 --- a/actionmailbox/app/controllers/action_mailbox/ingresses/amazon/inbound_emails_controller.rb +++ b/actionmailbox/app/controllers/action_mailbox/ingresses/amazon/inbound_emails_controller.rb @@ -37,7 +37,7 @@ module ActionMailbox def self.prepare self.verifier ||= begin - require "aws-sdk-sns/message_verifier" + require "aws-sdk-sns" Aws::SNS::MessageVerifier.new end end diff --git a/actionmailbox/app/controllers/action_mailbox/ingresses/postmark/inbound_emails_controller.rb b/actionmailbox/app/controllers/action_mailbox/ingresses/postmark/inbound_emails_controller.rb new file mode 100644 index 0000000000..309085c82a --- /dev/null +++ b/actionmailbox/app/controllers/action_mailbox/ingresses/postmark/inbound_emails_controller.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +module ActionMailbox + # Ingests inbound emails from Postmark. Requires a +RawEmail+ parameter containing a full RFC 822 message. + # + # Authenticates requests using HTTP basic access authentication. The username is always +actionmailbox+, and the + # password is read from the application's encrypted credentials or an environment variable. See the Usage section below. + # + # Note that basic authentication is insecure over unencrypted HTTP. An attacker that intercepts cleartext requests to + # the Postmark ingress can learn its password. You should only use the Postmark ingress over HTTPS. + # + # Returns: + # + # - <tt>204 No Content</tt> if an inbound email is successfully recorded and enqueued for routing to the appropriate mailbox + # - <tt>401 Unauthorized</tt> if the request's signature could not be validated + # - <tt>404 Not Found</tt> if Action Mailbox is not configured to accept inbound emails from Postmark + # - <tt>422 Unprocessable Entity</tt> if the request is missing the required +RawEmail+ parameter + # - <tt>500 Server Error</tt> if the ingress password is not configured, or if one of the Active Record database, + # the Active Storage service, or the Active Job backend is misconfigured or unavailable + # + # == Usage + # + # 1. Tell Action Mailbox to accept emails from Postmark: + # + # # config/environments/production.rb + # config.action_mailbox.ingress = :postmark + # + # 2. Generate a strong password that Action Mailbox can use to authenticate requests to the Postmark ingress. + # + # Use <tt>rails credentials:edit</tt> to add the password to your application's encrypted credentials under + # +action_mailbox.ingress_password+, where Action Mailbox will automatically find it: + # + # action_mailbox: + # ingress_password: ... + # + # Alternatively, provide the password in the +RAILS_INBOUND_EMAIL_PASSWORD+ environment variable. + # + # 3. {Configure Postmark}[https://postmarkapp.com/manual#configure-your-inbound-webhook-url] to forward inbound emails + # to +/rails/action_mailbox/postmark/inbound_emails+ with the username +actionmailbox+ and the password you + # previously generated. If your application lived at <tt>https://example.com</tt>, you would configure your + # Postmark inbound webhook with the following fully-qualified URL: + # + # https://actionmailbox:PASSWORD@example.com/rails/action_mailbox/postmark/inbound_emails + # + # *NOTE:* When configuring your Postmark inbound webhook, be sure to check the box labeled *"Include raw email + # content in JSON payload"*. Action Mailbox needs the raw email content to work. + class Ingresses::Postmark::InboundEmailsController < ActionMailbox::BaseController + before_action :authenticate_by_password + + def create + ActionMailbox::InboundEmail.create_and_extract_message_id! params.require("RawEmail") + rescue ActionController::ParameterMissing => error + logger.error <<~MESSAGE + #{error.message} + + When configuring your Postmark inbound webhook, be sure to check the box + labeled "Include raw email content in JSON payload". + MESSAGE + head :unprocessable_entity + end + end +end diff --git a/actionmailbox/config/routes.rb b/actionmailbox/config/routes.rb index f1bc9847f5..7aa230fdff 100644 --- a/actionmailbox/config/routes.rb +++ b/actionmailbox/config/routes.rb @@ -5,6 +5,7 @@ Rails.application.routes.draw do post "/amazon/inbound_emails" => "amazon/inbound_emails#create", as: :rails_amazon_inbound_emails post "/mandrill/inbound_emails" => "mandrill/inbound_emails#create", as: :rails_mandrill_inbound_emails post "/postfix/inbound_emails" => "postfix/inbound_emails#create", as: :rails_postfix_inbound_emails + post "/postmark/inbound_emails" => "postmark/inbound_emails#create", as: :rails_postmark_inbound_emails post "/sendgrid/inbound_emails" => "sendgrid/inbound_emails#create", as: :rails_sendgrid_inbound_emails # Mailgun requires that a webhook's URL end in 'mime' for it to receive the raw contents of emails. diff --git a/actionmailbox/test/controllers/ingresses/postmark/inbound_emails_controller_test.rb b/actionmailbox/test/controllers/ingresses/postmark/inbound_emails_controller_test.rb new file mode 100644 index 0000000000..11b579b39c --- /dev/null +++ b/actionmailbox/test/controllers/ingresses/postmark/inbound_emails_controller_test.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +require "test_helper" + +class ActionMailbox::Ingresses::Postmark::InboundEmailsControllerTest < ActionDispatch::IntegrationTest + setup { ActionMailbox.ingress = :postmark } + + test "receiving an inbound email from Postmark" do + assert_difference -> { ActionMailbox::InboundEmail.count }, +1 do + post rails_postmark_inbound_emails_url, + headers: { authorization: credentials }, params: { RawEmail: file_fixture("../files/welcome.eml").read } + end + + assert_response :no_content + + inbound_email = ActionMailbox::InboundEmail.last + assert_equal file_fixture("../files/welcome.eml").read, inbound_email.raw_email.download + assert_equal "0CB459E0-0336-41DA-BC88-E6E28C697DDB@37signals.com", inbound_email.message_id + end + + test "rejecting when RawEmail param is missing" do + assert_no_difference -> { ActionMailbox::InboundEmail.count } do + post rails_postmark_inbound_emails_url, + headers: { authorization: credentials }, params: { From: "someone@example.com" } + end + + assert_response :unprocessable_entity + end + + test "rejecting an unauthorized inbound email from Postmark" do + assert_no_difference -> { ActionMailbox::InboundEmail.count } do + post rails_postmark_inbound_emails_url, params: { RawEmail: file_fixture("../files/welcome.eml").read } + end + + assert_response :unauthorized + end + + test "raising when the configured password is nil" do + switch_password_to nil do + assert_raises ArgumentError do + post rails_postmark_inbound_emails_url, + headers: { authorization: credentials }, params: { RawEmail: file_fixture("../files/welcome.eml").read } + end + end + end + + test "raising when the configured password is blank" do + switch_password_to "" do + assert_raises ArgumentError do + post rails_postmark_inbound_emails_url, + headers: { authorization: credentials }, params: { RawEmail: file_fixture("../files/welcome.eml").read } + end + end + end +end diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 650dd8bbda..5610212fad 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -461,7 +461,7 @@ module ActionMailer helper ActionMailer::MailHelper - class_attribute :delivery_job, default: ::ActionMailer::MailDeliveryJob + class_attribute :delivery_job, default: ::ActionMailer::DeliveryJob class_attribute :default_params, default: { mime_version: "1.0", charset: "UTF-8", diff --git a/actionmailer/lib/action_mailer/parameterized.rb b/actionmailer/lib/action_mailer/parameterized.rb index 999435919e..0a97af8105 100644 --- a/actionmailer/lib/action_mailer/parameterized.rb +++ b/actionmailer/lib/action_mailer/parameterized.rb @@ -145,12 +145,20 @@ module ActionMailer if processed? super else - job = @mailer_class.delivery_job + job = delivery_job_class args = arguments_for(job, delivery_method) job.set(options).perform_later(*args) end end + def delivery_job_class + if @mailer_class.delivery_job <= MailDeliveryJob + @mailer_class.delivery_job + else + Parameterized::DeliveryJob + end + end + def arguments_for(delivery_job, delivery_method) if delivery_job <= MailDeliveryJob [@mailer_class.name, @action.to_s, delivery_method.to_s, params: @params, args: @args] diff --git a/actionmailer/lib/action_mailer/railtie.rb b/actionmailer/lib/action_mailer/railtie.rb index bb6141b406..23488db790 100644 --- a/actionmailer/lib/action_mailer/railtie.rb +++ b/actionmailer/lib/action_mailer/railtie.rb @@ -46,6 +46,10 @@ module ActionMailer register_preview_interceptors(options.delete(:preview_interceptors)) register_observers(options.delete(:observers)) + if delivery_job = options.delete(:delivery_job) + self.delivery_job = delivery_job.constantize + end + options.each { |k, v| send("#{k}=", v) } end diff --git a/actionmailer/test/abstract_unit.rb b/actionmailer/test/abstract_unit.rb index f647896374..448807c144 100644 --- a/actionmailer/test/abstract_unit.rb +++ b/actionmailer/test/abstract_unit.rb @@ -33,6 +33,8 @@ I18n.enforce_available_locales = false FIXTURE_LOAD_PATH = File.expand_path("fixtures", __dir__) ActionMailer::Base.view_paths = FIXTURE_LOAD_PATH +ActionMailer::Base.delivery_job = ActionMailer::MailDeliveryJob + class ActiveSupport::TestCase include ActiveSupport::Testing::MethodCallAssertions diff --git a/actionmailer/test/legacy_delivery_job_test.rb b/actionmailer/test/legacy_delivery_job_test.rb index 112c842beb..3a3872df47 100644 --- a/actionmailer/test/legacy_delivery_job_test.rb +++ b/actionmailer/test/legacy_delivery_job_test.rb @@ -11,9 +11,6 @@ class LegacyDeliveryJobTest < ActiveSupport::TestCase class LegacyDeliveryJob < ActionMailer::DeliveryJob end - class LegacyParmeterizedDeliveryJob < ActionMailer::Parameterized::DeliveryJob - end - setup do @previous_logger = ActiveJob::Base.logger ActiveJob::Base.logger = Logger.new(nil) @@ -42,9 +39,9 @@ class LegacyDeliveryJobTest < ActiveSupport::TestCase { inviter: "david@basecamp.com", invitee: "jason@basecamp.com" }, ] - with_delivery_job(LegacyParmeterizedDeliveryJob) do + with_delivery_job(LegacyDeliveryJob) do assert_deprecated do - assert_performed_with(job: LegacyParmeterizedDeliveryJob, args: args) do + assert_performed_with(job: ActionMailer::Parameterized::DeliveryJob, args: args) do mail.deliver_later end end diff --git a/actiontext/app/javascript/actiontext/attachment_upload.js b/actiontext/app/javascript/actiontext/attachment_upload.js index a716f1f589..77fbc97df6 100644 --- a/actiontext/app/javascript/actiontext/attachment_upload.js +++ b/actiontext/app/javascript/actiontext/attachment_upload.js @@ -1,4 +1,4 @@ -import { DirectUpload } from "activestorage" +import { DirectUpload } from "@rails/activestorage" export class AttachmentUpload { constructor(attachment, element) { diff --git a/actiontext/lib/templates/installer.rb b/actiontext/lib/templates/installer.rb index dc549a8af3..e7c6c2623e 100644 --- a/actiontext/lib/templates/installer.rb +++ b/actiontext/lib/templates/installer.rb @@ -8,15 +8,14 @@ say "Copying blob rendering partial to app/views/active_storage/blobs/_blob.html copy_file "#{__dir__}/../../app/views/active_storage/blobs/_blob.html.erb", "app/views/active_storage/blobs/_blob.html.erb" -# FIXME: Replace with release version on release say "Installing JavaScript dependency" -run "yarn add https://github.com/rails/actiontext" +run "yarn add @rails/actiontext" APPLICATION_PACK_PATH = "app/javascript/packs/application.js" -if File.exist?(APPLICATION_PACK_PATH) && File.read(APPLICATION_PACK_PATH) !~ /import "actiontext"/ +if File.exist?(APPLICATION_PACK_PATH) && File.read(APPLICATION_PACK_PATH) !~ /import "@rails\/actiontext"/ say "Adding import to default JavaScript pack" append_to_file APPLICATION_PACK_PATH, <<-EOS -import "actiontext" +import "@rails/actiontext" EOS end diff --git a/actiontext/package.json b/actiontext/package.json index b42838b1df..ec8f35fd3c 100644 --- a/actiontext/package.json +++ b/actiontext/package.json @@ -1,5 +1,5 @@ { - "name": "actiontext", + "name": "@rails/actiontext", "version": "6.0.0-alpha", "description": "Edit and display rich text in Rails applications", "main": "app/javascript/actiontext/index.js", @@ -21,7 +21,7 @@ ], "license": "MIT", "dependencies": { - "trix": ">=1.0.0", - "activestorage": "6.0.0-alpha" + "trix": "^1.0.0", + "@rails/activestorage": "^6.0.0-alpha" } } diff --git a/actiontext/test/dummy/app/javascript/packs/application.js b/actiontext/test/dummy/app/javascript/packs/application.js index 90eb1a1841..13ac17ed58 100644 --- a/actiontext/test/dummy/app/javascript/packs/application.js +++ b/actiontext/test/dummy/app/javascript/packs/application.js @@ -1 +1 @@ -import "actiontext" +import "@rails/actiontext" diff --git a/actiontext/yarn.lock b/actiontext/yarn.lock deleted file mode 100644 index f98622eb64..0000000000 --- a/actiontext/yarn.lock +++ /dev/null @@ -1,11 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"activestorage@>= 5.2.0-rc1": - version "5.2.0-rc1" - resolved "https://registry.yarnpkg.com/activestorage/-/activestorage-5.2.0-rc1.tgz#79898996eceb0f13575eff41fb109051fbfa49b0" - -trix@^0.11.1: - version "0.11.1" - resolved "https://registry.yarnpkg.com/trix/-/trix-0.11.1.tgz#ffe54f2757c2c2385b8424fd5c5d2ab712a09acc" diff --git a/actionview/app/assets/javascripts/README.md b/actionview/app/assets/javascripts/README.md index b74fa1afad..2b110e604f 100644 --- a/actionview/app/assets/javascripts/README.md +++ b/actionview/app/assets/javascripts/README.md @@ -17,11 +17,11 @@ Note that the `data` attributes this library adds are a feature of HTML5. If you ### NPM - npm install rails-ujs --save - + npm install @rails/ujs --save + ### Yarn - - yarn add rails-ujs + + yarn add @rails/ujs Ensure that `.yarnclean` does not include `assets` if you use [yarn autoclean](https://yarnpkg.com/lang/en/docs/cli/autoclean/). @@ -40,7 +40,7 @@ In a conventional Rails application that uses the asset pipeline, require `rails If you're using the Webpacker gem or some other JavaScript bundler, add the following to your main JS file: ```javascript -import Rails from 'rails-ujs'; +import Rails from "@rails/ujs" Rails.start() ``` diff --git a/actionview/lib/action_view/helpers/form_options_helper.rb b/actionview/lib/action_view/helpers/form_options_helper.rb index ebdd96f570..a7747456a4 100644 --- a/actionview/lib/action_view/helpers/form_options_helper.rb +++ b/actionview/lib/action_view/helpers/form_options_helper.rb @@ -654,7 +654,7 @@ module ActionView # # ==== Gotcha # - # The HTML specification says when nothing is select on a collection of radio buttons + # The HTML specification says when nothing is selected on a collection of radio buttons # web browsers do not send any value to server. # Unfortunately this introduces a gotcha: # if a +User+ model has a +category_id+ field and in the form no category is selected, no +category_id+ parameter is sent. So, diff --git a/actionview/package.json b/actionview/package.json index 1f74df79d3..d6cf412c6d 100644 --- a/actionview/package.json +++ b/actionview/package.json @@ -1,5 +1,5 @@ { - "name": "rails-ujs", + "name": "@rails/ujs", "version": "6.0.0-alpha", "description": "Ruby on Rails unobtrusive scripting adapter", "main": "lib/assets/compiled/rails-ujs.js", diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb index 2299fc0214..79d71bfb5d 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb @@ -123,7 +123,7 @@ module ActiveRecord # +binds+ as the bind substitutes. +name+ is logged along with # the executed +sql+ statement. def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil) - sql, binds = sql_for_insert(sql, pk, nil, sequence_name, binds) + sql, binds = sql_for_insert(sql, pk, sequence_name, binds) exec_query(sql, name, binds) end @@ -464,7 +464,7 @@ module ActiveRecord exec_query(sql, name, binds, prepare: true) end - def sql_for_insert(sql, pk, id_value, sequence_name, binds) + def sql_for_insert(sql, pk, sequence_name, binds) [sql, binds] end diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index 346d4b067a..0d2d66f919 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -504,15 +504,17 @@ module ActiveRecord @connection end - def case_sensitive_comparison(table, attribute, column, value) # :nodoc: - table[attribute].eq(value) + def case_sensitive_comparison(attribute, value) # :nodoc: + attribute.eq(value) end - def case_insensitive_comparison(table, attribute, column, value) # :nodoc: + def case_insensitive_comparison(attribute, value) # :nodoc: + column = column_for_attribute(attribute) + if can_perform_case_insensitive_comparison_for?(column) - table[attribute].lower.eq(table.lower(value)) + attribute.lower.eq(attribute.relation.lower(value)) else - table[attribute].eq(value) + attribute.eq(value) end end @@ -659,6 +661,11 @@ module ActiveRecord raise(ActiveRecordError, "No such column: #{table_name}.#{column_name}") end + def column_for_attribute(attribute) + table_name = attribute.relation.name + schema_cache.columns_hash(table_name)[attribute.name.to_s] + end + def collector if prepared_statements Arel::Collectors::Composite.new( diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index cccd6e2210..70d281b62b 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -476,9 +476,11 @@ module ActiveRecord SQL end - def case_sensitive_comparison(table, attribute, column, value) # :nodoc: + def case_sensitive_comparison(attribute, value) # :nodoc: + column = column_for_attribute(attribute) + if column.collation && !column.case_sensitive? - table[attribute].eq(Arel::Nodes::Bin.new(value)) + attribute.eq(Arel::Nodes::Bin.new(value)) else super end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb index c70a4fa875..41633872e2 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb @@ -110,7 +110,7 @@ module ActiveRecord end alias :exec_update :exec_delete - def sql_for_insert(sql, pk, id_value, sequence_name, binds) # :nodoc: + def sql_for_insert(sql, pk, sequence_name, binds) # :nodoc: if pk.nil? # Extract the table from the insert sql. Yuck. table_ref = extract_table_ref_from_insert_sql(sql) diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index ba221a333b..a863227276 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -44,6 +44,11 @@ module ActiveRecord end def bind_attribute(name, value) # :nodoc: + if reflection = klass._reflect_on_association(name) + name = reflection.foreign_key + value = value.read_attribute(reflection.klass.primary_key) unless value.nil? + end + attr = arel_attribute(name) bind = predicate_builder.build_bind_attribute(attr.name, value) yield attr, bind diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb index 5a1dbc8e53..111b6c9a64 100644 --- a/activerecord/lib/active_record/validations/uniqueness.rb +++ b/activerecord/lib/active_record/validations/uniqueness.rb @@ -56,33 +56,21 @@ module ActiveRecord end def build_relation(klass, attribute, value) - if reflection = klass._reflect_on_association(attribute) - attribute = reflection.foreign_key - value = value.attributes[reflection.klass.primary_key] unless value.nil? - end - - if value.nil? - return klass.unscoped.where!(attribute => value) - end - - # the attribute may be an aliased attribute - if klass.attribute_alias?(attribute) - attribute = klass.attribute_alias(attribute) + relation = klass.unscoped + comparison = relation.bind_attribute(attribute, value) do |attr, bind| + return relation.none! unless bind.boundable? + + if bind.nil? + attr.eq(bind) + elsif options[:case_sensitive] + klass.connection.case_sensitive_comparison(attr, bind) + else + # will use SQL LOWER function before comparison, unless it detects a case insensitive collation + klass.connection.case_insensitive_comparison(attr, bind) + end end - attribute_name = attribute.to_s - value = klass.predicate_builder.build_bind_attribute(attribute_name, value) - - table = klass.arel_table - column = klass.columns_hash[attribute_name] - - comparison = if !options[:case_sensitive] - # will use SQL LOWER function before comparison, unless it detects a case insensitive collation - klass.connection.case_insensitive_comparison(table, attribute, column, value) - else - klass.connection.case_sensitive_comparison(table, attribute, column, value) - end - klass.unscoped.where!(comparison) + relation.where!(comparison) end def scope_relation(record, relation) diff --git a/activerecord/test/cases/adapters/postgresql/case_insensitive_test.rb b/activerecord/test/cases/adapters/postgresql/case_insensitive_test.rb index 305e033642..79e9efcf06 100644 --- a/activerecord/test/cases/adapters/postgresql/case_insensitive_test.rb +++ b/activerecord/test/cases/adapters/postgresql/case_insensitive_test.rb @@ -7,22 +7,21 @@ class PostgresqlCaseInsensitiveTest < ActiveRecord::PostgreSQLTestCase def test_case_insensitiveness connection = ActiveRecord::Base.connection - table = Default.arel_table - column = Default.columns_hash["char1"] - comparison = connection.case_insensitive_comparison table, :char1, column, nil + attr = Default.arel_attribute(:char1) + comparison = connection.case_insensitive_comparison(attr, nil) assert_match(/lower/i, comparison.to_sql) - column = Default.columns_hash["char2"] - comparison = connection.case_insensitive_comparison table, :char2, column, nil + attr = Default.arel_attribute(:char2) + comparison = connection.case_insensitive_comparison(attr, nil) assert_match(/lower/i, comparison.to_sql) - column = Default.columns_hash["char3"] - comparison = connection.case_insensitive_comparison table, :char3, column, nil + attr = Default.arel_attribute(:char3) + comparison = connection.case_insensitive_comparison(attr, nil) assert_match(/lower/i, comparison.to_sql) - column = Default.columns_hash["multiline_default"] - comparison = connection.case_insensitive_comparison table, :multiline_default, column, nil + attr = Default.arel_attribute(:multiline_default) + comparison = connection.case_insensitive_comparison(attr, nil) assert_match(/lower/i, comparison.to_sql) end end diff --git a/activerecord/test/cases/serialized_attribute_test.rb b/activerecord/test/cases/serialized_attribute_test.rb index f6cd4f85ee..fa136fe8da 100644 --- a/activerecord/test/cases/serialized_attribute_test.rb +++ b/activerecord/test/cases/serialized_attribute_test.rb @@ -22,7 +22,7 @@ class SerializedAttributeTest < ActiveRecord::TestCase end def test_serialize_does_not_eagerly_load_columns - Topic.reset_column_information + reset_column_information_of(Topic) assert_no_queries do Topic.serialize(:content) end @@ -377,7 +377,8 @@ class SerializedAttributeTest < ActiveRecord::TestCase topic.update group: "1" model.serialize :group, JSON - model.reset_column_information + + reset_column_information_of(model) # This isn't strictly necessary for the test, but a little bit of # knowledge of internals allows us to make failures far more likely. @@ -397,4 +398,12 @@ class SerializedAttributeTest < ActiveRecord::TestCase # raw string ("1"), or raise an exception. assert_equal [1] * threads.size, threads.map(&:value) end + + private + + def reset_column_information_of(topic_class) + topic_class.reset_column_information + # reset original topic to undefine attribute methods + ::Topic.reset_column_information + end end diff --git a/activestorage/README.md b/activestorage/README.md index bd31f0ea58..4a683dd8cd 100644 --- a/activestorage/README.md +++ b/activestorage/README.md @@ -118,7 +118,7 @@ Active Storage, with its included JavaScript library, supports uploading directl ``` Using the npm package: ```js - import * as ActiveStorage from "activestorage" + import * as ActiveStorage from "@rails/activestorage" ActiveStorage.start() ``` 2. Annotate file inputs with the direct upload URL. diff --git a/activestorage/package.json b/activestorage/package.json index 00876985cf..37706efe37 100644 --- a/activestorage/package.json +++ b/activestorage/package.json @@ -1,5 +1,5 @@ { - "name": "activestorage", + "name": "@rails/activestorage", "version": "6.0.0-alpha", "description": "Attach cloud and local files in Rails applications", "main": "app/assets/javascripts/activestorage.js", diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 360cef2b41..d4eaee9f6d 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,7 @@ +* Fix `String#safe_constantize` throwing a `LoadError` for incorrectly cased constant references. + + *Keenan Brock* + * Preserve key order passed to `ActiveSupport::CacheStore#fetch_multi`. `fetch_multi(*names)` now returns its results in the same order as the `*names` requested, rather than returning cache hits followed by cache misses. diff --git a/activesupport/lib/active_support/duration.rb b/activesupport/lib/active_support/duration.rb index 314c926ac0..97b4634d7b 100644 --- a/activesupport/lib/active_support/duration.rb +++ b/activesupport/lib/active_support/duration.rb @@ -214,8 +214,11 @@ module ActiveSupport end def coerce(other) #:nodoc: - if Scalar === other + case other + when Scalar [other, self] + when Duration + [Scalar.new(other.value), self] else [Scalar.new(other), self] end diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb index 1af9833d46..ee193add6f 100644 --- a/activesupport/lib/active_support/inflector/methods.rb +++ b/activesupport/lib/active_support/inflector/methods.rb @@ -328,6 +328,8 @@ module ActiveSupport e.name.to_s == camel_cased_word.to_s) rescue ArgumentError => e raise unless /not missing constant #{const_regexp(camel_cased_word)}!$/.match?(e.message) + rescue LoadError => e + raise unless /Unable to autoload constant #{const_regexp(camel_cased_word)}/.match?(e.message) end # Returns the suffix that should be added to a number to denote the position diff --git a/activesupport/test/autoloading_fixtures/raises_load_error.rb b/activesupport/test/autoloading_fixtures/raises_load_error.rb new file mode 100644 index 0000000000..f97be29b71 --- /dev/null +++ b/activesupport/test/autoloading_fixtures/raises_load_error.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true + +# raises a load error typical of the dynamic code that manually raises load errors +raise LoadError, "required gem not present kind of error" diff --git a/activesupport/test/constantize_test_cases.rb b/activesupport/test/constantize_test_cases.rb index 2c6145940b..cdb8441b81 100644 --- a/activesupport/test/constantize_test_cases.rb +++ b/activesupport/test/constantize_test_cases.rb @@ -112,6 +112,16 @@ module ConstantizeTestCases assert_nil yield("A::Object::B") assert_nil yield("A::Object::Object::Object::B") + with_autoloading_fixtures do + assert_nil yield("Em") + end + + assert_raises(LoadError) do + with_autoloading_fixtures do + yield("RaisesLoadError") + end + end + assert_raises(NameError) do with_autoloading_fixtures do yield("RaisesNameError") diff --git a/guides/source/action_cable_overview.md b/guides/source/action_cable_overview.md index 7809607574..77a1b73bae 100644 --- a/guides/source/action_cable_overview.md +++ b/guides/source/action_cable_overview.md @@ -151,7 +151,7 @@ established using the following JavaScript, which is generated by default by Rai // Action Cable provides the framework to deal with WebSockets in Rails. // You can generate new channels where WebSocket features live using the `rails generate channel` command. -import ActionCable from "actioncable" +import ActionCable from "@rails/actioncable" export default ActionCable.createConsumer() ``` diff --git a/guides/source/action_mailbox_basics.md b/guides/source/action_mailbox_basics.md index eb8a14b4d2..c5ec921ad5 100644 --- a/guides/source/action_mailbox_basics.md +++ b/guides/source/action_mailbox_basics.md @@ -20,8 +20,8 @@ Introduction Action Mailbox routes incoming emails to controller-like mailboxes for processing in Rails. It ships with ingresses for Amazon SES, Mailgun, Mandrill, -and SendGrid. You can also handle inbound mails directly via the built-in -Postfix ingress. +Postmark, and SendGrid. You can also handle inbound mails directly via the +built-in Postfix ingress. The inbound emails are turned into `InboundEmail` records using Active Record and feature lifecycle tracking, storage of the original email on cloud storage @@ -155,6 +155,42 @@ would look like this: $ URL=https://example.com/rails/action_mailbox/postfix/inbound_emails INGRESS_PASSWORD=... rails action_mailbox:ingress:postfix ``` +### Postmark + +Tell Action Mailbox to accept emails from Postmark: + +```ruby +# config/environments/production.rb +config.action_mailbox.ingress = :postmark +``` + +Generate a strong password that Action Mailbox can use to authenticate +requests to the Postmark ingress. + +Use `rails credentials:edit` to add the password to your application's +encrypted credentials under `action_mailbox.ingress_password`, +where Action Mailbox will automatically find it: + +```yaml +action_mailbox: + ingress_password: ... +``` + +Alternatively, provide the password in the `RAILS_INBOUND_EMAIL_PASSWORD` +environment variable. + +[Configure Postmark inbound webhook](https://postmarkapp.com/manual#configure-your-inbound-webhook-url) +to forward inbound emails to `/rails/action_mailbox/postmark/inbound_emails` with the username `actionmailbox` +and the password you previously generated. If your application lived at `https://example.com`, you would +configure Postmark with the following fully-qualified URL: + +``` +https://actionmailbox:PASSWORD@example.com/rails/action_mailbox/postmark/inbound_emails +``` + +NOTE: When configuring your Postmark inbound webhook, be sure to check the box labeled **"Include raw email content in JSON payload"**. +Action Mailbox needs the raw email content to work. + ### SendGrid Tell Action Mailbox to accept emails from SendGrid: diff --git a/guides/source/active_record_basics.md b/guides/source/active_record_basics.md index a67e2924d7..b0d4bbd2c0 100644 --- a/guides/source/active_record_basics.md +++ b/guides/source/active_record_basics.md @@ -105,9 +105,9 @@ depending on the purpose of these columns. fields that Active Record will look for when you create associations between your models. * **Primary keys** - By default, Active Record will use an integer column named - `id` as the table's primary key. When using [Active Record - Migrations](active_record_migrations.html) to create your tables, this column will be - automatically created. + `id` as the table's primary key (`bigint` for Postgres and MYSQL, `integer` + for SQLite). When using [Active Record Migrations](active_record_migrations.html) + to create your tables, this column will be automatically created. There are also some optional column names that will add additional features to Active Record instances: diff --git a/guides/source/active_storage_overview.md b/guides/source/active_storage_overview.md index 51f50e8931..6d07d34dd7 100644 --- a/guides/source/active_storage_overview.md +++ b/guides/source/active_storage_overview.md @@ -489,7 +489,7 @@ directly from the client to the cloud. Using the npm package: ```js - import * as ActiveStorage from "activestorage" + import * as ActiveStorage from "@rails/activestorage" ActiveStorage.start() ``` @@ -616,7 +616,7 @@ of choice, instantiate a DirectUpload and call its create method. Create takes a callback to invoke when the upload completes. ```js -import { DirectUpload } from "activestorage" +import { DirectUpload } from "@rails/activestorage" const input = document.querySelector('input[type=file]') @@ -664,7 +664,7 @@ will call the object's `directUploadWillStoreFileWithXHR` method. You can then bind your own progress handler on the XHR. ```js -import { DirectUpload } from "activestorage" +import { DirectUpload } from "@rails/activestorage" class Uploader { constructor(file, url) { diff --git a/guides/source/configuring.md b/guides/source/configuring.md index 3a7baf84a9..32682fb91f 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -721,6 +721,8 @@ There are a number of settings available on `config.action_mailer`: * `config.action_mailer.perform_caching` specifies whether the mailer templates should perform fragment caching or not. By default this is `false` in all environments. +* `config.action_mailer.delivery_job` specifies delivery job for mail. Defaults to `ActionMailer::DeliveryJob`. + ### Configuring Active Support @@ -905,6 +907,7 @@ text/javascript image/svg+xml application/postscript application/x-shockwave-fla - `config.action_view.default_enforce_utf8`: `false` - `config.action_dispatch.use_cookies_with_metadata`: `true` +- `config.action_mailer.delivery_job`: `"ActionMailer::MailDeliveryJob"` - `config.active_job.return_false_on_aborted_enqueue`: `true` - `config.active_storage.queues.analysis`: `:active_storage_analysis` - `config.active_storage.queues.purge`: `:active_storage_purge` diff --git a/guides/source/i18n.md b/guides/source/i18n.md index 08cad375ef..d146685675 100644 --- a/guides/source/i18n.md +++ b/guides/source/i18n.md @@ -139,10 +139,12 @@ Note that appending directly to `I18n.load_paths` instead of to the application' ### Managing the Locale across Requests -The default locale is used for all translations unless `I18n.locale` is explicitly set. - A localized application will likely need to provide support for multiple locales. To accomplish this, the locale should be set at the beginning of each request so that all strings are translated using the desired locale during the lifetime of that request. +The default locale is used for all translations unless `I18n.locale=` or `I18n.with_locale` is used. + +`I18n.locale` can leak into subsequent requests served by the same thread/process if it is not consistently set in every controller. For example executing `I18n.locale = :es` in one POST requests will have effects for all later requests to controllers that don't set the locale, but only in that particular thread/process. For that reason, instead of `I18n.locale =` you can use `I18n.with_locale` which does not have this leak issue. + The locale can be set in an `around_action` in the `ApplicationController`: ```ruby diff --git a/guides/source/routing.md b/guides/source/routing.md index 0a0f1b6754..a33ac6a589 100644 --- a/guides/source/routing.md +++ b/guides/source/routing.md @@ -519,7 +519,7 @@ resources :photos do end ``` -You can leave out the `:on` option, this will create the same member route except that the resource id value will be available in `params[:photo_id]` instead of `params[:id]`. +You can leave out the `:on` option, this will create the same member route except that the resource id value will be available in `params[:photo_id]` instead of `params[:id]`. Route helpers will also be renamed from `preview_photo_url` and `preview_photo_path` to `photo_preview_url` and `photo_preview_path`. #### Adding Collection Routes diff --git a/package.json b/package.json index 88029de141..43055fa6bc 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "private": true, "workspaces": [ "actioncable", + "actiontext", "activestorage", "actionview", "tmp/templates/app_template", diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index 7dcdad2ac9..3595f60bf8 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -130,6 +130,10 @@ module Rails action_dispatch.use_cookies_with_metadata = true end + if respond_to?(:action_mailer) + action_mailer.delivery_job = "ActionMailer::MailDeliveryJob" + end + if respond_to?(:active_job) active_job.return_false_on_aborted_enqueue = true end diff --git a/railties/lib/rails/generators/rails/app/templates/app/javascript/channels/consumer.js b/railties/lib/rails/generators/rails/app/templates/app/javascript/channels/consumer.js index 76ca3d0f2f..eec7e54b8a 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/javascript/channels/consumer.js +++ b/railties/lib/rails/generators/rails/app/templates/app/javascript/channels/consumer.js @@ -1,6 +1,6 @@ // Action Cable provides the framework to deal with WebSockets in Rails. // You can generate new channels where WebSocket features live using the `rails generate channel` command. -import ActionCable from "actioncable" +import ActionCable from "@rails/actioncable" export default ActionCable.createConsumer() diff --git a/railties/lib/rails/generators/rails/app/templates/app/javascript/packs/application.js.tt b/railties/lib/rails/generators/rails/app/templates/app/javascript/packs/application.js.tt index 4d7a145cd6..de91713546 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/javascript/packs/application.js.tt +++ b/railties/lib/rails/generators/rails/app/templates/app/javascript/packs/application.js.tt @@ -3,7 +3,7 @@ // a relevant structure within app/javascript and only use these pack files to reference // that code so it'll be compiled. -import Rails from "rails-ujs" +import Rails from "@rails/ujs" Rails.start() <%- unless options[:skip_turbolinks] -%> @@ -12,7 +12,7 @@ Turbolinks.start() <%- end -%> <%- unless skip_active_storage? -%> -import * as ActiveStorage from "activestorage" +import * as ActiveStorage from "@rails/activestorage" ActiveStorage.start() <%- end -%> <%- unless options[:skip_action_cable] -%> diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/frontbase.yml.tt b/railties/lib/rails/generators/rails/app/templates/config/databases/frontbase.yml.tt index 33f422c622..6ab4a26084 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/databases/frontbase.yml.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/databases/frontbase.yml.tt @@ -24,7 +24,7 @@ test: <<: *default database: <%= app_name %>_test -# As with config/secrets.yml, you never want to store sensitive information, +# As with config/credentials.yml, you never want to store sensitive information, # like your database password, in your source code. If your source code is # ever seen by anyone, they now have access to your database. # diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml.tt b/railties/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml.tt index 681c765e93..e422aa31fc 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/databases/ibm_db.yml.tt @@ -60,7 +60,7 @@ test: <<: *default database: <%= app_name[0,4] %>_tst -# As with config/secrets.yml, you never want to store sensitive information, +# As with config/credentials.yml, you never want to store sensitive information, # like your database password, in your source code. If your source code is # ever seen by anyone, they now have access to your database. # diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt index af69f12059..678455c622 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbc.yml.tt @@ -54,7 +54,7 @@ test: <<: *default url: jdbc:db://localhost/<%= app_name %>_test -# As with config/secrets.yml, you never want to store sensitive information, +# As with config/credentials.yml, you never want to store sensitive information, # like your database password, in your source code. If your source code is # ever seen by anyone, they now have access to your database. # diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt index f39593372c..b5a0efef47 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcmysql.yml.tt @@ -27,7 +27,7 @@ test: <<: *default database: <%= app_name %>_test -# As with config/secrets.yml, you never want to store sensitive information, +# As with config/credentials.yml, you never want to store sensitive information, # like your database password, in your source code. If your source code is # ever seen by anyone, they now have access to your database. # diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt index 2383fe97d3..009a81a6b8 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/databases/jdbcpostgresql.yml.tt @@ -43,7 +43,7 @@ test: <<: *default database: <%= app_name %>_test -# As with config/secrets.yml, you never want to store sensitive information, +# As with config/credentials.yml, you never want to store sensitive information, # like your database password, in your source code. If your source code is # ever seen by anyone, they now have access to your database. # diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt b/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt index b6c2e7448a..386eb511e5 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/databases/mysql.yml.tt @@ -32,7 +32,7 @@ test: <<: *default database: <%= app_name %>_test -# As with config/secrets.yml, you never want to store sensitive information, +# As with config/credentials.yml, you never want to store sensitive information, # like your database password, in your source code. If your source code is # ever seen by anyone, they now have access to your database. # diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt b/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt index 8d9d33ba6c..f7b6dfafab 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/databases/oracle.yml.tt @@ -33,7 +33,7 @@ test: <<: *default database: <%= app_name %>_test -# As with config/secrets.yml, you never want to store sensitive information, +# As with config/credentials.yml, you never want to store sensitive information, # like your database password, in your source code. If your source code is # ever seen by anyone, they now have access to your database. # diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt b/railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt index 2f51030756..44dafbd0c0 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml.tt @@ -59,7 +59,7 @@ test: <<: *default database: <%= app_name %>_test -# As with config/secrets.yml, you never want to store sensitive information, +# As with config/credentials.yml, you never want to store sensitive information, # like your database password, in your source code. If your source code is # ever seen by anyone, they now have access to your database. # diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt b/railties/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt index 0246fb0d02..27e8f2f35d 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml.tt @@ -26,7 +26,7 @@ test: <<: *default database: <%= app_name %>_test -# As with config/secrets.yml, you never want to store sensitive information, +# As with config/credentials.yml, you never want to store sensitive information, # like your database password, in your source code. If your source code is # ever seen by anyone, they now have access to your database. # diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_6_0.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_6_0.rb.tt index 9914b2cf2a..d25552e923 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_6_0.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults_6_0.rb.tt @@ -22,3 +22,12 @@ # Send Active Storage analysis and purge jobs to dedicated queues. # Rails.application.config.active_storage.queues.analysis = :active_storage_analysis # Rails.application.config.active_storage.queues.purge = :active_storage_purge + +# Use ActionMailer::MailDeliveryJob for sending parameterized and normal mail. +# +# The default delivery jobs (ActionMailer::Parameterized::DeliveryJob, ActionMailer::DeliveryJob), +# will be removed in Rails 6.1. This setting is not backwards compatible with earlier Rails versions. +# If you send mail in the background, job workers need to have a copy of +# MailDeliveryJob to ensure all delivery jobs are processed properly. +# Make sure your entire app is migrated and stable on 6.0 before using this setting. +# Rails.application.config.action_mailer.delivery_job = "ActionMailer::MailDeliveryJob" diff --git a/railties/lib/rails/generators/rails/app/templates/package.json.tt b/railties/lib/rails/generators/rails/app/templates/package.json.tt index 7174116989..07207e1747 100644 --- a/railties/lib/rails/generators/rails/app/templates/package.json.tt +++ b/railties/lib/rails/generators/rails/app/templates/package.json.tt @@ -2,10 +2,10 @@ "name": "<%= app_name %>", "private": true, "dependencies": { - "rails-ujs": ">=5.2.1"<% unless options[:skip_turbolinks] %>, - "turbolinks": "5.1.1"<% end -%><% unless skip_active_storage? %>, - "activestorage": ">=5.2.1"<% end -%><% unless options[:skip_action_cable] %>, - "actioncable": ">=5.2.1"<% end %> + "@rails/ujs": "^6.0.0-alpha"<% unless options[:skip_turbolinks] %>, + "turbolinks": "^5.2.0"<% end -%><% unless skip_active_storage? %>, + "@rails/activestorage": "^6.0.0-alpha"<% end -%><% unless options[:skip_action_cable] %>, + "@rails/actioncable": "^6.0.0-alpha"<% end %> }, "version": "0.1.0" } diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index 149f0e5af1..f2d64ce80b 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -2325,6 +2325,33 @@ module ApplicationTests assert_equal :another_queue, ActionMailbox.queues[:routing] end + test "ActionMailer::Base.delivery_job is ActionMailer::MailDeliveryJob by default" do + app "development" + + assert_equal ActionMailer::MailDeliveryJob, ActionMailer::Base.delivery_job + end + + test "ActionMailer::Base.delivery_job is ActionMailer::DeliveryJob in the 5.x defaults" do + remove_from_config '.*config\.load_defaults.*\n' + add_to_config 'config.load_defaults "5.2"' + + app "development" + + assert_equal ActionMailer::DeliveryJob, ActionMailer::Base.delivery_job + end + + test "ActionMailer::Base.delivery_job can be configured in the new framework defaults" do + remove_from_config '.*config\.load_defaults.*\n' + + app_file "config/initializers/new_framework_defaults_6_0.rb", <<-RUBY + Rails.application.config.action_mailer.delivery_job = "ActionMailer::MailDeliveryJob" + RUBY + + app "development" + + assert_equal ActionMailer::MailDeliveryJob, ActionMailer::Base.delivery_job + end + test "ActiveRecord::Base.filter_attributes should equal to filter_parameters" do app_file "config/initializers/filter_parameters_logging.rb", <<-RUBY Rails.application.config.filter_parameters += [ :password, :credit_card_number ] diff --git a/railties/test/application/rake/routes_test.rb b/railties/test/application/rake/routes_test.rb index 933c735078..bbcda7c258 100644 --- a/railties/test/application/rake/routes_test.rb +++ b/railties/test/application/rake/routes_test.rb @@ -23,6 +23,7 @@ module ApplicationTests rails_amazon_inbound_emails POST /rails/action_mailbox/amazon/inbound_emails(.:format) action_mailbox/ingresses/amazon/inbound_emails#create rails_mandrill_inbound_emails POST /rails/action_mailbox/mandrill/inbound_emails(.:format) action_mailbox/ingresses/mandrill/inbound_emails#create rails_postfix_inbound_emails POST /rails/action_mailbox/postfix/inbound_emails(.:format) action_mailbox/ingresses/postfix/inbound_emails#create + rails_postmark_inbound_emails POST /rails/action_mailbox/postmark/inbound_emails(.:format) action_mailbox/ingresses/postmark/inbound_emails#create rails_sendgrid_inbound_emails POST /rails/action_mailbox/sendgrid/inbound_emails(.:format) action_mailbox/ingresses/sendgrid/inbound_emails#create rails_mailgun_inbound_emails POST /rails/action_mailbox/mailgun/inbound_emails/mime(.:format) action_mailbox/ingresses/mailgun/inbound_emails#create rails_conductor_inbound_emails GET /rails/conductor/action_mailbox/inbound_emails(.:format) rails/conductor/action_mailbox/inbound_emails#index diff --git a/railties/test/commands/routes_test.rb b/railties/test/commands/routes_test.rb index a43a6d32b9..f77214ac2a 100644 --- a/railties/test/commands/routes_test.rb +++ b/railties/test/commands/routes_test.rb @@ -18,15 +18,16 @@ class Rails::Command::RoutesTest < ActiveSupport::TestCase RUBY assert_equal <<~OUTPUT, run_routes_command([ "-c", "PostController" ]) - Prefix Verb URI Pattern Controller#Action - new_post GET /post/new(.:format) posts#new - edit_post GET /post/edit(.:format) posts#edit - post GET /post(.:format) posts#show - PATCH /post(.:format) posts#update - PUT /post(.:format) posts#update - DELETE /post(.:format) posts#destroy - POST /post(.:format) posts#create - rails_postfix_inbound_emails POST /rails/action_mailbox/postfix/inbound_emails(.:format) action_mailbox/ingresses/postfix/inbound_emails#create + Prefix Verb URI Pattern Controller#Action + new_post GET /post/new(.:format) posts#new + edit_post GET /post/edit(.:format) posts#edit + post GET /post(.:format) posts#show + PATCH /post(.:format) posts#update + PUT /post(.:format) posts#update + DELETE /post(.:format) posts#destroy + POST /post(.:format) posts#create + rails_postfix_inbound_emails POST /rails/action_mailbox/postfix/inbound_emails(.:format) action_mailbox/ingresses/postfix/inbound_emails#create + rails_postmark_inbound_emails POST /rails/action_mailbox/postmark/inbound_emails(.:format) action_mailbox/ingresses/postmark/inbound_emails#create OUTPUT assert_equal <<~OUTPUT, run_routes_command([ "-c", "UserPermissionController" ]) @@ -65,6 +66,7 @@ class Rails::Command::RoutesTest < ActiveSupport::TestCase rails_amazon_inbound_emails POST /rails/action_mailbox/amazon/inbound_emails(.:format) action_mailbox/ingresses/amazon/inbound_emails#create rails_mandrill_inbound_emails POST /rails/action_mailbox/mandrill/inbound_emails(.:format) action_mailbox/ingresses/mandrill/inbound_emails#create rails_postfix_inbound_emails POST /rails/action_mailbox/postfix/inbound_emails(.:format) action_mailbox/ingresses/postfix/inbound_emails#create + rails_postmark_inbound_emails POST /rails/action_mailbox/postmark/inbound_emails(.:format) action_mailbox/ingresses/postmark/inbound_emails#create rails_sendgrid_inbound_emails POST /rails/action_mailbox/sendgrid/inbound_emails(.:format) action_mailbox/ingresses/sendgrid/inbound_emails#create rails_mailgun_inbound_emails POST /rails/action_mailbox/mailgun/inbound_emails/mime(.:format) action_mailbox/ingresses/mailgun/inbound_emails#create POST /rails/conductor/action_mailbox/inbound_emails(.:format) rails/conductor/action_mailbox/inbound_emails#create @@ -131,15 +133,16 @@ class Rails::Command::RoutesTest < ActiveSupport::TestCase OUTPUT assert_equal <<~OUTPUT, run_routes_command([ "-c", "PostController" ]) - Prefix Verb URI Pattern Controller#Action - new_admin_post GET /admin/post/new(.:format) admin/posts#new - edit_admin_post GET /admin/post/edit(.:format) admin/posts#edit - admin_post GET /admin/post(.:format) admin/posts#show - PATCH /admin/post(.:format) admin/posts#update - PUT /admin/post(.:format) admin/posts#update - DELETE /admin/post(.:format) admin/posts#destroy - POST /admin/post(.:format) admin/posts#create - rails_postfix_inbound_emails POST /rails/action_mailbox/postfix/inbound_emails(.:format) action_mailbox/ingresses/postfix/inbound_emails#create + Prefix Verb URI Pattern Controller#Action + new_admin_post GET /admin/post/new(.:format) admin/posts#new + edit_admin_post GET /admin/post/edit(.:format) admin/posts#edit + admin_post GET /admin/post(.:format) admin/posts#show + PATCH /admin/post(.:format) admin/posts#update + PUT /admin/post(.:format) admin/posts#update + DELETE /admin/post(.:format) admin/posts#destroy + POST /admin/post(.:format) admin/posts#create + rails_postfix_inbound_emails POST /rails/action_mailbox/postfix/inbound_emails(.:format) action_mailbox/ingresses/postfix/inbound_emails#create + rails_postmark_inbound_emails POST /rails/action_mailbox/postmark/inbound_emails(.:format) action_mailbox/ingresses/postmark/inbound_emails#create OUTPUT expected_permission_output = <<~OUTPUT @@ -168,6 +171,7 @@ class Rails::Command::RoutesTest < ActiveSupport::TestCase rails_amazon_inbound_emails POST /rails/action_mailbox/amazon/inbound_emails(.:format) action_mailbox/ingresses/amazon/inbound_emails#create rails_mandrill_inbound_emails POST /rails/action_mailbox/mandrill/inbound_emails(.:format) action_mailbox/ingresses/mandrill/inbound_emails#create rails_postfix_inbound_emails POST /rails/action_mailbox/postfix/inbound_emails(.:format) action_mailbox/ingresses/postfix/inbound_emails#create + rails_postmark_inbound_emails POST /rails/action_mailbox/postmark/inbound_emails(.:format) action_mailbox/ingresses/postmark/inbound_emails#create rails_sendgrid_inbound_emails POST /rails/action_mailbox/sendgrid/inbound_emails(.:format) action_mailbox/ingresses/sendgrid/inbound_emails#create rails_mailgun_inbound_emails POST /rails/action_mailbox/mailgun/inbound_emails/mime(.:format) action_mailbox/ingresses/mailgun/inbound_emails#create rails_conductor_inbound_emails GET /rails/conductor/action_mailbox/inbound_emails(.:format) rails/conductor/action_mailbox/inbound_emails#index @@ -220,81 +224,86 @@ class Rails::Command::RoutesTest < ActiveSupport::TestCase URI | /rails/action_mailbox/postfix/inbound_emails(.:format) Controller#Action | action_mailbox/ingresses/postfix/inbound_emails#create --[ Route 5 ]-------------- + Prefix | rails_postmark_inbound_emails + Verb | POST + URI | /rails/action_mailbox/postmark/inbound_emails(.:format) + Controller#Action | action_mailbox/ingresses/postmark/inbound_emails#create + --[ Route 6 ]-------------- Prefix | rails_sendgrid_inbound_emails Verb | POST URI | /rails/action_mailbox/sendgrid/inbound_emails(.:format) Controller#Action | action_mailbox/ingresses/sendgrid/inbound_emails#create - --[ Route 6 ]-------------- + --[ Route 7 ]-------------- Prefix | rails_mailgun_inbound_emails Verb | POST URI | /rails/action_mailbox/mailgun/inbound_emails/mime(.:format) Controller#Action | action_mailbox/ingresses/mailgun/inbound_emails#create - --[ Route 7 ]-------------- + --[ Route 8 ]-------------- Prefix | rails_conductor_inbound_emails Verb | GET URI | /rails/conductor/action_mailbox/inbound_emails(.:format) Controller#Action | rails/conductor/action_mailbox/inbound_emails#index - --[ Route 8 ]-------------- + --[ Route 9 ]-------------- Prefix | Verb | POST URI | /rails/conductor/action_mailbox/inbound_emails(.:format) Controller#Action | rails/conductor/action_mailbox/inbound_emails#create - --[ Route 9 ]-------------- + --[ Route 10 ]------------- Prefix | new_rails_conductor_inbound_email Verb | GET URI | /rails/conductor/action_mailbox/inbound_emails/new(.:format) Controller#Action | rails/conductor/action_mailbox/inbound_emails#new - --[ Route 10 ]------------- + --[ Route 11 ]------------- Prefix | edit_rails_conductor_inbound_email Verb | GET URI | /rails/conductor/action_mailbox/inbound_emails/:id/edit(.:format) Controller#Action | rails/conductor/action_mailbox/inbound_emails#edit - --[ Route 11 ]------------- + --[ Route 12 ]------------- Prefix | rails_conductor_inbound_email Verb | GET URI | /rails/conductor/action_mailbox/inbound_emails/:id(.:format) Controller#Action | rails/conductor/action_mailbox/inbound_emails#show - --[ Route 12 ]------------- + --[ Route 13 ]------------- Prefix | Verb | PATCH URI | /rails/conductor/action_mailbox/inbound_emails/:id(.:format) Controller#Action | rails/conductor/action_mailbox/inbound_emails#update - --[ Route 13 ]------------- + --[ Route 14 ]------------- Prefix | Verb | PUT URI | /rails/conductor/action_mailbox/inbound_emails/:id(.:format) Controller#Action | rails/conductor/action_mailbox/inbound_emails#update - --[ Route 14 ]------------- + --[ Route 15 ]------------- Prefix | Verb | DELETE URI | /rails/conductor/action_mailbox/inbound_emails/:id(.:format) Controller#Action | rails/conductor/action_mailbox/inbound_emails#destroy - --[ Route 15 ]------------- + --[ Route 16 ]------------- Prefix | rails_conductor_inbound_email_reroute Verb | POST URI | /rails/conductor/action_mailbox/:inbound_email_id/reroute(.:format) Controller#Action | rails/conductor/action_mailbox/reroutes#create - --[ Route 16 ]------------- + --[ Route 17 ]------------- Prefix | rails_service_blob Verb | GET URI | /rails/active_storage/blobs/:signed_id/*filename(.:format) Controller#Action | active_storage/blobs#show - --[ Route 17 ]------------- + --[ Route 18 ]------------- Prefix | rails_blob_representation Verb | GET URI | /rails/active_storage/representations/:signed_blob_id/:variation_key/*filename(.:format) Controller#Action | active_storage/representations#show - --[ Route 18 ]------------- + --[ Route 19 ]------------- Prefix | rails_disk_service Verb | GET URI | /rails/active_storage/disk/:encoded_key/*filename(.:format) Controller#Action | active_storage/disk#show - --[ Route 19 ]------------- + --[ Route 20 ]------------- Prefix | update_rails_disk_service Verb | PUT URI | /rails/active_storage/disk/:encoded_token(.:format) Controller#Action | active_storage/disk#update - --[ Route 20 ]------------- + --[ Route 21 ]------------- Prefix | rails_direct_uploads Verb | POST URI | /rails/active_storage/direct_uploads(.:format) diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb index 4dfcb35ad9..f673832caa 100644 --- a/railties/test/generators/shared_generator_tests.rb +++ b/railties/test/generators/shared_generator_tests.rb @@ -206,7 +206,7 @@ module SharedGeneratorTests unless generator_class.name == "Rails::Generators::PluginGenerator" assert_file "#{application_path}/app/javascript/packs/application.js" do |content| - assert_match(/^import \* as ActiveStorage from "activestorage"\nActiveStorage.start\(\)/, content) + assert_match(/^import \* as ActiveStorage from "@rails\/activestorage"\nActiveStorage.start\(\)/, content) end end @@ -267,7 +267,7 @@ module SharedGeneratorTests assert_file "#{application_path}/config/application.rb", /#\s+require\s+["']active_storage\/engine["']/ assert_file "#{application_path}/app/javascript/packs/application.js" do |content| - assert_no_match(/^import * as ActiveStorage from "activestorage"\nActiveStorage.start\(\)/, content) + assert_no_match(/^import * as ActiveStorage from "@rails\/activestorage"\nActiveStorage.start\(\)/, content) end assert_file "#{application_path}/config/environments/development.rb" do |content| @@ -5692,6 +5692,11 @@ trim-right@^1.0.1: resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= +trix@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/trix/-/trix-1.0.0.tgz#e9cc98cf6030c908f8d54e317b5b072f927b0c6b" + integrity sha512-feli9QVXe6gzZOCUfpPGpNDURW9jMciIRVQ5gkDudOctcA1oMtI5K/qEbsL2rFCoGl1rSoeRt+HPhIFGyQscKg== + tslib@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" |