• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Rails is not just Ruby
 

Rails is not just Ruby

on

  • 2,436 views

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

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

Statistics

Views

Total Views
2,436
Views on SlideShare
2,394
Embed Views
42

Actions

Likes
1
Downloads
6
Comments
0

2 Embeds 42

http://www.slideshare.net 28
http://log.simplabs.com 14

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Rails is not just Ruby Rails is not just Ruby Presentation Transcript

    • Rails is not just Ruby
    • Marco Otte-Witte Software Engineer, Consultant, Trainer http://simplabs.com Open Source http://github.com/marcoow http://github.com/simplabs
    • JavaScript is serious Business!
    • It‘s not just adding lib after lib after lib!
    • Give your JavaScript the same love your Ruby code gets!
    • Know your tools!
    • Know your tools! var inputs = $$('input'); for (var i = 0; i < inputs.length; i++) { alert(inputs[i].name); }
    • Know your tools! X var inputs = $$('input'); for (var i = 0; i < inputs.length; i++) { } alert(inputs[i].name);
    • Know your tools! Protoype.js $$('input').each(function(input) { alert(input.name); }); jQuery $.each('input', function() { alert(this.name); });
    • Know your tools! function setupPage() { $('userName').update( readUserName(); ); } function readUserName() { //read user's name from cookie }
    • Know your tools! X function setupPage() { $('userName').update( readUserName(); ); } function readUserName() { //read user's name from cookie }
    • Know your tools! var Application = (function() { //private var readUserName = function() { //read user's name from cookie }; return { //public setupPage: function() { $('userName').update( readUserName(); ); } } })();
    • Know your tools! var timeout = window.setTimeout( "element.update(" + someContent + ");", 1000 );
    • Know your tools! X var timeout = window.setTimeout( "element.update(" + someContent + ");", 1000 );
    • Know your tools! Protoype.js element.update.bind(element).curry( someContent ).delay(1)
    • Know your tools! var loginField = document.getElementById('#user_login'); alert(loginField.value);
    • Know your tools! X var loginField = document.getElementById('#user_login'); alert(loginField.value);
    • Know your tools! Protoype.js alert($F('user_login')); jQuery alert($('#user_login').val());
    • Know your tools! var loginField = document.getElementById('#user_login'); loginField.style.display = 'none';
    • Know your tools! X var loginField = document.getElementById('#user_login'); loginField.style.display = 'none';
    • Know your tools! Protoype.js $('user_login').hide(); jQuery $('#user_login').hide();
    • 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); }
    • Know your tools! X 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); }
    • Know your tools! Protoype.js $('user_login').observe( 'change', function(event) { alert($F('user_login')); }); jQuery $('#user_login').change(function() { alert(this.val()); });
    • Write valid JavaScript!
    • Write valid JavaScript! someValue = 0; anotherValue = 1; function fun(param) { alert(param) }
    • Write valid JavaScript! X someValue = 0; anotherValue = 1; function fun(param) { alert(param) }
    • Write valid JavaScript! var someValue = 0; var anotherValue = 1; function fun(param) { alert(param); }
    • Write valid JavaScript! someValue = 0; anotherValue = 1; function fun(param) { alert(param) }
    • Write valid JavaScript! someValue = 0; anotherValue = 1; function fun(param) { alert(param) }
    • Write valid JavaScript! someValue = 0; Missing semicolon. anotherValue = 1; Implied globals: function fun(param) { someValue, anotherValue alert(param) }
    • JavaScript and Rails
    • JavaScript and Rails •RESTful actions (delete, put, post) •AJAX •Effects •etc.
    • the Demo App
    • the Demo App POST/replace
    • the Demo App POST/replace Code is at http://github.com/marcoow/js-and-rails
    • 3 possible Solutions
    • the classic Solution
    • the classic Solution •Helpers (remote_form_for, link_to_remote etc.) •RJS •onclick=“... •href=“javascript:...
    • the classic Solution index.html.erb <div id="someElement"> some text that's replaced later </div> <%= link_to_remote 'Replace', :url => classic_solution_replace_path, :method => :post %>
    • the classic Solution class ClassicSolutionController < ApplicationController def index end def replace end end
    • the classic Solution replace.rjs page.replace_html 'someElement', :partial => 'new_content'
    • the classic Solution _new_content.html.erb <b>Fresh new content rendered at <%= Time.now %></b> <%= link_to_remote 'Replace again', :url => classic_solution_replace_path, :method => :post %>
    • the classic Solution •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
    • Full Separation
    • Full Separation •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 •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 replacer.js var 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 } ); } });
    • Full Separation application.js var 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(); } } })();
    • Full Separation application.js document.observe('dom:loaded', function() { Application.setupOnLoad(); Ajax.Responders.register({ onComplete: Application.setupOnPageUpdate }); });
    • Full Separation application.js document.observe('dom:loaded', function() { Application.setupOnLoad(); Ajax.Responders.register({ onComplete: Application.setupOnPageUpdate }); }); Replacer controls are initialized on page load and after every AJAX request
    • Full Separation index.html.erb <div id="someElement"> some text that's replaced later </div> <%= link_to 'Replace', full_separation_replace_path, :'data-replaces' => 'someElement' %>
    • Full Separation class FullSeparationController < ApplicationController def index end def replace respond_to do |format| format.js { render :partial => 'new_content' } end end end
    • Full Separation _new_content.html.erb <b>Fresh new content rendered at <%= Time.now %></b> <%= link_to 'Replace again', full_separation_replace_path, :'data-replaces' => 'someElement' %>
    • Full Separation •clean, semantic HTML •full separation of concerns •clean HTML/CSS/JS is crucial •Behaviour is (kind of) implicit •discipline required
    • explicit Controls
    • explicit Controls •like Full Separation •but controls are initialized in the templates •more explicit/ obvious what‘s going on
    • explicit Controls index.html.erb <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>
    • explicit Controls class ControlsController < ApplicationController def index end def replace respond_to do |format| format.js { render :partial => 'new_content' } end end end
    • explicit Controls _new_content.html.erb <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>
    • explicit Controls _new_content.html.erb <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> No initialization on dom:loaded here as this is the result of an AJAX request (dom:loaded not fired)
    • explicit Controls •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
    • Either go with Full Separation or explicit Controls!
    • Avoid the classic Solution when you can!
    • Resources
    • Resources •http://ejohn.org/apps/learn/ •http://www.jslint.com/ •http://api.prototypejs.org/ •http://docs.jquery.com •http://github.com/marcoow/js-and-rails •http://javascriptrocks.com
    • Q&A