B4J Code Snippet POC: ORM

Having a background on Ruby On Rails there are 2 things i miss everytime i come back to B4x: ActiveRecord and Testings, so today i decided to tackle both them.

so far i have achived 20% of what i want to do, but i am very happy with the results.
My current approach consists of using the Type system of B4x to map them into the database. lets see the example:

B4X:
Type supplier(id As String, nombre As String, nombre_corto As String, invoices As List)
the type supplier matches to the table suppliers in the database (singular -plural), each field also match to a column. EXCEPT of course for the list, this one matches to the table invoices (hence the plural)

B4X:
Type invoice(id As String, folio As String, supplier_id As String)
the type invoice has a supplier_id, this way i am creating a One to Many relation ship.

The next step is simply to connect to a database and let the magic begin!

B4X:
    DB_ORM.Initialize(MP)
   
    TakeTime
    Dim p As supplier = Createsupplier("testorm","tm")
   
    For i = 0 To 10
        Dim f As invoice = Createinvoice(i,DB_ORM.uuid_null)
        p.invoices.Add(f)
    Next
   
    DB_ORM.save(p,Null)
    CallSub(Me, "StopTakeTime")
    Log(p.id) 'Elapsed time: 00:01:896
    StartMessageLoop
this code will create the following information in to the database.
1638164972281.png

The code will not hit the database until i call the save method, it will automatically detect the child tables (based on the type of the fields classes) each one of the invoice objects will be saved into the database too without having to do anything extra. it can also detect wheter it has to update or insert.

i was a bit hesitant on the performance, but inserting 11 records to a remote database (in a vps in another country) takes 2 seconds on avarage. If there is a performance hit it seems to be neglible.

Thats it for now! there is a bunch to do so far, the next steps will be to do some query SELECTORS
Okey then, sorry for the teasing as it is not ready to be released i want to know if this is something that could interest to the community and if so, what functionality would you like to appear?

P.D. of course, with this technique creating TESTS would be almost the same!
 

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
hi! welcome to another episode of ORM!
Today i will show some more advancements, most if not all of the ORMS are designed to work in conjuction with other tools, mainly with webframeworks so i decided to extend it to the next level. In the last post i showed you a database to b4x type conversions that usually would be called the MODEL in MVC frameworks. You may not be aware, but we already have the Controller in form of the handlers of jserver.

So if we already have the M and the C what is missing? the VIEW!!

so i present to you:
Well not exactly that but i extracted freemarker from the spring framework and make it work with B4J.

First our model:
B4X:
Type supplier(id As String, name As String, alias As String, invoices As List)

then our controller side.
B4X:
    Dim qb As query_builder
    Dim suppliers As List = qb.Initialize("supplier").get_all(sql)
    
    If suppliers.Size = 0 Then
        Return
    End If
    
    Dim p As supplier = suppliers.Get(0)
    
    Dim view As Map
    view.Initialize
    view.Put("supplier",p)
    
    Dim t As Template = templates.getTemplate($"form.html"$) 'freemarker
    resp.Write(t.stdOut(root))

and finaly from the view side:
B4X:
        <div class="flex flex-wrap -mx-3 mb-6">
            <div class="w-full px-3">
                <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="razon_social">
                Razon Social
                </label>
                <input 
                    class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" 
                    id="razon_social" 
                    type="text" 
                    name="razon_social"
                    value="${supplier.name}"
                >
            </div>
            <div class="w-full px-3">
                <label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="alias">
                Alias
                </label>
                <input 
                    class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" 
                    id="alias" 
                    type="text" 
                    name="alias"
                    value="${supplier.alias}"
                >
            </div>
        </div>

A good observer will see the following text:
"${supplier.name}"
"${supplier.alias}"

this match the type properties.
and the result?
1638909823491.png

As you can see this is in the browser.

with just a couple of lines of code we are able to extract from database the model, prepare it in the controller and show it in the browser!!

i will try to release a teaser project soon!
 

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
Are you ready to share how you work with the FreeMarker template engine in B4J?
I've been using it in production for quite some time now, it is quite powerful (the whole framework)

but i havent released it because:
1. I dont know which license to use, i dont want it to be open source / free
2. i may not have time to give support if i sell it.

but send me a PM and i can share the freemarker part with you
 
Top