Skip to content

Commit

Permalink
Build parent structs when their FK is provided
Browse files Browse the repository at this point in the history
  • Loading branch information
solnic committed Dec 15, 2023
1 parent 93bb520 commit e5f083a
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 14 deletions.
9 changes: 6 additions & 3 deletions lib/rom/factory/attributes/association.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,14 @@ def call(attrs, persist: true)
assoc.associate(attrs, attrs[name])
elsif assoc_data.is_a?(ROM::Struct)
assoc.associate(attrs, assoc_data)
elsif !attrs[foreign_key]
parent = if persist
else
parent = if persist && !attrs[foreign_key]
builder.persistable.create(*parent_traits, **assoc_data)
else
builder.struct(*parent_traits, **assoc_data)
builder.struct(
*parent_traits,
**assoc_data.merge(assoc.target.primary_key => attrs[foreign_key])
)
end

tuple = {name => parent}
Expand Down
24 changes: 13 additions & 11 deletions lib/rom/factory/tuple_evaluator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,20 +68,22 @@ def struct(*traits, **attrs)
attributes = merged_attrs.reject(&is_callable)

materialized_callables = {}
callables.each do |_name, callable|
callables.each_value do |callable|
materialized_callables.merge!(callable.call(attributes, persist: false))
end

attributes.merge!(materialized_callables)

assoc_attrs = attributes.slice(*assoc_names(traits)).merge(assoc_names(traits)
.select { |key|
build_assoc?(key, attributes)
}
.map { |key|
[key, build_assoc_attrs(key, attributes[relation.primary_key], attributes[key])]
}
.to_h)
assoc_attrs = attributes.slice(*assoc_names(traits)).merge(
assoc_names(traits)
.select { |key|
build_assoc?(key, attributes)
}
.map { |key|
[key, build_assoc_attrs(key, attributes[relation.primary_key], attributes[key])]
}
.to_h
)

model_attrs = relation.output_schema[attributes]
model_attrs.update(assoc_attrs)
Expand All @@ -91,8 +93,8 @@ def struct(*traits, **attrs)
raise TupleEvaluatorError.new(relation, e, attrs, traits, assoc_attrs)
end

def build_assoc?(key, attributes)
attributes.key?(key) && attributes[key] != [] && !attributes[key].nil?
def build_assoc?(name, attributes)
attributes.key?(name) && attributes[name] != [] && !attributes[name].nil?
end

def build_assoc_attrs(key, fk, value)
Expand Down
7 changes: 7 additions & 0 deletions spec/integration/rom/factory_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1146,6 +1146,13 @@ class Admin < ROM::Struct
expect(rom.relations[:tasks].count).to be(0)
end

it "respects FK" do
task = factories.structs[:task, user_id: 312]

expect(task.user_id).to be(312)
expect(task.user.id).to be(312)
end

it "raises UnknownFactoryAttributes when unknown attributes are used" do
expect { factories.structs[:user, name: "Joe"] }
.to raise_error(ROM::Factory::UnknownFactoryAttributes, /name/)
Expand Down

0 comments on commit e5f083a

Please sign in to comment.