【问题标题】:Send email to only certain Users, Rails 5仅向某些用户发送电子邮件,Rails 5
【发布时间】:2017-09-28 21:06:04
【问题描述】:

我无法仅向布尔值设置为 true 的某些用户发送电子邮件群发邮件,而无法将电子邮件发送给布尔值设置为 false 的用户。

在我的应用中,我有粉丝通过艺术家关系关注艺术家。在我的 ArtistRelationship 模型中,我有一个布尔值,粉丝可以根据他们是否希望在艺术家发帖时发送来自艺术家的电子邮件来将其设置为真或假。

到目前为止,我有这个:

艺术家.rb

class Artist < ApplicationRecord

  def self.fan_post_email
    Artist.inlcudes(:fans).find_each do |fan|
      fan.includes(:artist_relationships).where(:post_email => true).find_each do |fan|
        FanMailer.post_email(fan).deliver_now
      end
    end
  end

end

posts_controller.rb

class Artists::PostsController < ApplicationController

  def create
    @artist = current_artist
    @post = @artist.artist_posts.build(post_params)
    if @post.save
      redirect_to artist_path(@artist)
      @artist.fan_post_email
    else
      render 'new'
      flash.now[:alert] = "You've failed!"
    end
  end

end

我无法让fan_post_email 方法工作。我不完全确定如何在 ArtistRelationship 模型中找到布尔值设置为 true 的粉丝。

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-4 ruby-on-rails-5


    【解决方案1】:

    您想向特定艺术家的粉丝发送邮件。因此,您调用

    @artist.fan_post_email
    

    也就是说,您在 Artist 类的 实例 上调用方法。实例方法未使用self.[METHOD_NAME] 定义。这样做定义了 class 方法(如果你在哪里调用,例如Artist.foo)。

    然后第一部分是删除self. 部分,第二部分是调整范围。完整的方法应该是这样的:

    def fan_post_email
      artists_relationships
        .includes(:fan)
        .where(post_email: true)
        .find_each do |relationship|
          FanMailer.post_email(relationship.fan).deliver_now
        end
      end
    end
    

    让我们来看看这个方法。

    我们需要吸引所有粉丝才能向他们发送邮件。这可以通过使用artist_relationships 关联来完成。但由于我们只想让那些粉丝检查电子邮件标志,我们通过where 声明来限制它们。

    生成的 SQL 条件将为我们提供所有此类关系。但是我们分批进行(find_each),以便不必预先将所有记录加载到内存中。

    提供给find_each 的块是通过artist_relationships 实例产生的。但是我们需要粉丝实例而不是 Artists_relationships 实例来在我们的块中发送邮件,因此调用post_email 并使用与关系关联的粉丝实例。为了避免那里出现 N+1 次查询(逐个查询每条artist_relationships 记录的粉丝记录),我们急切地在artist_relationships 上加载粉丝关联。


    与问题无关

    在用户请求的正常请求/响应周期内使用该方法可能会大大降低应用程序的速度。如果一个艺术家有很多粉丝,应用程序会在为用户呈现响应之前向每个人发送一封电子邮件。如果是当红艺人,我很容易想象这需要几分钟。

    deliver_now 对应的是deliver_later (documentation。作业就像发送电子邮件一样,可以独立于请求/响应周期进行排队和解决。这需要设置一个工作人员喜欢Sidekiqdelayed_job,但性能的提升绝对值得。

    如果设置了排队机制,将调用移至那里的fan_post_email 可能是有意义的,而且方法本身也可能需要一些时间。

    此外,以 BCC 的形式发送电子邮件可能更有意义,这样您就可以同时向多个粉丝发送一封电子邮件。

    【讨论】:

      猜你喜欢
      • 2019-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-01
      • 2013-01-31
      • 2017-08-01
      • 2011-07-05
      • 2013-12-03
      相关资源
      最近更新 更多