Hi,

Currently, defining classes or other constants inside a Ruby source code
block like this fails with an "unexpected class definition in method
body" error:

#+begin_src ruby
class Three
  def number = 3
end
Three.new.number
#+end_src

This happens because ob-ruby wraps the code in a method before evaling
it, and classes can not be defined inside methods.

Wrapping it inside a Ruby lambda instead makes this work. The two other
options I could think of, `instance_exec` or simply a `begin ... end`
block would both break the behaviour of toplevel `return` statements in
the evaled code, which some people might rely on. The added tests ensure
that `return` still works as before.


cheers, Til
From 56ec93825f91c272159672ef00b4c1cd027aa6af Mon Sep 17 00:00:00 2001
From: Tilmann Singer <[email protected]>
Date: Thu, 1 Jan 2026 23:32:35 +0100
Subject: [PATCH] ob-ruby: Wrap evaled code in lambda instead of method

* lisp/ob-ruby.el (org-babel-ruby-wrapper-method,
org-babel-ruby-pp-wrapper-method): wrap evaled Ruby code inside a
lambda instead of a method.  This way, defining constants such as
classes becomes possible.

* testing/lisp/test-ob-ruby.el: add tests for the result methods value
and pp
---
 lisp/ob-ruby.el              | 10 +++---
 testing/lisp/test-ob-ruby.el | 60 ++++++++++++++++++++++++++++++++++++
 2 files changed, 64 insertions(+), 6 deletions(-)

diff --git a/lisp/ob-ruby.el b/lisp/ob-ruby.el
index e7e470dc8..003fc809e 100644
--- a/lisp/ob-ruby.el
+++ b/lisp/ob-ruby.el
@@ -213,20 +213,18 @@ Session settings (`:ruby' header arg value) are taken from PARAMS."
 
 (defvar org-babel-ruby-wrapper-method
   "
-def main()
+results = (lambda do
 %s
-end
-results = main()
+end).call
 File.open('%s', 'w'){ |f| f.write((results.class == String) ? results : results.inspect) }
 ")
 
 (defvar org-babel-ruby-pp-wrapper-method
   "
 require 'pp'
-def main()
+results = (lambda do
 %s
-end
-results = main()
+end).call
 File.open('%s', 'w') do |f|
   $stdout = f
   pp results
diff --git a/testing/lisp/test-ob-ruby.el b/testing/lisp/test-ob-ruby.el
index 27f96f6da..c4d75a80f 100644
--- a/testing/lisp/test-ob-ruby.el
+++ b/testing/lisp/test-ob-ruby.el
@@ -78,6 +78,66 @@ s = \"6\"
 : 5
 ")))
 
+(ert-deftest test-ob-ruby/value ()
+  (should
+   (equal 3
+          (org-test-with-temp-text "#+begin_src ruby :results value
+1 + 2
+#+end_src"
+            (org-babel-execute-src-block)))))
+
+(ert-deftest test-ob-ruby/value-with-class-definition ()
+  (should
+   (equal 3
+          (org-test-with-temp-text "#+begin_src ruby :results value
+class Three
+  def result
+    1 + 2
+  end
+end
+Three.new.result
+#+end_src"
+            (org-babel-execute-src-block)))))
+
+(ert-deftest test-ob-ruby/value-with-return ()
+  (should
+   (equal 3
+          (org-test-with-temp-text "#+begin_src ruby :results value
+return 3
+2
+#+end_src"
+            (org-babel-execute-src-block)))))
+
+(ert-deftest test-ob-ruby/pp ()
+  (should
+   (equal "3\n"
+          (org-test-with-temp-text "#+begin_src ruby :results pp
+1 + 2
+#+end_src"
+                   (org-babel-execute-src-block)))))
+
+(ert-deftest test-ob-ruby/pp-with-class-definition ()
+  (should
+   (equal "3\n"
+          (org-test-with-temp-text "#+begin_src ruby :results pp
+class Three
+  def result
+    1 + 2
+  end
+end
+Three.new.result
+#+end_src"
+                   (org-babel-execute-src-block)))))
+
+(ert-deftest test-ob-ruby/pp-with-return ()
+  (should
+   (equal "3\n"
+          (org-test-with-temp-text "#+begin_src ruby :results pp
+return 3
+2
+#+end_src"
+                   (org-babel-execute-src-block)))))
+
 (provide 'test-ob-ruby)
 
 ;;; test-ob-ruby.el ends here
-- 
2.52.0

Attachment: signature.asc
Description: PGP signature

Reply via email to