diff --git a/src/ruby/ext/grpc/rb_call.c b/src/ruby/ext/grpc/rb_call.c
index b5a256d5a67d4b79ff6b8ab342506932761eff32..f2a275ecdb87289ab4ee44d23f6ca72c776d4d6c 100644
--- a/src/ruby/ext/grpc/rb_call.c
+++ b/src/ruby/ext/grpc/rb_call.c
@@ -500,6 +500,26 @@ void Init_grpc_error_codes() {
   rb_obj_freeze(rb_error_code_details);
 }
 
+void Init_grpc_op_codes() {
+  /* Constants representing operation type codes in grpc.h */
+  VALUE rb_CallOps = rb_define_module_under(rb_mGrpcCore, "CallOps");
+  rb_define_const(rb_CallOps, "SEND_INITIAL_METADATA",
+                  UINT2NUM(GRPC_OP_SEND_INITIAL_METADATA));
+  rb_define_const(rb_CallOps, "SEND_MESSAGE", UINT2NUM(GRPC_OP_SEND_MESSAGE));
+  rb_define_const(rb_CallOps, "SEND_CLOSE_FROM_CLIENT",
+                  UINT2NUM(GRPC_OP_SEND_CLOSE_FROM_CLIENT));
+  rb_define_const(rb_CallOps, "SEND_STATUS_FROM_SERVER",
+                  UINT2NUM(GRPC_OP_SEND_STATUS_FROM_SERVER));
+  rb_define_const(rb_CallOps, "RECV_INITIAL_METADATA",
+                  UINT2NUM(GRPC_OP_RECV_INITIAL_METADATA));
+  rb_define_const(rb_CallOps, "RECV_MESSAGE",
+                  UINT2NUM(GRPC_OP_RECV_MESSAGE));
+  rb_define_const(rb_CallOps, "RECV_STATUS_ON_CLIENT",
+                  UINT2NUM(GRPC_OP_RECV_STATUS_ON_CLIENT));
+  rb_define_const(rb_CallOps, "RECV_CLOSE_ON_SERVER",
+                  UINT2NUM(GRPC_OP_RECV_CLOSE_ON_SERVER));
+}
+
 void Init_grpc_call() {
   /* CallError inherits from Exception to signal that it is non-recoverable */
   rb_eCallError =
@@ -543,6 +563,7 @@ void Init_grpc_call() {
   rb_define_const(rb_cCall, "INTERNAL_ALL_CALLs", hash_all_calls);
 
   Init_grpc_error_codes();
+  Init_grpc_op_codes();
 }
 
 /* Gets the call from the ruby object */
diff --git a/src/ruby/spec/call_spec.rb b/src/ruby/spec/call_spec.rb
index 781c735e750a5a709f2c5de57636d97c94d2b965..108051a1e5de1b43c22c8fd62f3393a98f7bdc3a 100644
--- a/src/ruby/spec/call_spec.rb
+++ b/src/ruby/spec/call_spec.rb
@@ -66,6 +66,27 @@ describe GRPC::Core::RpcErrors do
   end
 end
 
+describe GRPC::Core::CallOps do
+  before(:each) do
+    @known_types = {
+      SEND_INITIAL_METADATA: 0,
+      SEND_MESSAGE: 1,
+      SEND_CLOSE_FROM_CLIENT: 2,
+      SEND_STATUS_FROM_SERVER: 3,
+      RECV_INITIAL_METADATA: 4,
+      RECV_MESSAGE: 5,
+      RECV_STATUS_ON_CLIENT: 6,
+      RECV_CLOSE_ON_SERVER: 7,
+    }
+  end
+
+  it 'should have symbols for all the known operation types' do
+    m = GRPC::Core::CallOps
+    syms_and_codes = m.constants.collect { |c| [c, m.const_get(c)] }
+    expect(Hash[syms_and_codes]).to eq(@known_types)
+  end
+end
+
 describe GRPC::Core::Call do
   let (:client_queue) { GRPC::Core::CompletionQueue.new }
   let (:test_tag)  { Object.new }