#ruby-on-rails #activerecord #sti
#ruby-on-rails #activerecord #sti
Вопрос:
Я реализовал STI для разделения 2 типов объектов навыков: DefinedSkill и DeployedSkill. Они физически очень близки, но управляются по-разному.
Одним из методов DefinedSkill является метод deploy , который создает почти идентичный DeployedSkill .
Изначально я написал это:
def deploy
@template_skill = DefinedSkill.find(params[:id])
if @template_skill.status.code == "ACCEPTED"
@deployed_skill = @template_skill.deep_clone include: [:translations]
@deployed_skill.type = 'DeployedSkill'
---
@deployed_skill.save
end
end
Но это создает объект класса DefinedSkill, хотя я пытаюсь присвоить атрибут type .
Затем я попытался работать на уровне атрибутов и написал это:
def deploy
@template_skill = DefinedSkill.find(params[:id])
if @template_skill.status.code == "ACCEPTED"
@deployed_skill = DeployedSkill.new(@template_skill.attributes.except(:id, :type))
# @deployed_skill.type = 'DeployedSkill' (useless as type is managed by STI feature)
---
@deployed_skill.save
end
end
Но это приводит к следующей ошибке:
ActiveRecord::SubclassNotFound (Invalid single-table inheritance type: DefinedSkill is not a subclass of DeployedSkill)
Итак, это мой вопрос: как я могу создать объект родственного класса в контексте STI?
Комментарии:
1. В первом примере у него все еще есть класс DefinedSkill даже после перезагрузки объекта?
2. Становится! метод также может быть полезен: apidock.com/rails/ActiveRecord/Persistence/becomes!
Ответ №1:
Вместо настройки @deployed_skill = type
попробуйте использовать becomes
метод:
@deployed_skill.becomes(DeployedSkill)
Ответ №2:
Большое спасибо msencenb и felipeecst за то, что указали мне путь. Прочитав документ и попробовав, я пришел к выводу, что существующий объект не может быть преобразован, но преобразование класса должно быть выполнено при создании нового экземпляра.
Решение, которое я применил, это:
@deployed_skill = @template_skill.becomes!(DeployedSkill).deep_clone include: [:translations]
что решило мою проблему.