Hi, I’m trying to dynamically pass an option hash to the rename_keys transformer but it looks like I cant access the class scope inside de define! block
$global_keys = {user_name: :name}
class MyMapper < Dry::Transformer::Pipe
import Dry::Transformer::ArrayTransformations
import Dry::Transformer::HashTransformations
def initialize(rename_keys)
@rename_keys = rename_keys
end
define! do
map_array do
symbolize_keys
# rename_keys @rename_keys
rename_keys $global_keys
# rename_keys user_name: :name
nest :address, [:city, :street, :zipcode]
end
end
end
I believe its a scope problem because I can access the contents of the global variable but not the class variable.
That almost works. I’m not really sure what am I doing wrong, I modified that test to look like my use case.
# frozen_string_literal: true
RSpec.describe Dry::Transformer, "instance variables" do
subject(:transformer) do
Class.new(Dry::Transformer[registry]) do
def initialize(rename_keys)
@rename_keys = rename_keys
end
def my_keys
@rename_keys
end
define! do
map_array do
rename_keys "user_name" => :user # this works as expected
# rename_keys @rename_keys # this dont work
end
end
end.new({"user_name" => :user})
end
let(:registry) do
Module.new do
extend Dry::Transformer::Registry
import Dry::Transformer::HashTransformations
import Dry::Transformer::ArrayTransformations
end
end
it "registers a new transformation function" do
expect(transformer.call([{"user_name" => "jane"}])).to eql([{user: "jane"}])
end
end
When using the instance variable when the transformer reach the self.rename_keys(source_hash, mapping) method the mapping parameter is nil
Looks like I’m not supposed to pass a hash to rename_keys, I tried splatting the args like rename_keys *@rename_keys but no success, it turns the mapping value into [:fn, [:my_keys, []]]
I also modified the test to look like this
# frozen_string_literal: true
RSpec.describe Dry::Transformer, "instance methods" do
subject(:transformer) do
Class.new(Dry::Transformer[registry]) do
def initialize(append_value)
@append_value = append_value
end
define! do
map_array(&:append)
end
def append(input)
"#{input} #{@append_value}"
end
end.new("baz")
end
let(:registry) do
Module.new do
extend Dry::Transformer::Registry
import Dry::Transformer::ArrayTransformations
end
end
it "registers a new transformation function" do
expect(transformer.call(%w[foo bar])).to eql(["foo baz", "bar baz"])
end
end
And this one works as expected. So the problem might be that I dont know how to properly use rename_keys
After thinking a little bit about this I had an idea.
What if we had to explicitly pass a method(:my_method) to the transformer instead of assuming that we want the method instead of the methods return
def k
@my_keys
end
define! do
map_array do
rename_keys method(:k) # will pass the method to be called by the visit_fn on the compiler
rename_keys k # will pass the return value of `k` to rename_keys
end
end