Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a rails engine to interact with main App

I am creating a rails engine used as an interface to a payment service. I have to handle the use cases where the payment service is sending me message outside of any transaction. I will take the following use case :

The engine receive a message that subscription FooBar42 has been correctly billed(through it's own routes). What does my engine do next? If i start to call models specific to my app, my engine is only good for this app. Only example i could find is Devise, but in devise, it just add methods to your user model and the engine handle how the user is stored and all the code.

How do i create a reusable system where my engine can call/trigger code in the main app ?

Do i override engine controller ? Do i generate a service object with empty methods that will be used as an engine-app communication system?

like image 793
Syl Avatar asked Jul 24 '14 14:07

Syl


1 Answers

You need to have a way to configure your engine either in an initializer or through calling class methods in your model, much like how you configure Devise to use your User model when you call devise in the body of the User class:

class User < ActiveRecord::Base
  devise :database_authenticatable
end

For one of my engines I use an initializer that stores the classes the engine interacts with using a config object.

Given a config object:

class Configuration
  attr_reader :models_to_interact_with

  def initialize
    @models_to_interact_with = []
  end
end

You can then provide a config hook as a module method in your main engine file in lib:

require 'my_engine/configuration'

module MyEngine
  mattr_reader :config

  def self.configure(&block)
    self.config ||= Configuration.new
    block.call self.config
  end
end

Now when you're in the main app, you can create an initializer in config/initializers/my_engine.rb and add the models to your Configuration:

MyEngine.configure do |config|
  config.models_to_interact_with << User
  config.models_to_interact_with << SomeOtherModel
end

Now you have access to this from you engine without having to hardcode the model in your engine:

# in some controller in your engine:

def payment_webhook
  MyEngine.config.models_to_interact_with.each do |model|
    model.send_notification_or_something!
  end
end

Hope that answers your question.

like image 57
DiegoSalazar Avatar answered Oct 06 '22 00:10

DiegoSalazar