Search code examples
ruby-on-railsformshtml-tablemultiple-inheritancecocoon-gem

HTML table form with multiple inheritance, in cocoon?


I have a table with cells.

Using cocoon how would I make a form in which each cell belongs_to the row, column, and table?

For Example:

# Table
class Roster < ApplicationRecord
    has_many :timeslots, inverse_of: :roster
    has_many :games, inverse_of: :roster

    accepts_nested_attributes_for :timeslots, reject_if: :all_blank, allow_destroy: true
    accepts_nested_attributes_for :games, reject_if: :all_blank, allow_destroy: true
end

# Column
class Court < ApplicationRecord
  belongs_to :roster
  has_many :games

  accepts_nested_attributes_for :games, reject_if: :all_blank, allow_destroy: true
end

# Row
class Timeslot < ApplicationRecord
    belongs_to :roster
    has_many :games

    accepts_nested_attributes_for :games, reject_if: :all_blank, allow_destroy: true
end

# Cell
class Game < ApplicationRecord
    belongs_to :timeslot
    belongs_to :roster
end

I am trying now with a hidden <input> for each game's :timeslot_id and :court_id the only problem is you cannot get the id before the timeslot and court is saved. The other idea I ma working on is to for each game to have a hidden <input> of the row/column they are in.


Solution

  • I finally figured it out: Each cell had two hidden inputs:

    <%= cell.hidden_field :row %>
    <%= cell.hidden_field :column %>
    

    The cell belongs_to association had to be optional:

    class Cell < ApplicationRecord
        belongs_to :table
        belongs_to :column, optional: true
        belongs_to :row, optional: true
    end
    

    And the Table had an after_save callback:

    after_save do |table|
        table.rows.each_with_index do |row,row_number|
            table.cells.each do |cell|
                if cell.row-1 == row_number
                    cell.row = row
                    cell.save()
                end
            end
        end
        table.columns.each_with_index do |column,column_number|
            table.cells.each do |cell|
                if cell.column-1 == column_number
                    cell.column = column
                    cell.save()
                end
            end
        end
    end
    

    There is probably a better way to do this but I think this is the simplest. You will need to add an extra two columns to your database: row and column (The main drawback)