Извлечение даты вручную из Rails помощников объекта модели даты - PullRequest
0 голосов
/ 10 февраля 2020

Я работаю с формой Rails (v5.1), в которой используются помощники даты объекта модели , которые представляют даты, выбранные с помощью трех выпадающих меню (д / м / г), в качестве параметров типа

{..."next_inspection_date(3i)"=>"14", "next_inspection_date(2i)"=>"8", "next_inspection_date(1i)"=>"2019"...}

By Rails magi c, MyModel.new(params) знает, что с этим делать, но у меня есть несколько дополнительных логи c Я хотел бы применить, когда форма отправлена. Я мог бы написать что-то вроде

TimeWithZone.parse("#{params[:next_inspection_date(1i)]}-#{params[:next_inspection_date(2i)]}-#{params[:next_inspection_date(3i)]}")

, чтобы извлечь дату, но это будет быстро повторяться с несколькими датами. Для DRY это вручную, скорее всего, даст что-то довольно лаконичное для чтения и представит множество логик c, которые действительно отвлекут от того, что я пытаюсь сделать. Мне было интересно, есть ли в Rails встроенный помощник, чтобы я мог написать что-то вроде

MyModel.next_inspection_date = useful_date_helper(params, :next_inspection_date)

Руководства Rails просто утверждают, что такие методы, как update или new понимают, что делать с этими параметрами .

Заранее благодарим за любые предложения.

1 Ответ

0 голосов
/ 10 февраля 2020

Эти атрибуты известны как многопараметрические атрибуты, и функциональность, к сожалению, скрыта глубоко внутри ActiveRecord :: AttributeAssignment . Но вы можете просто использовать реализацию ActiveRecord, не сохраняя запись:

next_inspection_date = MyModel.new(params.permit(:next_inspection_date)).next_inspection_date

Вы также можете скопировать ее, что действительно более интересно, если вы создаете что-то вроде объектов запроса или виртуальных моделей:

module MultiparamExtractor
  # Extracts 'i' from foo(3i)
  REGEXP = /\w*\(\d*(?<type>[a-z])\)/.freeze

  # Extracts an array of cast values from a hash containing one multi-parameter attribute
  # @param hash [Hash|ActionController::Parameters]
  # @return [Array]
  def self.call(multi_params)
    # coerce input into a hash
    if multi_params.respond_to?(:permit)
      multi_params.dup.permit!.to_h  # .dup prevents mutating the arguments
    else
      multi_params
    end.sort # sorts by key <=> other key and returns an array
       .map do |(key,value)|
         typecast(value, REGEXP.match(key)[:type])
       end
  end

  private
  # @todo handle casting more types
  def self.typecast(value, type)
    case type
    when 'i'
      value.to_i
    else
      value
    end
  end
end
# Just for the sake of the example
params = ActionController::Parameters.new("next_inspection_date(3i)"=>"14", "next_inspection_date(2i)"=>"8", "next_inspection_date(1i)"=>"2019", "foo" => "bar")
date = Date.new(*MultiparamExtractor.call(params.permit(:next_inspection_date))).in_time_zone
# Wed, 14 Aug 2019 00:00:00 UTC +00:00
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...