Проверка атрибута на основе роли пользователя - PullRequest
0 голосов
/ 20 сентября 2018

Я хочу проверить атрибут amount.Разрешенная сумма зависит от роли администратора.Поэтому необходимо обновлять (или нет) в зависимости от роли администратора, который обновляет средства, а не пользователя, которому принадлежат средства.

  class UserFund
    validate :validate_amount

      def validate_amount
        if current_user.admin?
          amount <= 100
        elsif current_user.cs?
          amount <= 25
        elsif current_user.staff?
          amount <= 15
        end
      end
    end

User has_many :user_funds UserFund belongs_to :user НО current_user! = Пользователь.пользователь, который редактирует фонды (current_user), является администратором, а не пользователем, которому принадлежат фонды.

Но вы не должны использовать current_user в модели, я думаю.Какова будет лучшая практика для решения этой проблемы?

Ответы [ 3 ]

0 голосов
/ 20 сентября 2018

Если current_user не имеет отношения к UserFund объекту, который будет сохранен, то я думаю, что было бы лучше преобразовать валидатор в отдельный метод.А поскольку этот метод подразумевает некоторые знания о User классе, имеет смысл переместить его в User класс как метод экземпляра (или если admin и user различны, то в класс admin):

class User < ApplicationRecord
  def amount_too_big?(amount)
    return admin? && amount > 100 || cs? && amount > 25 || staff? && amount > 15
  end
end

и вызовите этот метод в контроллере перед сохранением UserFund объекта:

if current_user.amount_too_big?(amount)
  # Render error message about unacceptably big funds 
  return
end

Почему так?Весьма вероятно, что объект current_user определяется некоторым фильтром контроллера, поэтому он доступен только в контроллерах и представлениях.А UserFund объект имеет доступ только к User модельным фондам, к которым он относится.Предоставление доступа к current_user из UserFund возможно только путем вызова другого метода и передачи current_user в качестве аргумента, который не принимается при проверке.

Другой момент: при запуске из консоли rails, current_user не определено.UserFund объект не будет знать, что такое current_user, поэтому вообще не может его использовать.

0 голосов
/ 20 сентября 2018

Я думаю, что это хороший случай для "контекста" проверок https://guides.rubyonrails.org/active_record_validations.html#on

Вы можете определять разные проверки в разных контекстах (то есть: разные роли).

validate :admin_amount, on: :admin
validate :cs_amount, on: :cs
validate :staff_amount, on: :staff

def admin_amount
  errors.add(:amount, 'is too long') if amount > 100
end

def cs_amount
  errors.add(:amount, 'is too long') if amount > 25
end

def staff_amount
  errors.add(:amount, 'is too long') if amount > 15
end
#of course, you can DRY this a lot, i'm just repeating a lot of code to make it clearer

Теперь вы можете сохранить запись (или проверить, является ли она действительной), используя клавишу «context».

fund = UserFund.new
fund.save(context: current_user.role.to_sym) #assuming the role is a string
# of fund.valid?(context: current_user.role.to_sym)
0 голосов
/ 20 сентября 2018

Если эта проверка основана на данных из той же модели, вы можете просто пропустить current_user.Например, если предположить, что это проверка для модели User с методами экземпляра admin?, cs? и staff?, ее можно записать как:

class User < ApplicationRecord
  validate :validate_amount

  def validate_amount
    if admin?
      amount <= 100
    elsif cs?
      amount <= 25
    elsif staff?
      amount <= 15
    end
  end
end

Однако метод ActiveRecord valid?проверит, что коллекция ошибок пуста, поэтому ваши пользовательские методы проверки должны добавить к ней ошибки, если вы хотите, чтобы проверка завершилась неудачей:

class User < ApplicationRecord
  validate :validate_amount

  def validate_amount
    if admin? && amount > 100 || cs? && amount > 25 || staff? && amount > 15
      errors.add(:amount, "is too big")
    end
  end
end

Подробнее здесь: https://guides.rubyonrails.org/active_record_validations.html#custom-methods

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...