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

我已经尝试了命名范围的许多不同变体(添加一个 :have 子句,添加额外的分组)但是每次我添加一些东西时,postgreSQL 中都会出现一个新错误,所以我已经恢复到我原来的简单命名范围。第一个作用域的重点是检索所有角色名称为“admin”的用户,第二个作用域是检索具有除“admin”以外的角色的用户。我将它与其他模型的搜索逻辑一起使用,它在 SQLite 中按预期工作,但在 postgreSQL 中没有(例如 User.user_role_assignments_has_admin_role)。

How can I modify these named_scopes to work with postgreSQL?

4

1 回答 1

0

Postgres is much more picky about GROUP BY clauses than sqlite3.

You'll have to add all of the user_role_assignments column names to your GROUP BY clause:

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

If that doesn't work, you can try this next (but I'm not sure if it will work).

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 回答