简体   繁体   English

Rails 4 - Resque背景作业里面的印象派

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM