Skip to content

Commit cbf169f

Browse files
committed
Add check to pass through compiled classes
1 parent 02be15d commit cbf169f

File tree

4 files changed

+53
-3
lines changed

4 files changed

+53
-3
lines changed

lib/mortymer/contract.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,19 @@ def initialize(errors)
2424
end
2525

2626
def self.__internal_struct_repr__
27-
@__internal_struct_repr__ || StructCompiler.new.compile(schema.json_schema)
27+
@__internal_struct_repr__ ||= StructCompiler.new.compile(schema.json_schema)
2828
end
2929

3030
def self.json_schema
3131
Generator.new.from_validation(self)
3232
end
3333

3434
def self.structify(params)
35+
# If params are already built using the internal struct, then there is
36+
# no need to re-validate it
37+
return params if params.instance_of?(__internal_struct_repr__)
38+
39+
params = params.to_h if params.is_a?(Dry::Struct)
3540
result = new.call(params)
3641
raise ContractError, result.errors.to_h unless result.errors.empty?
3742

lib/mortymer/model.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,13 @@ def self.structify(params)
2424
end
2525

2626
def [](key)
27-
@attributes[key.to_sym]
27+
public_send(key)
2828
end
29+
30+
def key?(attr)
31+
attributes.key?(attr.to_sym)
32+
end
33+
34+
alias has_key? key?
2935
end
3036
end

lib/mortymer/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# frozen_string_literal: true
22

33
module Mortymer
4-
VERSION = "0.0.12"
4+
VERSION = "0.0.13"
55
end

spec/lib/mortymer/contract_spec.rb

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,45 @@ class EnumContract < Mortymer::Contract
224224
end
225225
end
226226

227+
context "with already structified input" do
228+
it "returns the input directly if it's already an instance of the internal struct" do
229+
# First create a valid struct instance
230+
params = {
231+
name: "John Doe",
232+
age: 30,
233+
active: true
234+
}
235+
struct_instance = BasicContract.structify(params)
236+
237+
# Now pass that instance back to structify
238+
result = BasicContract.structify(struct_instance)
239+
240+
# Should be the exact same object (not just equal)
241+
expect(result.object_id).to eq(struct_instance.object_id)
242+
end
243+
244+
it "still validates if input is a different struct type" do
245+
# Create a similar but different struct class
246+
different_struct = Class.new(Mortymer::Model) do
247+
attribute :name, Mortymer::Model::String
248+
attribute :age, Mortymer::Model::Integer
249+
attribute :active, Mortymer::Model::Bool
250+
end
251+
252+
# Create an instance of the different struct
253+
different_instance = different_struct.new(
254+
name: "John Doe",
255+
age: 30,
256+
active: true
257+
)
258+
259+
# Should create a new struct of the correct type
260+
result = BasicContract.structify(different_instance)
261+
expect(result).to be_an_instance_of(BasicContract.__internal_struct_repr__)
262+
expect(result).not_to be_an_instance_of(different_struct)
263+
end
264+
end
265+
227266
context "with symbol keys and values" do
228267
it "handles symbol keys in input" do
229268
params = {

0 commit comments

Comments
 (0)