2017-09-10 1 views
1

Ich habe eine Ruby on Rails-Anwendung mit zwei Datenbank-Backends - PostgreSQL und MemSQL (eine MySQL-kompatible Analysedatenbank).ActiveRecord-Modell mit zwei Datenbanken gleichzeitig

Wie kann ich die Einrichtung eines Model so dass es für beide Datenbanken beibehalten wird gleichzeitig, so dass CREATE, UPDATE und DELETE-Anweisungen werden auf beide ausgeführt und SELECT-Abfragen nur auf PostgreSQL ausgeführt werden?

Mit anderen Worten - wie kann ich zwei Datenbank-Backends immer identisch mit dem gleichen ActiveRecord-Modell pflegen?

+0

Ich weiß, dass dies nicht mit der Programmierung verwandt ist, aber wäre es nicht einfacher, eine Spiegeldatenbank zu entwerfen, also würden Sie die gleichen Daten haben, ohne eine andere Abfrage in der Anwendung auszuführen? – CatBrownie

Antwort

1

Sie können dies tatsächlich tun, indem Sie zwei Modellklassen haben. Aber die Nachteile sind vielfältig, wenn es um Zusammensetzung und Komplexität geht. Active Aktien Verbindungen von ihnen in der Basisklasse zu speichern:

class MemSQLBase < ActiveRecord::Base 
    establish_connection configurations['memsql'][Rails.env] 
    self.abstract_class = true 
end 

class Post < ApplicationRecord 
    after_save :push_to_memsql! 
    def push_to_memsql! 
    MemSQLPost.save_or_update!(self.attributes) 
    end 
end 

class MemSQLPost < MemSQLBase 
    self.table_name = :posts 
    def self.model_name 
    ActiveModel::Name.new("Post") 
    end 
end 

Der peinliche Teil ist, dass Code zu teilen zwischen Post und MemSQLPost Sie Module verwenden, da sie nicht über eine Basisklasse teilen.

Es kann möglich sein, dies zu umgehen, indem die Klassenverbindungsmethoden monkeypatching:

# this class does nothing except holding the connection pool 
class MemSQLBase < ActiveRecord::Base 
    establish_connection configurations['memsql'][Rails.env] 
    self.abstract_class = true 
end 

module MemSQLMonkeyPatch 
    extend ActiveSupport::Concern 

    class_methods do 
    def connection_pool 
     MemSQLBase.connection_pool 
    end 

    def retrieve_connection 
     MemSQLBase.retrieve_connection 
    end 

    def connected? 
     MemSQLBase.connected? 
    end 

    def remove_connection(klass = self) 
     MemSQLBase.remove_connection 
    end 
    end 
end 

class Post < ApplicationRecord 
    after_save :push_to_memsql! 
    def push_to_memsql! 
    MemSQLPost.save_or_update!(self.attributes) 
    end 
end 

class Post < MemSQLBase 
    include MemSQLMonkeyPatch 
    self.table_name = :posts 
end 

ich nicht getestet haben, obwohl, so dass Sie auf eigene Faust.

+0

Es gibt jedoch noch einiges mehr - Sie müssen die Migrationen auf beide Datenbanken anwenden (oder sie duplizieren). Es gibt viele Blog-Posts über Multi-DB-Schienen-Apps, die einen guten Startpunkt bieten sollten. – max