Ruby on Railsのマルチテーブルモデル

こんにちは、読者の皆様。 おそらく、人気のあるWebフレームワークRuby on Railsに精通しているでしょう。 そうでない場合は、 この投稿で多くの興味深く有益な情報を見つけることができます。 彼のルールの1つは「1つのモデル-1つのテーブル」です。 それに続いて、Catモデルは、別の名前が指定されていない限り、catsテーブルから情報を取得する必要があります。 モデルが複数のテーブルで構成されている場合、たとえば6つのテーブルがありますか? activerecordの標準的な結合/インクルードメソッドは、もはや役に立ちません。





問題の声明


したがって、提示されたソリューションを視覚化するために、問題をシミュレートします。 Productモデルが必要だとします。 モデルのグラフィック構造を図に示します:

画像



モデルの基礎は、アイテムテーブルです。 色、種類、店舗、製造者テーブルへの単一のリンクがあります。 同様に、最後の2つはアドレス多形リンクに関連付けられています。



この場合の解決策の1つは、この性質の単純な要求を作成することです。

ActiveRecord::Base.connection.execute('SELECT items.*, colors.name as color, types.name as type, stores.name as store_name ... FROM items LEFT JOIN colors ON items.color_id = colors.id LEFT JOIN types ON items.type_id = types.id LEFT JOIN stores ON items.store_id = stores.id ...
      
      







これに応答して、列名またはエイリアスの値を持つキーを持つハッシュのコレクションを取得します。 しかし、このアプローチには多くの欠点があります。 まず、値による通常の検索はありません。 第二に、レコードが多数ある場合は、独自のページネーションを作成する必要があります。 しかし、多くの人がRails for ActiveRecord、will_paginate、kaminari、meta_searchライブラリを愛しています。 したがって、大規模なクエリをActiveRecordに関連付ける必要があります。



SQLビューの呼び出し


このために、SQLの表現に慣れていない場合は、慣れる必要があります。 ビュー(VIEW)-ビューへのアクセス時にSELECTステートメントを使用して定義されたデータベースへのクエリを実行した結果であるデータベースオブジェクト。 しかし、ビューは仮想読み取り専用テーブルと間違われる可能性もあります。 詳細については、mysqlを例として使用して、プレゼンテーションをここで説明します 。 私たちにとって、activerecordはそれをテーブルとして数え、その強力な可能性を提供することが重要です。



最初に、移行を作成します。

 rails g migration AddProducts
      
      





その中に以下を書きます。

  def up execute ' CREATE VIEW products AS SELECT i.id AS id, i.name AS name, i.weight AS weight, i.size AS size, c.name as color, t.name as type, s.name AS store_name, sa.street AS store_street, sa.city AS store_city, sa.country AS store_country, sa.phone AS store_phone, m.name AS manufacture_name, ma.street AS manufacture_street, ma.city AS manufacture_city, ma.country AS manufacture_country, ma.phone AS manufacture_phone FROM items AS i LEFT JOIN colors AS c ON i.color_id = c.id LEFT JOIN types AS t ON i.type_id = t.id LEFT JOIN stores AS s ON i.store_id = s.id LEFT JOIN addresses AS sa ON s.id = sa.addressat_id AND sa.addressat_type = "Store" LEFT JOIN manufactures AS m ON i.manufacture_id = m.id LEFT JOIN addresses AS ma ON m.id = ma.addressat_id AND ma.addressat_type = "Manufacture" ' end def down execute 'DROP VIEW products ' end
      
      





Productモデルを作成した後、読み取り専用にします。

 class Products < ActiveRecord::Base # Prevent creation of new records and modification to existing records def readonly? return true end # Prevent objects from being destroyed def before_destroy raise ActiveRecord::ReadOnlyRecord end end
      
      





これで、activerecord、arel、およびその他のライブラリのフルパワーを使用して、複雑なモデルを受信、フィルタリング、およびページ分割することができます。

 blue_guitars_in_kiev = Product.where(:color => 'Blue', :type => 'Guitar', :store_city => 'Kiev') blue_guitars_in_kiev.each do |product| puts product.store_name end
      
      





リクエストは1つのトランザクションで迅速に実行され、ルビーコードは最小限に抑えられます。 このソリューションの唯一の欠点は、名前を変更したり列を削除したりするときに、この仮想テーブルを常に再作成する必要があることです。



以上です。 私の投稿があなたにとって有益であることを願っています。



All Articles