为自引用关联创建/更新记录(和相关记录)的更好方法

时间:2016-05-02 17:51:36

标签: ruby-on-rails ruby rails-activerecord

我需要知道创建/更新自引用关联记录的更好方法。

我有一个名为Template的模型,以及与此模型的self-referential has_many :through关联:

has_many :related_templates, :foreign_key => :parent_id
has_many :children, :through => :related_templates, :source => :child

has_many :inverse_related_templates, class_name: "RelatedTemplate", :foreign_key => :child_id
has_many :parents, :through => :inverse_related_templates, :source => :parent

这样RelatedTemplates是一个连接模型。

对于new表格:

1)填写parent template详细信息

2)通过在同一表单中创建新模板或将现有模板作为子模板添加到此父模板,添加child templates

对于edit表格:

1)显示parent template

的详细信息

2)编辑已分配给它的child template个详细信息。用户还应该能够edit已经关联的模板的详细信息。

由于新的和编辑的表单相同。用户还可以在编辑页面中create新的或add来自现有的。

我的create方法是这样的:

def create
  Template.transaction do
    parent_template = Template.new template_params
    if parent_template.save
      children_templates = []
      # if params of new templates are sent
      if params[:template][:children_attributes].present?
        new_templates = params[:template][:children_attributes]
        new_templates.each do |child|
          template = Template.new(attrs)
          template.save
          children_templates << template
        end
      end
      # if params of existing templates are sent
      if params[:template][:existingChildTemplates].present?
        existing_ids = params[:template][:existingChildTemplates]
        children_templates << Template.where(id: existing_ids)
      end
      parent_template.children << children_templates
      render json: { success: true, template_id: parent_template.id, message: "Created Successfully" }
    else
      render_422 parent_template, 'Could not save Parent Template.'
    end
  end
rescue ActiveRecord::RecordInvalid => exception
  render json: { success: false, message: "#{exception}" }, status: 500
end

同样,我写的是update

def update
  if @template.update_attributes template_params
    if params[:template][:children_attributes].present?
      associated_templates = @template.children
      new_templates = params[:template][:children_attributes]
      new_templates.each do |child|
        unless child[:id].present?
          # if new template added
          associated_templates.build(attrs)
          @template.save
        else
          # if template attributes updated
          new_template_params = child.permit(attrs)
          child_template = associated_templates.where(id: child[:id]).first
          if (child_template[:name] != child[:name]) || (child_template[:role_id] != child[:role_id])
            child_template.update_attributes(new_template_params)
          end
        end
      end
    end
    if params[:template][:existingChildTemplates].present?
      children_templates = []
    # if selected from the existing one
      existing_ids = params[:template][:existingChildTemplates]
      children_templates << Template.where(id: existing_ids)
      @template.children << children_templates
    end
    render json: { success: true, message: 'Updated.' }
  else
    render_422 @template, 'Template could not be updated.'
  end
end

问题

  1. 如何列出children_attributes白名单?我在这里手动使用params。我尝试在permit方法中添加children_attributes: [],在模型中添加accepts_nested_attributes_for :children 但仍然是Unpermitted Parameter

  2. 编写create/update方法的更好方法是什么?我应该如何处理validation错误?

0 个答案:

没有答案