Slide 1

Slide 1 text

Client-Server GUI Web Components With Ext JS And Rails Max Gorin @uptomax

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

eval

Slide 6

Slide 6 text

Challenges hundreds of data models most of which need a dedicated GUI comlpex compound views

Slide 7

Slide 7 text

Our options?

Slide 8

Slide 8 text

Conventional MVC partial hell

Slide 9

Slide 9 text

Monolithic client side connected to Rails API Monstrous client-side code Separated client and server code duplicated logic no single point of configuration

Slide 10

Slide 10 text

Pain to maintain!

Slide 11

Slide 11 text

Something better client-server GUI components

Slide 12

Slide 12 text

Divide and conquer!

Slide 13

Slide 13 text

Floralogic app

Slide 14

Slide 14 text

Orders nested in...

Slide 15

Slide 15 text

ShipmentsAndOrders nested in...

Slide 16

Slide 16 text

Workspace nested in...

Slide 17

Slide 17 text

Application

Slide 18

Slide 18 text

My tools Rails Mostly ActiveRecord & ActiveSupport Sencha Ext JS Rich extendable views with JavaScript Netzke (netzke.org) Binding those together in a modular way

Slide 19

Slide 19 text

Netzke component

Slide 20

Slide 20 text

Netzke component

Slide 21

Slide 21 text

Inheritance

Slide 22

Slide 22 text

Reusability

Slide 23

Slide 23 text

Netzke::Basepack::Grid class Contacts < Netzke::Basepack::Grid def configure(c) super c.model = "Contact" end end

Slide 24

Slide 24 text

Netzke::Basepack::Grid CRUD pagination sorting filtering/searching association support on-the-fly column configuration and more

Slide 25

Slide 25 text

Modular development

Slide 26

Slide 26 text

No content

Slide 27

Slide 27 text

No content

Slide 28

Slide 28 text

Orders

Slide 29

Slide 29 text

Tests first!

Slide 30

Slide 30 text

Mocha specs describe 'Orders', -> it 'searches by seller', (done) -> wait -> expect(gridCount('Orders')).to.eql 5 select 'One', from: combo('seller_id') wait -> expect(gridCount('Orders')).to.eql 3 select 'Two', from: combo('seller_id') wait -> expect(gridCount('Orders')).to.eql 2 done()

Slide 31

Slide 31 text

Running specs

Slide 32

Slide 32 text

Composability

Slide 33

Slide 33 text

ShipmentsAndOrders

Slide 34

Slide 34 text

ShipmentsAndOrders

Slide 35

Slide 35 text

Nesting class ShipmentsAndOrders < Netzke::Base component :shipments do |c| c.klass = Shipments::Grid end component :orders do |c| c.klass = Orders::Grid end def configure(c) super c.items = [:shipments, :orders] end end

Slide 36

Slide 36 text

Client-side code handles user clicking a shipment outside of this talk's scope

Slide 37

Slide 37 text

Dynamic component loading

Slide 38

Slide 38 text

Can have hundreds of models and even a bigger number of components

Slide 39

Slide 39 text

Loading them at once? bad idea let's load them on request

Slide 40

Slide 40 text

Attachments

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

No content

Slide 43

Slide 43 text

No content

Slide 44

Slide 44 text

class Shipments < Netzke::Basepack::Grid component :attachment_window do |c| c.klass = Attachment::Window end end

Slide 45

Slide 45 text

client code onManageAttachments: function(){ var row = this.getSelectionModel().selected.first(); if (row) { this.netzkeLoadComponent('attachment_window', { clientConfig: { id: row.get('id') }, callback: function(w){ w.show(); } }); } }

Slide 46

Slide 46 text

Recapping: our arms reusability ✓ extensibility (OOP) ✓ modular development ✓ composability (nesting) ✓ dynamic loading ✓

Slide 47

Slide 47 text

Our score MAINTAINABLE CODE

Slide 48

Slide 48 text

About Max Gorin author and maintainer of @netzke on Rails since 2007 freelance nomad since 2008 tweets at @uptomax

Slide 49

Slide 49 text

No content