I am trying to create a form to save quite a complexish relationship. The models for the relationship are below.
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
So a goal can have many parents or it can have many children or both. I have tried using a multi select drop down to save these relationships and setting child_ids/parent_ids, but that doesn't seem to work because the goal_dependency requires both fields - i.e. child_id and parent_id. Rails only sets the one. So if I am saving a list of child_ids it sets those, but it doesn't know to set the parent_id with the current goal and visa versa.
I have tried using accepts_nested_attributes, but I am not really sure how I can use this with a multi-select drop down.
Any guidance or direction on how I could approach this would be appreciated.
Example of my current form.
.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
After further investigation I thought of another way to do this, but I am not really happy with it. I can split the concept of a dependency into a parent dependency and a child dependency and have these as different models. The relationship can then be handled differently. See the code below for the child dependency.
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
From what I have read rails can't deal with composite keys and my case seems to be a case where a composite key would make sense.
Anyway if anyone can figure out how to make my initial code work that would be great.