The document discusses how to integrate jQuery and JavaScript functionality into Ruby on Rails and Merb web applications. Key points include:
- Rails and Merb do not have built-in helpers for jQuery, but jQuery is easy to use and Ruby helpers can be written to support it
- The frameworks produce consistent markup that jQuery code can be written to add interactive behavior to
- Options like metadata can be passed to jQuery plugins via the markup generated by helpers
- Helpers, jQuery code, and techniques like the <base> tag allow JavaScript features to be unobtrusively integrated into the MVC frameworks
4. Me
• On jQuery Team
• On Merb Team
• Use jQuery and Rails Daily
• Love Rapid Development
5. Me
• On jQuery Team
• On Merb Team
• Use jQuery and Rails Daily
• Love Rapid Development
6. Rails
• Simplifies:
• HTML Generation
• Database access
• API creation for your web app
• Routing
7. Rails
• Tries but fails at:
• Nontrivial Ajax
• Nontrivial in-browser JS (i.e. form validation)
• Shielding you from JavaScript
• Key: You can’t avoid JS through Rails
8. Merb
• New Ruby Web Framework
• ORM Agnostic
• JS Framework Agnostic
• Similar controller/routing to Rails
• Faster and smaller than Rails
9. Merb
• New Ruby Web Framework
• ORM Agnostic
• JS Framework Agnostic
• Similar controller/routing to Rails
• Faster and smaller than Rails
10. MVC Web Frameworks
• Models encapsulate database information
• Controllers route and process requests
• Views provide the raw HTML that goes to the browser
• Rails uses helpers to simplify views
• Rails helpers spit out JS
• We want to be unobtrusive
11. Our Approach to JS in MVC
• Typically, JS represents site-wide behavior (like CSS)
• Common markup format represents behavior
• <table class=quot;sortablequot;>
• Use Ruby to generate markup
• Use CSS to apply style to markup
• Use jQuery to apply behavior to markup
• Profit!
12. Our Approach to JS in MVC
• Typically, JS represents site-wide behavior (like CSS)
• Common markup format represents behavior
• <table class=quot;sortablequot;>
• Use Ruby to generate markup
• Use CSS to apply style to markup
• Use jQuery to apply behavior to markup
• Profit!
13. Helpers in Rails
• Generate Markup
• Not JavaScript def sortable_table(&block)
html = content_tag(:table, :class => quot;sortablequot;) do
• capture(&block)
Remember: end
concat(html, block.binding)
• concat
end
• capture
14. Helpers in Merb
• Generate Markup
Very similar to Rails
• Not JavaScript
def sortable_table(&block)
• Remember: html = tag(:table, capture(&block), :class => quot;sortablequot;)
concat(html, block.binding)
end
• concat
• capture
15. Mixing it Up
• We have consistent markup <table class='sortable'>
produced by our framework <thead>
<tr><th>Name</th><th>Price</th></tr>
</thead>
<tbody>
<tr>
<td>Bones: The Complete Second Season</td>
<td>$40.99</td>
</tr>
<tr>
<td>Heroes: Season 1</td>
<td>$39.99</td>
</tr>
<tr>
<td>Charmed: The Final Season</td>
<td>$32.99</td>
</tr>
</tbody>
</table>
16. jQuery Code
• We have consistent
markup produced by our
framework
• We can add behavior
$(quot;table.sortablequot;).tablesorter();
17. Markup Code
• We have consistent <table class='sortable' metaData='{cssHeader: quot;sort-headerquot;,
cssAsc: quot;sort-header-ascquot;, cssDesc: quot;sort-header-descquot;}'>
markup produced by our <thead>
framework <tr><th>Name</th><th>Price</th></tr>
</thead>
<tbody>
• <tr>
We can add behavior <td>Bones: The Complete Second Season</td>
<td>$40.99</td>
• </tr>
We can support options <tr>
<td>Heroes: Season 1</td>
<td>$39.99</td>
</tr>
<tr>
<td>Charmed: The Final Season</td>
<td>$32.99</td>
</tr>
</tbody>
</table>
18. Markup Code
• We have consistent
class Hash
markup produced by our def metadata
framework data = self.map {|k,v| quot;#{k.js_case}:#{v.metadata}quot; }
quot;{#{data.join(quot;,quot;)}}quot;
end
• end
We can add behavior
class String
• def metadata
We can support options quot;'#{self}'quot;
end
• Via some glue code def js_case
r = camelcase
r[0] = r[0].chr.downcase
r
end
end
19. Markup Code
• We have consistent
markup produced by our
framework
class Symbol
def js_case
• We can add behavior self.to_s.js_case
end
end
• We can support options
class Object
def metadata
• Via some glue code quot;#{self.to_s}quot;
end
end
20. Rails Helper
• We have consistent
markup produced by our
framework
• We can add behavior def sortable_table(options = {}, &block)
html = content_tag(:table, :class => quot;sortablequot;,
• :metadata => options.meta_data) do
We can support options capture(&block)
end
•
end
Via some glue code
• And a Rails helper
21. Merb Helper
• We have consistent
markup produced by our
framework
• We can add behavior
def sortable_table(options = {}, &block)
html = tag(:table, capture(&block),
• We can support options :class => quot;sortablequot;, :meta_data => options.metadata)
concat(html, block.binding)
end
• Via some glue code
• And a Rails helper
• Or a Merb Helper
22. Rails Helper
• We have consistent
markup produced by our
framework
• We can add behavior
$(quot;table.sortablequot;).each(function() {
• We can support options $(this).tablesorter($(this).metadata());
});
• Via a Rails helper
• Or a Merb Helper
• And with a quick jQuery
change...
24. Markup
• Use everything at your disposal
<a href=quot;ajax_urlquot; rel=quot;#targetquot; class=quot;remotequot;>
Load it In
</a>
25. jQuery
• Use everything at your disposal
• Write jQuery Code
$(quot;a.remotequot;).click(function() {
$(this.rel).load(this.href);
});
26. Rails Helper
• Use everything at your disposal
• Write jQuery code
• Write a Rails helper def remote_link(contents, url, update = nil)
url = url_for(url) if url.is_a?(Hash)
options = {:href => url}
options.merge!(:rel => update) if update
content_tag(:a, contents, options)
end
27. Merb Helper
• Use everything at your disposal
• Write jQuery code
• Write a Rails helper def remote_link(contents, url_param, update = nil)
url = url_param.is_a?(Hash) ? url(url_param) : url
• options = {:href => url}
Or a Merb Helper options.merge!(:rel => update) if update
tag(:a, contents, options)
end
28. Use Helper
• Use everything at your disposal
• Write jQuery code
• Write a Rails helper
<%= remote_link(quot;Hey lookey herequot;, :controller =>
quot;fooquot;, :action => quot;fooquot;) %>
• Or a Merb Helper
<%= remote_link(quot;Hey lookey herequot;, {:controller =>
quot;fooquot;, :action => quot;fooquot;}, quot;#updatequot;) %>
• Profit!
29. Some Caveats
• Relative URLs won't work like you expect
• Check out the <base> tag
• Application.js can get pretty big
• Check out Cascading JavaScript
• http://www.redhillonrails.org/
#cascading_javascripts
30. The <base> Tag
• <base href=quot;http://mysite.com/foo/barquot; />
• Makes all URLs (including JS) operate relative to it
• Needs to be before any other URLs are specified (top of head)
• With routing:
• /foo/bar/1 and /foo/bar should have the same relative URL
• Browsers interpret the /1 as a new directory
31. The <base> Tag
• <base href=quot;http://mysite.com/foo/barquot; />
• Makes all URLs (including JS) operate relative to it
• Needs to be before any other URLs are specified (top of head)
• With routing:
• /foo/bar/1 and /foo/bar should have the same relative URL
• Browsers interpret the /1 as a new directory
Rails Merb
<%= tag(:base, :href => url_for(:id => quot;quot;) %> <%= self_closing_tag(:base, :href => url(:id => quot;quot;))%>
#=> <base href=quot;/controller/action/quot; />
32. Summary
• Rails/Merb don't have built-in helpers for jQuery
34. Summary
• Rails/Merb don't have built-in helpers for jQuery
• jQuery is easy
• Writing Ruby helpers is easy
35. Summary
• Rails/Merb don't have built-in helpers for jQuery
• jQuery is easy
• Writing Ruby helpers is easy
• Making Ruby frameworks work with jQuery is easy
36. Summary
• Rails/Merb don't have built-in helpers for jQuery
• jQuery is easy
• Writing Ruby helpers is easy
• Making Ruby frameworks work with jQuery is easy
• We need to share our helpers and jQuery
code
37. Demo and Some Code
• http://10.0.2.6:4000/jquery_camp
• Give me a sec to demo it before creating things ;)