# frozen_string_literal: true require "active_mocker/inspectable" module ActiveMocker class MockCreator using ActiveMocker::Inspectable def initialize(file:, file_out:, schema_scrapper:, template_creator: nil, class_introspector: nil, enabled_partials: nil, klasses_to_be_mocked:, mock_append_name:, active_record_model:, active_record_base_klass: ActiveRecord::Base) @file = file @file_out = file_out @schema_scrapper = schema_scrapper @template_creator = template_creator || template_creator_default(file_out) @class_introspector = class_introspector || class_introspector_default @enabled_partials = enabled_partials || self.class.enabled_partials_default @klasses_to_be_mocked = klasses_to_be_mocked @active_record_base_klass = active_record_base_klass @mock_append_name = mock_append_name @active_record_model = active_record_model @errors = [] @completed = false end def create verify_class if errors.empty? begin template_creator.render rescue => e raise e unless error_already_collected?(e) end file_out.close @completed = true end self end def completed? @completed end attr_reader :errors private attr_reader :file, :file_out, :schema_scrapper, :template_creator, :class_introspector, :enabled_partials, :klasses_to_be_mocked, :active_record_base_klass, :mock_append_name def error_already_collected?(e) errors.any? { |eo| eo.original_error == e } end # -- Defaults -- # def template_creator_default(file_out) TemplateCreator.new(file_out: file_out, erb_template: File.new(File.join(File.dirname(__FILE__), "mock_template.erb"), "r"), binding: binding, post_process: lambda do |str| ruby_code = DissociatedIntrospection::RubyCode.build_from_source(str, parse_with_comments: true) DissociatedIntrospection::WrapInModules.new(ruby_code: ruby_code) .call(modules: nested_modules) .source_from_ast.gsub(/end\n/, "end\n\n") end) end def class_introspector_default DissociatedIntrospection::Inspection.new(file: file) end class << self def enabled_partials_default [ :modules_constants, :class_methods, :attributes, :scopes, :recreate_class_method_calls, :defined_methods, :associations, ] end public :enabled_partials_default end # -- END defaults -- # def verify_class v = ParentClass.new(parsed_source: class_introspector.parsed_source, klasses_to_be_mocked: klasses_to_be_mocked, mock_append_name: mock_append_name).call errors << v.error if v.error @parent_class = v.parent_mock_name end public def partials OpenStruct.new(enabled_partials.each_with_object({}) do |p, hash| begin file = File.new(File.join(File.dirname(__FILE__), "mock_template/_#{p}.erb")) extend("ActiveMocker::MockCreator::#{p.to_s.camelize}".constantize) hash[p] = ERB.new(file.read, nil, "-", "_sub#{p}").result(binding) rescue => e errors << ErrorObject.new(class_name: class_name, original_error: e, type: :generation, level: :error, message: e.message) errors << ErrorObject.new(class_name: class_name, original_error: e, type: :erb, level: :debug, message: "Erb template: #{p} failed.\n#{file.path}") raise e end end) end def class_name @class_name ||= class_introspector.parsed_source.class_name.split("::").last end def nested_modules @nested_modules ||= begin class_introspector.parsed_source.module_nesting.join("::") end end attr_reader :parent_class, :active_record_model def primary_key @primary_key ||= ActiveRecordSchemaScrapper::Attribute.new(name: "id", type: :integer) end module ModulesConstants require "active_mocker/mock/unrepresentable_const_value" class Inspectable attr_reader :inspect def initialize(inspect) @inspect = inspect end end def constants class_introspector.get_class.constants.each_with_object({}) do |v, const| c = class_introspector.get_class.const_get(v) next if [Module, Class].include?(c.class) if /\A#