質問
私はレールで初心者ですとMySQLに参加左を実行しようとします。
ユーザーとメッセージ -2つのオブジェクトが存在します。
ユーザーhas_and_belongs_to_manyアソシエーションメッセージ、メッセージhas_and_belongs_to_manyアソシエーションのユーザー
現在、単にuser.messagesを書き込むことによって、私は、コンソールでクエリを以下の取得
SELECT * FROM `messages` INNER JOIN `messages_users` ON `messages`.id = `messages_users`.message_id WHERE (`users_messages`.group_id = 1 )
== falseはなく、任意のユーザーに接続していないれる制限されたとのメッセージが任意のユーザによってアクセス可能であり、そして私は、コレクションMessage.allを追加する必要がありuser.messagesに(=> falseの制限)
私の問題を解決するクエリは以下のようになります:
select * from messages left join messages_users on messages_users.message_id=messages.id and messages_users.user_id=1 where (messages_users.user_id is NULL and messages.restricted=false) OR (messages_users.user_id=1 and messages.restricted=true);
私は、できるだけエレガントレールでそれを書くのですか?
は、
のようになめらかになりますMessage.find(:all,:conditions => "(messages_users.user_id is NULL and messages.restricted=false) OR (messages_users.user_id=1 and messages.restricted=true)", :joins => "left join messages_groups on messages_users.message_id=messages.id and messages_users.user_id=1 " )
またはそれがよりよいすることができますか?
私が使用しているレール2.3.2
おかげで、 パベル
解決
私は正しくそれを理解していた場合、私はあなたはそれが単一のクエリとして行わたい場合は、それを行うには良い方法が表示されません。あなたはそれの2つのクエリを作るというアイデアに開いている場合(おそらく実行速度を遅くしながら)しかし、あなたは、コード内で少しそれをクリーンアップすることができます。ここで代替の設定は次のとおりです。
class Message < ActiveRecord:Base
has_and_belongs_to_many :users
named_scope :restricted, :conditions => {:restricted => true}
named_scope :unrestricted, :conditions => {:restricted => false}
named_scope :public, :conditions => "id NOT IN (SELECT DISTINCT message_id FROM messages_users)"
end
class User < ActiveRecord:Base
has_and_belongs_to_many :messages
end
以下のコード内のリストを取得しますが、2つのデータベースを必要とするヒットにあなたが行うことができます:
@current_user.messages.restricted + Message.unrestricted.public
のいずれかの場合には、あなたは彼らが適切にインデックス化されているか、これは任意の負荷を遅くしようとしていることを確認する必要があり、これらのテーブル内のデータの実質的な量があるかどうか。これは送信されたメッセージの多くのアプリであれば、あなたはおそらく、単一のクエリとの方がいいでしょう。それはあまり使用されないだけでサイド関数の場合、私はおそらくクリーンバージョンを取るだろう。
どのようなおそらくモデルの観点から、より良い仕事とは、HABTM関係を取り除くと、明示的な関係をモデル化することです。その後、メッセージの送信/配信/(ETC送ら時間、時間の読み取りを、追跡のような)受信処理に関する他のデータを追跡するための便利な場所を持っています。それは私がちょうどHABTMに至るまで、多くを持っていることを好む、上記の議論のいずれかを変更しません。
class Message < ActiveRecord:Base
has_many :subscriptions
has_many :users, :through => :subscriptions
named_scope :restricted, :conditions => {:restricted => true}
named_scope :unrestricted, :conditions => {:restricted => false}
named_scope :public, :conditions => "id NOT IN (SELECT DISTINCT message_id FROM subscriptions)"
end
class User < ActiveRecord:Base
has_many :subscriptions
has_many :messages, :through => :subscriptions
end
class Subscription < ActiveRecord:Base
belongs_to :message
belongs_to :user
end
他のヒント
は使用しない理由は?含める
私はnamed_scopesは、あなたの答えかもしれないと思います。お使いのモデルのようなものを入れます:
named_scope :restricted, :conditions => {:restricted => true}
named_scope :unrestricted, :conditions => {:restricted => false}
次に、あなたのようなものを呼び出すことができます
Message.restricted
=> All restricted messages
User.first.messages.unrestricted
=> All unrestricted messages belonging to the first user.
私はHABTM団体を介してこれらの作業を信じています。