Rails Arel соединяет соединительные столы - PullRequest
1 голос
/ 01 октября 2019

Поэтому я пытаюсь фильтровать, когда имя роли пользователя совпадает с именем региона, и я застреваю в объединении Arel между тремя таблицами.

У пользователя есть имя, role_id, email и т. Д. Пользователь has_many ролей. Ролевая таблица имеет идентификатор и имя. Регион имеет название, местоположение. Регион не принадлежит пользователю.

Пример:

  • Идентификатор Джона Смита: 20, идентификатор роли: 15
  • Идентификатор роли: 15, имя: Северо-западный регион Тихого океана
  • Идентификатор региона: 5, имя: Тихоокеанский Северо-Запад

Так что я подумал бы присоединиться к региону, где имя региона совпадает

Что у меня есть:

scope :for_user, lambda { |user|
 if user.super_admin?
  self
 else
  joins(:region).where(
  Region.arel_table[:name].matches(Role.arel_table[:id].eq(User.arel_table[:role_id]))
 )
 end
}

def viewable_by?(user)
 return user.super_admin? || user&.role.name == region.name
end

Я ссылаюсь на for_user и viewable_by в контроллере событий

def index
 @events = search_event.paginate(page: params[:page])
end

def search_event
 Event.order(sortable_query)
    .for_user(current_user)
    .includes(:region)
    .advanced_search(
     params[:search],
     params[:region_id]
    )
end

def load_event
 @event = Event.find_by!(id: params[:id])
 raise DeniedError unless @event.viewable_by?(current_user)
end

Я подумал, что это может быть проблема совпадений, поэтому я тоже попробовал. Возникает та же проблема: нет неявного преобразования Symbol в String.

Идея состоит в том, что пользователю назначена роль, и он может просматривать только те события, имя которых соответствует этой роли.

Так что, если Джон Смит войдет в систему, он увидит только эти события на Тихоокеанском северо-западе.

Ответы [ 2 ]

2 голосов
/ 01 октября 2019

Я, возможно, не полностью ухватился за ваш вопрос, но похоже, что вы должны быть в состоянии сделать что-то вроде:

Event < ApplicationRecord
  belongs_to :region

  class << self

    def for_user(user)
      return self if user.super_admin?
      joins(:region).where(region: {id: Region.where(name: user.role.name)})
    end

  end
end

Это должно вернуть все Event s, где event.region_id содержитid любого Region с name, совпадающим с name в user role.

Подробнее об этом можно узнать в Указание условий в присоединенииТаблицы из документов .

Я вижу, что у вас есть подход, который работает с использованием arel_table. Я оставлю это здесь как не arel_table, не lambda, не scope подход.

Также я еще раз повторю из своего комментария, что docs state:

Использование метода класса является предпочтительным способом получения аргументов для областей.

0 голосов
/ 01 октября 2019

На жаворонке я пробовал, и это сработало:

joins(:region).where(
              Region.arel_table[:name].matches("%#{user&.role.name}%")
            )
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...