a better ujs for rails

39
A Better UJS for Rails Codemy.net presents @zacksiri by: Monday, June 10, 13

Upload: sakchai-siripanyawuth

Post on 25-May-2015

1.011 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: A Better UJS for Rails

A Better UJS for Rails

Codemy.net

presents

@zacksiriby:

Monday, June 10, 13

Page 2: A Better UJS for Rails

Javascript is a big part of Rails Project

Monday, June 10, 13

Page 3: A Better UJS for Rails

No real convention for working with JS files

Monday, June 10, 13

Page 4: A Better UJS for Rails

Backbone is Great but...

Monday, June 10, 13

Page 5: A Better UJS for Rails

I miss working with Ruby

Monday, June 10, 13

Page 6: A Better UJS for Rails

And then I saw Turbolinks...

Monday, June 10, 13

Page 7: A Better UJS for Rails

Monday, June 10, 13

Page 8: A Better UJS for Rails

Turbolinks Backbone / MV*

Control / Complexity for Client

Less Ruby

Monday, June 10, 13

Page 9: A Better UJS for Rails

So I thought long and hard

Monday, June 10, 13

Page 10: A Better UJS for Rails

Turbolinks Backbone / MV*

?Something is

missing

Control / Complexity for Client

Less Ruby

Monday, June 10, 13

Page 11: A Better UJS for Rails

Transponder JS

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

Extracted from Codemy

Monday, June 10, 13

Page 12: A Better UJS for Rails

3 Core Components

• Helpers

• Presenters

• Services

Monday, June 10, 13

Page 13: A Better UJS for Rails

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

Page 14: A Better UJS for Rails

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

Page 15: A Better UJS for Rails

• maps to your controller actions

• calls helper functions when needed

• trigger services

• modify the DOM as needed

Presenters

Monday, June 10, 13

Page 16: A Better UJS for Rails

How does it work?

Monday, June 10, 13

Page 17: A Better UJS for Rails

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

Page 18: A Better UJS for Rails

Ok so how do I trigger the event?

Monday, June 10, 13

Page 19: A Better UJS for Rails

$('#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

Page 20: A Better UJS for Rails

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

Page 21: A Better UJS for Rails

Presenters Provide

• Better code reusability (Dryer)

• Cleaner

• Provides Structure

• Use what you already know!

• Logicless View in Rails

Monday, June 10, 13

Page 22: A Better UJS for Rails

What are services?

Monday, June 10, 13

Page 23: A Better UJS for Rails

Monday, June 10, 13

Page 24: A Better UJS for Rails

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

Monday, June 10, 13

Page 25: A Better UJS for Rails

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

Page 26: A Better UJS for Rails

<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

Page 27: A Better UJS for Rails

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

Page 28: A Better UJS for Rails

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

Page 29: A Better UJS for Rails

How do they all Work Together?

Monday, June 10, 13

Page 30: A Better UJS for Rails

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

Page 31: A Better UJS for Rails

Monday, June 10, 13

Page 32: A Better UJS for Rails

$(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

Page 33: A Better UJS for Rails

Transponder works with Everything

Monday, June 10, 13

Page 34: A Better UJS for Rails

Not Saying don’t use Backbone

Monday, June 10, 13

Page 35: A Better UJS for Rails

Use the right tools for the job.

Monday, June 10, 13

Page 36: A Better UJS for Rails

Codemy uses Turbolinks with Transponder and Backbone when

appropriate

Monday, June 10, 13

Page 37: A Better UJS for Rails

Transponder is out!

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

Monday, June 10, 13

Page 38: A Better UJS for Rails

# TODO:

• Clean up some APIs

• Add Documentation

• Video Screencasts

• More Generators

• Example Rails Project

Monday, June 10, 13

Page 39: A Better UJS for Rails

Thank You!

@codemy_net

Questions?

@zacksiri

Monday, June 10, 13