【问题标题】:Rails named_scope error in postgreSQL, works in SQLitepostgreSQL中的Rails named_scope错误,适用于SQLite
【发布时间】:2010-09-10 00:10:39
【问题描述】:

我有以下模型将用户与角色相关联:

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”以外的角色的用户。我将它与其他模型的 searchlogic 一起使用,它在 SQLite 中按预期工作,但在 postgreSQL 中没有(例如 User.user_role_assignments_has_admin_role)。

如何修改这些 named_scope 以使用 postgreSQL?

【问题讨论】:

    标签: ruby-on-rails postgresql named-scope


    【解决方案1】:

    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
    

    【讨论】:

    • 这不太奏效,但让我做了部分工作。还必须将 user_role_assignments 的每一列添加到“select”子句中。该命名范围在从 UserRoleAssignments 使用时有效,但在与其他模型链接时无效,因此最终不是很有用。我正在编写几个不同模型中的命名范围,而不是依赖于链接这个。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-25
    • 2013-02-26
    • 1970-01-01
    相关资源
    最近更新 更多