Datamapper を使用してテーブルを動的に作成し、クエリを実行したいと考えています。
Datamapper を使用すると、レガシー テーブルとスキーマを操作できますが、この方法で使用されるテーブル名を設定できますが、これはアプリケーション内ではなく、初期化中にのみ行われます。
アプリケーションで割り当てられたテーブル名を持つモデルを移行/アップグレードするよう Datamapper に指示し、次にこのテーブルを照会するように指示する簡単な方法はありますか?
Datamapper を使用してテーブルを動的に作成し、クエリを実行したいと考えています。
Datamapper を使用すると、レガシー テーブルとスキーマを操作できますが、この方法で使用されるテーブル名を設定できますが、これはアプリケーション内ではなく、初期化中にのみ行われます。
アプリケーションで割り当てられたテーブル名を持つモデルを移行/アップグレードするよう Datamapper に指示し、次にこのテーブルを照会するように指示する簡単な方法はありますか?
これは問題になりません。
すべての Ruby クラスを作成し、実行時に再定義できます。初期化も実行時に行われます。他のコードが実行される前に、たまたま初期化が最初に実行されます。
そのため、モンキーパッチは非常に簡単に機能します。クラスを再定義して追加のメソッドや変数などを追加するのは、初期化時の単なる追加コードです。
コンパイル時にのみ実行されるという意味で「特別な」Ruby コードはありません。Ruby はインタープリター言語です。
クラスを動的に作成するには、Ruby でクラスを動的に作成する を参照してください。
文字列の配列からクラスを動的に作成する必要がないと仮定すると、 で追加のメソッドを定義するdefine_method
か、実行時に Datamapper メソッドを呼び出して属性を追加できます。
クラスで新しいメソッドを定義するには:
Post.send :define_method, :new_method_name do
end
Datamapper プロパティを使用して新しいプロパティを定義するには:
class Post
include DataMapper::Resource
property :title, String # the static way
end
Post.send :property, :title, String # add property the dynamic way (at run-time)
サーバーを再起動すると、これらを動的に生成するコードが再実行されない限り、実行時に定義したテーブルまたはプロパティは使用できなくなることに注意してください。
実行時にテーブルを更新するには、通常と同じことを行うだけです。つまり、次のように呼び出します。
DataMapper.auto_upgrade!
単一のテーブルのみをアップグレードするには、次のこともできます。
Post.auto_upgrade!
2 番目の警告: 複数のプロセスがある場合、各プロセスで動的コードを実行する必要があります。そうしないと、追加のテーブル モデルとプロパティを使用できなくなります。
これは、本番環境で発生する可能性があるように、複数のワーカー プロセスがある場合に問題になります (たとえば、複数の Unicorn ワーカーを持つ Nginx、または Ha_proxy の背後にある複数の Mongrel ワーカー)。
単一のプロセス サーバーを使用している場合、それは問題ではありません。ただし、複数のワーカー プロセスがある場合は、動的コードを実行して各プロセスでこれらの追加のクラスとプロパティを生成し、使用できるようにする必要があります。
これは実際には初期化の場合と同じです。各プロセスが初期化を実行するためです (または、フォークされた場合は初期化を継承します)。
内部で何も変更しない最も簡単な方法は、テーブルの代わりに別のデータベースを使用し (リレーションシップも別のデータベースに格納されると仮定して)、ブロック内の追加のリポジトリへの接続を開くことです。
DataMapper.setup(:external, "adapter://username:password@hostname/dbname")
DataMapper.repository(:external) do...end