2016-01-11 8 views
5

Userには多くのプロジェクトがあり、Projectには多くの役割があるアプリケーションに取り組んでいます。 Roleには、誰かがその役割を果たしたことを示すためのブール値filledがあります。モデルの子の属性に基づいてモデルのインスタンスを返すために、このRails/PostgreSQLクエリをどのように構造化できますか?

私はどちらかが何の役割を持っていないか、すべてのを埋めてきた役割を持っているすべてのプロジェクトを返すクエリを構築したいと思います。これは私がこれまで持っている最も近い:

@user.projects.includes(:roles).where("roles.id IS NULL OR roles.filled IS TRUE").references(:roles) 

問題は、クエリのroles.filled IS TRUE一部が充填され、充填されていない役割の混合物でプロジェクトをマッチングしていることです。 すべての役割が満たされているプロジェクトとのみ一致する必要があります。 bool_andが進むべき道は、おそらくですが、私のSQLのスキルが大きくないと私はそれがまだ働いて得ることができていないよう

はPostgreSQLのドキュメントを検索する、それが見えます。

私はこれをselectまたはrejectで簡単に行うことができたが、データベースを照会するだけで効率的に保ちたいと思います。

誰かアドバイスをお願いいたします。

更新:(簡体字)のモデルとそれらの関係:

APP /モデル/ user.rb

class User < ActiveRecord::Base 
    has_many :projects 
end 

APP /モデル/ project.rb

class Project < ActiveRecord::Base 
    belongs_to :user 
    has_many :roles 
end 

app/models/role.rb

class Role < ActiveRecord::Base 
    belongs_to :project 

    # `filled` is a boolean attribute with a default value of false 
end 
+1

は、だからあなた条件は、プロジェクトにはすべてのロールが埋め込まれている必要がありますか?お互いのモデルがどのように関連しているかを見せていただけますか? – lcguida

+0

@lcguida質問にモデルを追加しました:) – Simon

+1

私は答えましたが、正確であるようにすべてのroles.idがnullかany roles.idがnullである必要があるかどうかを知る必要があります。 – charlysisto

答えて

1

条件は(roles.filledのすべてのフィールドが真でなければならない)多くのレコードの組み合わせに適用されますので、あなたはaggregate functionに頼らなければなりません。

@user.projects. 
     joins("left outer join roles on roles.project_id = projects.id"). 
     group("projects.id"). 
     having("every(roles.filled IS TRUE) OR every(roles.id IS NULL)") 
     select("projects.*") 

更新:ここ

は提案です: every(roles.filled)がtrueの場合、だからグループが projects.idによると、すべての役割を確認し[OK]を、ここで、このSQLの背後にあるロジックです:

for every project, I'll check if it has NO roles.id OR ONLY roles.filled. The reason you cannot use the where clause for roles.id IS TRUE is that it would only select those, before grouping and filtering in the having clause and therefore excluding the roles.filled rows. In other words it would be the equivalent of doing roles.id is NULL AND Roles.filled IS TRUE

+0

これは私には似ていますが、 'PG :: UndefinedTable'エラーが発生しています: ' '':SELECT projects。* FROM "projects" WHERE "projects"。 "user_id "= $ 1 GROUP BY roles.project_id bool_and(roles.filled IS TRUE)またはbool_or(roles.id IS NULL) ActiveRecord :: StatementInvalid:PG :: UndefinedTable:ERROR:テーブル" roles "のFROM-clauseエントリがありません LINE 1:... d "= $ 1 GROUP BY roles.project_idを持っていますbool_and(roles.fill ...' '' – Simon

+0

申し訳ありませんが、コメントの書式設定はちょっと変わっています。 com/sstarr/85caa3f5973c004548ee – Simon

+1

ああ、奇妙な....(答えで修正されたように)includesの代わりにeager_loadを試してください – charlysisto

関連する問題