# class WIN32OLE::Record

`WIN32OLE::Record` objects represents VT_RECORD OLE variant. Win32OLE returns `WIN32OLE::Record` object if the result value of invoking OLE methods.

If COM server in VB.NET ComServer project is the following:

    Imports System.Runtime.InteropServices
    Public Class ComClass
        Public Structure Book
            <MarshalAs(UnmanagedType.BStr)> _
            Public title As String
            Public cost As Integer
        End Structure
        Public Function getBook() As Book
            Dim book As New Book
            book.title = "The Ruby Book"
            book.cost = 20
            Return book
        End Function
    End Class

then, you can retrieve getBook return value from the following Ruby script:

    require 'win32ole'
    obj = WIN32OLE.new('ComServer.ComClass')
    book = obj.getBook
    book.class # => WIN32OLE::Record
    book.title # => "The Ruby Book"
    book.cost  # => 20

### Public Class Methods

new(typename, obj) → WIN32OLE::Record object
Source

    static VALUE
    folerecord_initialize(VALUE self, VALUE typename, VALUE oleobj) {
        HRESULT hr;
        ITypeLib *pTypeLib = NULL;
        IRecordInfo *pri = NULL;

        if (!RB_TYPE_P(typename, T_STRING) && !RB_TYPE_P(typename, T_SYMBOL)) {
            rb_raise(rb_eArgError, "1st argument should be String or Symbol");
        }
        if (RB_TYPE_P(typename, T_SYMBOL)) {
            typename = rb_sym2str(typename);
        }

        hr = S_OK;
        if(rb_obj_is_kind_of(oleobj, cWIN32OLE)) {
            hr = typelib_from_val(oleobj, &pTypeLib);
        } else if (rb_obj_is_kind_of(oleobj, cWIN32OLE_TYPELIB)) {
            pTypeLib = itypelib(oleobj);
            OLE_ADDREF(pTypeLib);
            if (pTypeLib) {
                hr = S_OK;
            } else {
                hr = E_FAIL;
            }
        } else {
            rb_raise(rb_eArgError, "2nd argument should be WIN32OLE object or WIN32OLE::TypeLib object");
        }

        if (FAILED(hr)) {
            ole_raise(hr, eWIN32OLERuntimeError, "fail to query ITypeLib interface");
        }

        hr = recordinfo_from_itypelib(pTypeLib, typename, &pri);
        OLE_RELEASE(pTypeLib);
        if (FAILED(hr)) {
            ole_raise(hr, eWIN32OLERuntimeError, "fail to query IRecordInfo interface for `%s'", StringValuePtr(typename));
        }

        olerecord_set_ivar(self, pri, NULL);

        return self;
    }

Returns `WIN32OLE::Record` object. The first argument is struct name (`String` or `Symbol`). The second parameter obj should be `WIN32OLE` object or `WIN32OLE::TypeLib` object. If COM server in VB.NET ComServer project is the following:

    Imports System.Runtime.InteropServices
    Public Class ComClass
        Public Structure Book
            <MarshalAs(UnmanagedType.BStr)> _
            Public title As String
            Public cost As Integer
        End Structure
    End Class

then, you can create `WIN32OLE::Record` object is as following:

    require 'win32ole'
    obj = WIN32OLE.new('ComServer.ComClass')
    book1 = WIN32OLE::Record.new('Book', obj) # => WIN32OLE::Record object
    tlib = obj.ole_typelib
    book2 = WIN32OLE::Record.new('Book', tlib) # => WIN32OLE::Record object

### Public Instance Methods

inspect → String
Source

    static VALUE
    folerecord_inspect(VALUE self)
    {
        VALUE tname;
        VALUE field;
        tname = folerecord_typename(self);
        if (tname == Qnil) {
            tname = rb_inspect(tname);
        }
        field = rb_inspect(folerecord_to_h(self));
        return rb_sprintf("#<WIN32OLE::Record(%"PRIsVALUE") %"PRIsVALUE">",
                          tname,
                          field);
    }

Returns the OLE struct name and member name and the value of member

If COM server in VB.NET ComServer project is the following:

    Imports System.Runtime.InteropServices
    Public Class ComClass
        <MarshalAs(UnmanagedType.BStr)> _
        Public title As String
        Public cost As Integer
    End Class

then

    srver = WIN32OLE.new('ComServer.ComClass')
    obj = WIN32OLE::Record.new('Book', server)
    obj.inspect # => <WIN32OLE::Record(ComClass) {"title" => nil, "cost" => nil}>

method_missing(name)
Source

    static VALUE
    folerecord_method_missing(int argc, VALUE *argv, VALUE self)
    {
        VALUE name;
        rb_check_arity(argc, 1, 2);
        name = rb_sym2str(argv[0]);

    #if SIZEOF_SIZE_T > SIZEOF_LONG
        {
            size_t n = strlen(StringValueCStr(name));
            if (n >= LONG_MAX) {
                rb_raise(rb_eRuntimeError, "too long member name");
            }
        }
    #endif

        if (argc == 1) {
            return olerecord_ivar_get(self, name);
        } else if (argc == 2) {
            return olerecord_ivar_set(self, name, argv[1]);
        }
        return Qnil;
    }

Returns value specified by the member name of VT_RECORD OLE variable. Or sets value specified by the member name of VT_RECORD OLE variable. If the member name is not correct, `KeyError` exception is raised.

If COM server in VB.NET ComServer project is the following:

    Imports System.Runtime.InteropServices
    Public Class ComClass
        Public Structure Book
            <MarshalAs(UnmanagedType.BStr)> _
            Public title As String
            Public cost As Integer
        End Structure
    End Class

Then getting/setting value from Ruby is as the following:

    obj = WIN32OLE.new('ComServer.ComClass')
    book = WIN32OLE::Record.new('Book', obj)
    book.title # => nil ( book.method_missing(:title) is invoked. )
    book.title = "Ruby" # ( book.method_missing(:title=, "Ruby") is invoked. )

ole_instance_variable_get(name)
Source

    static VALUE
    folerecord_ole_instance_variable_get(VALUE self, VALUE name)
    {
        VALUE sname;
        if(!RB_TYPE_P(name, T_STRING) && !RB_TYPE_P(name, T_SYMBOL)) {
            rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
        }
        sname = name;
        if (RB_TYPE_P(name, T_SYMBOL)) {
            sname = rb_sym2str(name);
        }
        return olerecord_ivar_get(self, sname);
    }

Returns value specified by the member name of VT_RECORD OLE object. If the member name is not correct, `KeyError` exception is raised. If you can’t access member variable of VT_RECORD OLE object directly, use this method.

If COM server in VB.NET ComServer project is the following:

    Imports System.Runtime.InteropServices
    Public Class ComClass
        Public Structure ComObject
            Public object_id As Ineger
        End Structure
    End Class

and Ruby `Object` class has title attribute:

then accessing object_id of ComObject from Ruby is as the following:

    srver = WIN32OLE.new('ComServer.ComClass')
    obj = WIN32OLE::Record.new('ComObject', server)
    # obj.object_id returns Ruby Object#object_id
    obj.ole_instance_variable_get(:object_id) # => nil

ole_instance_variable_set(name, val)
Source

    static VALUE
    folerecord_ole_instance_variable_set(VALUE self, VALUE name, VALUE val)
    {
        VALUE sname;
        if(!RB_TYPE_P(name, T_STRING) && !RB_TYPE_P(name, T_SYMBOL)) {
            rb_raise(rb_eTypeError, "wrong argument type (expected String or Symbol)");
        }
        sname = name;
        if (RB_TYPE_P(name, T_SYMBOL)) {
            sname = rb_sym2str(name);
        }
        return olerecord_ivar_set(self, sname, val);
    }

Sets value specified by the member name of VT_RECORD OLE object. If the member name is not correct, `KeyError` exception is raised. If you can’t set value of member of VT_RECORD OLE object directly, use this method.

If COM server in VB.NET ComServer project is the following:

    Imports System.Runtime.InteropServices
    Public Class ComClass
        <MarshalAs(UnmanagedType.BStr)> _
        Public title As String
        Public cost As Integer
    End Class

then setting value of the ‘title’ member is as following:

    srver = WIN32OLE.new('ComServer.ComClass')
    obj = WIN32OLE::Record.new('Book', server)
    obj.ole_instance_variable_set(:title, "The Ruby Book")

WIN32OLE::Record#to_h #→ Ruby Hash object.
Source

    static VALUE
    folerecord_to_h(VALUE self)
    {
        return rb_ivar_get(self, rb_intern("fields"));
    }

Returns Ruby `Hash` object which represents VT_RECORD variable. The keys of `Hash` object are member names of VT_RECORD OLE variable and the values of `Hash` object are values of VT_RECORD OLE variable.

If COM server in VB.NET ComServer project is the following:

    Imports System.Runtime.InteropServices
    Public Class ComClass
        Public Structure Book
            <MarshalAs(UnmanagedType.BStr)> _
            Public title As String
            Public cost As Integer
        End Structure
        Public Function getBook() As Book
            Dim book As New Book
            book.title = "The Ruby Book"
            book.cost = 20
            Return book
        End Function
    End Class

then, the result of `WIN32OLE::Record#to_h` is the following:

    require 'win32ole'
    obj = WIN32OLE.new('ComServer.ComClass')
    book = obj.getBook
    book.to_h # => {"title"=>"The Ruby Book", "cost"=>20}

typename #→ String object
Source

    static VALUE
    folerecord_typename(VALUE self)
    {
        return rb_ivar_get(self, rb_intern("typename"));
    }

Returns the type name of VT_RECORD OLE variable.

If COM server in VB.NET ComServer project is the following:

    Imports System.Runtime.InteropServices
    Public Class ComClass
        Public Structure Book
            <MarshalAs(UnmanagedType.BStr)> _
            Public title As String
            Public cost As Integer
        End Structure
        Public Function getBook() As Book
            Dim book As New Book
            book.title = "The Ruby Book"
            book.cost = 20
            Return book
        End Function
    End Class

then, the result of `WIN32OLE::Record#typename` is the following:

    require 'win32ole'
    obj = WIN32OLE.new('ComServer.ComClass')
    book = obj.getBook
    book.typename # => "Book"