ruby-on-railsrubyruby-on-rails-4activeresourcedata-exchange

Exchange data between 2 Rails apps (preferably offline) on the same server


I have 2 Ruby on Rails 4 apps on the same server (they do not - and should not - share database):

deploy@Ubuntu-1404-trusty-64-minimal:~/applications$ ls
app1  app2

How do I exchange data between app1 and app2?

My current implementation is unstable and not secure:

app1 requests app2 to update first and last name of the user with username bobby:

# app1
HTTParty.get("https://app2.com/update_full_name?username=bobby&first_name=Bob&last_name=Dylan")

app2 receives app1's request and processes:

# app2 app/controllers/some_controller.rb
def update_full_name
  user = User.find_or_create_by(username: params[:username])
  user.update_attributes(first_name: params[:first_name], last_name: params[:last_name])
end

I have read that ActiveResource has been removed from Rails 4. I never really understood ActiveResource anyway, so I will not explore it further and will prefer a different solution.


Solution

  • I had the same problem and explored every option: ActiveResource (which is deprecated), callbacks with my own homegrown API wrappers, queueing with Redis or RabbitMQ. Nothing was easy enough for my simple mind to implement. If Model1 in App1 will always update Model2 in App2, then best solution I've found with Rails is the Promiscuous gem

    It's makes it pretty simple to run a pub/sub system that keeps data synched up between two ruby/rails apps. It works with both ActiveRecord & Mongoid. The documentation goes into more depth, but here are a few gotchas I found when trying to set it up using the Quick Start guide on the github page.

    1. Make sure you have an initializer file in both apps that connects to your shared RabbitMQ instance.
    2. If using ActiveRecord on the publisher side, you will need to create a new table (subscriber does not need this table to my knowledge):

      create_table :_promiscuous do |t|
        t.string    :batch
        t.timestamp :at, :default => :now
      end
      
    3. You will also need to add a column to every publisher and subscriber model

      # in App1 - publisher
      add_column :publisher_model, :_v, :integer, limit: 8, default: 1
      
      # in App2 - subscriber
      add_column :subscriber_model, :_v, :integer, limit: 8
      
    4. You can set the name of the published model. For example if I have a namespaced class Admin::User in App1, I can publish the attributes :as => 'AdminUser' and App2 has the model AdminUser it will listen correctly.

    5. If you've followed the instructions from the github page, included your mixins and set publishable/subscribable attributes, you will inevitably want to run it in production in which case your subscriber will need to run a worker. I use a pretty shameless ripoff of this Resque deploy script, my version for Promiscuous can be found here and it seems to work.

    I'm finding more and more ways to use this setup. Gives me a lot more flexibility with sharing and managing my data. Good luck.