My Ruby on Rails application has a DocumentType model and a PersonType model. A Document is of a DocumentType (eg Letter, Postcard) and lists one or more People. Each Person is assigned a PersonType to represent their relationship to a Document (sender, receipient, author etc.). A user is only allowed to assign People to the PersonTypes relevant to the DocumentType.
Table definitions:
create_table "document_types", :force => true do |t|
t.string "name"
end
create_table "document_types_person_types", :id => false, :force => true do |t|
t.integer "document_type_id"
t.integer "person_type_id"
end
create_table "person_types", :force => true do |t|
t.string "name"
end
Model Definitions:
class Document < ActiveRecord::Base
has_many :people, :dependent => :destroy
belongs_to :document_type
end
class DocumentType < ActiveRecord::Base
has_many :documents
has_and_belongs_to_many :person_types
end
class Person < ActiveRecord::Base
belongs_to :document
has_and_belongs_to_many :person_types
end
class PersonType < ActiveRecord::Base
has_and_belongs_to_many :people
has_and_belongs_to_many :document_types
end
Table examples:
documents
id: 1
document_type_id: 1
name: Letter from John Smith to Jane and Joe Smith
document_types
id: 1 | name: letter
document_types_person_types
document_type_id: 1 | person_type_id: 1
document_type_id: 1 | person_type_id: 2
document_type_id: 1 | person_type_id: 4
person_types
id: 1 | name: Sender
id: 2 | name: Recipient
id: 3 | name: Photographer
id: 4 | name: Author
people
id: 1 | document_id: 1 | name: John Smith | person_type_id: 1
id: 2 | document_id: 1 | name: Jane Smith | person_type_id: 2
id: 3 | document_id: 1 | name: Joe Smith | person_type_id: 2
When a user is adding a Person to a Document, they will select what the relationship that Person is to the Document, and that will be stored within the Person model (or extended model).
A Document will only present PersonTypes that are relevant to that DocumentType (for example, a Photograph won't have an Author, but will have a Photographer).
So after all that...What I want to achieve is an admin interface for the DocumentTypes, representing the document_types_person_types table which shows all the PersonTypes and allows me to select a checkbox if a PersonType is applicable:
EDIT DocumentType Letter
Sender [x]
Recipient [x]
Photographer [ ]
Author [x]
Those PersonTypes selected will then be the only PersonTypes available when adding a Person to a Document. Hopefully more straight forward than my convaluted attempt at explaining may have represented. Could anyone provide any pointers?
edit: For future reference, based on Frederick's answer below, this worked
<% for pt in PersonType.find(:all) %>
<%= check_box_tag "document_type[person_type_ids][]", pt.id, @document_type.person_types.include?(pt) %>
<%= pt.name %>
<% end %>
With an association like this, DocumentType will have a person_type_ids
method that returns an array of the ids of the associated person types.
Therefore if you create a set of check boxes where the name is document_type[person_type_ids][]
and whose value is the id of each person type then what will be submitted is an array containing the ids of the checked person types, so
document_type.update_attributes params[:document_type]
Would update the association. The only subtlety here is that if no checkboxes are checked then no array is submitted (you can't submit an empty array) and the list of associated person types won't be cleared. I normally get around this by having a hidden field that adds the value 0 to the array (since I know that will never be a legitimate id) and then strip that 0 from the array in the controller.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With