4

現在、モバイル アプリケーションの Web サービスとして使用される Rails アプリ (基本的には CRUD) があります。

現在、ユーザーがアプリでコンテンツを変更すると、同じデータベースを使用しているため、変更はモバイル アプリケーションに反映されます。

ライブ データ (アプリによってフェッチされる) とユーザーが CRUD で変更できるデータを分離する方法はありますか? そのために使用できる DBMS 機能、または gem はありますか?

現在 MySQL を使用していますが、代替手段 (例えば Postgresql) を積極的に探しています。

編集:当面はファイルシステム キャッシュを使用して、コンテンツの最新でないバージョンを全員に提供することにしました。全員が最新バージョンを使用できるように、すべてが問題ない場合は無効化に進みます。しかし、これは信頼できる解決策ではないと思います...

Edit2:この質問の全体的な目的は、モバイル アプリケーションによって読み取られるものを何らかの制御、ある種のモデレーションにしたいということです。基本的に、変更とさまざまな状態/バージョン/スナップショットを管理できるようにしたいと考えています。

4

4 に答える 4

3

私が正しく理解していれば、これはあなたの問題です:

  • 1 つの Rails アプリが、モバイル アプリからの READ と WRITE リクエストの両方を処理します。
  • 1 つの Rails アプリで異なる READ データベースと WRITE データベースを使用したい
  • また、WRITE が READ DB に伝播されるタイミングをカスタム制御できるようにする必要があります。

問題を解決する最もクリーンな方法は次のとおりです。

2 つのデータベースを作成し (それらを READ DB と WRITE DB と呼びましょう)、それらの間でマスター/スレーブ レプリケーションをセットアップします。したがって、WRITE DB で作成したクエリは、READ DB にレプリケートされ、いつ、どのようにレプリケーションがトリガーされるかを制御できます。ほぼすべてのデータベースが、これをすぐに使用できるようにサポートしています。MySQLの手順は次のとおりです。マスター/スレーブ レプリケーションは標準で堅牢であるため、PostgreSQL に切り替える必要さえありません。

Rails アプリの場合、次の 2 つのデータベースを構成しますconfig/database/yml

production:
  # configuration for your WRITE DB
  adapter: mysql
  database: ...
  host: ...
  username: ...
  password: ...

production_read:
  # configuration for your READ DB
  adapter: mysql
  database: ...
  host: ...
  username: ...
  password: ...

そして、次の 2 つの選択肢があります。

  1. 同じインスタンスを 2 つデプロイします。RAILS_ENV=production_readコードに変更はありませんが、READ 用のインスタンスとRAILS_ENV=productionWRITE用のインスタンスの 2 つのインスタンスをデプロイするだけです。モバイル アプリを変更して、READ が最初のインスタンス URL に移動し、WRITE が他のインスタンス URL に移動するようにします。

    (また)

  2. Rails アプリのインスタンスを 1 つだけ実行し、productionproduction_readデータベースを切り替えるだけです。適切な Web サービスがあるので、データの読み取りに GET 要求を使用していると仮定します。他のすべての (POST/PUT/DELETE/etc) 要求は書き込み要求です。これを行っていない場合は、まずとにかくこれを行うことをお勧めします。読み取りに GET を使用している場合は、次のようにします。

    # app/controllers/application_controller.rb
    class ApplicationController
      before_filter do
        # Switch to production_read or production configurations
        # based on request method
        if request.get?
          ActiveRecord::Base.establish_connection "production_read"
        else
          ActiveRecord::Base.establish_connection "production"
        end
      end
    

これは、リクエスト方法に応じて、あなたproduction_readと構成の間で切り替わります。また、認証と承認の後にのみ切り替えが発生し、最終的にコントローラー ロジックの直前に切り替えが行われるように、 をproduction注文することもできます。before_filter

establish_connectionまた、すべてのモデル クラスに対して同じことを行う必要がある場合もあります。その場合は、ActiveRecord::Baseサブクラスをループして、同じ Establish_connection ロジックを呼び出すだけです。接続を切り替える前に、いくつかのサブクラスを省略することもできます。

ActiveRecord::Base.descendants.each do |model_class|
  model_class.establish_connection (request.get? ? "production_read" : "production")
end

# Or let's say you want to switch all models *except* User/Session models to the READ DB
(ActiveRecord::Base.descendants - [User, Session]).each do ...
于 2013-06-15T17:05:23.400 に答える
0

vestal_versions gem またはpaper_trail gem が役に立ちます。それらについての Railscasts の素晴らしいエピソードがあります。

于 2013-06-19T16:25:48.343 に答える
0

大まかな問題の説明を見ると、おそらくデータベース ビューが必要だと思います。または、より機敏なソリューションは、権限の低いユーザーになる可能性があります。

次に、CRUD 以外のユーザーが別の Rails モデルを介してデータを取得し、別の低い権限のデータベース接続に接続することができます。Rails 3 ではこれを簡単に行うことができます。問題の大部分はデータベースにあります。基本的に、選択のみの権限でデータベースを設定します。

要するに、これをデータベース レベルで解決し、Rails レベルで対応できるはずです。

于 2013-06-19T17:23:34.353 に答える