Search code examples
ruby-on-railsrspec-rails

RubyOnRails classes / Preloading vs. new


The use case is the following : some external app sends a webhook, which the rails app receive. I'm using a custom class to retarget the payload elsewhere.

This custom class pretty much always does the same thing via the same method.

The class code :

class Retarget
  def order_paid(params)
    # do some processing
  end
end

Used like so in a controller :

def process_webhook
  insert = Retarget.new
  data = params.except(:action, :controller)
  insert.order_paid(data)
  head :ok
end

My problem is the following, if I want to verify if the method is called in a request spec, it would obviously fails. Some code below :

it 'triggers' do
  ... some call that fire the controller action
  expect(Retarget).to receive(:order_paid).with(..matching data)
end

Double checking that the method is called while testing the controller request sounds a safe check for me.

I was wondering if it could be achieved somehow. Or if things should remain tested separately — which would then let one assume the line presence in the controller (insert.order_paid(data)) would be enough

My Idea would be to preload at boot the class (eg. RetargetWebhook = Retarget.new in a config/initializers file), so it could be used anywhere; but I guess there would be a downfall to do so


Solution

  • I am not sure why you need an instance, but to be safe, lets keep it. I suggest:

    class Retarget  
      def self.order_paid(params)
        new.order_paid(params)
      end
    
      def order_paid(params)
        # do some processing
      end
    end
    

    And use it:

    Retarget.order_paid(params.except(:action, :controller))
    

    This way Retarget.order_paid would create the instance itself.

    Other options could lead to use singleton but I would stay away from this as there is few added value, and its potentially a path towards confusion if you rely on instance variables and you start memoizing.