A Better UJS for Rails

Post on 25-May-2015

1.009 views 1 download

Tags:

Transcript of A Better UJS for Rails

A Better UJS for Rails

Codemy.net

presents

@zacksiriby:

Monday, June 10, 13

Javascript is a big part of Rails Project

Monday, June 10, 13

No real convention for working with JS files

Monday, June 10, 13

Backbone is Great but...

Monday, June 10, 13

I miss working with Ruby

Monday, June 10, 13

And then I saw Turbolinks...

Monday, June 10, 13

Monday, June 10, 13

Turbolinks Backbone / MV*

Control / Complexity for Client

Less Ruby

Monday, June 10, 13

So I thought long and hard

Monday, June 10, 13

Turbolinks Backbone / MV*

?Something is

missing

Control / Complexity for Client

Less Ruby

Monday, June 10, 13

Transponder JS

http://www.github.com/zacksiri/transponder

Extracted from Codemy

Monday, June 10, 13

3 Core Components

• Helpers

• Presenters

• Services

Monday, June 10, 13

CH.calendar = Codemy.Helpers.Calendar =  dateOnly: (date_time) ->    moment(date_time).format('YYYY-MM-DD')   timeInISO: (date_time) ->    moment(date_time).format('YYYY-MM-DD HH:mm:ss Z')   timeInHour: (date_time) ->    moment(date_time).format('HH:mm A')

Monday, June 10, 13

class CommentsPresenter extends Transponder.Presenter  presenterName: 'comments'  modelName: 'comment'

   index: ->    if @params.page      CH.infiniteLoader.loadNext        element: @element        response: @response        modelName: @modelName        putAt: 'prepend'   show: ->    $(@element).replaceWith(@response)    $(@element).trigger('codemy:services:highlight') ....   create: ->    $('#new_comment').replaceWith(@response)    $(".comment:last").effect('highlight', {}, 500)   destroy: ->    $(@element).fadeOut 300, ->      $(this).remove()

Monday, June 10, 13

• maps to your controller actions

• calls helper functions when needed

• trigger services

• modify the DOM as needed

Presenters

Monday, June 10, 13

How does it work?

Monday, June 10, 13

class CommentsPresenter extends Transponder.Presenter  presenterName: 'comments'  modelName: 'comment'   index: ->    # your code for modifying the DOM    # listens for event ujs:comments:index   update: ->    # listens for even ujs:comments:update

...

• ujs:comments:index triggers index()

• ujs:comments:show triggers show()

• ujs:comments:edit triggers edit()

• ujs:comments:update triggers update()

• ujs:comments:create triggers create()

• ujs:comments:destroy triggers destroy()

Monday, June 10, 13

Ok so how do I trigger the event?

Monday, June 10, 13

$('#comments').trigger("<%= j ujs_event_type %>", "<%= j render 'comments' %>");

app/views/comments/index.js.erb

app/views/comments/update.js.erb

$('#comment_1').trigger("<%= j ujs_event_type %>", "<%= j render @comment %>"); {

ujs:comments:update{controller_name:action_name

Monday, June 10, 13

class CommentsPresenter extends Transponder.Presenter  presenterName: 'comments'  modelName: 'comment'   index: ->    if @params.page      CH.infiniteLoader.loadNext        element: @element        response: @response        modelName: @modelName        putAt: 'prepend'   update: ->    $(@element).replaceWith(@response)   ...

Monday, June 10, 13

Presenters Provide

• Better code reusability (Dryer)

• Cleaner

• Provides Structure

• Use what you already know!

• Logicless View in Rails

Monday, June 10, 13

What are services?

Monday, June 10, 13

Monday, June 10, 13

<select>  <option value="drafting">drafting</option>  <option value="request_approval"> awaiting approval </option></select>

Monday, June 10, 13

class Codemy.Services.SubmitOnChange extends Transponder.Service  serviceName: 'codemy:services:submit_on_change'   serve: ->    @element.on 'change', (e) ->      e.preventDefault()      form = $(this).parents('form')      $.ajax         url: form.attr('action')        type: 'PUT'        dataType: 'script'        data: $(form).serialize()

Monday, June 10, 13

<select class="submit_on_change">  <option value="drafting">drafting</option>  <option value="request_approval"> awaiting approval </option></select>

$('body.courses.index').trigger('codemy:services:submit_on_change');

<select class="submit_on_change submit_on_change_active">  <option value="drafting">drafting</option>  <option value="request_approval"> awaiting approval </option></select>

Monday, June 10, 13

Transponder.service_manifest = ->  $("body.questions,      body.apprentice.objectives.show,     body.mentor.owned_levels.show,      body.mentor.objectives.show,     body.mentor.posts,     body.posts.show").trigger       'codemy:services:live_preview'    $("body.questions,     body.mentor.posts").trigger     'codemy:services:tag_select'    $("body.questions,     body.apprentice,     body.mentor,     body.activities,     body.posts.show").trigger       'codemy:services:highlight'

Monday, June 10, 13

What Services Do

• Write once use everywhere (again Dryer code)

• Better Maintainability

• Makes sure it doesn’t run on a node that has that service

already running

• Makes it easier to manage all your code via manifest

Monday, June 10, 13

How do they all Work Together?

Monday, June 10, 13

class BadgesPresenter extends Transponder.Presenter  nameSpace: "mentor"  presenterName: "badges"  modelName: "badge"

   show: ->    $(@element).replaceWith(@response)    $(@element).trigger('codemy:services:poller')    $(@element).trigger('codemy:services:uploader')   update: ->    @show()

Monday, June 10, 13

Monday, June 10, 13

$(document).readytriggers uploader service

User uploads uploader service runs

Runs Update action in Presenter

Triggers poller service

renders processed image to browser

through presenter

1

23

45

6

Monday, June 10, 13

Transponder works with Everything

Monday, June 10, 13

Not Saying don’t use Backbone

Monday, June 10, 13

Use the right tools for the job.

Monday, June 10, 13

Codemy uses Turbolinks with Transponder and Backbone when

appropriate

Monday, June 10, 13

Transponder is out!

http://www.github.com/zacksiri/transponder

Monday, June 10, 13

# TODO:

• Clean up some APIs

• Add Documentation

• Video Screencasts

• More Generators

• Example Rails Project

Monday, June 10, 13

Thank You!

@codemy_net

Questions?

@zacksiri

Monday, June 10, 13