仅向某些用户发送电子邮件,Rails 5

时间:2017-09-28 21:06:05

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

我无法向布尔值设置为true的某些用户发送电子邮件,并且不会将电子邮件发送给将其设置为false的用户。

在我的应用程序中,我通过艺术家关系跟随艺术家。在我的ArtistRelationship模型中,我有一个布尔值,粉丝可以设置为真或假,基于他们是否需要艺术家的电子邮件爆炸,或者当艺术家发帖时。

到目前为止,我有这个:

artist.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的Fans。

1 个答案:

答案 0 :(得分:2)

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

@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的块是使用artists_relationships实例产生的。但是我们需要粉丝实例而不是artists_relationships实例来发送我们块中的邮件,从而使用与关系相关联的粉丝实例调用post_email。为了避免N + 1个查询(逐个查询每个artist_relationships记录的粉丝记录),我们急切地在artists_relationships上加载粉丝关联。

与问题无关

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

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

如果设置了排队机制,将呼叫转移到fan_post_email可能是有意义的,方法本身也可能需要一些时间。

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