[英]Rails 4 - Impressionist Inside of a Resque Background Job
I am using Rails 4 w/ the impressionist and resque gem. 我正在使用Rails 4 w /印象派和resque gem。
I am using impressionist to log unique session hits on my article show page. 我正在使用印象派来记录我的文章显示页面上的唯一会话点击。 Due to performance issues and no need to display hits to users (it is for admins only), I would like to move logging impressions off into the background.
由于性能问题而且无需向用户显示匹配(仅限管理员),我希望将日志记录显示移至后台。
Normally I would log an impression using impressionist(@article, unique: [:session_hash])
but to move it off into the bg via resque I am now doing something like this... 通常我会使用
impressionist(@article, unique: [:session_hash])
记录一个印象impressionist(@article, unique: [:session_hash])
但是通过resque将它移到bg中我现在正在做这样的事情......
articles_controller: articles_controller:
def show
.
.
.
Resque.enqueue(ImpressionLogger, @article.id)
end
app/workers/impression_logger.rb: 应用程序/工人/ impression_logger.rb:
class ImpressionLogger
@queue = :impression_queue
def self.perform(article_id)
article = Article.find(article_id)
impressionist(article, unique: [:session_hash])
end
end
When I set it up like this, when resque tries to process the job, it is returning undefined method "impressionist" for ImpressionLogger:Class
. 当我这样设置时,当resque尝试处理作业时,它会返回
undefined method "impressionist" for ImpressionLogger:Class
。 What do you guys think the best way to go about this is? 你认为最好的方法是什么? I am not sure how to include impressionist methods inside of my resque worker.
我不确定如何在我的resque工作者中包含印象派方法。
Is impressionist installed properly with bundler? 印象派是否与捆绑器正确安装? If so Rails should be loading it into your environment.
如果是这样,Rails应该将它加载到您的环境中。 I would check whether you can access
impressionist
functionality elsewhere in your Rails code (ie without going through Resque) as the first step to debugging this. 我会检查你是否可以在你的Rails代码中的其他地方访问
impressionist
功能(即不通过Resque)作为调试它的第一步。
The issue 问题
Your problem stems from the fact that it looks like Impressionist works on the controller level due to including a module with the impressionist
method in an engine initializer on any instances of ActionController: 您的问题源于这样一个事实:由于在ActionController的任何实例上的引擎初始化程序中包含一个带有
impressionist
方法的模块,因此Impressionist在控制器级别上工作:
https://github.com/charlotte-ruby/impressionist/blob/master/lib/impressionist/engine.rb#L11 https://github.com/charlotte-ruby/impressionist/blob/master/lib/impressionist/engine.rb#L11
You're trying to call the impressionist method from a regular class being invoked in a Resque job, so it's not going to have that method defined. 您试图从Resque作业中调用的常规类调用impressionist方法,因此它不会定义该方法。
Solution 解
It's kind of gross, but if you really want to use impressionist, we can delve into this... Looking at the actual implementation of the impressionist method found here , we see the following: 这有点粗,但是如果你真的想使用印象派,我们可以深入研究这个......看看这里找到的印象派方法的实际实现,我们看到以下内容:
def impressionist(obj,message=nil,opts={})
if should_count_impression?(opts)
if obj.respond_to?("impressionable?")
if unique_instance?(obj, opts[:unique])
obj.impressions.create(associative_create_statement({:message => message}))
end
else
# we could create an impression anyway. for classes, too. why not?
raise "#{obj.class.to_s} is not impressionable!"
end
end
end
Assuming that you'd be calling something like this manually (as you want to from a resque job) the key are these three lines: 假设你手动调用这样的东西(你想从resque工作中调用),关键是这三行:
if unique_instance?(obj, opts[:unique])
obj.impressions.create(associative_create_statement({:message => message}))
end
The if wrapper only seems to be important if you want to implement this functionality. 如果要实现此功能,if包装器似乎很重要。 Which it looks like you do.
它看起来像你做的。 The call to
associative_create_statement
seems to be pulling parameters based off of the controller name as well as parameters passed from Rack such as the useragent string and ip address ( here ). 对
associative_create_statement
的调用似乎是根据控制器名称以及从Rack传递的参数(例如useragent字符串和ip地址( 此处 ))来提取参数。 So, you'll have to resolve these values prior to invoking the Resque job. 因此,您必须在调用Resque作业之前解析这些值。
What I would suggest at this point is implementing a Resque class that takes in two parameters, an article_id and the impression parameters that you want. 我在这一点上建议实现一个Resque类,它接受两个参数,一个article_id和你想要的印象参数。 The resque class would then just directly create the impression on the impressionable object.
然后,resque类将直接在可展示对象上创建印象。 Your Resque class would become:
您的Resque课程将成为:
class ImpressionLogger
@queue = :impression_queue
def self.perform(article_id, impression_params = {})
article = Article.find(article_id)
article.impressions.create(impression_params)
end
end
And your controller method would look something like this: 你的控制器方法看起来像这样:
def show
.
.
.
Resque.enqueue(ImpressionLogger, @article.id, associative_create_statement({message: nil})) if unique_instance?(@article, [:session_hash])
end
Disclaimer 放弃
There's a fairly big disclaimer that comes with doing it this way though... the method associative_create_statement
is marked protected and unique_instance?
尽管这样做有一个相当大的免责声明......方法
associative_create_statement
被标记为protected和unique_instance?
is marked private... so neither of these is part of the impressionist gem's public API, so this code might break between versions of the gem. 被标记为私有...所以这些都不是印象派宝石的公共API的一部分,所以这个代码可能会在gem的版本之间中断。
How are you starting your resque workers? 你是如何开始你的resque工人的? If you need your Rails environment loaded, try
rake environment resque:work
. 如果您需要加载Rails环境,请尝试
rake environment resque:work
。
https://github.com/resque/resque/wiki/FAQ#how-do-i-ensure-my-rails-classesenvironment-is-loaded https://github.com/resque/resque/wiki/FAQ#how-do-i-ensure-my-rails-classesenvironment-is-loaded
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.