Использование ruby в помощниках проверки рельсов внутри пользовательских проверок - PullRequest
0 голосов
/ 14 апреля 2020

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

Обычно мы видим следующее.

class User < ApplicationRecord
   validates :foo, inclusion: { in: ['some', 'array'] }
   validates :bar, inclusion: { in: ['another', 'array'] }
   validates :moo, inclusion: { in: ['one_more', 'array'] }
end

У меня много таких проверок в моей модели, и я хочу DRY проверить их. Поэтому я попробовал следующее, но я получаю сообщение об ошибке undefined method 'validates' for #User:0x00007fdc10370408.

class User < ApplicationRecord
  VALIDATION_ENUMS = {
    foo: %w[foo1 foo2],
    bar: %w[bar1 bar2]
  }.freeze

  validate :validate_enums

  def validate_enums
    VALIDATION_ENUMS.each_key do |attribute|
      validates attribute, inclusion: { in: VALIDATION_ENUMS[attribute] }
    end
  end
end

Как мне получить доступ к вспомогательным методам ActiveModel :: Validations из моей функции?

Или есть лучший способ сделать это?

Ответы [ 2 ]

1 голос
/ 14 апреля 2020

Помните, что validates - это метод класса, который выполняется только один раз, когда класс загружается, чтобы установить sh, что будет проверено. validate вызывает метод экземпляра.

Лучшим способом может быть выполнение кода DRY сразу при загрузке класса.

class User < ApplicationRecord
 validate_enums = {
    foo: %w[foo1 foo2],
    bar: %w[bar1 bar2]
  }.freeze

   validate_enums.each do |key, array|
     validates key, inclusion: { in: array }
   end

Обратите внимание, что вы не ссылаетесь validate_enums когда-либо снова, вам не нужно делать это константой класса, вот почему я этого не сделал.

Но вы на самом деле не сохраняете никаких строк и не добавляете сложности, поэтому я бы придерживался с явным validates, я сам.

0 голосов
/ 14 апреля 2020

Такой подход не сработает. Методы проверки - это методы класса, которые изменяют сам класс, когда вы пишете метод экземпляра, который вызывается для экземпляра класса при вызове #valid?.

Если вы хотите динамически добавить существующие проверки в класс, вам нужно создать метод класса:

class User < ApplicationRecord
  def self.add_inclusion_validations(hash)
    # don't use each_key if you're iterating over both keys and values
    hash.each do |key, values|
      validates_presence_of key, in: values
    end
  end

  add_inclusion_validations(
    foo: %w[foo1 foo2],
    bar: %w[bar1 bar2]
  )
end

Конечно, вы также можете просто полностью пропустить метод:

class User < ApplicationRecord
  {
    foo: %w[foo1 foo2],
    bar: %w[bar1 bar2]
  }.each do |key, values|
      validates_presence_of key, in: values
  end
end

Если вам вместо этого нужно написать метод проверки, который использует существующую функциональность других проверок, вы бы создали подкласс ActiveRecord::Validator или ActiveRecord::EachValidator и использовали там существующие проверки. Но вам действительно нужно начать с чтения руководств и документации по API, чтобы у вас было общее представление о том, как это работает.

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