title: Rails: multiple models operating on same table
body: <p>I'm building a system that has some records in tables that are template records, which are viewable by all accounts and can be later copied to create live records for an individual account.</p>
  
  <p>The reasoning behind this design decision is that template records and live records share 95%+ of the same code, so I didn't want to create a separate table to track mostly the same fields.</p>
  
  <p>For instance, I have a <code>workflows</code> table:</p>
  
  <ul>
  <li>id:integer</li>
  <li>account_id:integer</li>
  <li>name:string (required)</li>
  <li>is_a_template:boolean (default: false)</li>
  <li>is_in_template_library:boolean (default: false)</li>
  </ul>
  
  <p>In this table, I have some records that are templates.  When I go to create a new live record, I can use a template record:</p>
  
  <pre><code># workflows_controller.rb (pseudo-code, not fully tested)
  def create
    @workflow_template = Workflow.where(is_a_template: true).find_by(id: params[:workflow_template_id])
    @workflow = current_account.workflows.new(workflow_params.merge(@workflow_template.dup))
  
    if @workflow.save
      ...
    else
      ...
    end
  end
  </code></pre>
  
  <p>As I build more functionality, I find that I really need 2 different models that operate differently on the table.  There are several more differences, but those listed below are enough to show the differences:</p>
  
  <pre><code>class Workflow &lt; ApplicationRecord
    default_scope -&gt; { where(is_a_template: false) }
  
    belongs_to :account
  
    validates :account, presence: true
    validates :name, presence: true
  end
  
  class WorkflowTemplate &lt; ApplicationRecord
    default_scope -&gt; { where(is_a_template: true) }
  
    validates :name, presence: true
  end
  
  class WorkflowLibraryTemplate &lt; ApplicationRecord
    default_scope -&gt; { where(is_a_template: true, is_in_template_library: true) }
  
    validates :name, presence: true
  end
  </code></pre>
  
  <p>As you can see, the <code>workflows</code> table has 3 different "types" of records:</p>
  
  <ol>
  <li>"live" workflows that belong to an account</li>
  <li>template workflows that also belong to an account and are copied to create "live" workflows</li>
  <li>library template workflows that do NOT belong to an account and can be viewed by any account, so they can copy them into their own list of templates</li>
  </ol>
  
  <p><strong>Question</strong></p>
  
  <p>What I'm trying to figure out, is at what point do I break up this single table into multiple tables, versus keeping the same table and having multiple models, or what solution is there to a problem like this?</p>
  
  <p>The frustrating part is that there are 5+ other tables that are "children" associations of the <code>workflows</code> table.  So if I decide that I need separate tables for each, I would end up going from 6 tables to something like 18, and everytime I add a field, I have to do it to all 3 "versions" of the table.</p>
  
  <p>Thus I'm very reluctant to go down the multiple tables route.</p>
  
  <p>If I keep a single table and multiple models, I then end up with different version of data in the table, which isn't the end of the world.  I only interact with the data through my application (or a future API I control).</p>
  
  <p>Another solution I'm thinking about is adding a <code>role:string</code> field to the table, which operates very much like the <code>type</code> field in Rails.  I didn't want to use STI, however, because there are too many baked-in requirements with Rails that I don't want to conflict with.</p>
  
  <p>What I'm envisioning is:</p>
  
  <pre><code>class Workflow &lt; ApplicationRecord
    scope :templates, -&gt; { where(role: "template") }
    scope :library_templates, -&gt; { where(role: "library_template") }
  
    validates :account, presence: true, if: :account_required?
    validates :name, presence: true
  
    # If record.role matches one of these, account is required
    def account_required
      ["live", "template"].include?(role.to_s.downcase)
    end
  end
  </code></pre>
  
  <p>This seems to address several of the issues, keeps me with 1 table and 1 model, but begins to have conditional logic in the model, which seems like a bad idea to me as well.</p>
  
  <p>Is there a cleaner way to implement a templating system within a table?</p>