Rails 4 - импрессионист внутри фоновой работы Resque
Я использую Rails 4 с импрессионистами и жемчужиной.
Я использую импрессионистов, чтобы регистрировать уникальные хиты сессий на моей странице показа статьи. Из-за проблем с производительностью и отсутствия необходимости отображать хиты для пользователей (это только для администраторов), я хотел бы перенести регистрацию показов в фоновом режиме.
Обычно я регистрирую показ, используя impressionist(@article, unique: [:session_hash])
но чтобы перенести его в bg через resque, я сейчас делаю что-то вроде этого...
articles_controller:
def show
.
.
.
Resque.enqueue(ImpressionLogger, @article.id)
end
приложение / рабочие / 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
Когда я настраиваю его так, когда resque пытается обработать задание, он возвращается undefined method "impressionist" for ImpressionLogger:Class
, Как вы думаете, что лучший способ это сделать? Я не уверен, как включить импрессионистские методы в моего работника.
3 ответа
Проблема
Ваша проблема проистекает из того факта, что импрессионист работает на уровне контроллера из-за включения модуля с impressionist
Метод в инициализаторе движка на любых экземплярах ActionController:
https://github.com/charlotte-ruby/impressionist/blob/master/lib/impressionist/engine.rb#L11
Вы пытаетесь вызвать метод импрессиониста из обычного класса, вызываемого в задании Resque, поэтому этот метод не будет определен.
Решение
Это довольно грубо, но если вы действительно хотите использовать импрессионистов, мы можем углубиться в это... Глядя на фактическую реализацию импрессионистского метода, найденную здесь, мы видим следующее:
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
Предполагая, что вы будете вызывать что-то подобное вручную (как вы хотите из задания resque), ключ состоит из трех строк:
if unique_instance?(obj, opts[:unique])
obj.impressions.create(associative_create_statement({:message => message}))
end
Обертка if кажется важной, только если вы хотите реализовать эту функцию. Что, похоже, так и есть. Призыв к associative_create_statement
похоже, что параметры извлекаются на основе имени контроллера, а также параметров, передаваемых из Rack, таких как строка useragent и IP-адрес ( здесь). Таким образом, вам придется разрешить эти значения до вызова задания Resque.
На этом этапе я бы предложил реализовать класс Resque, который принимает два параметра, article_id и требуемые параметры показа. Тогда класс resque будет просто создавать впечатление на впечатлительный объект. Ваш класс 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
И ваш метод контроллера будет выглядеть примерно так:
def show
.
.
.
Resque.enqueue(ImpressionLogger, @article.id, associative_create_statement({message: nil})) if unique_instance?(@article, [:session_hash])
end
отказ
Есть довольно большой отказ от ответственности, который идет с этим, хотя... метод associative_create_statement
помечен как защищенный и unique_instance?
помечен как частный... так что ни один из них не является частью открытого API импрессионистского гема, поэтому этот код может разрываться между версиями гема.
Правильно ли установлен импрессионист в связке? В этом случае Rails должен загружать его в вашу среду. Я бы проверил, можете ли вы получить доступ impressionist
функциональность в другом месте вашего кода Rails (т.е. без прохождения Resque) в качестве первого шага к отладке.
Как вы начинаете свои рабочие? Если вам нужна загруженная среда Rails, попробуйте rake environment resque:work
,