我无法向布尔值设置为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。
答案 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_later
(documentation。作业,就像发送电子邮件一样,可以独立于请求/响应周期进行排队和解决。需要设置像Sidekiq或delayed_job这样的工作人员,但性能的提升绝对值得。
如果设置了排队机制,将呼叫转移到fan_post_email
可能是有意义的,方法本身也可能需要一些时间。
此外,将电子邮件发送为 BCC 可能是有意义的,这样您就可以同时向多个粉丝发送一封电子邮件。