From 84905dc7333d6ad030b61ccf713bb803a451a4f3 Mon Sep 17 00:00:00 2001 From: George MacKerron Date: Tue, 24 Feb 2026 09:48:43 +0000 Subject: [PATCH] Add support for lambda or Proc :password key in connection Hash --- lib/pg/connection.rb | 4 ++++ spec/pg/connection_spec.rb | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/lib/pg/connection.rb b/lib/pg/connection.rb index eb607ab82..b1a0dfc2c 100644 --- a/lib/pg/connection.rb +++ b/lib/pg/connection.rb @@ -58,11 +58,15 @@ def self.connect_hash_to_string( hash ) # * URI string # * URI object # * positional arguments + # + # If an option Hash is used, :password can be a Proc or lambda that returns a + # string, so as to support dynamic passwords. # # The method adds the option "fallback_application_name" if it isn't already set. # It returns a connection string with "key=value" pairs. def self.parse_connect_args( *args ) hash_arg = args.last.is_a?( Hash ) ? args.pop.transform_keys(&:to_sym) : {} + hash_arg[:password] = hash_arg[:password].call if hash_arg[:password].respond_to?(:call) iopts = {} if args.length == 1 diff --git a/spec/pg/connection_spec.rb b/spec/pg/connection_spec.rb index 7763493a2..d41c6a623 100644 --- a/spec/pg/connection_spec.rb +++ b/spec/pg/connection_spec.rb @@ -313,6 +313,28 @@ PG::Connection.class_eval("PROGRAM_NAME=PG.make_shareable(#{old_script_name.inspect})") end end + + it "accepts a lambda as the :password key of a Hash parameter" do + optstring = described_class.parse_connect_args( + :dbname => 'db01', + :password => lambda { 'password_via_lambda' } + ) + + expect( optstring ).to be_a( String ) + expect( optstring ).to match( /(^|\s)dbname='db01'/ ) + expect( optstring ).to match( /(^|\s)password='password_via_lambda'/ ) + end + + it "accepts a Proc as the :password key of a Hash parameter" do + optstring = described_class.parse_connect_args( + :dbname => 'db01', + :password => Proc.new { 'password_via_Proc' } + ) + + expect( optstring ).to be_a( String ) + expect( optstring ).to match( /(^|\s)dbname='db01'/ ) + expect( optstring ).to match( /(^|\s)password='password_via_Proc'/ ) + end end it "connects successfully with connection string" do