diff --git a/lib/versioning/ruby/strategies/replace.ts b/lib/versioning/ruby/strategies/replace.ts
index b223412b57b6816d4e14f94436eeb2d5762aa7ad..8db76c96713f6f324be1387d360f732da1cf5549 100644
--- a/lib/versioning/ruby/strategies/replace.ts
+++ b/lib/versioning/ruby/strategies/replace.ts
@@ -6,6 +6,15 @@ function countInstancesOf(str: string, char: string): number {
   return str.split(char).length - 1;
 }
 
+function isMajorRange(range: string): boolean {
+  const splitRange = range.split(',').map(part => part.trim());
+  return (
+    splitRange.length === 1 &&
+    splitRange[0].startsWith('~>') &&
+    countInstancesOf(splitRange[0], '.') === 0
+  );
+}
+
 function isCommonRubyMajorRange(range: string): boolean {
   const splitRange = range.split(',').map(part => part.trim());
   return (
@@ -45,6 +54,9 @@ export default ({ to, range }: { range: string; to: string }): string => {
   } else if (isCommonRubyMinorRange(range)) {
     const firstPart = reduceOnePrecision(to) + '.0';
     newRange = `~> ${firstPart}, >= ${to}`;
+  } else if (isMajorRange(range)) {
+    const majorPart = to.split('.')[0];
+    newRange = '~>' + (range.includes(' ') ? ' ' : '') + majorPart;
   } else {
     const lastPart = range
       .split(',')
diff --git a/test/versioning/ruby.spec.ts b/test/versioning/ruby.spec.ts
index d725c6af18daa44e4c8b9bea698ec131f5d92850..1fd0771805cda8aab4c572889edfe14af36f0385 100644
--- a/test/versioning/ruby.spec.ts
+++ b/test/versioning/ruby.spec.ts
@@ -426,6 +426,11 @@ describe('semverRuby', () => {
         semverRuby.getNewValue('4.2.5.1', 'replace', '4.2.5.1', '4.3.0')
       ).toEqual('4.3.0');
     });
+    it('handles major ranges', () => {
+      expect(
+        semverRuby.getNewValue('~> 1', 'replace', '1.2.0', '2.0.3')
+      ).toEqual('~> 2');
+    });
 
     it('returns correct version for replace strategy', () => {
       [