recommendable icon indicating copy to clipboard operation
recommendable copied to clipboard

NoMethodError (undefined method `perform_async' for Recommendable::Workers::Sidekiq:Class)

Open abhiramm opened this issue 12 years ago • 8 comments

when am trying to give a like am getting following error

NoMethodError (undefined method `perform_async' for Recommendable::Workers::Sidekiq:Class)

In my controller :

@vote = Vote.create(:option_id => params[:option_id], :dbrick_id => params[:dbrick_id], :user_id => current_user.id) @vote.save!
current_user.like(@vote.dbrick) #getting error in this line logger.info("Voted")

Versions:

Sidekiq : 2.8.0 Rails : 3.1.11 Ruby: 1.9.3p194 Recommendable : 2.1.0.1

abhiramm avatar Apr 18 '13 12:04 abhiramm

Does sidekiq appear before recommendable in your Gemfile? It should.

mhuggins avatar Apr 18 '13 17:04 mhuggins

Hmm. I wonder how I can best make Gemfile ordering not matter?

davidcelis avatar Apr 19 '13 01:04 davidcelis

+1 :+1:

mathieugagne avatar Apr 27 '13 03:04 mathieugagne

Thanks alot mhuggins.. as you said gem order change worked like a charm :) :+1:

abhiramm avatar Apr 27 '13 09:04 abhiramm

@davidcelis - The reason this happens is that when your gem is included (via gem 'recommendable'), your gem checks for the existence of other modules/classes defined by DelayedJob, Sidekiq, etc. If they aren't defined yet, then it won't initialize with the proper async handler as expected.

I think there are a few possible approaches to resolve this issue:

  1. Update the readme to make it clear that gem 'recommendable' should appear in the Gemfile after gem 'sidekiq' (or whatever async processor is used).
  2. Create separate gems recommendable-sidekiq, recommendable-delayed_job, etc. that would no longer check for the existence of the appropriate classes/modules, but would instead assume they exist no matter what since you're defining them in your Gemfile. These gems should include recommendable as a dependency so that I don't have to also include it in my Gemfile along with one of these. An additional benefit of this approach is that you potentially wouldn't have to modify the recommendable gem itself to support new async processors in the future, and could instead release a new gem that bridges the two.
  3. Not sure if bundler has any kind of hooking mechanism, but if it does, perhaps an after-hook could be added to this gem to perform the check for Sidekiq/DJ/etc. existence, and bridge them there.

I'm sure there are some other approaches I haven't considered as well.

mhuggins avatar May 14 '13 14:05 mhuggins

Yeah, the reason is something I'm familiar... The best approach to take was what's been bugging me. Maybe approach 2 is the best? Require that people explicitly bundle an extra package to provide the job. If they don't, they can manually update similarities and recommendations like the user in #77 was asking about.

davidcelis avatar May 14 '13 14:05 davidcelis

Hm. As much as I hate the idea of a million little recommendable baby gems (I'd rather be able to just detect a configuration), maybe this IS the best approach.

recommendable-sidekiq, recommendable-resque, and recommendable-delayed_job could provide the after hooks that queue for recommendations to be generated.

recommendable-activerecord, recommendable-datamapper, recommendable-sequel, recommendable-mongoid, and recommendable-mongomapper could all then provide the queueing interface to retrieve rated items from the specified database.

recommendable at its base, then, would be what it should be: a DSL for liking and disliking things. Or perhaps that should be recommendable-core? Where recommendable is a gem package (a la pry-full) that requires recommendable-core, recommendable-activerecord and recommendable-sidekiq).

I could even try to break Redis out into recommendable-redis and provide alternative datastores (a friend is already working on recommendable-postgresql. Though on second though, recommendable really needs a datastore. Perhaps a better approach there would be for recommendable to use Redis but extract it in a way such that it's easy for other gems to override and thus use a different datastore.

An organization for this would be easy enough.

davidcelis avatar May 14 '13 15:05 davidcelis

Oh, and @mhuggins, I really appreciate the suggestion! This is sounding more and more like the right choice, so thanks!

davidcelis avatar May 14 '13 15:05 davidcelis