app/models/topic_type.rb
class TopicType < ActiveRecord::Base
# dependent topics should be what if a topic_type is destroyed?
has_many :topics
has_many :topic_type_to_field_mappings, dependent: :destroy, order: 'position'
# Walter McGinnis (walter@katipo.co.nz), 2006-10-05
# these association extension maybe able to be cleaned up with modules or something in rails proper down the line
# code based on work by hasmanythrough.com
# you have to do the elimination of duplicates through the sql
# otherwise, rails will reorder by topic_type_to_field_mapping.id after the sql has bee run
has_many :form_fields, through: :topic_type_to_field_mappings, source: :extended_field, select: 'distinct topic_type_to_field_mappings.position, extended_fields.*', order: 'position' do
def <<(extended_field)
TopicTypeToFieldMapping.add_as_to('false', self, extended_field)
end
end
has_many :required_form_fields, through: :topic_type_to_field_mappings, source: :required_form_field, select: 'distinct topic_type_to_field_mappings.position, extended_fields.*', conditions: "topic_type_to_field_mappings.required = 'true'", order: 'position' do
def <<(required_form_field)
TopicTypeToFieldMapping.add_as_to('true', self, required_form_field)
end
end
# imports are processes to bring in content to a basket
# they specify a topic type of thing they are importing
# or a topic type for the item that relates groups of things
# that they are importing
has_many :imports, dependent: :destroy
scope :from_urlified_name, lambda { |urlified_name| where('LOWER(name) = ?', urlified_name.downcase.tr('_', ' ')) }
validates_presence_of :name, :description
validates_uniqueness_of :name, case_sensitive: false
# don't allow special characters in label that will break urls
validates_format_of :name, with: /^[^\'\":<>\&,\/\\\?\.]*$/, message: lambda { I18n.t('topic_type_model.invalid_chars', invalid_chars: ": \', \\, /, &, \", ?, <, >, and .") }
# to support inheritance of fields from ancestor topic types
acts_as_nested_set
# TODO: globalize stuff, uncomment later
# translates :name, :description
# we have a generic topic_type of Topic from which all types inherit their attributes
# since these default fields reflect the state of the Topic model
# then we also have ancestor fields for all the topic types above this topic type
def available_fields
@available_fields = ExtendedField.find_available_fields(self, 'TopicType')
end
def mapped_fields(options = {})
options[:with_ancestors] ||= true
relevant_topic_types = options[:with_ancestors] ? self_and_ancestors : [self]
# TODO: might want to reconsider using a subselect here
ExtendedField.where('id in (select extended_field_id from topic_type_to_field_mappings where topic_type_id in (?))', relevant_topic_types).all
end
def self_and_ancestors_ids
@self_and_ancestors_ids ||= self_and_ancestors.collect { |a| a.id }
end
# MySQL ordering doesn't work well here so we do our own ordering
def all_field_mappings
mappings = TopicTypeToFieldMapping.find_all_by_topic_type_id(self_and_ancestors_ids, order: 'position ASC')
self_and_ancestors_ids.collect do |id|
mappings.select { |mapping| mapping.topic_type_id == id }
end.flatten
rescue
[]
end
def urlified_name
name.downcase.gsub(/\s/, '_')
end
def full_set
self_and_descendants
end
end