rails is not just ruby

67
Rails is not just Ruby

Upload: marco-otte-witte

Post on 06-May-2015

1.546 views

Category:

Technology


2 download

DESCRIPTION

Talk on Rails and JavaScript and how JavaScript should be written, structured, separated from the HTML etc.

TRANSCRIPT

Page 1: Rails is not just Ruby

Rails is not just Ruby

Page 2: Rails is not just Ruby

Software Engineer, Consultant, Trainer

http://simplabs.com

Open Source

http://github.com/marcoowhttp://github.com/simplabs

Marco Otte-Witte

Page 3: Rails is not just Ruby

JavaScript is serious

Business!

Page 4: Rails is not just Ruby

It‘s not just adding lib after

lib after lib!

Page 5: Rails is not just Ruby

Give your JavaScript the

same love your Ruby code

gets!

Page 6: Rails is not just Ruby

Know your tools!

Page 7: Rails is not just Ruby

Know your tools!

var inputs = $$('input');for (var i = 0; i < inputs.length; i++) { alert(inputs[i].name);}

Page 8: Rails is not just Ruby

Know your tools!

var inputs = $$('input');for (var i = 0; i < inputs.length; i++) { alert(inputs[i].name);} X

Page 9: Rails is not just Ruby

Know your tools!

$$('input').each(function(input) { alert(input.name);});

Protoype.js

$.each('input', function() { alert(this.name);});

jQuery

Page 10: Rails is not just Ruby

Know your tools!

function setupPage() { $('userName').update( readUserName(); );} function readUserName() { //read user's name from cookie}

Page 11: Rails is not just Ruby

Know your tools!

function setupPage() { $('userName').update( readUserName(); );} function readUserName() { //read user's name from cookie}

X

Page 12: Rails is not just Ruby

Know your tools!var Application = (function() { //private var readUserName = function() { //read user's name from cookie };

return { //public setupPage: function() { $('userName').update( readUserName(); ); }

}

})();

Page 13: Rails is not just Ruby

Know your tools!

var timeout = window.setTimeout( "element.update(" + someContent + ");", 1000);

Page 14: Rails is not just Ruby

Know your tools!

var timeout = window.setTimeout( "element.update(" + someContent + ");", 1000); X

Page 15: Rails is not just Ruby

Know your tools!

element.update.bind(element).curry( someContent).delay(1)

Protoype.js

Page 16: Rails is not just Ruby

Know your tools!

var loginField = document.getElementById('#user_login');alert(loginField.value);

Page 17: Rails is not just Ruby

Know your tools!

var loginField = document.getElementById('#user_login');alert(loginField.value);X

Page 18: Rails is not just Ruby

Know your tools!

alert($F('user_login'));Protoype.js

alert($('#user_login').val());jQuery

Page 19: Rails is not just Ruby

Know your tools!

var loginField = document.getElementById('#user_login');loginField.style.display = 'none';

Page 20: Rails is not just Ruby

Know your tools!

var loginField = document.getElementById('#user_login');loginField.style.display = 'none';X

Page 21: Rails is not just Ruby

Know your tools!

$('user_login').hide();Protoype.js

$('#user_login').hide();jQuery

Page 22: Rails is not just Ruby

Know your tools!var loginField = document.getElementById('user_login');function loginChanged() { alert(loginField.value);}if (loginField.addEventListener) { loginField.addEventListener( 'change', loginChanged, false);} else if (obj.attachEvent) { obj.attachEvent('onchange', loginChanged);}

Page 23: Rails is not just Ruby

Know your tools!var loginField = document.getElementById('user_login');function loginChanged() { alert(loginField.value);}if (loginField.addEventListener) { loginField.addEventListener( 'change', loginChanged, false);} else if (obj.attachEvent) { obj.attachEvent('onchange', loginChanged);}

X

Page 24: Rails is not just Ruby

Know your tools!

$('user_login').observe( 'change', function(event) { alert($F('user_login'));});

Protoype.js

$('#user_login').change(function() { alert(this.val());});

jQuery

Page 25: Rails is not just Ruby

Write valid JavaScript!

Page 26: Rails is not just Ruby

Write valid JavaScript!

someValue = 0;anotherValue = 1; function fun(param) { alert(param)}

Page 27: Rails is not just Ruby

Write valid JavaScript!

someValue = 0;anotherValue = 1; function fun(param) { alert(param)} X

Page 28: Rails is not just Ruby

Write valid JavaScript!

var someValue = 0;var anotherValue = 1;

function fun(param) { alert(param);}

Page 29: Rails is not just Ruby

Write valid JavaScript!

someValue = 0;anotherValue = 1; function fun(param) { alert(param)}

Page 30: Rails is not just Ruby

Write valid JavaScript!

someValue = 0;anotherValue = 1; function fun(param) { alert(param)}

Page 31: Rails is not just Ruby

Write valid JavaScript!

someValue = 0;anotherValue = 1; function fun(param) { alert(param)}

Missing semicolon.

Implied globals: someValue, anotherValue

Page 32: Rails is not just Ruby

JavaScript and Rails

Page 33: Rails is not just Ruby

JavaScript and Rails

•RESTful actions (delete, put, post)

•AJAX

•Effects

•etc.

Page 34: Rails is not just Ruby

the Demo App

Page 35: Rails is not just Ruby

the Demo App

POST/replace

Page 36: Rails is not just Ruby

the Demo App

POST/replaceCode is at http://github.com/marcoow/js-and-rails

Page 37: Rails is not just Ruby

3 possible Solutions

Page 38: Rails is not just Ruby

the classic Solution

Page 39: Rails is not just Ruby

•Helpers (remote_form_for, link_to_remote etc.)

•RJS

•onclick=“...•href=“javascript:...

the classic Solution

Page 40: Rails is not just Ruby

the classic Solution

<div id="someElement"> some text that's replaced later</div><%= link_to_remote 'Replace', :url => classic_solution_replace_path, :method => :post %>

index.html.erb

Page 41: Rails is not just Ruby

the classic Solution

class ClassicSolutionController < ApplicationController

def index end

def replace end

end

Page 42: Rails is not just Ruby

the classic Solution

page.replace_html 'someElement', :partial => 'new_content'

replace.rjs

Page 43: Rails is not just Ruby

the classic Solution

<b>Fresh new content rendered at <%= Time.now %></b><%= link_to_remote 'Replace again', :url => classic_solution_replace_path, :method => :post %>

_new_content.html.erb

Page 44: Rails is not just Ruby

•strong coupling

•hard to maintain

•no/ little code reuse

•bloated HTML

•code that actually belongs together is distributed over several places

•easy to write in the first place

the classic Solution

Page 45: Rails is not just Ruby

Full Separation

Page 46: Rails is not just Ruby

•define JavaScript controls that encapsulate all frontend logic

•mark elements with class, rel or HTML5‘s

data-* attributes

•full separation of HTML and JavaScript

•Initialization of controls on dom:loaded event

Full Separation

Page 47: Rails is not just Ruby

•define JavaScript controls that encapsulate all frontend logic

•mark elements with class, rel or HTML5‘s

data-* attributes

•full separation of HTML and JavaScript

•Initialization of controls on dom:loaded event

Full Separation

Page 48: Rails is not just Ruby

Full Separationvar Replacer = Class.create({

initialize: function(container, target) { this.container = $(container); this.target = $(target); this.container.observe('click', this.onClick.bindAsEventListener(this)); },

onClick: function(event) { event.stop(); new Ajax.Updater( this.target, this.container.href, { method: 'post', evalScripts: true } ); }

});

replacer.js

Page 49: Rails is not just Ruby

Full Separationvar Application = (function() {

var initializeReplacers = function() { $$('a[data-replaces]').each(function(replacingLink) { if (!replacingLink._initializedReplacer) { new Replacer(replacingLink, replacingLink.readAttribute('data-replaces')); replacingLink._initializedReplacer = true; } }); };

return {

setupOnLoad: function() { initializeReplacers(); },

setupOnPageUpdate: function() { initializeReplacers(); }

}

})();

application.js

Page 50: Rails is not just Ruby

Full Separation

document.observe('dom:loaded', function() { Application.setupOnLoad(); Ajax.Responders.register({ onComplete: Application.setupOnPageUpdate });});

application.js

Page 51: Rails is not just Ruby

Full Separation

document.observe('dom:loaded', function() { Application.setupOnLoad(); Ajax.Responders.register({ onComplete: Application.setupOnPageUpdate });});

application.js

Replacer controls are initialized on page load and after every AJAX request

Page 52: Rails is not just Ruby

Full Separation

<div id="someElement"> some text that's replaced later</div><%= link_to 'Replace', full_separation_replace_path, :'data-replaces' => 'someElement' %>

index.html.erb

Page 53: Rails is not just Ruby

Full Separationclass FullSeparationController < ApplicationController

def index end

def replace respond_to do |format| format.js { render :partial => 'new_content' } end end

end

Page 54: Rails is not just Ruby

Full Separation

<b>Fresh new content rendered at <%= Time.now %></b><%= link_to 'Replace again', full_separation_replace_path, :'data-replaces' => 'someElement' %>

_new_content.html.erb

Page 55: Rails is not just Ruby

•clean, semantic HTML

•full separation of concerns

•clean HTML/CSS/JS is crucial

•Behaviour is (kind of) implicit

•discipline required

Full Separation

Page 56: Rails is not just Ruby

explicit Controls

Page 57: Rails is not just Ruby

•like Full Separation

•but controls are initialized in the templates

•more explicit/ obvious what‘s going on

explicit Controls

Page 58: Rails is not just Ruby

explicit Controls

<div id="someElement"> some text that's replaced later</div><%= link_to 'Replace', controls_replace_path, :id => 'replacerLink' %><script type="text/javascript" charset="utf-8"> document.observe('dom:loaded', function() { var replacer = new Replacer('replacerLink', 'someElement'); });</script>

index.html.erb

Page 59: Rails is not just Ruby

explicit Controlsclass ControlsController < ApplicationController

def index end

def replace respond_to do |format| format.js { render :partial => 'new_content' } end end

end

Page 60: Rails is not just Ruby

explicit Controls

<b>Fresh new content rendered at <%= Time.now %></b><%= link_to 'Replace again', controls_replace_path, :id => 'secondReplacerLink' %><script type="text/javascript" charset="utf-8"> var newReplacer = new Replacer( 'secondReplacerLink', 'someElement' );</script>

_new_content.html.erb

Page 61: Rails is not just Ruby

explicit Controls

<b>Fresh new content rendered at <%= Time.now %></b><%= link_to 'Replace again', controls_replace_path, :id => 'secondReplacerLink' %><script type="text/javascript" charset="utf-8"> var newReplacer = new Replacer( 'secondReplacerLink', 'someElement' );</script>

_new_content.html.erb

No initialization on dom:loaded here as this is the result of an AJAX request (dom:loaded not fired)

Page 62: Rails is not just Ruby

•HTML is (mostly) clean and semantic

•Behaviour is explicit in the templates

•easier to grasp what‘s going on than with Full Separation

•though not as nice as full separation

explicit Controls

Page 63: Rails is not just Ruby

Either go with Full Separation

or explicit Controls!

Page 64: Rails is not just Ruby

Avoid the classic Solution when you can!

Page 65: Rails is not just Ruby

Resources

Page 67: Rails is not just Ruby

Q&A