Db.rake 邮件插件在重建应用时失败

我开发了我的第一个插件,它通过外部 API 在注册时检查是否为一次性邮箱。

目前运行符合预期…

但现在,在重建/升级应用时,db.rake 似乎出现了某种问题:

rails aborted!
ActiveRecord::RecordInvalid: Validation failed: Email is not allowed from that email provider. Please use another email address.
(eval):39:in `block (2 levels) in run_file'
/src/lib/tasks/db.rake:222:in `block in <main>'
bin/rails:17:in `<main>'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)

可能是因为 db.rake 中的这一行想要初始化一些数据,但由于我的插件会检查无效邮箱并产生干扰,导致无法执行:

SeedFu.seed(SeedHelper.paths, SeedHelper.filter)

但在同一文件中,我发现插件可以排除某些种子数据文件的执行:

  def self.filter
    # Allows a plugin to exclude any specified seed data files from running
    DiscoursePluginRegistry.seedfu_filter.any? ?
      /^(?!.*(#{DiscoursePluginRegistry.seedfu_filter.to_a.join("|")})).*$/ : nil
  end
end

但具体该如何操作?是否有其他插件实现这一功能的示例?或者我需要采取其他措施来绕过这个问题?提前感谢任何帮助。

您收到的错误消息是否未列出导致问题的实际种子数据文件?

一旦您知道是哪个种子数据文件导致问题,就可以在插件中通过以下方式将其过滤掉:

after_initialize do
  register_seedfu_filter "00X_seed_filename"
  ...
end

太棒了。

关于报错,我目前就只有这些信息。

== 20200819021210 AddUserSelectableColumnToColorSchemes: migrating ============
-- add_column(:color_schemes, :user_selectable, :bool, {:null=>false, :default=>false})
   -> 0.0062s
== 20200819021210 AddUserSelectableColumnToColorSchemes: migrated (0.0100s) ===

== 20200819203846 AddColorSchemeIdToUserOptions: migrating ====================
-- add_column(:user_options, :color_scheme_id, :integer)
   -> 0.0035s
== 20200819203846 AddColorSchemeIdToUserOptions: migrated (0.0051s) ===========

== 20200820174703 AddPartialTargetIdIndexToReviewables: migrating =============
-- add_index(:reviewables, [:target_id], {:where=>"target_type = 'Post'", :algorithm=>:concurrently, :name=>"index_reviewables_on_target_id_where_post_type_eq_post"})
   -> 0.0079s
== 20200820174703 AddPartialTargetIdIndexToReviewables: migrated (0.0091s) ====

rails aborted!
ActiveRecord::RecordInvalid: Validation failed: Email is not allowed from that email provider. Please use another email address.
(eval):39:in `block (2 levels) in run_file'
/src/lib/tasks/db.rake:222:in `block in <main>'
bin/rails:17:in `<main>'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)

有没有可能找出/调试到底是哪个文件导致我的这个小新插件出了问题?我怀疑是任何设置用户邮箱的操作。

以下是更多调试信息:

Summary

terrapop@terrapop:/var/www/discourse$ d/rails --trace db:migrate RAILS_ENV=development
** Invoke db:migrate (first_time)
** Invoke db:load_config (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute db:load_config
** Invoke environment
** Invoke set_locale (first_time)
** Execute set_locale
** Execute db:migrate
** Invoke db:_dump (first_time)
** Execute db:_dump
** Invoke db:structure:dump (first_time)
** Invoke db:load_config
** Execute db:structure:dump
rails aborted!
ActiveRecord::RecordInvalid: Validation failed: Email is not allowed from that email provider. Please use another email address.
/usr/local/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.2/lib/active_record/validations.rb:80:in raise_validation_error' /usr/local/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.2/lib/active_record/validations.rb:53:in save!’
/usr/local/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.2/lib/active_record/transactions.rb:318:in block in save!' /usr/local/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.2/lib/active_record/transactions.rb:375:in block in with_transaction_returning_status’
/usr/local/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/abstract/database_statements.rb:278:in transaction' /usr/local/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.2/lib/active_record/transactions.rb:212:in transaction’
/usr/local/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.2/lib/active_record/transactions.rb:366:in with_transaction_returning_status' /usr/local/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.2/lib/active_record/transactions.rb:318:in save!’
/usr/local/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.2/lib/active_record/suppressor.rb:48:in save!' /usr/local/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.2/lib/active_record/persistence.rb:635:in block in update!’
/usr/local/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.2/lib/active_record/transactions.rb:375:in block in with_transaction_returning_status' /usr/local/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/abstract/database_statements.rb:278:in transaction’
/usr/local/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.2/lib/active_record/transactions.rb:212:in transaction' /usr/local/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.2/lib/active_record/transactions.rb:366:in with_transaction_returning_status’
/usr/local/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.2/lib/active_record/persistence.rb:633:in update!' (eval):39:in block (2 levels) in run_file’
/usr/local/lib/ruby/gems/2.6.0/gems/seed-fu-2.3.9/lib/seed-fu/runner.rb:46:in eval' /usr/local/lib/ruby/gems/2.6.0/gems/seed-fu-2.3.9/lib/seed-fu/runner.rb:46:in block (2 levels) in run_file’
/usr/local/lib/ruby/gems/2.6.0/gems/seed-fu-2.3.9/lib/seed-fu/runner.rb:58:in block in open' /usr/local/lib/ruby/gems/2.6.0/gems/seed-fu-2.3.9/lib/seed-fu/runner.rb:57:in open’
/usr/local/lib/ruby/gems/2.6.0/gems/seed-fu-2.3.9/lib/seed-fu/runner.rb:57:in open' /usr/local/lib/ruby/gems/2.6.0/gems/seed-fu-2.3.9/lib/seed-fu/runner.rb:36:in block in run_file’
/usr/local/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/abstract/database_statements.rb:280:in block in transaction' /usr/local/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/abstract/transaction.rb:280:in block in within_new_transaction’
/usr/local/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:26:in block (2 levels) in synchronize' /usr/local/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in handle_interrupt’
/usr/local/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25:in block in synchronize' /usr/local/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in handle_interrupt’
/usr/local/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21:in synchronize' /usr/local/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/abstract/transaction.rb:278:in within_new_transaction’
/usr/local/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.2/lib/active_record/connection_adapters/abstract/database_statements.rb:280:in transaction' /usr/local/lib/ruby/gems/2.6.0/gems/activerecord-6.0.3.2/lib/active_record/transactions.rb:212:in transaction’
/usr/local/lib/ruby/gems/2.6.0/gems/seed-fu-2.3.9/lib/seed-fu/runner.rb:35:in run_file' /usr/local/lib/ruby/gems/2.6.0/gems/seed-fu-2.3.9/lib/seed-fu/runner.rb:26:in block in run’
/usr/local/lib/ruby/gems/2.6.0/gems/seed-fu-2.3.9/lib/seed-fu/runner.rb:25:in each' /usr/local/lib/ruby/gems/2.6.0/gems/seed-fu-2.3.9/lib/seed-fu/runner.rb:25:in run’
/usr/local/lib/ruby/gems/2.6.0/gems/seed-fu-2.3.9/lib/seed-fu.rb:29:in seed' /src/lib/tasks/db.rake:222:in block in ’
/usr/local/lib/ruby/gems/2.6.0/gems/rake-13.0.1/lib/rake/task.rb:281:in block in execute' /usr/local/lib/ruby/gems/2.6.0/gems/rake-13.0.1/lib/rake/task.rb:281:in each’
/usr/local/lib/ruby/gems/2.6.0/gems/rake-13.0.1/lib/rake/task.rb:281:in execute' /usr/local/lib/ruby/gems/2.6.0/gems/rake-13.0.1/lib/rake/task.rb:219:in block in invoke_with_call_chain’
/usr/local/lib/ruby/2.6.0/monitor.rb:235:in mon_synchronize' /usr/local/lib/ruby/gems/2.6.0/gems/rake-13.0.1/lib/rake/task.rb:199:in invoke_with_call_chain’
/usr/local/lib/ruby/gems/2.6.0/gems/rake-13.0.1/lib/rake/task.rb:188:in invoke' /usr/local/lib/ruby/gems/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:160:in invoke_task’
/usr/local/lib/ruby/gems/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:116:in block (2 levels) in top_level' /usr/local/lib/ruby/gems/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:116:in each’
/usr/local/lib/ruby/gems/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:116:in block in top_level' /usr/local/lib/ruby/gems/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:125:in run_with_threads’
/usr/local/lib/ruby/gems/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:110:in top_level' /usr/local/lib/ruby/gems/2.6.0/gems/railties-6.0.3.2/lib/rails/commands/rake/rake_command.rb:23:in block in perform’
/usr/local/lib/ruby/gems/2.6.0/gems/rake-13.0.1/lib/rake/application.rb:186:in standard_exception_handling' /usr/local/lib/ruby/gems/2.6.0/gems/railties-6.0.3.2/lib/rails/commands/rake/rake_command.rb:20:in perform’
/usr/local/lib/ruby/gems/2.6.0/gems/railties-6.0.3.2/lib/rails/command.rb:48:in invoke' /usr/local/lib/ruby/gems/2.6.0/gems/railties-6.0.3.2/lib/rails/commands.rb:18:in
/usr/local/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.8/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in require' /usr/local/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.8/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in block in require_with_bootsnap_lfi’
/usr/local/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.8/lib/bootsnap/load_path_cache/loaded_features_index.rb:92:in register' /usr/local/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.8/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:22:in require_with_bootsnap_lfi’
/usr/local/lib/ruby/gems/2.6.0/gems/bootsnap-1.4.8/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:31:in require' /usr/local/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.2/lib/active_support/dependencies.rb:324:in block in require’
/usr/local/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.2/lib/active_support/dependencies.rb:291:in load_dependency' /usr/local/lib/ruby/gems/2.6.0/gems/activesupport-6.0.3.2/lib/active_support/dependencies.rb:324:in require’
bin/rails:17:in `’
Tasks: TOP => db:migrate

更新:

已找到并修复问题:

def seed_primary_email
  UserEmail.seed do |ue|
    ue.id = DiscourseNarrativeBot::BOT_USER_ID
    ue.email = "discobot_email"
    ue.primary = true
    ue.user_id = DiscourseNarrativeBot::BOT_USER_ID
  end
end

在 discourse/plugins/discourse-narrative-bot/db/fixtures/001_discobot.rb 中引发了该问题。

添加 register_seedfu_filter "001_discobot" 后问题已解决。

感谢 @blake 为我指明正确方向。现在可以正常工作了。

最后一个问题:未来如何注册多个过滤器?像这样吗?

register_seedfu_filter "001_discobot|002_xxxxxx|003_yyyy"

可能有一种方法可以在一行内完成,但要注册多个过滤器,您可以使用多行

register_seedfu_filter "001..."
register_seedfu_filter "002..."

不过,使用 seedfu_filter API 时需要极其谨慎!

我真的不建议您将其添加到您的插件中,因为如果您的插件用户尚未运行该种子文件,这可能会导致其他用户的 discobot 出现问题。

或许您可以排除 ID 小于 0 的用户,这样您的插件就不会检查系统和 discobot 的邮箱。您可以使用 .human_users 方法来实现这一点。

很有意思,我肯定会按照你的建议去查看并修改。

@blake

我现在添加了以下行:

return unless value.present?
return unless defined? record.id
return unless record.password_validation_required?

另外加上:

return unless record.should_validate_email_address?

由于 disco_bot 在 db.migrate 中创建时已经带有 id,因此现在可以正常工作了。

此外,我还必须添加 password_validation_required 验证器,否则插件在登录和更改用户头像时也会被触发。

现在,它确实仅绑定到 sign_up 表单,不再需要 seedfu 过滤器。