如何保存我的多对多关系?

时间:2015-03-16 18:21:12

标签: ruby-on-rails ruby ruby-on-rails-4 many-to-many has-many-through

我正在尝试创建一个表单以保存相当复杂的关系。这种关系的模型如下。

class Goal < ActiveRecord::Base
  belongs_to :goal_status
  belongs_to :goal_type

  has_many :users, through: :user_goals
  has_many :user_goals

  has_many :parent_goals, class_name: 'GoalDependency', foreign_key: :parent_id
  has_many :child_goals, class_name: 'GoalDependency', foreign_key: :child_id

  has_many :children, through: :child_goals
  has_many :parents, through: :parent_goals

  validates_presence_of :goal_status_id, :goal_type_id
end

class GoalDependency < ActiveRecord::Base
  belongs_to :parent, class_name: 'Goal', foreign_key: 'parent_id'
  belongs_to :child, class_name: 'Goal', foreign_key: 'child_id'
end

所以一个目标可以有很多父母,也可以有很多孩子或两者兼而有之。我尝试使用多选下拉列表来保存这些关系并设置child_ids / parent_ids,但这似乎不起作用,因为goal_dependency需要两个字段 - 即child_id和parent_id。 Rails只设置一个。因此,如果我保存一个child_ids列表,它会设置那些,但它不知道将parent_id设置为当前目标,反之亦然。

我尝试过使用accepts_nested_attributes,但我不确定如何在多选下拉列表中使用它。

对于我如何处理此问题的任何指导或指示都将不胜感激。

我目前的表格示例。

.row
  .col-md-6
    = simple_form_for(@goal) do |f|
      - if @goal.errors.any?
        #error_explanation
          h2 = "#{pluralize(@goal.errors.count, 'error')} prohibited this goal from being saved:"

          ul
            -@goal.errors.full_messages.each do |message|
              li = message

      = f.input :description
      = f.input :goal_status_id, collection: @goal_statuses, value_method: :id, label_method: :name, as: :select
      = f.input :goal_type_id, collection: @goal_types, value_method: :id, label_method: :name, as: :select
      = f.input :user_ids, collection: @users, as: :select, label: 'Assigned To', input_html: { class: 'chosen-select', multiple: true }, selected: @goal.user_ids
      = f.input :child_ids, collection: @goals, as: :select, label: 'Children Goals', input_html: { class: 'chosen-select', multiple: true }, selected: @goal.child_ids, value_method: :id, label_method: :description

      br
      = f.submit

经过进一步调查后,我想到了另一种方法,但我并不满意。我可以将依赖关系的概念拆分为父依赖关系和子依赖关系,并将它们作为不同的模型。然后可以以不同方式处理该关系。请参阅下面的代码了解子依赖项。

class Goal < ActiveRecord::Base
  belongs_to :goal_status
  belongs_to :goal_type

  has_many :users, through: :user_goals
  has_many :user_goals

  has_many :child_goals, class_name: 'GoalChildDependency'
  has_many :children, through: :child_goals

  validates_presence_of :goal_status_id, :goal_type_id
end

class GoalChildDependency < ActiveRecord::Base
  belongs_to :goal
  belongs_to :child, class_name: 'Goal', foreign_key: :child_id
end

从我所看到的内容中,rails不能处理复合键,而我的情况似乎是复合键有意义的情况。

无论如何,如果有人能弄清楚如何让我的初始代码工作那么棒。

1 个答案:

答案 0 :(得分:0)

将单个目标模型与自引用parent_id列放在一起可能会更容易。你能做到的地方

has_many :child_goals, class_name: 'Goal', foreign_key: :parent_id

belongs_to :parent_goal, class_name: 'Goal'

此外,如果您还需要ChildGoal模型,则可以使用单个表继承模型,将列type添加到目标表并使用ChildGoal < Goal并按照上述类似方法进行操作。