0

The Problem:

I need to create an application that allows "admin" users to create checklists. Each checklist has :many items. The user will be able to add and remove items from the checklist, as they so choose. (Via a gem like Cocoon, since it handles nested resources so gracefully.)

An example form would look something like this:


Checklist

  1. Item
  2. Item
  3. Item

[Add Items +]


Once a form has been created, normal users would then be able to complete/follow a checklist. Checked is good/true, Unchecked is bad/false.


Automobile

  1. Check Oil [checkbox]
  2. Check Tires [checkbox]
  3. Check Lights [checkbox]

[Submit]


This is the difficult part. One approach I have considered...

Create a Record model, that belongs to the Checklist model,

Checklist

   class Checklist < ActiveRecord::Base
      has_many :records
    end

Record

class Record < ActiveRecord::Base
  belongs_to :checklist
end

Then, serialize the results into a hash...

class Record < ActiveRecord::Base
  belongs_to :checklist

  serialize :list_history, Hash
end

I would use the item.id as the key, and the user true/false input as the value. So, the stored result would look something like:

[ 2 => true, 54 => true, 34 => false]

This way, users could complete a checklist many times, and then an "admin" could pull up the results of previous checklists.

Issue A

This seems like it could work, except for when "admin" users want to edit a checklist. If they remove an "item" from the checklist, even though I can remove the "item" from the association, the "item", must be kept in the database. Otherwise, if Oil has an ID of 2, and Oil is removed in an Edit, then the record's list_history hash will have [ 2 => true], which is a key that points to nowhere. I can visualize a backlog of items pilling up.

Issue B

I'm not sure if this is the best way to tackle this problem. I've been using rails for 2 1/2 years now, and still feel like I did on day 1. (Actually, I I feel as though I know even less.) Maybe there is a better solution just around the corner, that I haven't thought of yet.

Aaron
  • 667
  • 4
  • 19

1 Answers1

1

This should really be a comment.

Maybe structure it like:

class Checklist < ActiveRecord::Base
  has_many :items
end

class Item < ActiveRecord::Base
  belongs_to :checklist
  has_many :user_items, dependent: :destroy
  has_many :users, through: :user_items
end

class UserItem
  belongs_to :item
  belongs_to :user
end

class User
  has_many :user_items, dependent: :destroy
  has_many :items, through: :user_items
end

Checklist The whole list

Items Each task

Dependent destroy on the user_item relationship will delete the records associated with the parent when destroyed.(Solves Issue A)

UserItems Join table for each users entries.

User Your users model.

DickieBoy
  • 4,886
  • 1
  • 28
  • 47
  • This is a good solution. Too often we want to force our object into a DB, rather than doing things the DB's "way". Some times you have to let the DB do the work the way it wants because that's what it's designed to do. A join table like `users_items` is a good way to represent this data and the DB will handle calls to it very efficiently. Rails can then return a hash to you from the query. – Beartech Mar 20 '15 at 17:56