Rails模型-使用模板创建

时间:2018-09-12 19:19:21

标签: ruby-on-rails ruby

在我的应用程序中,我可以创建“课程”,并且每个课程都包含多个“组件”。现在,我正在尝试实现从模板创建课程的功能,以便它将模板中的组件复制/重新创建到新课程。

我的component的数据结构是这样的:

{
  id: 123,
  type: Section,
  content: "abc",
  section_id: null
},
{
  id: 124,
  type: Question,
  content: "abc?",
  section_id: 123
},
{
  id: 125,
  type: Section,
  content: "defg",
  section_id: null
},
{
  id: 126,
  type: Outcome,
  content: "defg?",
  section_id: 125
},

所需结果:

{
  id: 993,
  type: Section,
  content: "abc",
  section_id: null
},
{
  id: 994,
  type: Question,
  content: "abc?",
  section_id: 993
},
{
  id: 995,
  type: Section,
  content: "defg",
  section_id: null
},
{
  id: 996,
  type: Outcome,
  content: "defg?",
  section_id: 995
},

您会发现Question / OutcomeSectionsection_id之间存在关联。

在我的课程模型中,我遍历了模板的组件,并为新创建的课程组件获取了它们的属性。

class Lesson

  attr_accessor :lesson_template_id

  # == Callbacks ==============================
  after_create :create_template_components, if: :lesson_template_id_present?

  def lesson_template
    if @lesson_template_id != ''
      LessonTemplate.find(@lesson_template_id)
    else
      nil
    end
  end


private

  def lesson_template_id_present?
    !!@lesson_template_id
  end


  def create_template_components
    if lesson_template
      lesson_template.components.each do |c|
        self.components.create!({
          type: c.type,
          content: c.content,
          section_id: c.section_id
        })
      end
    end
  end

但是问题是section_id是不正确的,因为新创建的节将具有新的/不同的id。如何修改模型以确保正确创建组件?

2 个答案:

答案 0 :(得分:1)

创建Section对象的浅表副本,然后创建它并将其附加到新组件上。

def create_template_components
  if lesson_template
    lesson_template.components.each do |c|
      newSection = if c.type == 'Question'
        c.section && c.section.dup
      else
        nil
      end
      newSection.save if newSection
      self.components.create!({
        type: c.type,
        content: c.content,
        section_id: newSection.try(:id)
      })
    end
  end
end

#dup

  

重复对象没有未分配ID ,并被视为记录。注意   这是一个“浅”副本,因为它复制了对象的属性   仅,而不是其关联。 “深层”副本的范围是应用程序   具体的,因此留给应用程序来实施   根据其需要。 dup方法不保留时间戳   (创建|更新)_(在|开)。

答案 1 :(得分:1)

我的想法是复制部分的外部循环。在内部循环中重新创建其他组件(结果和问题)时,会使用 new 部分ID,这将使关联保持更新和正确。

lesson_template.sections.each do |old_section|
  # outer loop: recreate section
   new_section = self.sections.create!({
    content: old_section.content
  })
  old_section.components.each do |old_non_section_component|
    # inner loop: recreate all components belonging to section
    self.component.create!({
      type: old_non_section_component.type,
      content: old_non_section_component.content,
      # use id from newly-created section, keeping correct association
      section_id: new_section.id # <-- IMPORTANT
    })
  end
end

可能值得更新您的问题,以提及您正在使用自引用单表继承或这种技术的名称。这不是我经常看到的东西。