diff --git a/lib/manager/bundler/range.spec.ts b/lib/manager/bundler/range.spec.ts
index a14cce7bdb386807cdfbd1e7f8020cc11b9301e6..e12af89204e2c28d033733c3be8e1ff1311c4333 100644
--- a/lib/manager/bundler/range.spec.ts
+++ b/lib/manager/bundler/range.spec.ts
@@ -1,9 +1,15 @@
+import { RangeConfig } from '../common';
 import { getRangeStrategy } from '.';
 
 describe('lib/manager/bundler/range', () => {
   describe('getRangeStrategy()', () => {
-    it('always returns replace', () => {
-      expect(getRangeStrategy()).toEqual('replace');
+    it('returns replace when rangeStrategy is auto', () => {
+      const config: RangeConfig = { rangeStrategy: 'auto' };
+      expect(getRangeStrategy(config)).toEqual('replace');
+    });
+    it('returns the config value when rangeStrategy is different than auto', () => {
+      const config: RangeConfig = { rangeStrategy: 'update-lockfile' };
+      expect(getRangeStrategy(config)).toEqual('update-lockfile');
     });
   });
 });
diff --git a/lib/manager/bundler/range.ts b/lib/manager/bundler/range.ts
index ae7626226f7a23c4c656d980297e0ae9c6ad048e..2bd725bf79ae259e91285c707e01418ae02cdab6 100644
--- a/lib/manager/bundler/range.ts
+++ b/lib/manager/bundler/range.ts
@@ -1,4 +1,5 @@
 import { RangeStrategy } from '../../versioning';
+import { RangeConfig } from '../common';
 
 /*
  * The getRangeStrategy() function is optional and can be removed if not applicable.
@@ -12,7 +13,10 @@ import { RangeStrategy } from '../../versioning';
  * If this function is not present then the default 'replace' value will be used.
  *
  */
+export function getRangeStrategy(config: RangeConfig): RangeStrategy {
+  if (config.rangeStrategy === 'auto') {
+    return 'replace';
+  }
 
-export function getRangeStrategy(): RangeStrategy {
-  return 'replace';
+  return config.rangeStrategy;
 }
diff --git a/lib/versioning/ruby/index.spec.ts b/lib/versioning/ruby/index.spec.ts
index f93730f93906c4665ea1e815ef47f7e3bad01625..bef39d480fe861b4b5f592a69b266814cc44aa09 100644
--- a/lib/versioning/ruby/index.spec.ts
+++ b/lib/versioning/ruby/index.spec.ts
@@ -529,5 +529,22 @@ describe('semverRuby', () => {
         }
       );
     });
+    it('returns correct version for update-lockfile strategy', () => {
+      [
+        ['~> 6.0.0', '~> 6.0.0', 'update-lockfile', '6.0.2', '6.0.3'],
+        ['~> 7.0.0', '~> 6.0.0', 'update-lockfile', '6.0.2', '7.0.0'],
+      ].forEach(
+        ([expected, currentValue, rangeStrategy, fromVersion, toVersion]) => {
+          expect(
+            semverRuby.getNewValue({
+              currentValue,
+              rangeStrategy: rangeStrategy as RangeStrategy,
+              fromVersion,
+              toVersion,
+            })
+          ).toEqual(expected);
+        }
+      );
+    });
   });
 });
diff --git a/lib/versioning/ruby/index.ts b/lib/versioning/ruby/index.ts
index 0f1960d3ed53c301791066507156a9b3e2a88536..b4c14327fb5ce0a90a85df18d31fc8f886536ae6 100644
--- a/lib/versioning/ruby/index.ts
+++ b/lib/versioning/ruby/index.ts
@@ -91,6 +91,18 @@ const getNewValue = ({
     newValue = currentValue.replace(fromVersion, toVersion);
   } else {
     switch (rangeStrategy) {
+      case 'update-lockfile':
+        if (satisfies(toVersion, currentValue)) {
+          newValue = currentValue;
+        } else {
+          newValue = getNewValue({
+            currentValue,
+            rangeStrategy: 'replace',
+            fromVersion,
+            toVersion,
+          });
+        }
+        break;
       case 'pin':
         newValue = pin({ to: vtrim(toVersion) });
         break;