Оптимизируйте эту проверку и инициализацию

ruby-on-rails validation

166 просмотра

2 ответа

У меня есть очень специальное решение на сайте Rails 4.2, где у меня много сложных вычислений. Проблемы, которые я имею, рассматривают проверку и инициализацию.

Я создаю отдельный класс для каждого вычисления, и все они выглядят практически одинаково, как показано ниже (код упрощен, чтобы его было легче пропустить). Я немного нахожусь здесь, потому что я не делал ничего подобного раньше, и некоторые из них - это «проб и ошибок», но это работает.

Я использую код в контроллерах и т.д., используя запросы PUT, как это:

C_9.calculate_me(params)

где params может выглядеть так:

{"utf8"=>"✓", "_method"=>"put", "authenticity_token"=>"...", "start_date"=>"2016-08-20", "nbr_of_days"=>"90", "commit"=>"Calculate", "controller"=>"calculations", "action"=>"result", "id"=>"9"}

Код

class C_9
  include ActiveModel::Validations  
  include ValidationFunctions     

  attr_accessor :start_date, :nbr_of_days
  validates_length_of :start_date, :minimum => 8, :message => "value_is_not_a_proper_date"  
  validates_numericality_of :nbr_of_days, :greater_than => 0, :message => "value_must_be_number_over_zero"
    validate :validate_buggy_start_date   

  def initialize(params = {}, options = {}) 
    @start_date = params[:start_date]
    @nbr_of_days = params[:nbr_of_days]
  end 

  def calculate_me(params)
    @start_date = @start_date.to_date

      result_date = @start_date +  @nbr_of_days.day    
  end   

end

Функции проверки

Это проверочные функции, которые являются общими для многих различных вычислений.

    def validate_buggy_start_date # Don't know why the validate_start_date will not work for this...
        errors.add(:start_date, 'value_is_not_a_proper_date') unless validate_date(start_date)
    end

  def validate_date(this_date)
    begin
      Date.parse(this_date)
      this_date.to_date
    rescue
      proper_date = false
    else   
      proper_date = true
    end

конец

С чем мне нужна помощь

Система работает, но есть некоторые проблемы, которые мне нужно оптимизировать:

  1. Есть ли способ, которым я могу проверить дату в ValidationFunction без необходимости создавать новую функцию (например def validate_buggy_start_date) для каждой даты, которая называется по-разному. Есть ли способ, которым я могу использовать validate_date()-функцию прямо из C_9 (то есть без необходимости проходить validate_buggy_start_date)?

  2. Я хотел бы инициализировать параметры и в то же время убедиться, что они, например, float / string / date и т variable.to_date. Д. Я не могу, однако, так как инициализация выполняется до валидации, поэтому это приведет к сбою приложения. Теперь я решаю эту проблему, восстанавливая их в calculate_me()-функции, но она не слишком СУХАЯ. Есть ли способ обойти это?

  3. По какой-то причине, которую я не могу понять, мне нужно назвать переменные точно так же, как имя атрибута, например, @nbr_of_daysнужно назвать именно это. Если я назову его, @day_numbersон не будет работать (значение не будет установлено). Почему это так? Есть ли более разумный способ обойти это?

Короче, пожалуйста, помогите мне сделать эту функциональность умнее и более СУХОЙ, если это возможно!

Автор: Christoffer Источник Размещён: 08.11.2019 11:11

Ответы (2)


1 плюс

Решение

Расширяя ответ SteveTurczyn: (без исправления в ActiveRecord :: Base)

Вы можете создавать собственные валидаторы для моделей ActiveRecord. Смотрите руководства

Так что в вашем случае это будет решение:

# app/models/date_validator.rb
class DateValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    Date.parse(value.to_s)
  rescue ArgumentError
    record.errors[attribute] << "value_is_not_a_proper_date"
  end
end

А затем используйте валидатор в вашей модели:

# app/models/c_9.rb
class C_9
  include ActiveModel::Validations
  validates_with DateValidator, attributes: [:start_date]
end

Пример использования:

c = C_9.new(start_date: "2016-12-12", end_date: "2014-01-22")
c.valid? # => false
c.start_date # => Mon, 12 Dec 2016 (Date object)
c.other_date = "2016-07-23"
c.valid? # => true
c.other_date # => Sat, 23 Jul 2016
Автор: siegy22 Размещён: 29.08.2016 08:06

0 плюса

Вы можете создавать свои собственные проверки, а не просто метод проверки. Это позволит вам сделать ...

validates_buggy_date :start_date, :end_date, :other_date

создать файл config / initializers / validates_buggy_date.rb

ActiveRecord::Base.class_eval do
  def self.validates_buggy_date(*columns)
    validates_each(columns, {}) do |record, attribute, value|
      begin
        Date.parse(value)
        value.to_date
      rescue
        record.errors[attribute] << 'value_is_not_a_proper_date'
      end
    end
  end
end
Автор: SteveTurczyn Размещён: 24.08.2016 11:21
Вопросы из категории :
32x32