Ruby on rails Rails模型-使用模板创建

Ruby on rails Rails模型-使用模板创建,ruby-on-rails,ruby,Ruby On Rails,Ruby,在我的应用程序中,我有能力创建“课程”,每个课程包含几个“组件”。现在,我正在尝试实现从模板创建课程的功能,以便它可以将模板中的组件复制/重新创建到新课程中 我的组件的数据结构如下所示: { id: 123, type: Section, content: "abc", section_id: null }, { id: 124, type: Question, content: "abc?", section_id: 123 }, { id: 125,

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

我的
组件的数据结构如下所示:

{
  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
},
您可以看到
问题
/
结果
部分
部分
之间存在关联

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

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

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

创建
部分
对象的浅层副本,然后创建它并将其附加到新组件

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

被复制的对象没有分配id,并被视为新记录。注 这是一个“浅”副本,因为它复制对象的属性 只是,不是它的关联。“深度”副本的范围取决于应用程序 特定的,因此留给应用程序来实现 根据需要。dup方法不保留时间戳 (创建|更新)|(在|上)


创建
部分
对象的浅层副本,然后创建它并将其附加到新组件

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

被复制的对象没有分配id,并被视为新记录。注 这是一个“浅”副本,因为它复制对象的属性 只是,不是它的关联。“深度”副本的范围取决于应用程序 特定的,因此留给应用程序来实现 根据需要。dup方法不保留时间戳 (创建|更新)|(在|上)


我的想法是一个复制部分的外部循环。当在内部循环中重新创建其他组件(结果和问题)时,将使用新的部分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
lesson_template.sections.each do|old_节|
#外循环:重新创建节
新建分区=self.sections.create!({
内容:旧_section.content
})
old_section.components.每个do|old_non_section_组件|
#内部循环:重新创建属于节的所有组件
self.component.create!({
类型:旧的\u非\u节\u组件.type,
内容:旧的\u非\u节\u component.content,
#使用新创建的节中的id,保持正确的关联

section_id:new_section.id#我的想法是一个复制节的外部循环。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
lesson_template.sections.each do|old_节|
#外循环:重新创建节
新建分区=self.sections.create({
内容:旧_section.content
})
old_section.components.每个do|old_non_section_组件|
#内部循环:重新创建属于节的所有组件
self.component.create({
类型:旧的\u非\u节\u组件.type,
内容:旧的\u非\u节\u component.content,
#使用新创建的节中的id,保持正确的关联

section\u id:new\u section.id#你的意思是
section\u id:c.section\u id
总是错误的?很抱歉,我没有遇到问题。你能告诉我更多吗?是的,使用
创建模板\u组件
section\u id
总是123(例如),即使
section\u id
将是新的。你的意思是
section\u id:c.section\u id
总是错误的?很抱歉,我没有遇到问题。你能告诉我更多吗?是的,使用
create\u template\u components
section\u id
总是123(例如),即使
部分\u id
将是新的。如果我有多个部分(123和125),该怎么办,以及与这些节关联的单独组件?例如,与节123关联的组件124和与节125关联的组件126。@jj008从模板组件复制时是否始终要创建一个新节?如果不希望,何时要创建一个新节?是的,我要在创建新节时创建一个新节因此,如果我创建新课程,我希望组件994与第993节关联,组件996与第995节关联(例如)好的,那么我给出的代码,总是创建新的节..
newSection=c.section&&c.section.dup.create
对于
c.section
,你的意思是
c.type='section'
?另外,我收到一个错误,说undefined method
create
如果我有多个节(123和125),该怎么办,以及与这些节关联的单独组件?例如,与节123关联的组件124和与节125关联的组件126。@jj008从模板组件复制时是否始终要创建一个新节?如果不希望,何时要创建一个新节?是的,我要在创建新节时创建一个新节因此,如果我创建新课程,我希望组件994与第993节关联,组件996与第995节关联(例如)好的,那么我给出的代码,总是创建新的部分。
newSection=c.section&&c.section.dup.create
对于
c.section
,你的意思是
c.type='section'
?另外,我收到一个错误,说undefined method
create
,我想这和我要找的很接近,但主要的问题是,当我创建一个新组件,我如何使用正确和新的节id(当我有不同的节和不同的组件关联时)