在 Rails 4 中创建自引用关联的最佳方法是什么?

Whats the best way to create a self-referential association in Rails 4?

在我的项目中,我正在处理称为工作流的对象。每个工作流都可以有许多子流(它调用的工作流)。同时,每个工作流(包括具有子流的工作流)也可能充当调用子流的超级流,并且可能有许多将其称为子流的超级流。

我目前正在尝试通过一个名为 FlowRelation 的模型使用连接 table 来做到这一点。

我已按照我能找到的所有教程进行操作,并阅读了我能找到的每篇文章,但我仍然无法正常工作。

工作流模型:

class Workflow < ActiveRecord::Base
 belongs_to :superflow, :class_name => 'Workflow'
 has_many :subflows, :class_name => 'Workflow', :foreign_key => 'subflow_id'
end 

流关系模型:

class FlowRelation < ActiveRecord::Base
 belongs_to :workflow
 belongs_to :flow, :class_name => "Workflow"
end

在我的工作流程中 edit.html.erb(使用 SimpleForm)

<%= simple_form_for @workflow, :html => { :class => 'form-horizontal', :multipart => true } do |f| %>
<%= f.input :workflow_id %>
<%= error_span(@workflow[:workflow_id]) %>

<%= f.association :subflows, :include_blank => t('.select_workflow') %>
<%= error_span(@workflow[:subflow_id]) %>  

<%= f.association :superflow, :include_blank => t('.select_workflow') %>
<%= error_span(@workflow[:superflow_id]) %>

我的 Workflow Controller 非常简单

def new
  @workflow = Workflow.new
end

def edit
  @workflow = Workflow.find(params[:id])
  @workflow.save    
end 

目前,当我尝试将新的 sub_flows 保存到现有或新的工作流程时,什么都不会保存。数据库中没有显示任何内容,我也没有看到任何错误。

我还有一个 FlowRelationsController

class FlowRelationsController < ApplicationController

 before_action :set_flow_relation, only: [:show, :edit, :update, :destroy]

  def create
    @flow_relation = current_workflow.flow_relations.build(:flow_id => params[:flow_id])
if @flow_relation.save
  flash[:notice] = "Added flow."
  redirect_to root_url
else
  flash[:error] = "Unable to add flow."
  redirect_to root_url
end
end

如果我尝试使用

创建一个添加 sub_flow 按钮到我的工作流索引
<%= link_to "Add Subflow", flow_relations_path(:flow_id => workflow), :method => :post %>

我的 flow_relations table 也是空的。我收到以下错误:

undefined local variable or method `current_workflow' for #   
<FlowRelationsController:0x007f70154921e0>

我知道它有一堆,但我完全被卡住了,几天来我一直在用头撞墙。有人看到我在这里失踪的东西吗?我一直在尝试实现类似于 RailsCasts 上所描述的东西,但没有成功:http://railscasts.com/episodes/163-self-referential-association?view=asciicast

请帮助!

谢谢

如果不深入研究您在此处执行的任何其他自引用模型内容,您看到的错误是控制器错误。它不知道 'current_workflow'。我的猜测是,在回调之前的 'set_flow_relation' 中,您正在设置 @current_workflow。如果没有看到您的其余控制器代码,我无法确定。

问题解决后,请post 解决您遇到的任何后续问题。

我误解了一些不同的事情。我想我会回答我自己的问题,以帮助可能在同一条船上的任何其他人清楚。

我在上面遇到的第一个主要问题是 FlowRelationsController。我正在使用一个不存在的名为 current_workflow 的对象。发生这种情况是因为关注了我在网上可以找到的关于此主题的唯一视频:http://railscasts.com/episodes/163-self-referential-association。这是一个创建资源,但与我试图完成的并不完全相同。 current_workflow 对象在我的案例中没有被创建,因为我是从一个索引而不是我的应用程序的工作流细节部分开始的

现在,关于如何实现我最初的目标。这是我最终得到的结果:

工作流模型

has_many :flow_relations
has_many :subflows, :through => :flow_relations

流关系模型

self.primary_key = :workflow_id

belongs_to :workflow
belongs_to :subflow, :class_name => 'Workflow'

我的 simpleForm 内部用于创建和编辑工作流。 (这是一个需要理解的非常关键的部分。- 将所有工作流对象的集合关联到子流。

  <%= f.association :subflows, collection: Workflow.all, prompt: "Select Subflows" %>
  <%= error_span(@workflow[:subflow_id]) %>

由于 Rails 4,Workflow 控制器基本保持不变,只有一个关键差异。- 我不得不更改 workflow_params 以允许!。我在 Worfklow 控制器和 FlowRelations 控制器上都这样做了。不确定我是否仍然理解应该如何配置以获得更好的安全性,但在这个特定的应用程序中,安全性不是问题,因为它在内部 运行。

def new
  @workflow = Workflow.new
end

def edit
  @workflow = Workflow.find(params[:id])
  @workflow.save    
end 

def workflow_params
  #params.require(:workflow).permit(:workflow_id, :flow_relations, :re_workflow_id, :name, :description, :superflow_id, :client_id, :variable_id, :required_variable_id, :flow_file)
 params.require(:workflow).permit!
end

我删除了添加子流程按钮,因为现在它可以通过标准的创建或编辑操作来完成

它是一堆东西,但基本上,最终结果是我现在有一个 Workflow 对象,它可以包含 mnay 个子流,所有这些子流都可以是许多 Workflow 的成员,所有这些都在一个 Workflow 中 class和一个 FlowRelations class 用于处理连接。