web-dev-qa-db-ja.com

2つのRailsアプリ間で共有されるモデル-ワークフローの理想的なソリューションは何ですか?

私は現在、Rails 3プロジェクトに取り組んでおり、4つの部分に分かれています:

  • 一般向けウェブサイト
  • 管理Webサイト/バックエンド
  • モデル
  • サードパーティのデータアクセス用のAPI

モデルは3つの主要なコンポーネント間で共有されるため、1つのメインプロジェクトに含めないようにしますが、各パーツはモデルにアクセスする必要がありますが、コードを繰り返したくなく、どこにでも異なるバージョンを用意したくありません。

現在、gemにモデルコードがあり、各プロジェクトのGemfileで次の行を使用してそれらを参照しています。

gem "my_models", :path => "../my_models/"

ただし、同僚がシステムを評価するためにテストサーバーに展開するときは、外部リポジトリからモデルをプルする必要があるため、上記の行を次のように置き換えます。

gem "my_models", :git => "[email protected]:username/my_models.git"

これ自体はうまく機能しますが、「バージョン」の点ではかなり不格好です(つまり、変更をテストサーバーに展開するたびにバージョンをバンプする必要があります)。ローカルではなくgitを使用するように行を切り替えます。ファイルが適切にプッシュされていることを確認します。

以前は共有gitサブモジュールを使用していましたが、これは同じように扱いにくいものでした。

これらは巨大で保守が困難になる傾向があるため、すべてを1つのメガプロジェクトに構築するのではなく、可能であれば懸念事項を分離したいので、管理サイトに加えた変更にはほとんど影響がありません。他のコンポーネントに影響を与える可能性-明らかにモデルには問題が発生する可能性がありますが、それは私が検討して理解したリスクです。

このようなことになると、人々は何を提案するでしょうか?または、私はそれを完全に間違った方法で行っていますか?

追加の背景:

このアプリは、「すべてを1つのプロジェクトにまとめる」というモデルに従った既存のWebサイトを書き換えたものです。残念ながら、ここには2つの問題があります。

  1. アプリの開発が悪かった-私はこのプロジェクトを継承し、最初にそれを拾ったとき、読み込み時間は1人のユーザーで1ページあたり最大2分でした-これはその後減少しましたが、それでも全体的に問題があります
  2. 現在、現在のサイトの容量制限に達しており、今後6か月でより多くの負荷をかける必要があると予想しています。ただし、「オールインワン」アプリでスケールアウトすると、スケールアウトにリソースを浪費することになりますそれを必要としないサイトのバックエンド。

本質的には、分離したい2つの点があります。フロントエンド(パブリックWebサイトとAPIであること)とバックエンドです。ソフトウェア開発について知っているすべてのことから、これらをすべて組み合わせるのは理想的なソリューションではないことがわかります(過去の履歴が表示されます)これら2つを分割することは、フロントエンドのパフォーマンスを保証するという点で良い方向だと私は考えています)。

多分私はこれを別の角度から見る必要があります-モデルを各プロジェクトに保持し、プロジェクト間でモデルを共有する代わりに、各機能領域の機能の一部を削減します(つまり、バックエンドは投稿を作成した人を知る必要がありますが、フロントエンドは実際にはそれを気にしないので、モデルを読み込むときはそのロジックを省略します)。

53
Matthew Savage

モデルプロジェクトをドロップし(モデルを他のパーツの1つに入れます。「より重要」と思われるものは何でもお勧めします)、すべてのプロジェクトを単一のリポジトリ(個別のプロジェクトフォルダ)に入れ、models/libs/apis/whateverへのシンボリックリンクを作成します。

コードは相互に高度に結合されており、多くの場合、一度にいくつかのプロジェクトに変更を加える必要があります(モデルの更新andそれらを使用するAPIの更新など)

シングルリポジトリシンボリックセットアップの良い点の1つは、コミットの断片化が少なくなり、通常は完全な機能の実装を表す-バグの追跡、履歴の読み取り、コードベースの保守が容易になることです。

また、デプロイするときに、多くのリポジトリから読み取る必要はありません-すぐに失敗するポイントが1つ少なくなります

このようなモデルを使用すると、ブランチがすべてのプロジェクトのスコープを保持するようになるため、リリースプロセスも簡単になります

シンボリックリンクがウィンドウでうまく機能しないなどの欠点がありますが、私にとっては完全に機能します

20
keymone

共有モデルを含むマウント可能なエンジンを作成し、それから宝石を作成できます。これにより、名前の間隔の問題がエレガントに処理されます。ここでのその他の素晴らしい点は、アセットも共有できることです。

詳細はこちら railscast をご覧ください。

8
Harish Shetty

テストする必要のある変更をリモートリポジトリにプッシュすることで「バージョン」を管理する必要がありますが、Bundler 1.2の新しいlocal構成を使用できます

http://gembundler.com/man/bundle-config.1.html#LOCAL-GIT-REPOS

これにより、ローカルコミットが取得され、展開時にGemfileを変更し続ける必要がなくなります。

3
wprater

これはあなたの特定の問題の解決策ではないことを知っています。ただし、すべてのプロジェクトを1つにマージすることをお勧めします。このすべてのパーツを1つのアプリケーションに含めるのはごく一般的なことで、オーバーヘッドはありません。この問題を解決するのに厄介な方法はないと思います。

0
iafonov

プロジェクトには十分なコードカバレッジがありますか?もしそうなら、私はそれが理にかなっている場所でロジックを分離しようとします、そしてモデルが異なるプロジェクトで使用されているなら、ちょうどそれに合うものを選んでその上にAPIを書いてください。

次に、そのAPIを使用して、他のプロジェクトのモデルに(できればActiveModelなどを使用して)アクセスします。それでも単純なCRUDはありますが、すべてのコアモデルロジックは外部で処理されます。

ただし、分割する前によく考えてください。引き裂きたいBehemothから作成する各アプリでドメインをタイトに保ちたいと考えています。

エンジンについて:

私は同じ問題にエンジンを使用しましたが、それでも役立ちますが、開発時にローカルパスを指すようにGemfileを変更し、gemをプッシュしてから、現在のプロジェクトでそれをプルする必要がありました。好きではない。

0