0

ユーザーをロールに関連付ける次のモデルがあります。

class User < ActiveRecord::Base
  has_many :user_role_assignments, :dependent => :destroy
  has_many :user_roles, :through => :user_role_assignments
end

class UserRole < ActiveRecord::Base
  has_many :user_role_assignments
  has_many :users, :through => :user_role_assignments
end

class UserRoleAssignment < ActiveRecord::Base
  belongs_to :user
  belongs_to :user_role

  named_scope :has_admin_role, 
    :joins => :user_role, 
    :conditions => "user_roles.name = 'admin'",
    :group => "user_role_assignments.user_id" 

  named_scope :has_non_admin_role, 
    :joins => :user_role, 
    :conditions => "user_roles.name <> 'admin'",
    :group => "user_role_assignments.user_id" 
end

UserRoleAssignment の名前付きスコープは SQLite では機能しますが、postgreSQL では機能しないため、次のエラーが発生します。

ActiveRecord::StatementInvalid: PGError: ERROR:  column "user_role_assignments.id" must appear in the GROUP BY clause or be used in an aggregate function
: SELECT "user_role_assignments".* FROM "user_role_assignments"   INNER JOIN "user_roles" ON "user_roles".id = "user_role_assignments".user_role_id  WHERE (user_roles.name = 'admin')  GROUP BY user_role_assignments.user_id

名前付きスコープのさまざまなバリエーション (:having 句の追加、追加のグループ化の追加) を試しましたが、何かを追加するたびに、postgreSQL で新しいエラーが発生するため、元の単純な名前付きスコープに戻りました。最初のスコープのポイントは、「admin」という名前のロールを持つすべてのユーザーを取得することであり、2 番目のスコープは、「admin」以外のロールを持つユーザーを取得することです。これを他のモデルの検索ロジックで使用すると、SQLite では期待どおりに動作しますが、postgreSQL では動作しません (例: User.user_role_assignments_has_admin_role)。

これらの named_scopes を postgreSQL で動作するように変更するにはどうすればよいですか?

4

1 に答える 1

0

Postgres は GROUP BY 句に関して sqlite3 よりもはるかにうるさいです。

すべての user_role_assignments 列名を GROUP BY 句に追加する必要があります。

class UserRoleAssignment < ActiveRecord::Base
  belongs_to :user
  belongs_to :user_role

  named_scope :has_admin_role, 
    :joins => :user_role, 
    :conditions => "user_roles.name = 'admin'",
    :group => "user_role_assignments.id, user_role_assignments.user_id, user_role_assignments.user_role_id" 

  named_scope :has_non_admin_role, 
    :joins => :user_role, 
    :conditions => "user_roles.name <> 'admin'",
    :group => "user_role_assignments.id, user_role_assignments.user_id, user_role_assignments.user_role_id" 
end

それがうまくいかない場合は、次にこれを試すことができます (ただし、うまくいくかどうかはわかりません)。

class UserRoleAssignment < ActiveRecord::Base
  belongs_to :user
  belongs_to :user_role

  named_scope :has_admin_role, 
    :joins => :user_role, 
    :conditions => "user_roles.name = 'admin'",
    :group => "user_role_assignments.*" 

  named_scope :has_non_admin_role, 
    :joins => :user_role, 
    :conditions => "user_roles.name <> 'admin'",
    :group => "user_role_assignments.*" 
end
于 2010-09-10T03:03:28.920 に答える