Skip to content

Commit

Permalink
Skip building inversed assocs in ManyToOne
Browse files Browse the repository at this point in the history
  • Loading branch information
solnic committed Dec 2, 2023
1 parent 2e47229 commit 0833947
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 17 deletions.
4 changes: 4 additions & 0 deletions lib/rom/factory/attribute_registry.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ def associations
self.class.new(elements.select { |e| e.is_a?(Attributes::Association::Core) })
end

def reject(&block)
self.class.new(elements.reject(&block))
end

private

# @api private
Expand Down
23 changes: 18 additions & 5 deletions lib/rom/factory/attributes/association.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,28 @@ def call(attrs, persist: true)
elsif assoc_data.is_a?(ROM::Struct)
assoc.associate(attrs, assoc_data)
elsif !(attrs.key?(name) && attrs[name].nil?) && !attrs[foreign_key]
struct = if persist
builder.persistable.create(*traits, **assoc_data)
parent = if persist
builder.persistable.create(*parent_traits, **assoc_data)
else
builder.struct(*traits, **assoc_data)
builder.struct(*parent_traits, **assoc_data)
end
tuple = {name => struct}
assoc.associate(tuple, struct)

tuple = {name => parent}

assoc.associate(tuple, parent)
end
end

private

def parent_traits
@parent_traits ||=
if assoc.target.associations.key?(assoc.source.name)
traits + [assoc.target.associations[assoc.source.name].name => false]
else
traits
end
end
end

# @api private
Expand Down
6 changes: 5 additions & 1 deletion lib/rom/factory/builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,11 @@ def persistable

# @api private
def tuple_evaluator
@__tuple_evaluator__ ||= TupleEvaluator.new(attributes, tuple_evaluator_relation, traits)
@__tuple_evaluator__ ||= TupleEvaluator.new(
attributes,
tuple_evaluator_relation,
traits
)
end

# @api private
Expand Down
21 changes: 14 additions & 7 deletions lib/rom/factory/tuple_evaluator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,15 @@ def assoc_names(traits = [])
end

def assocs(traits_names = [])
traits
found_assocs = traits
.values_at(*traits_names)
.compact
.map(&:associations).flat_map(&:elements)
.inject(AttributeRegistry.new(attributes.associations.elements), :<<)

exclude = traits_names.select { |t| t.is_a?(Hash) }.reduce(:merge) || EMPTY_HASH

found_assocs.reject { |a| exclude[a.name] == false }
end

# @api private
Expand All @@ -109,7 +114,7 @@ def primary_key
# @api private
def evaluate(traits, attrs, opts)
evaluate_values(attrs)
.merge(evaluate_associations(attrs, opts))
.merge(evaluate_associations(traits, attrs, opts))
.merge(evaluate_traits(traits, attrs, opts))
end

Expand All @@ -125,17 +130,19 @@ def evaluate_values(attrs)
end
end

def evaluate_traits(traits, attrs, opts)
return {} if traits.empty?
def evaluate_traits(trait_list, attrs, opts)
return {} if trait_list.empty?

traits = trait_list.map { |v| v.is_a?(Hash) ? v : {v => true} }.reduce(:merge)

traits_attrs = self.traits.values_at(*traits).flat_map(&:elements)
traits_attrs = self.traits.select { |key, value| traits[key] }.values.flat_map(&:elements)

Check failure on line 138 in lib/rom/factory/tuple_evaluator.rb

View workflow job for this annotation

GitHub Actions / Lint

Lint/UnusedBlockArgument: Unused block argument - `value`. If it's necessary, use `_` or `_value` as an argument name to indicate that it won't be used.
registry = AttributeRegistry.new(traits_attrs)
self.class.new(registry, relation).defaults([], attrs, **opts)
end

# @api private
def evaluate_associations(attrs, opts)
attributes.associations.each_with_object({}) do |assoc, h|
def evaluate_associations(traits, attrs, opts)
assocs(traits).associations.each_with_object({}) do |assoc, h|
if assoc.dependency?(relation)
h[assoc.name] = ->(parent, call_opts) do
assoc.call(parent, **opts, **call_opts)
Expand Down
13 changes: 9 additions & 4 deletions spec/integration/rom/factory_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,16 @@
f.last_name "Doe"
f.email "[email protected]"
f.timestamps

f.association(:tasks)
end
end

it "does not pass provided attributes into associations" do
expect { factories.structs[:task, title: "Bar"] }.not_to raise_error
it "creates a struct with associated parent" do
task = factories.structs[:task, title: "Bar"]

expect(task.title).to eql("Bar")
expect(task.user.first_name).to eql("Jane")
end

it "does not build associated struct if it's set to nil explicitly" do
Expand All @@ -109,9 +114,9 @@
end

it "creates the associated record with provided attributes" do
task = factories[:task, user: {first_name: "Jane"}]
task = factories[:task, user: {first_name: "John"}]

expect(task.user.first_name).to eql("Jane")
expect(task.user.first_name).to eql("John")
end
end

Expand Down

0 comments on commit 0833947

Please sign in to comment.