0

I made the following join table to be used in a HABTM relationship between tasks and itself:

create_table :tasks_tasks, id: false do |t|
  t.belongs_to(
    :dropoff_task,
    null: false,
    foreign_key: { to_table: :tasks }
  )
  t.belongs_to(
    :pickup_task,
    null: false,
    foreign_key: { to_table: :tasks }
  )

  t.timestamps
end

In the Task model, I defined the following associations and validations:

has_and_belongs_to_many :dropoff_tasks,
  class_name: "Task",
  foreign_key: :dropoff_task_id,
  inverse_of: :pickup_task_id,
  association_foreign_key: :pickup_task_id,
  validates_associated: true
has_and_belongs_to_many :pickup_tasks,
  class_name: "Task",
  foreign_key: :pickup_task_id,
  inverse_of: :dropoff_task_id,
  association_foreign_key: :dropoff_task_id,
  validates_associated: true

validates :dropoff_tasks, absence: true, if: -> { activity.dropoff? }
validates :pickup_tasks, absence: true, if: -> { activity.pickup? }

Assuming two Task objects pickup_task and pickup_task_2:

> pickup_task.activity.pickup?
=> true
> pickup_task_2.activity.pickup?
=> true 
> pickup_task.dropoff_tasks = [pickup_task_2]
=> [#<Task:0x00007fbab461e880...>]
> pickup_task_2.pickup_tasks
=> []
> pickup_task.valid?
=> true
> pickup_task_2.valid?
=> true

Now the fact that pickup_task_2.pickup_tasks is [] means that Rails is recognizing that pickup_tasks should be absent if pickup? is true, which it is in the case of pickup_task_2. So there is a recognition that the validation is failing.

Q1. Is there any way for the validation to fail by raising an error when I do pickup_task.dropoff_tasks = [pickup_task_2] instead of silently failing and just not assigning any pickup_tasks to pickup_task_2?

Q2. Why is calling valid? on both pickup_task and pickup_task_2 giving true?

Hope this was clear. Please let me know if you need any more details.

4
  • This is a very very strange design. Why one table with two nullable foreign key columns instead of two discrete tables with non-nullable foreign keys that won't be 50% empty?
    – max
    Commented Jul 10 at 13:43
  • a) I'm trying to work with existing designs and b) there are a lot of other columns and associations that are shared for both kinds of "tasks"
    – rwg05
    Commented Jul 10 at 16:21
  • Splitting the tasks_tasks join table into two tables is hardly a huge undertaking as it only has three columns.
    – max
    Commented Jul 11 at 11:35
  • Oh you're talking about tasks_tasks. You're maybe misunderstanding somewhere.. it will never be 50% empty... what made you think that? I specifically added null: false
    – rwg05
    Commented Jul 11 at 16:47

0