class ActiveExplorer::Exploration
Constants
- ASSOCIATION_FILTER_VALUES
Public Class Methods
new(object, depth: 5, class_filter: nil, attribute_filter: nil, attribute_limit: nil, association_filter: nil, parent_object: nil)
click to toggle source
Creates new exploration and generates exploration hash.
@param association_filter [Array]
Values of array: `:has_many`, `:has_one`, `:belongs_to`, `:all`. When empty then it "follows previous association" (i.e. uses `:belongs_to` when previous assoc. was `:belongs_to` and uses `:has_xxx` when previous assoc. was `:has_xxx`). To always follow all associations you must specify all associations (e.g. uses `ActiveExplorer::Exploration::ASSOCIATION_FILTER_VALUES` as a value).
@param class_filter [Array or Hash]
If Array is used then it means to show only those classes in Array. When Hash is used then it can have these keys: - `:show` - Shows these classes, ignores at all other classes. - `:ignore` - Stops processing at these, does not show it and does not go to children. Processing goes back to parent. Use plural form (e.g. `books`).
@param depth [Integer]
How deep into the subobjects should the explorere go. Depth 1 is only direct children. Depth 0 returns no children.
# File lib/exploration.rb, line 27 def initialize(object, depth: 5, class_filter: nil, attribute_filter: nil, attribute_limit: nil, association_filter: nil, parent_object: nil) raise TypeError, "Parameter 'class_filter' must be Array or Hash but is #{class_filter.class}." unless class_filter.nil? || class_filter.is_a?(Array) || class_filter.is_a?(Hash) raise TypeError, "Parameter 'association_filter' must be Array but is #{association_filter.class}." unless association_filter.nil? || association_filter.is_a?(Array) raise TypeError, "Parameter 'association_filter' must only contain values #{ASSOCIATION_FILTER_VALUES.to_s[1..-2]}." unless association_filter.nil? || association_filter.empty? || (association_filter & ASSOCIATION_FILTER_VALUES).any? @object = object @depth = depth @parent_object = parent_object @attribute_limit = attribute_limit || ActiveExplorer::Config.attribute_limit @attribute_filter = attribute_filter || ActiveExplorer::Config.attribute_filter @hash = { class_name: make_safe(@object.class.name), attributes: attributes } unless @depth.zero? @class_filter = class_filter || ActiveExplorer::Config.class_filter @class_filter = { show: @class_filter } if @class_filter.is_a?(Array) if @class_filter [:show, :ignore].each do |group| @class_filter[group] = @class_filter[group].present? ? each_val_to_s(@class_filter[group]) : [] end end @association_filter = association_filter || ActiveExplorer::Config.association_filter @association_filter = ASSOCIATION_FILTER_VALUES if @association_filter.present? && @association_filter.include?(:all) @associations = associtations(@object, @class_filter, @association_filter) subobject_hash = subobjects_hash(@object, @associations) @hash[:subobjects] = subobject_hash unless subobject_hash.empty? end end
Public Instance Methods
attributes()
click to toggle source
# File lib/exploration.rb, line 62 def attributes attrs = @object.attributes.symbolize_keys attrs = attrs.first(@attribute_limit).to_h if @attribute_limit return attrs if @attribute_filter.nil? filter = @attribute_filter[@object.class.name.downcase.pluralize.to_sym] if filter attrs.select { |key| filter.include?(key) } else attrs end end
get_hash()
click to toggle source
# File lib/exploration.rb, line 77 def get_hash @hash.dup end
to_console()
click to toggle source
# File lib/exploration.rb, line 81 def to_console Writer.new(self).write end
to_image(file, origin_as_root: false)
click to toggle source
# File lib/exploration.rb, line 85 def to_image(file, origin_as_root: false) Painter.new(self, file).paint(origin_as_root: origin_as_root) end
Private Instance Methods
add_error_hash(message)
click to toggle source
# File lib/exploration.rb, line 177 def add_error_hash(message) @hash[:class_name] = make_safe(@object.class.name) @hash[:attributes] = attributes @hash[:error_message] = "Error in #{@object.class.name}(#{@object.id}): #{message}" end
association_type(association)
click to toggle source
# File lib/exploration.rb, line 184 def association_type(association) association.macro end
associtations(object, class_filter, association_filter)
click to toggle source
# File lib/exploration.rb, line 151 def associtations(object, class_filter, association_filter) associations = object.class.reflections.collect do |reflection| reflection.second end if !association_filter.nil? && association_filter.any? && !association_filter.include?(:all) associations.select! do |association| association_filter.include? association_type(association) end end if class_filter if class_filter[:show].any? associations.select! do |association| should_show?(association) end elsif class_filter[:ignore].any? associations.reject! do |association| should_ignore?(association) end end end associations end
each_val_to_s(array)
click to toggle source
# File lib/exploration.rb, line 199 def each_val_to_s(array) array.collect { |a| a.to_s } end
explore(object, parent_object:, association_type:)
click to toggle source
# File lib/exploration.rb, line 133 def explore(object, parent_object:, association_type:) association_filter = if !@association_filter.nil? && @association_filter.any? @association_filter elsif association_type == :belongs_to [:belongs_to] else [:has_many, :has_one] end Exploration.new object, depth: @depth - 1, class_filter: @class_filter, attribute_filter: @attribute_filter, attribute_limit: @attribute_limit, association_filter: association_filter, parent_object: parent_object end
is_parent?(object)
click to toggle source
# File lib/exploration.rb, line 203 def is_parent?(object) object === @parent_object end
make_safe(text)
click to toggle source
Replace characters that conflict with DOT language (used in GraphViz). These: ‘{`, `}`, `<`, `>`, `|`, ``
# File lib/exploration.rb, line 195 def make_safe(text) text.tr('{}<>|\\', '') end
make_short(text)
click to toggle source
# File lib/exploration.rb, line 188 def make_short(text) text.length < 70 ? text : text[0..70] + " (...)" end
should_ignore?(association)
click to toggle source
# File lib/exploration.rb, line 211 def should_ignore?(association) @class_filter[:ignore].include? association.plural_name.to_s end
should_show?(association)
click to toggle source
# File lib/exploration.rb, line 207 def should_show?(association) @class_filter[:show].include? association.plural_name.to_s end
subobject_hash(association, object, subobject)
click to toggle source
# File lib/exploration.rb, line 113 def subobject_hash(association, object, subobject) association_type = association_type(association) exploration = explore(subobject, parent_object: object, association_type: association_type) hash = exploration.get_hash hash[:association] = association_type hash end
subobjects_from_association(object, association)
click to toggle source
# File lib/exploration.rb, line 123 def subobjects_from_association(object, association) subobjects = object.send(association.name) subobjects.present? ? subobjects : nil rescue NameError, ActiveRecord::StatementInvalid, ActiveRecord::RecordNotFound => e association_type = association.macro add_error_hash("#{e.message} in #{association_type} :#{association.name}") nil end
subobjects_hash(object, associations)
click to toggle source
# File lib/exploration.rb, line 91 def subobjects_hash(object, associations) associations.each_with_object([]) do |association, results| case association_type(association) when :belongs_to subobject = subobjects_from_association(object, association) if subobject.present? results.push subobject_hash(association, object, subobject) unless is_parent?(subobject) end when :has_many, :has_one subobjects = subobjects_from_association(object, association) if subobjects.present? subobjects.each do |subobject| results.push subobject_hash(association, object, subobject) unless is_parent?(subobject) end end end end end