title: How to Architect a scalable solution for User preference that triggers actions in an application based on state changes of domain model
body: <p>In my Rails app, I want to be able to listen for s<strong>tate changes or callback triggers on the various Active Record model that exists</strong>. I have opted out to use the Observer pattern by using <a href="https://github.com/rails/rails-observers" rel="nofollow noreferrer">Rails Observer.</a> So I can do this </p>
  
  <pre><code>class Product &lt; ActiveRecord; end 
  
  class ProductObserver &lt; ActiveRecord::Observer
    def after_create(product) 
       #do something here
    end
  
    def after_destroy(product)
      #do something here 
    end 
  end 
  </code></pre>
  
  <p>This is awesome. However, each retailer in the application can enable one or more settings. An example below </p>
  
  <p>Assuming we have retailer A, B, C and D </p>
  
  <p><strong>When a new product is created</strong>,  </p>
  
  <p><em>Retailer A has the following settings configured</em>: </p>
  
  <ul>
  <li>send me an email</li>
  <li>send all my customers newsletter</li>
  <li>send my previous sales report</li>
  </ul>
  
  <p><em>Retailer B has the following settings configured</em> </p>
  
  <ul>
  <li>send me an email </li>
  </ul>
  
  <p><em>Retailer C has the following settings configured</em> </p>
  
  <ul>
  <li>inform my customers about the new products</li>
  </ul>
  
  <p><em>Retailer D may decide they don't want anything to happen</em> </p>
  
  <p><strong><em>Note</strong>, these settings are all configurable from a UI.</em></p>
  
  <p>Also, there would be various settings that can be configured on different callback triggers or model state change for the various ActiveRecord model in my application. </p>
  
  <p>How do I model this problem so that it scales, testable and without coupling? </p>
  
  <p>Here is a few solution I have come up with, but a colleague suggest they would prefer not to have verbs in their class name, but that is the most optimal solution I see for now. </p>
  
  <pre><code>class ProductObserver &lt; ActiveRecord::Observer
    def after_create(product)
      retailer = product.retailer 
      #find user settings from db 
      # fetch all methods they want to be triggered 
      # use meta programming to tirgger that method 
  
      retailer.observable_event_settings.actions.each do|action| 
        klass = "ProductCreate::#{action.camelize}".constantize
        klass.notify(product)
      end 
    end
  end
  
  
  module ObservableEvent 
    module ProductCreate 
      class SendNewsLetter
        def self.notify(observable)
        end 
      end 
  
      class OfferDiscount
        def self.notify(observable)
        end 
      end 
    end 
  end 
  
  #ObservableEvents 
  [
    {
      id: 1, 
      model: 'product'
      event: 'create', 
      actions: [:send_news_letter, :offer_discount]
    },
    {
      id: 2, 
      model: 'product', 
      event: 'destroy'
      actions: [:set_product_not_visible, :set_quantity_to_zero]
    }
  ]
  
  #ObservableEventSettings
  [
    {
      retailer_id: 1, 
      observable_event_id: 1,
      actions: [:send_news_letter] 
    },
  
    {
      retailer_id: 2, 
      observable_event_id: 1, 
      actions: [:send_news_letter, :offer_discount]
    }
  ]
  </code></pre>
  
  <p>This is the best I have been able to come up with so far. How would you go around this? Any help is most appreciated.</p>