lib/rails_erd/domain.rb in rails-erd-0.3.0 vs lib/rails_erd/domain.rb in rails-erd-0.4.0
- old
+ new
@@ -1,10 +1,10 @@
-require "set"
require "rails_erd"
-require "rails_erd/entity"
-require "rails_erd/relationship"
-require "rails_erd/attribute"
+require "rails_erd/domain/attribute"
+require "rails_erd/domain/entity"
+require "rails_erd/domain/relationship"
+require "rails_erd/domain/specialization"
module RailsERD
# The domain describes your Rails domain model. This class is the starting
# point to get information about your models.
#
@@ -26,48 +26,55 @@
def generate(options = {})
new ActiveRecord::Base.descendants, options
end
end
+ extend Inspectable
+ inspection_attributes
+
# The options that are used to generate this domain model.
attr_reader :options
# Create a new domain model object based on the given array of models.
# The given models are assumed to be subclasses of <tt>ActiveRecord::Base</tt>.
def initialize(models = [], options = {})
- @models, @options = models, RailsERD.options.merge(options)
+ @source_models, @options = models, RailsERD.options.merge(options)
end
# Returns the domain model name, which is the name of your Rails
# application or +nil+ outside of Rails.
def name
defined? Rails and Rails.application and Rails.application.class.parent.name
end
# Returns all entities of your domain model.
def entities
- @entities ||= Entity.from_models(self, @models)
+ @entities ||= Entity.from_models(self, models)
end
# Returns all relationships in your domain model.
def relationships
@relationships ||= Relationship.from_associations(self, associations)
end
+ # Returns all specializations in your domain model.
+ def specializations
+ @specializations ||= Specialization.from_models(self, models)
+ end
+
# Returns a specific entity object for the given Active Record model.
- def entity_for(model) # @private :nodoc:
- entity_mapping[model] or raise "model #{model} exists, but is not included in domain"
+ def entity_by_name(name) # @private :nodoc:
+ entity_mapping[name]
end
# Returns an array of relationships for the given Active Record model.
- def relationships_for(model) # @private :nodoc:
- relationships_mapping[model] or []
+ def relationships_by_entity_name(name) # @private :nodoc:
+ relationships_mapping[name] or []
end
-
- def inspect # @private :nodoc:
- "#<#{self.class}:0x%.14x {%s}>" %
- [object_id << 1, relationships.map { |rel| "#{rel.source} => #{rel.destination}" } * ", "]
+
+ def specializations_by_entity_name(name)
+ specializations_mapping[name] or []
end
def warn(message) # @private :nodoc:
puts "Warning: #{message}" if options.warn
end
@@ -75,36 +82,57 @@
private
def entity_mapping
@entity_mapping ||= {}.tap do |mapping|
entities.each do |entity|
- mapping[entity.model] = entity
+ mapping[entity.name] = entity
end
end
end
def relationships_mapping
@relationships_mapping ||= {}.tap do |mapping|
relationships.each do |relationship|
- (mapping[relationship.source.model] ||= []) << relationship
- (mapping[relationship.destination.model] ||= []) << relationship
+ (mapping[relationship.source.name] ||= []) << relationship
+ (mapping[relationship.destination.name] ||= []) << relationship
end
end
end
+ def specializations_mapping
+ @specializations_mapping ||= {}.tap do |mapping|
+ specializations.each do |specialization|
+ (mapping[specialization.generalized.name] ||= []) << specialization
+ (mapping[specialization.specialized.name] ||= []) << specialization
+ end
+ end
+ end
+
+ def models
+ @models ||= @source_models.reject(&:abstract_class?).select { |model| check_model_validity(model) }
+ end
+
def associations
- @associations ||= @models.collect(&:reflect_on_all_associations).flatten.select { |assoc| check_association_validity(assoc) }
+ @associations ||= models.collect(&:reflect_on_all_associations).flatten.select { |assoc| check_association_validity(assoc) }
end
+ def check_model_validity(model)
+ model.table_exists? or raise "table #{model.table_name} does not exist"
+ rescue => e
+ warn "Ignoring invalid model #{model.name} (#{e.message})"
+ end
+
def check_association_validity(association)
# Raises an ActiveRecord::ActiveRecordError if the association is broken.
association.check_validity!
- # Raises NameError if the associated class cannot be found.
- model = association.klass
-
- # Raises error if model is not in the domain.
- entity_for model
+ if association.options[:polymorphic]
+ entity_name = association.class_name
+ entity_by_name(entity_name) or raise "polymorphic interface #{entity_name} does not exist"
+ else
+ entity_name = association.klass.name # Raises NameError if the associated class cannot be found.
+ entity_by_name(entity_name) or raise "model #{entity_name} exists, but is not included in domain"
+ end
rescue => e
warn "Ignoring invalid association #{association_description(association)} (#{e.message})"
end
def association_description(association)