Skip to content

Commit

Permalink
Struct compiler now checks if a class exists before creating a new one
Browse files Browse the repository at this point in the history
A class may already exist and just not be available (yet) because it hasn't been autoloaded. The StructCompiler class should call const_get in an attempt to load this class. If it can load the class, then it should use this class and not go to Dry::Core::ClassBuilder to build an entirely new class.
  • Loading branch information
Ryan Bigg committed May 15, 2018
1 parent 7571b18 commit bca4319
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 4 deletions.
19 changes: 15 additions & 4 deletions mapper/lib/rom/struct_compiler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@ def call(*args)
if attributes.empty?
ROM::OpenStruct
else
build_class(name, ROM::Struct, ns) do |klass|
attributes.each do |(attr_name, type)|
klass.attribute(attr_name, type)
end
klass = get_class(name, ns) || build_class(name, ROM::Struct, ns)

attributes.each do |(attr_name, type)|
klass.attribute(attr_name, type)
end

klass
end
end
end
Expand Down Expand Up @@ -95,6 +97,15 @@ def visit_enum(node)
visit(type_node)
end

# @api private
def get_class(name, ns)
begin
ns.const_get(class_name(name))
rescue NameError
nil
end
end

# @api private
def build_class(name, parent, ns, &block)
Dry::Core::ClassBuilder.
Expand Down
4 changes: 4 additions & 0 deletions mapper/spec/unit/rom/struct_compiler_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ def attr_ast(name, type, **opts)
[:users, [[:attribute, attr_ast(:id, :Int)], [:attribute, attr_ast(:name, :String)]]]
end

before do
ROM::Struct.send(:remove_const, :User) if ROM::Struct.constants.include?(:User)
end

context 'ROM::Struct' do
it 'generates a struct for a given relation name and columns' do
struct = struct_compiler[*input, ROM::Struct]
Expand Down

0 comments on commit bca4319

Please sign in to comment.