Я использую:
- Ruby 2.6.5
- Рельсы 6.0.2.1
- PostgreSQL 11
Проблема:
Я пытаюсь создать запрос Scope для Pundit, чтобы проверить, есть ли у пользователя доступ к секрету (паролю), который он хочет посетить. Я пытался присоединиться / включить вложенных пользователей в команды / проекты и пользователей, у которых есть доступ к паролю таким образом (запись из того, что я помню):
Что я пытался
# secret_policy.rb
class SecretPolicy < ApplicationPolicy
class Scope < Scope
def resolve
test = scope.includes(:projects => {:teams => :users}).includes(:teams =>
{:users}).includes(:users)
test.where(projects: {teams: {users: {id: user}}})
.or(test.where(teams: {users: {id: user}}).or(test.where(users: {id: user})))
end
end
# [...]
end
, а затем в контроллере:
# secret_controller.rb
class SecretController < ApplicationController
[...]
def show
@secret = policy_scope(Secret).find(params[:id])
end
[...]
end
, который должен был объединить все связанные сущности с Secret
моделью и выполнить вложенные запросы, но в конце было то, что даже 1026 * работал должным образом, включая все необходимые данные, в конце в предложении where
использовалось одно и то же имя объединения для выполнения запроса: users
, что неверно, поскольку должны вызываться разные имена соединений, содержащие необходимые данные.
Подробнее:
У меня есть такая структура:
# user.rb
class User < ApplicationRecord
has_and_belongs_to_many :teams
has_and_belongs_to_many :secrets
end
# secret.rb
class Secret < ApplicationRecord
belongs_to :user
has_and_belongs_to_many :teams
has_and_belongs_to_many :users
has_and_belongs_to_many :projects
end
# team.rb
class Team < ApplicationRecord
belongs_to :project
belongs_to :user
has_and_belongs_to_many :users
has_and_belongs_to_many :secrets
end
# project.rb
class Project < ApplicationRecord
belongs_to :user
has_many :teams
has_and_belongs_to_many :secrets
end
Я вроде новичок в Rails (ActiveRecords), поэтому мое отображение может быть немного неправильным. Вот что должно быть просто, чтобы прояснить:
Пользователь:
- может быть владельцем паролей
- может иметь доступ к паролям, предоставленным другими пользователями
- может принадлежать командам
- может принадлежать проектам
Секрет:
- может принадлежать 1 пользователю
- может использоваться несколькими командами
- может использоваться многими пользователями (не включая владельца. У владельца уже есть доступ)
- может использоваться многими проектами
Команда:
- может принадлежать 1 проекту
- принадлежит только 1 пользователю
- много пользователей могут присоединиться к команде
- много секретов может быть общий доступ к команде
Проекты:
- принадлежит только 1 пользователю
- может иметь много команд (уникально)
- много секретов может использоваться в проектах
Я нашел много ресурсов, рассказывающих о случае, когда вы можете сделать это с помощью вложенных отношений, но обычно это делается с помощью в предложении where находится только 1 ресурс, поэтому с неправильно использованными объединениями проблем не возникало. Я собирался сдаться и попытаться переписать это на родном SQL, но я считаю, что должно быть что-то.