Rails 类给出 NoMethodError 未定义的方法“每个”

Posted

技术标签:

【中文标题】Rails 类给出 NoMethodError 未定义的方法“每个”【英文标题】:Rails class gives NoMethodError undefined method `each' 【发布时间】:2020-10-17 04:12:25 【问题描述】:

我正在使用 redmine,并且我已经安装了一个用于管理邮件的插件。

当我尝试发送邮件时,我收到以下错误

[ActiveJob] [ActionMailer::DeliveryJob] [uuid] Error performing ActionMailer::DeliveryJob (Job ID: uuid) from Async(mailers) in 41.81ms: NoMethodError (undefined method `each' for #<User:id>):

这是给我错误的文件

模块加密邮件

  def self.included(base) # :nodoc:
    base.send(:include, InstanceMethods)
    base.class_eval 做
      别名方法 :mail_without_relocation, :mail
      别名方法 :mail, :mail_with_relocation
    结尾
  结尾

  模块实例方法

    # 这个插件要处理的动作名称
    定义动作
      [
        'attachments_add',
        'document_add',
        'issue_add',
        '问题编辑',
        'message_posted',
        'news_add',
        'news_comment_added',
        'wiki_content_added',
        'wiki_content_updated'
      ]
    结尾

    # 发送邮件方法
    def mail_with_relocation(headers=, &block)

      # 传递不变,如果动作不匹配或插件不活动
      act = Setting.plugin_openpgp['activation']
      如果返回 mail_without_relocation(headers, &block)
        act == 'none' 或不 actions.include? @_action_name 或
        (act == 'project' 而不是 project.try('module_enabled?', 'openpgp'))

      # 重新定位收件人
      收件人 = relocate_recipients(标头)
      标头 = @_message.header.to_s

      # 渲染和发送加密邮件
      重置(标题)
      m = mail_without_relocation prepare_headers(
        标头,收件人[:加密],加密 = true,签名 = true
      ) 做|格式|
        格式.文本
      结尾
      m.deliver

      # 渲染和传递过滤后的邮件
      重置(标题)
      tpl = @_action_name + '.filtered'
      m = mail_without_relocation prepare_headers(
        标头,收件人[:过滤],加密 = 假,签名 = 真
      ) 做|格式|
        format.text  渲染 tpl 
        format.html  渲染 tpl  除非 Setting.plain_text_mail?
      结尾
      m.deliver

      # 渲染未更改的邮件(通过调用方法传递)
      重置(标题)
      m = mail_without_relocation prepare_headers(
        标头,收件人[:未更改],加密 = 假,签名 = 假
      ) 做|格式|
        格式.文本
        format.html 除非 Setting.plain_text_mail?
      结尾

      米
      结尾

    # 获取依赖于动作和对象的项目
    定义项目

      案例@_action_name
        当'attachments_add'
          @attachments.first.project
        当'document_added'
          @document.project
        当'issue_add','issue_edit'
          @issue.project
        当'message_posted'
          @message.project
        当'news_add','news_comment_added'
          @news.project
        当'wiki_content_add','wiki_content_updated'
          @wiki_content.project
        别的
          零
      结尾

    结尾

    # 重新定位消息的接收者 (to, cc)
    def relocate_recipients(标题)

      # 要返回的哈希值
      收件人 = 
        :encrypted => :to => [], :cc => [],
        :blocked => :to => [], :cc => [],
        :filtered => :to => [], :cc => [],
        :unchanged => :to => [], :cc => [],
        :lost => :to => [], :cc => []
      

      # 重新安置收件人
      [:to, :cc].each 做 |field|
        headers[field].each 做 |user|

          # 加密
          除非 Pgpkey.find_by(user_id: user.id).nil?
            recipients[:encrypted][field].push user and next
          结尾

          # 未加密
          案例 Setting.plugin_openpgp['unencrypted_mails']
            当“阻塞”时
              收件人[:blocked][field].push 用户
            当“过滤”时
              收件人[:filtered][field].push 用户
            当'不变'
              收件人[:unchanged][field].push 用户
            别的
              收件人[:丢失][字段].push 用户
          结尾

        除非 headers[field].blank?
      结尾

      收件人

    结尾

    # 重置邮件以多次发送邮件
    def 重置(标题)

      @_mail_was_call = 假
      @_message = Mail.new
      @_message.header 标头

    结尾

    # 为不同的配置准备头文件
    def prepare_headers(标头、收件人、加密、签名)

      h = headers.deep_dup

      # 收件人的标头
      h[:to] = 收件人[:to]
      h[:cc] = 收件人[:cc]

      #gpg 的头文件
      h[:gpg] = 
        加密:假,
        标志:假
      

      # 用于加密的标头
      如果加密
        h[:gpg][:encrypt] = 真
        # 为电子邮件添加 pgp 密钥
        h[:gpg][:keys] = 
        [:to, :cc].each 做 |field|
          h[field].each 做 |user|
            user_key = Pgpkey.find_by user_id: user.id
            除非 user_key.nil?
              h[:gpg][:keys][user.mail] = user_key.fpr
            结尾
          除非 h[field].blank 否则结束?
        结尾
      结尾

      # 签名头
      如果签名
        server_key = Pgpkey.find_by(:user_id => 0)
        除非 server_key.nil?
          h[:gpg][:sign] = 真
          h[:gpg][:sign_as] = 设置['mail_from']
          h[:gpg][:password] = server_key.secret
        结尾
      结尾

      H

    结尾

  结尾
结尾

日志堆栈告诉我错误在第 109 行

# 收件人的重新定位
[:to, :cc].each 做 |field|

我不是 ruby​​ 和 rails 专家,但我看到 each 是 Ruby 数组的一种方法,而不是自定义方法,所以我不明白为什么会出现错误。

我做错了什么,我该如何解决这个错误?

【问题讨论】:

您发送的价值是多少?看起来它不是数组undefined method 'each' for #&lt;User:id&gt; 它只是一个 id 还是什么?不太确定那个值是多少。您可以使用正在发送的数据示例来编辑问题吗? 我不知道如何检索数据,因为我说过它是 redmine 的插件,我不知道如何隔离问题。我已经看到删除 base.class_eval do 开头的 alias_method 部分,错误消失了,但邮件没有发送。我想在这种情况下根本没有调用该方法,因此它应该与之相关。 【参考方案1】:

你确定问题不在这条线上吗?

h[field].each do |user|

field 会有:to:cc 所以h[field] 可能是一个用户实例。

如果您想允许h[:to]h[:cc] 成为单个用户或用户数组,则将其包装在Array() 中:

# relocation of reciepients
[:to, :cc].each do |field|
  Array(headers[field]).each do |user|
  #^^^^

我还会移动那个尾随的unless,这样就不会错过它,可能是这样的:

%i[to cc].select  |field| headers[field].present? .each do |field|
  Array(headers[filed]).each do |user|
    #...
  end
end

【讨论】:

谢谢。我不知道问题出在哪里,我不知道 ruby​​,我正在检查记录器给出错误的代码行。

以上是关于Rails 类给出 NoMethodError 未定义的方法“每个”的主要内容,如果未能解决你的问题,请参考以下文章

Rails NoMethodError:未定义的方法“紧凑”错误

Rails嵌套属性给出错误:未定义的方法`build_priority'

Ruby on Rails - 未定义的方法`split'代表nil:StocksController中的NilClass / NoMethodError #search

部署到Heroku:NoMethodError:nil:NilClass的未定义方法'+'

Rspec 测试:NoMethodError - nil.Nilclass 的未定义方法“id”

NoMethodError:未定义的方法“has_attached_file”