Rails named_scope ошибка в postgreSQL, работает в SQLite - PullRequest
0 голосов
/ 10 сентября 2010

У меня есть следующие модели для привязки пользователей к ролям:

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

Я пробовал много разных вариаций именованной области (добавляя предложение: Имея, добавляя дополнительные группировки), но каждый раз, когда я что-то добавляю, в postgreSQL возникает новая ошибка, поэтому я возвращаюсь к своим оригинальным простым named_scopes. Задача первой области - получить всех пользователей, у которых есть роль с именем «admin», а вторая - получить пользователей, у которых есть роль, отличная от «admin». Я использую это с searchlogic из других моделей, и он работает, как и ожидалось, в SQLite, но не в postgreSQL (например, User.user_role_assignments_has_admin_role).

Как я могу изменить эти named_scopes для работы с postgreSQL?

1 Ответ

0 голосов
/ 10 сентября 2010

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
...