views:

348

answers:

3

Rails 2.1.0 (Cannot upgrade for now due to several constraints) I am trying to achieve this. Any hints?

  1. A project has many users through join model
  2. A user has many projects through join model
  3. Admin class inherits User class. It also has some Admin specific stuff.
  4. Admin like inheritance for Supervisor and Operator
  5. Project has one Admin, One supervisor and many operators.

Now I want to 1. submit data for project, admin, supervisor and operator in a single project form 2. validate all and show errors on the project form.

Project has_many :projects_users ; has_many :users, :through => :projects_users
User has_many :projects_users ; has_many :projects, :through => :projects_users
ProjectsUser = :id integer, :user_id :integer, :project_id :integer
ProjectUser belongs_to :project, belongs_to :user
Admin < User # User has 'type:string' column for STI
Supervisor < User
Operator < User

Is the approach correct? Any and all suggestions are welcome.

A: 

I guess Single Table Inberitance and nested forms may help you out here. You may wanna read about it at the documentation. http://api.rubyonrails.org/classes/ActiveRecord/Base.html

Hock
I do have the "type" column for single table inheritance.
ramonrails
A: 

I figured out the answer lies in single table inheritance with has_many :through

class Project < ActiveRecord::Base
  has_many :projects_users, :dependent => :destroy
  has_many :users, :through => :projects_users, :dependent => :destroy
  has_one :admin, :through => :projects_users, :source => :user, :conditions => {:type => "Admin"}
  has_one :supervisor, :through => :projects_users, :source => :user, :conditions => {:type => "Supervisor"}
  has_many :operators, :through => :projects_users, :source => :user, :conditions => {:type => "Operator"}
  validates_presence_of :name
  validates_associated :admin

  def admin_attributes=(attributes)
    # build an admin object and apply to this relation
  end

  def supervisor_attributes=(attributes)
    # build a supervisor object and apply to this relation
  end

  def operator_attributes=(operator_attributes)
    operator_attributes.each do |attributes|
      # build an operator object for each set of attributes and apply to this relation
    end
  end
end

class User < ActiveRecord::Base
  has_many :projects_users, :dependent => :destroy
  has_many :projects, :through => :projects_users, :dependent => :destroy
  validates_presence_of :name
  validates_associated :projects
end

class ProjectsUser < ActiveRecord::Base
  belongs_to :project
  belongs_to :user
end

class Admin < User
end

class Supervisor < User
end

class Operator < User
end

Now we can have the following

project1.users # User objects for admin, supervisor and operators
project1.admin # User object for Admin
project1.supervisor # User object for Supervisor
project1.operators # User objects for Operator

A complex form including all these can have

<% form_for :project ...
    <% fields_for "project[admin_attributes]", @project.admin do |admin_form|
    ...
    <% @project.operators.each do |operator| %>
        <% fields_for "project[operator_attributes][]", operator do |operator_form| %>

and so on...

ramonrails
A: 

I ended up using virtual attributes for admin, supervisor and operators everything else went through ORM associations

ramonrails