From dcc652a833783cfd83827c7a4ec9dc032c1a7cf9 Mon Sep 17 00:00:00 2001 From: Nikita Shilnikov Date: Sat, 11 May 2024 19:30:20 +0200 Subject: [PATCH] Fix using passed values in callable attributes It turned out it's not always possible to use the passed value in a block. Passing values requires more attention, there are opened issues about it, but it's a nice improvement anyway --- lib/rom/factory/tuple_evaluator.rb | 8 +++--- spec/integration/rom/factory_spec.rb | 37 ++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/lib/rom/factory/tuple_evaluator.rb b/lib/rom/factory/tuple_evaluator.rb index 4d0aeff..5aab381 100644 --- a/lib/rom/factory/tuple_evaluator.rb +++ b/lib/rom/factory/tuple_evaluator.rb @@ -151,9 +151,9 @@ def evaluate(traits, attrs, opts) # @api private def evaluate_values(attrs) - attributes.values.tsort.each_with_object({}) do |attr, h| - deps = attr.dependency_names.map { |k| h[k] }.compact - result = attr.(attrs, *deps) + attributes.values.tsort.each_with_object(attrs.dup) do |attr, h| + deps = attr.dependency_names.filter_map { |k| h[k] } + result = attr.(h, *deps) if result h.update(result) @@ -162,7 +162,7 @@ def evaluate_values(attrs) end def evaluate_traits(trait_list, attrs, opts) - return {} if trait_list.empty? + return EMPTY_HASH if trait_list.empty? traits = trait_list.map { |v| v.is_a?(Hash) ? v : {v => true} }.reduce(:merge) diff --git a/spec/integration/rom/factory_spec.rb b/spec/integration/rom/factory_spec.rb index 83fc7b9..77fb858 100644 --- a/spec/integration/rom/factory_spec.rb +++ b/spec/integration/rom/factory_spec.rb @@ -490,6 +490,43 @@ expect(user.email).to eql("#{user.first_name}.#{user.last_name}@test-1.org") end + + it "can use passed values in the block" do + factories.define(:user, relation: :users) do |f| + f.last_name { fake(:name) } + f.email { |first_name, last_name| "#{first_name}.#{last_name}@example.com" } + f.timestamps + end + + user = factories[:user, first_name: "Jane"] + + expect(user.email).to eql("Jane.#{user.last_name}@example.com") + end + + it "can use passed values in the block" do + factories.define(:user, relation: :users) do |f| + f.first_name nil + f.last_name { fake(:name) } + f.email { |first_name| "#{first_name}@example.com" } + f.timestamps + end + + user = factories[:user, first_name: "Jane"] + + expect(user.email).to eql("Jane@example.com") + end + + it "can use passed values in the block" do + factories.define(:user, relation: :users) do |f| + f.last_name { fake(:name) } + f.email { |first_name| "#{first_name}@example.com" } + f.timestamps + end + + user = factories[:user, first_name: "Jane"] + + expect(user.email).to eql("Jane@example.com") + end end context "changing values of dependant attributes" do