Как изменить тип записи и запустить проверки правильности класса в рельсах, используя столбец типа? - PullRequest
1 голос
/ 10 февраля 2011

У меня есть модель, которая использует наследование одной таблицы и имеет разные типы (учебный год типа семестр или квартал), и у каждого типа есть свои валидации.Если пользователь пытается изменить тип записи, он может выбрать тип учебного года из выпадающего списка и внести изменения.однако, если пользователь меняет тип, я не могу понять, как запустить новые проверки классов, а не старые проверки.Например, мой код выглядит следующим образом:

@school_year = SchoolYear.find(params[:id])
respond_to do |format|
  if SchoolYear::SUBCLASSES.include? params[:school_year]['type']
    @school_year[:type] = params[:school_year]['type']
  else
    raise "Invalid type"
  end

  if @school_year.update_attributes(params[:school_year])
   # done
  else
   # validation problem?
  end

теперь, если типом года был семестр, а пользователь меняет его на квартал, я ожидаю, что проверки QuarterSchoolYear будут выполняться, а не проверки семестра.Как внести изменения в код, чтобы он работал?

Ответы [ 3 ]

3 голосов
/ 26 ноября 2014

Это старый, но исправление и улучшение по предложению @ Arsen7, лучший способ перезагрузить ваш объект как новый тип - это использовать следующий метод ActiveRecord (который сделан по этой самой причине), и онпотребовать от вас сохранить объект после изменения его типа.Таким образом, вы не обращаетесь к базе данных дважды:

[..]
if type_differs_and_is_acceptable_to_change
  @school_year.type = params[:school_year][:type]
  @school_year = @school_year.becomes(@school_year.type.constantize)
end
if @school_year.update_attributes...
3 голосов
/ 10 февраля 2011

Полагаю, вам следует перезагрузить объект после изменения типа. Простое присвоение нового значения атрибуту type не изменит класс ruby ​​объекта. Конечно, когда вы сохраняете объект сразу после изменения типа, будут использоваться старые проверки.

Вы можете попытаться обновить атрибут type в базе данных, а затем загрузить объект. Что-то вроде:

[..]
if type_differs_and_is_acceptable_to_change
  SchoolYear.update_all(
    ['type = ?', params[:shool_year][:type] ],
    ['id = ?',@school_year.id ]
  )
  @school_year = SchoolYear.find(@school_year.id)
end
if @school_year.update_attributes...

Не забудьте: введите NOT в attr_accessible для этого класса.

Кроме того, меня немного беспокоит изменение типа объекта, но это может быть только мой личный страх. :)

1 голос
/ 11 февраля 2011

Вам нужно создать экземпляр с правильным типом модели для запуска проверок.Я не вижу способа сделать это, кроме как сохранить с новым типом и найти его снова:

new_type = params[:school_year]['type']
@school_year[:type] = new_type
@school_year.save!
@school_year = new_type.constantize.find(@school_year.id)
@school_year.update_attributes(params[:school_year])

Возможно, вы захотите поместить это в транзакцию, чтобы можно было откатить изменение типаесли update_attributes терпит неудачу.

...