Дата подтверждения даты рождения в Rails - PullRequest
0 голосов
/ 16 июня 2020

Я хочу подтвердить своего пользователя для его регистрации. У меня уже есть дата их рождения, хранящаяся в моей базе данных, поскольку они были отправлены клиентом API. Я хочу, чтобы пользователь подтвердил дату своего рождения, поэтому я настроил проверку подтверждения Rails. В моих параметрах указаны date_of_birth_confirmation, и это то, что я использую в своей форме.

          <%= f.label :date_of_birth_confirmation, "DATE OF BIRTH (MM/DD/YYYY)" %>
          <%= f.date_select :date_of_birth_confirmation, ...

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

  "user" => { "date_of_birth_confirmation(2i)"=>"10", "date_of_birth_confirmation(3i)"=>"5", "date_of_birth_confirmation(1i)"=>"1927" }

, что, как я полагаю, ожидается при выборе даты. Насколько я понимаю, если бы это был только пользователь date_of_birth, а не его dob_confirmation, Rails преобразовал бы его в объект даты, когда он был сохранен в базе данных.

Но когда сравнение выполняется с фактическим значением date_of_birth, оно всегда терпит неудачу, даже если они совпадают. Я предположил, что это из-за того, как работает проверка confirmation. Поскольку date_of_birth_confirmation - это всего лишь строка, означающая, что мне нужно преобразовать dob_confirmation в дату, чтобы их можно было сравнить, так что это оказалось моим решением

  def verification_params
    params[:user][:date_of_birth_confirmation] = format_date_of_birth_confirmation
    params.require(:user).permit(
      :date_of_birth_confirmation
    )
  end

  # Format date_of_birth_confirmation to be a date so the comparison can be made with date_of_birth
  def format_date_of_birth_confirmation
    year = params[:user].delete("date_of_birth_confirmation(1i)")
    month = params[:user].delete("date_of_birth_confirmation(2i)")
    day = params[:user].delete("date_of_birth_confirmation(3i)")

    return nil unless year.present? && month.present? && day.present?

    "#{year}-#{month}-#{day}".to_date
  end

Это работает, когда я его тестирую. Что хорошо!

Но я хотел знать, есть ли лучшее решение? Я не совсем уверен, есть ли более "железный" способ go по этому поводу.

Ответы [ 3 ]

1 голос
/ 17 июня 2020

Короткий ответ - нет, нет более прямого пути 'rails-y', чем то, что вы делаете, поскольку date_select всегда просто возвращает необработанные выбранные значения в виде независимых строк.

0 голосов
/ 18 июня 2020

Я закончил тем, что изменил logi c контроллера, чтобы вместо этого поместить logi c форматирования date_of_birth_confirmation в модель, которая, вероятно, там лучше подходит.

0 голосов
/ 16 июня 2020

Используйте проверки .

Сначала убедитесь, что date_of_birth - это дата, а не пустая и разумная. Я использую validates_timeliness .

class User < ApplicationRecord
  # Validate the actual date of birth.
  validates :date_of_birth,
    confirmation: true,
    presence: true,
    timeliness: {
      type => :date,
      # They're not from the future.
      on_or_before: lambda { Date.current },
      # They're not 120.
      after: '1900-01-01'
    }
end

Затем создайте модель формы для проверки и обработки ввода формы. Включив ActiveModel :: Model , мы получим класс, который может делать многие из тех же вещей, что и запись, но без таблицы.

class DateForm
  include ActiveModel::Model

  attr_accessor :year, :month, :day

  validates :year, :month, :day
    # They must be positive integers
    presence: true,
    numericality: { only_integer: true, greater_than_or_equal_to: 1 }

  def to_date
    Date.new(year, month, day)
  end
end

Затем вы можете использовать DateForm в своем контроллере для проверки формы и передачи даты пользователю.

def new
  @birth_date = DateForm.new
  @birth_date_confirmation = DateForm.new
  @user = User.new
end

def create
  @user = User.new(params[:user])
  @birth_date = DateForm.new(
    year = params[:birth_date]["date_of_birth(1i)"]
    month = params[:birth_date]["date_of_birth(2i)"]
    day = params[:birth_date]["date_of_birth(3i)"]
  )
  @birth_date_confirmation = DateForm.new(
    year = params[:birth_date_confirmation]["date_of_birth_confirmation(1i)"]
    month = params[:birth_date_confirmation]["date_of_birth_confirmation(2i)"]
    day = params[:birth_date_confirmation]["date_of_birth_confirmation(3i)"]
  )
  render 'new' if !@birth_date.valid? || !@birth_date_confirmation.valid?

  @user.date_of_birth = @birth_date.to_date
  @user.date_of_birth_confirmation = @birth_date_confirmation.to_date

  if @user.save
    redirect_to @user
  else
    render 'new'
  end
end

И используйте @birth_date и @birth_date_confirmation в вашем представлении как их собственные формы.

form_for(@birth_date, as: :birth_date do |f|
  ...
end

form_for(@birth_date_confirmation, as: :birth_date_confirmation) do |f|
  ...
end

Это также дает вам модель, которую вы можете легко протестировать, упростив тестирование контроллера.

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