Fix keyword argument decorators

If a decorator is keyword-only, like `do |x: nil, y: nil|`,
then the following does nto work properly:

	factory.mydecorator(x: 1, y: 2)

Instead, both of them remain nil.
Ruby 3.0 changed how keyword arguments work
which broke some metaprogramming-heavy libraries
(this bug does not reproduce under 2.7).

My fix for this is to unpack a trailing hash
in the provided decorator arguments
and double-splat it, so this:

	o.instance_exec(*args, &block)

becomes something like this:

	o.instance_exec(*args[0..-2], **args[-1], &block)
3 files changed, 40 insertions(+), 2 deletions(-)

M .ruby-version
M lib/fluent_fixtures/factory.rb
M spec/fluent_fixtures/factory_spec.rb
M .ruby-version +1 -1
@@ 1,1 1,1 @@ 
-2.7
+3.1

          
M lib/fluent_fixtures/factory.rb +7 -1
@@ 190,7 190,13 @@ class FluentFixtures::Factory
 		self.apply_prelude( instance, decorator_options[:prelude] ) if decorator_options[:prelude]
 
 		instance = self.try_to_save( instance ) if decorator_options[:presave]
-		instance.instance_exec( *args, &decorator_block )
+		if args[-1].is_a?(Hash)
+			kwargs = args[-1]
+			args = args[0..-2]
+		else
+			kwargs = {}
+		end
+		instance.instance_exec( *args, **kwargs, &decorator_block )
 
 		return instance
 	end

          
M spec/fluent_fixtures/factory_spec.rb +32 -0
@@ 336,6 336,38 @@ RSpec.describe FluentFixtures::Factory d
 	end
 
 
+	it "handles keyword-only decorators" do
+		fixture_module.decorator( :set_fields ) do |name: nil, email: nil|
+			self.name = name
+			self.email = email
+		end
+
+		object = factory.set_fields( name: 'x', email: 'a@b.c' ).instance
+
+		expect( object ).to be_a( fixtured_class )
+		expect( object.name ).to eq( 'x' )
+		expect( object.email ).to eq( 'a@b.c' )
+		expect( object ).to_not be_saved
+	end
+
+
+	it "handles mixed position and keyword decorators" do
+		fixture_module.decorator( :set_fields ) do |arg1, arg2=2, kwarg: nil|
+			self.name = arg1
+			self.email = arg2
+			self.login = kwarg
+		end
+
+		object = factory.set_fields( 'x', 'a@b.c', kwarg: 'mylogin' ).instance
+
+		expect( object ).to be_a( fixtured_class )
+		expect( object.name ).to eq( 'x' )
+		expect( object.email ).to eq( 'a@b.c' )
+		expect( object.login ).to eq( 'mylogin' )
+		expect( object ).to_not be_saved
+	end
+
+
 	describe "enumerator/generator" do
 
 		it "is Enumerable" do