And the Pending Tests — They Shall Pass!

Posted 16 days back at Katz Got Your Tongue?

While we’ve been working on ActionController::Base, there were a few tests for fixes in Rails 2.3 that were mostly hacked in and we were waiting for a cleaner underlying implementation to build them on top of. Today, we finally got all the pending tests passing!

There were basically two categories of pending tests:

Layout Selection

Rails 2 had a feature called :exempt_from_layout, which allowed users to specify that a particular kind of layout (defaulting to RJS) should be exempt from layout. The reason for this feature was that people were noticing that their RJS layouts were being wrapped in their HTML layouts.

When I first saw this feature, I had a simple question: “Why were RJS layouts being wrapped in HTML templates in the first place?” And also, if you want an RJS layout (application.js.erb), why shouldn’t you be allowed to.

As it turns out, the reason for this was that any number of parts of Rails render templates, and the layout lookup is completely separate. So when it came time to look up a layout, Rails didn’t realize that it had just rendered an RJS template (as far as it was concerned, since the available formats allow for HTML and JS, either would do).

The solution: Have template and layout lookup go through a deterministic process, and limit layout lookup to the mime type for the template that was actually rendered (not templates that might have been rendered).

The upshot: exempt_from_layout isn’t needed. If you don’t want a layout around your RJS templates, don’t make an application.js.*. If you do, do. Rails will do the right thing.

An aside: the hardest part of Rails layouts involves when to raise an exception for a missing layout. Since Rails allows layouts to be missing in certain circumstances, making sure an exception is raised in other circumstances is quite tricky. In master, we raise an exception if you explicitly provided a layout (layout "foo"), and none exist for any MIME type. Implicit layouts or explicit layouts that exist for another MIME are permitted to be absent. The exception to that rule is render :layout => true, which converts an implicit layout to a required, explicit one.

RJS and HTML

Rails 2 has a bunch of hardcoded rules that allow RJS templates to render HTML. This allows page[:foo].replace_html :partial => "some_partial" to render some_partial.html.erb.

Effectively, when you got into an RJS template, the acceptable formats list was hardcoded to [:html]. Again, this blocks the use of RJS partials, and if you supply only an RJS partial, it will not be used (a missing template error would be raised).

When we thought about it, we realized that what is desired is to look for templates matching the mime type of the current template first, and if such a template could not be found, to allow templates matching any mime (with HTML leading the list). If you’re in an RJS template and you call render :partial => "foo", and only a foo.xml.erb exists, we can assume that you mean to render that template.

This handles all of the cases supported by Rails 2, with one small change. If you have both a js and html template, the js template will win inside of RJS. If you didn’t want the js template to win, why did you create it?

That rule now applies to any template. Partials matching the existing mime will be rendered if they exist, but any other mime will work fine as a fallback. So no special rules required for RJS anymore. The same rules apply for other templates (:file etc.) rendered from the context of another template.

One last thing. If you do page[:customer].replace_html :partial => "world", an html template will be required. When we noticed that we could separate out the rules for replace_html from other partials, we realized that we could hardcode more restrictive rules for that specific API than the general API.

And with that, the remaining pending tests pass. I really enjoy being able to solve problems that required hacks in the past by reorganizing the code to produce conceptually nicer solutions.

<script type="text/javascript"> addthis_url = 'http%3A%2F%2Fyehudakatz.com%2F2009%2F06%2F18%2Fand-the-pending-tests-they-shall-pass%2F'; addthis_title = 'And+the+Pending+Tests+%26%238212%3B+They+Shall+Pass%21'; addthis_pub = ''; </script><script type="text/javascript" src="http://s7.addthis.com/js/addthis_widget.php?v=12"></script>

Calculating Line Item Extensions

Posted about 1 month back at Sterling Rose Design Blog

In my project, I have orders, and each order can have an unlimited number of line_items. Line_items are created by the user clicking on a button, which appends (via RJS) a new row to the line_items tabled form. So far, so good.

But I needed the extended price (quantity * price_per) of each line_item to be calculated every time the user tabbed out or clicked away from the price_per field. Further, I needed the subtotal, tax, total, and balance fields to be automatically re-calculated.

I messed around with it for several hours, trying Javascript, Prototype, and even jQuery, before I finally settled on a Prototype approach that worked. The real struggle was that using Rails 2.3’s nested forms functionality meant that each line_item would have an index key embedded in the middle of the text field’s name and id, and I could not come up with a good way to extract it, to pass it to the Javascript function.

Luckily, the numbering appears to be a 0-based index, so I cheated and used an incrementer.

I know it’s not a perfect solution (it’s obtrusive, it’s probably much more verbose than it needs to be) but it functions.

So, on to the code. Obviously, I’ve snipped out a lot of stuff that doesn’t have anything to do with this example.

/controllers/orders_controller.rb

def new
  @order = Order.new
  @order.line_items.build
  @order.zero_set_amounts
  @colors = Color.unremoved
end

def edit
  @order = Order.new
  @colors = Color.unremoved
end

/models/order.rb

def zero_set_amounts
  self.subtotal = 0
  self.tax = 0
  self.shipping = 0
  self.artwork = 0
  self.setup = 0
  self.printing_charge = 0
  self.misc_charge = 0
  self.total = 0
  self.balance = 0
  self.reorder ||= false
end

/views/layouts/application.html.erb

<head>
  <%= javascript_include_tag :defaults, 'main' %>
</head>

/views/orders/new.html.erb and /views/orders/edit.html.erb

<% form_for(@order) do |f| %>
  <%= render :partial => "form", :locals => {:f => f} %>
<% end %>

/views/orders/_form.html.erb

<div id="order_line_items">
  <%= render :partial => 'line_items', :locals => {:f => f, :order => @order} %>
  <div id="order_summary_fields">
    <div class="left"><%= f.label :subtotal %></div>
    <div class="right"><%= text_field_tag :subtotal, 0, :size => 10, 
      :disabled => true %></div>
    <div class="left"><%= f.label :artwork %></div>
    <div class="right"><%= f.text_field :artwork, :size => 10, :onblur => 
      'recalculateTotals();' %></div>
    <div class="left"><%= f.label :setup %></div>
    <div class="right"><%= f.text_field :setup, :size => 10, :onblur => 
      'recalculateTotals();' %></div>
    <div class="left"><%= f.label :printing_charge, "Printing" %></div>
    <div class="right"><%= f.text_field :printing_charge, :size => 10, :onblur => 
      'recalculateTotals();' %></div>
    <div class="left"><%= f.label :misc_charge, "Miscellaneous" %></div>
    <div class="right"><%= f.text_field :misc_charge, :size => 10, :onblur => 
      'recalculateTotals();' %></div>
    <div class="left"><%= f.label :shipping %></div>
    <div class="right"><%= f.text_field :shipping, :size => 10, :onblur => 
      'recalculateTotals();' %></div>
    <div class="left"><%= f.label :tax %></div>
    <div class="right"><%= text_field_tag :tax, 0, :size => 10, :disabled => true %></div>
    <div class="left"><strong><%= f.label :total %></strong></div>
    <div class="right"><%= text_field_tag :total, 0, :size => 10, 
      :disabled => true %></div>
    <div class="left"><%= f.label :balance %></div>
    <div class="right"><%= text_field_tag :balance, 0, :size => 10, 
      :disabled => true %></div>
    <%= render :partial => "shared/create_or_update", :locals => {:f => f} %>
    <%= f.hidden_field :subtotal %>
    <%= f.hidden_field :tax %>
    <%= f.hidden_field :total %>
    <%= f.hidden_field :balance%>
    <%= f.hidden_field :reorder %>
  </div>  
</div>

/views/order/_line_items.html.erb

<%= button_to_remote 'Add a New Line Item', {:url => new_line_item_path, :method => :get} %>
...
<% i = 0 %>
<% f.fields_for :line_items do |line_items_forms| %>
  <tr>
    <td><%= line_items_forms.text_field :quantity, :size => 5 %></td>
    <td><%= line_items_forms.text_field :description, :size => 30 %></td>
    <td><%= line_items_forms.select :color_id, @colors.map {|c| [c.name, c.id]} %></td>
    <td><%= line_items_forms.text_field :price_per, :size => 10, :onblur => 
      order.new_record? ? 'updateExtendedPrice("order_line_items_attributes_0_quantity", 
      this.id, "order_line_items_attributes_0_price_extended");' : 
      "updateExtendedPrice('order_line_items_attributes_#{i}_quantity', this.id, 
      'order_line_items_attributes_#{i}_price_extended');" %></td>
    <td><%= line_items_forms.text_field :price_extended, :size => 10, :class => 
      'fluffy_bunny' %></td>
   <% i += 1 %>
  </tr>
<% end %>

Yeah, I called my class “fluffy_bunny.” It’s not a class name I was likely to use anywhere else, and fluffy bunnies are cute. :)
/controllers/line_items_controller.rb

def new    
  begin
    @order = Order.find(params[:order_id])
    @line_item = @order.line_items.build
  rescue ActiveRecord::RecordNotFound
    @line_item = LineItem.new
  ensure
    @item_index = @order.nil? ? Time.now.to_i : (@order.line_items.length - 1)
  end

  respond_to do |format|
    format.html
    format.js do        
      @colors = Color.unremoved.collect {|c| [c.name, c.id]}
      @line_id = "order_line_items_attributes_#{@item_index}"
      @line_name = "order[line_items_attributes][#{@item_index}]"
    end
  end
end

/views/line_items/new.js.erb

$('line_item_table').insert(<%=js render(:partial => "new_line_item") %>, 'bottom');

/views/line_items/_new_line_item.html.erb

<tr> 
  <td><%= text_field_tag "#{@line_id}_quantity", '', :name => "#{@line_name}[quantity]", 
    :size => 5 -%></td> 
  <td><%= text_field_tag "#{@line_id}_description", '', :name => 
    "#{@line_name}[description]", :size => 30 -%></td> 
  <td><%= select_tag "#{@line_id}_color_id", options_for_select(@colors), :name => 
    "#{@line_name}[color_id]" -%></td>
  <td><%= text_field_tag "#{@line_id}_price_per", '', :name => 
    "#{@line_name}[price_per]", :size => 10, :onblur => 
    "updateExtendedPrice('order_line_items_attributes_#{@item_index}_quantity', this.id, 
    'order_line_items_attributes_#{@item_index}_price_extended');" -%></td>
  <td><%= text_field_tag "#{@line_id}_price_extended", '', :name => 
    "#{@line_name}[price_extended]", :size => 10, :class => 'fluffy_bunny' -%></td>
</tr>

/public/javascripts/main.js

function updateExtendedPrice(x,y,z) {
  $(z).value=parseFloat($(x).value) * parseFloat($(y).value);
  updateSubtotal();
  recalculateTotals();
}

function updateSubtotal() {
  var subtotal=0;
  var li;
  var line_item_extensions = $$('.fluffy_bunny');
  line_item_extensions.each(function(li) {subtotal += parseFloat(li.value);})
  $('order_subtotal').value=subtotal;
  $('subtotal').value=subtotal;
}

function updateTax() {
  /* Tax rate is 7% */
  var tax = ((parseFloat($('order_subtotal').value) + 
    parseFloat($('order_artwork').value) + parseFloat($('order_setup').value) + 
    parseFloat($('order_shipping').value) + parseFloat($('order_printing_charge').value) 
    + parseFloat($('order_misc_charge').value)) * 0.07).toFixed(2);
  $('order_tax').value=tax;
  $('tax').value=tax;
}

function updateTotal() {
  var total = (parseFloat($('order_subtotal').value) + 
  parseFloat($('order_artwork').value) + parseFloat($('order_setup').value) + 
  parseFloat($('order_tax').value) + parseFloat($('order_shipping').value) + 
  parseFloat($('order_printing_charge').value) + 
    parseFloat($('order_misc_charge').value)).toFixed(2);
  $('order_total').value=total;
  $('total').value=total;
}

function updateBalance() {
  balance = $('order_total').value;
  $('order_balance').value = balance;
  $('balance').value = balance;
}

function recalculateTotals() {
  updateTax();
  updateTotal();
  updateBalance();
}

Dear Railsists, Please Don’t be Obtrusive

Posted about 1 month back at Ruby, Rails, Web2.0

obtrusive_or_not.png Update: thanks to Jon Wood aka jellybob, a prototype demonstration has been added, which is even better than my original jQuery btw as it degrades gracefully. Check it out in the ‘prototype-unobtrusive’ directory.

I am guessing 9 out of 10 of you reading the title is prepared for yet-another Rails drama on some obtrusive community members, and because everyone is tired of Rails dramas, I am risking that some of you won’t care to read the article - but I couldn’t resist :-). Actually I’d like to talk about usage of (un)obtrusive Javascript - why is it a bad idea to be obtrusive, especially given that (as you will learn from the article) writing unobtrusive Javascript is not harder, and you get the warm, fuzzy feeling of writing nice and clean code!

The Drill

To demonstrate the differences, I’ll lead you through the creation of a quick AJAXy shout wall both the default/standard (and obtrusive) way, then do the same with unobtrusive Javascript to show you that contrary to the popular belief, you don’t need to memorize the “Tome of Javascript Black Magick Tricks” by heart, use obscure libraries or special coding techniques to achieve clean, unobtrusive code. The shout wall is simply a form for posting a new message, and a list of messages below it, like so:

shout_wall.png

(You can check out the code used in this post from it’s github repository).

The Standard Way

Note: If you’d like to follow along, please use the provided pastie links - do not try to cut & paste multiple lines from the page (single lines are OK), as it will be b0rk3d.

  1. Creating a new Rails application
    1. rails obtrusive-shout-wall
  2. Get into the Rails dir
    1. cd obtrusive-shout-wall
  3. Generate the resource message
    1. script/generate resource message
  4. Add this the following to the generated migration (some_timestamp_create_messages (Get it from pastie):
    1. t.string :author
    2. t.text :message
  5. Run the migrations:
    1. rake db:migrate
  6. Because we want to view the messages in reverse order (newest one first), we add a default scope to the Message model (in message.rb):
    1. default_scope :order => ‘created_at DESC’
  7. Create the application layout - create a new file in app/views/layouts called application.html.erb, and fill it with the following content (Get it from pastie):
    1. <html>
    2.   <head>
    3.     <%= stylesheet_link_tag "application" %>
    4.         <%= javascript_include_tag :defaults %>     
    5.   </head>
    6.     <body>
    7.     <%= yield %>
    8.     </body>
    9. </html>
  8. Create a file application.css and drop it into public/stylesheets. Add the following content (Get it from pastie):
    1. body {
    2.     background-color:#FFFFFF;
    3.     color:#333333;
    4.     font-family:"Lucida Grande",verdana,arial,helvetica,sans-serif;
    5.     margin:0 auto;
    6.     padding:0;
    7.     text-align:center;
    8.     width:960px;
    9. }
    10.  
    11. #messages {
    12.     text-align: left;
    13.     margin-left: 80px;
    14.     margin-top: 50px;
    15. }
    16.  
    17. #message-form {
    18.     text-align: left;
    19. }
    20.  
    21. #message-form dl {
    22.     margin:10px 0 0 80px;
    23. }
    24.  
    25. #message-form dd {
    26. color:#666666;
    27. font-size:11px;
    28. line-height:24px;
    29. margin:0 0 5px 80px;
    30. }
    31.  
    32. #message-form dt {
    33.     float:left;
    34.     font-size:14px;
    35.     line-height:24px;
    36.     width:80px;
    37.   text-align: left;
    38. }
    39.  
    40. #author {
    41.   margin-right: 640px;
    42. }
    43.  
    44. #message {
    45.   width: 600px;
    46.     height: 200px;
    47.   margin-right: 194px;
    48. }
    49.  
    50. .message {
    51.   margin-bottom: 20px;
    52. }
    53.  
    54. .first_row {
    55.   padding-bottom: 10px;
    56. }
    57.  
    58. .message-meta {
    59.     font-size: 12px;
    60. }
    61.  
    62. .author {
    63.   color: #FF5050;
    64.     font-weight: bold;
    65. }
    66.  
    67. .new-message-label {
    68.   text-align: left;
    69.   padding-top: 30px;
    70.   margin-left: 80px;
    71. }
    72.  
    73. #submit-button {
    74.   float : right;
    75.   margin-right: 195px;
    76.   margin-top: 10px;
    77. }
  9. Create a new action, index in MessagesController (Get it from pastie):
    1. def index
    2.   @messages = Message.all   
    3. end
  10. This goes into app/views/messages/index.html.erb (Get it from pastie):
    1. <h3 class="new-message-label">Enter new message!</h3>
    2. <% remote_form_for :message, :html => {:id => "message-form"} do |form| %> 
    3.   <dl>
    4.         <dt>Author:</dt>
    5.     <dd><%= text_field_tag ‘author’ %></dd>
    6.         <dt>Message:</dt>
    7.         <dd><%= text_area_tag ‘message’ %></dd>
    8.     </dl>
    9.     <%= submit_tag "Submit!", :id => "submit-button"%>
    10. <% end %>
    11.  
    12. <div id="messages">
    13.     <%= render :partial => ‘message’, :collection => @messages %>
    14. </div>
    We are showing the form for the messages and list the already exiting messages below the list. Note that we are using the _remote_form_for_ Rails helper to create an AJAXy form. This is already obtrusive, since if you observe the generated HTML, you will see that the form has an onsubmit parameter with some horribly looking code attached to it.:

    Obtrusive helper.png

    Sure, you can go ‘meh’ all the way, but slinging Javascript code all over the place is just as bad idea as writing inline CSS (or even worse, using HTML code for styling) or putting Rails code into views. It will work without any problems - but it’s just not the right way of doing things, especially if your code is going to hit a certain size.
  11. You probably noticed that we are rendering a message as a partial - so create a partial file app/views/messages/_message.html.erb with the following content (Get it from pastie):
    1. <div class="message" id="message-<%=message.id%>">
    2.   <div class="message-meta">on
    3.    <%= message.created_at.to_formatted_s(:long_ordinal) %>,
    4.    <span class="author"><%= message.author %></span>
    5.    said:
    6.   </div>
    7.   <div><%= message.message %></div>
    8. </div>
  12. We need a ‘create’ action in MessagesController in order to process the form submission (Get it from pastie):
    1. def create
    2.   @message = Message.create(:author => params[:author], :message => params[:message])
    3. end
  13. And obviously we’ll need to render something to respond to the create action. Using the standard Rails way, RJS, we might come up with something like this (in app/views/messages/create.js.rjs - Get it from pastie):
    1. page.insert_html :top, "messages", :partial => ‘message’, :object => @message
    2. page.visual_effect  :highlight, "message-#{@message.id}"
    Here we insert the “messages” partial, using the just created @message, and throw a splash of yellow fade into the mix for good measure. Easy peasy.
  14. We are done! Fire up script/server, hit localhost:3000/messages and voila!

The Good Way

Here I am presenting only the steps that are different from the above - i.e. if step 3 is skipped, use the one from above.

  1. Creating a new Rails application
    1. rails unobtrusive-shout-wall
  2. Get into the Rails dir
    1. cd unobtrusive-shout-wall
  3. Same as above
  4. Same as above
  5. Same as above
  6. Same as above
  7. Since we are going to use jQuery (unobtrusiveness is *not* a property of jQuery, you can be just as unobtrusive with Prorotype - but I switched to jQuery just before learning how, and now I am lazy to go back check out how in the ‘prototype unobtrusive’ directory in the github repository), you have to download jQuery with some basic effects, as well as an AJAX form handling library (still from the directory unobtrusive-shout-wall - Get it from pastie):
    1. curl http://jqueryjs.googlecode.com/files/jquery-1.3.1.min.js > public/javascripts/jquery.js
    2. curl http://www.malsup.com/jquery/form/jquery.form.js?2.28 > public/javascripts/jquery-form.js
    3. curl http://view.jquery.com/tags/ui/latest/ui/effects.core.js > public/javascripts/effects.core.js
    4. curl http://view.jquery.com/tags/ui/latest/ui/effects.highlight.js > public/javascripts/effects.highlight.js
    and replace
    1. <%= javascript_include_tag :defaults %>
    with
    1. <%= javascript_include_tag ‘jquery’ %>     
    2. <%= javascript_include_tag ‘jquery-form’ %>
    3. <%= javascript_include_tag ‘application’ %>
    4. <%= javascript_include_tag ‘effects.core’ %>
    5. <%= javascript_include_tag ‘effects.highlight’ %>
    in the layout file.
  8. Same as above
  9. Same as above
  10. Same as above - just delete “remote” from the name of the helper, i.e. use a standard Rails view helper, form_for
  11. Same as above
  12. Since we are not relying on Rails to do the rendering for as via a template file, we return the html chunk that we will render from Javascipt. So your create action should look like (Get it from pastie):
    1. def create
    2.   @message = Message.create(:author => params[:author], :message => params[:message])
    3.   render :partial => ‘message’, :object => @message
    4. end
  13. Now comes the fundamentally different part - instead of using RJS to respond to the create action, we move all our code to application.js (Get if from pastie):
    1. $(document).ready(function() {     
    2.   $("#message-form").ajaxForm({success: handleNewMessage});
    3.  
    4.   function handleNewMessage(response, statusText) {
    5.     $("#messages").prepend(response).effect("highlight", {}, 1500);
    6.   }   
    7. });
    I don’t think so that this code is particularly more complicated or hard to understand that the RJS one. Everything is inside the ready() function, which means that it’s only run once the document is properly loaded. Then we declare that “#message-form” is an AJAX form, and that upon successful submission, the handleNewMessage() method should be called. And if that happens, we add the response (which is the return value of the “create” action) to the “#messages” div, just as we did in RJS. Then we apply the yellow fade! w00t!
  14. Same as above

(You can check out the code used in this post from it’s github repository).

Conclusion

As you can see, the only real difference between the obtrusive and non-obtrusive version is in the last 2 points (downloading and including the jQuery header files can be easily solved with Rails templates): instead of leaving the rendering part to Rails, we return the response as a string and dynamically insert it from jQuery. With about the same effort, we kept all the Javascript code in application.js, which is much cleaner this way (you can open up 1 file and check out all the JS/AJAX behavior in one place), especially after introducing a lot of Javascript functionality into your code - in other words, for the same amount of work we got something much better. Please try to keep this in mind when you are working with Javascript and Rails the next time - believe me, it can save you from a lot of pain!

RailsConf Speaker Interview: Mike Subelsky

Posted 2 months back at ChadFowler.com

Next up in my series of RailsConf speaker interviews is Mike Subelsky, co-founder of OtherInbox and avid SproutCore developer. (SproutCore was used, among other things, to develop Apple’s MobileMe UI and presents a Cocoa-like environment for developing Rich browser-based user interfaces.)

Mike will be presenting both a tutorial on SproutCore development and a session on cloud computing gotchas at RailsConf in a couple of weeks.

How did OtherInbox get started? Was this your first startup? What were the hurdles in moving from consulting to product development?

We wanted to solve our own email overload problem—many people receive heavy volumes of “gray mail” or “bacn” and increasing volumes of more important email like receipts, social networking notifications, confirmations, etc. The other founder of the company, Joshua Baer, had the idea to build a product that would elegantly organize and make sense of this kind of mail, something we would use ourselves that would also help the average person.

This was my first startup; I knew Josh from a project class we had taken together at Carnegie Mellon and was lucky that he invited me to be the cofounder. I had been dabbling and freelancing as a Rails developer for the previous 18 months, and had always been hacking on side projects for my whole career.

Coming from a consulting background, there have been two big hurdles:

  1. I didn’t expect product development to have such a different tempo than consulting projects. You live with your code much longer (so you end up maintaining your own legacy code, and don’t have the next greenfield to look forward to), you have to deal more directly with the consequences of mistakes (there’s no one to bail you out), and the risks are higher (because you don’t know when or if your labors will pay off). Thus there are many peaks and valleys of happiness, and it’s not always easy to tell if you are being successful.
  1. When time and resources are so constrained, the development team has to become disciplined without sacrificing too much agility. You can’t rely on individual programming heroics to carry the day – otherwise you’re guaranteed to burn out and get sloppy. I haven’t completely overcome this hurdle yet, but I’m reading everything about software development processes that I can get my hands on. I’ve become a huge fan of Eric Ries’ lean startup blog Lessons Learned.

What makes SproutCore interesting and special to you?

SproutCore lets you build real client-server applications, delegating a lot of GUI work to the client that servers currently perform (like rendering HTML views or serving up cached HTML pages). The framework takes concepts that desktop developers have used for a long time and reimagines them for use in web applications. For example, key-value observation and bindings help you eliminate a lot of buggy, ugly glue code, saving a lot of time and aggravation).

It’s special to me because I think this technology has the potential to dramatically change application development in general. The core team has a strong point of view about how Internet clients should be built, and how to make JavaScript and web browsers perform. Writing SproutCore code reminds me of the feeling I got the first time I picked up a book about Rails—“using these tools is making me a better programmer”.

Also, I’ve never liked the feel of Flash, and I love how SproutCore uses only web-native technologies to do amazing things in the browser. PaperCube and MobileMe are examples of SproutCore apps that feel like desktop apps, but don’t require any plugins whatsoever.

Are SproutCore and Rails particularly well suited to one another? If so, how?

I think so—you can point a SproutCore client at any kind of server you want, but I think there’s probably a sweet spot for these two frameworks. Rails makes it easy to write a robust, easily extensible REST API, which makes it really easy to write web clients. SproutCore makes it easy to write robust, easily extensible web clients.

In OtherInbox, our Rails app has to worry about doing is sending back JSON as quickly as possible. The SproutCore app handles most of the user interaction (except for things like the signin page, which we’re keeping server-based for now) and focuses on making the browser experience as fast and fluid as possible. We don’t need to run as many web servers to keep up with our recent growth, because the servers aren’t bogged down generating HTML or RJS updates.

As a happy side-effect, since we built our app this way, someone has reverse engineered our JSON API to make an Android app.

Rails developers will also find many cultural similarities such as emphasis on unit testing and use of generators.

SproutCore’s model marks an extreme departure from the way we traditionally do JavaScript/AJAX applications on Rails. Do you think SproutCore or its patterns will catch on generally or is it bettered toward to a specific niche?

I think if you’re building an app where you need to add just a little dynamic behavior here and there, SproutCore is too much. Toolkits like Prototype and jQuery are much more appropriate. But if you’re making something like MobileMe, PaperCube, or OtherInbox, where the users expect desktop-like fluidity or where the client software can’t always rely on the server for everything, SproutCore will be a big win.

One thing that could help SproutCore catch on generally will be its support for multiple platforms. The 1.0 release candidate includes preliminary mobile support, so we should eventually be able to take the same code base and build it for web browsers, iPhones, Androids, etc., without having to change much. I think that will really turn some heads.

SproutCore’s learning curve appears to be pretty steep. What’s the best way to get into it on day one?

That’s tough, because there aren’t yet a lot of blogs or books to guide you. One of my goals for 2009 is to start contributing more tutorials, because I was lucky to be mentored by Erich Ocean. My best advice would be to get some familiarity with Cocoa because that will illuminate the parts of desktop development that are really different from web development. If you understand key-value observation, key-value coding, and bindings, it will be much easier to learn SproutCore.

Also, the #sproutcore IRC channel and Google group are really friendly places to get guidance.

20 Rails Development No-No's

Posted 3 months back at ChadFowler.com

Yesterday, I asked Twitter:

Rails programmers: what's an example of one thing you find in other people's Rails 
code that you (almost) always consider to be wrong?

Quite a few people responded, and several asked if I’d post the aggregated answers. Here’s an attempt. I don’t necessarily agree with everything here. I’d love to hear more of these in the comments.

1. Code in Views

@greg_fu

@briandoll

@mbleigh

@briandoll’s response was particularly interesting:

extensive logic in views. If the erb would be ugly and harder to pull off in
haml, it's likely a code smell

This is something I always liked in Java about XMLC:http://www.enhydra.org/tech/xmlc/index.html. It was really hard to end up with a mess of co-mingling code and views, because you would have to work harder in XMLC to even make that possible. Amrita used to have that same characteristic, but I’m not sure it still does (or if it is even maintained).

I’ve been resistant to HAML but maybe it’s time to give it another look.

Also, as @mbleigh points out, any code in views is suspect. CSS should be in CSS files. Javascript should be in Javascript files.

2. Tabs instead of spaces and bad indentation

@Tricon

@fowlduck

@boboroshi

Enough said.

3. Bad or Missing Tests

@rickbradley

@merbist

@alancfrancis

@joshuabates

@mattsoutherden

@seancribbs

@seancribbs singles out auto-generated tests. I’ll have to agree with him.

@alancfrancis says simply “rspec”. Certainly not a religious topic. I’m sure if you could somehow see in the code which editor someone used, we’d see a lot of TextMate, vi, and emacs in the responses.

4. Bad use of Polymorphic Associations and Single-Table Inheritance

@brendanbaldwin says “I’ve seen Polymorphic Associations and Single Table Inheritance abused to absurdity.”

As have I. I’ve also abused them to absurdity myself. The storage of a column called “type” which holds a class name is a pretty good indicator that something fishy is going on. It’s fishy but not always bad. I think, though, that any time you use it you should ask yourself more than once if it’s the right solution. Databases don’t do what they do best as well when you have lots of STI and polymorphic associations.

5. Cavalier Exception Handling

@technomancy

@mikesax

I once had to debug a problem with a commercial, Java-based portal product. The mail module was failing, saying it couldn’t connect to the mail server. In fact, what was happening was my login credentials were incorrect. Guess what the offending JSP looked like (pseudo-code)?

try {
  // do everything here
} catch (Exception e) {
  out.println("Unable to connect to the mail server")    ;
}

Exceptions are one of the only places in Ruby where you rely on checking the classes of objects to do useful and interesting things. Never rescue Exception unless it’s at the end of a stanza in which you’ve already handled one or more other exception types.

UPDATE: from the comments, Phil didn’t mean what I typed here:

That’s not actually what I meant. Never rescue Exception unless you’re working with code that abuses the   
exception hierarchy. In normal circumstances you should be rescuing StandardError instead. If you rescue  
Exception, you won’t even be able to ctrl-c your way out of your code(!) among other problems

More info on his weblog here

6. Accidental Local-variable Assignment

@technomancy

  class Potato
    attr_accessor :size
  end
  potato = Potato.new
  potato.instance_eval do
    size = 123
  end
  p potato.size
  # => nil

Ruby’s assignment to method-call syntax sugar only works when there’s an explicit receiver (such as self.size = 123)

7. Code That Produces Ruby Warnings

@tenderlove

Always run with -w. Fix any warnings you see. A good place to see them is when running your application’s comprehensive test suite.

8. Code that uses the features of Rails :)

@drawohara

@drawohara

@brianleroux

@joshuabates

RJS, render, nested named routes, and ERb are the targets of these criticisms.

9. Misuse of validates_uniqueness_of

@hedron

validates_uniqueness_of is a strange critter. It’s so easy to use, that it’s tempting to slap it into your code and consider it good enough. But even the documentation for it warns you:

Using this validation method in conjunction with ActiveRecord::Base#save
does not guarantee the absence of duplicate record insertions, because
uniqueness checks on the application level are inherently prone to race
conditions.

10. Code in the Wrong Place

@mperham

@bcalloway

@mikesax

@joshuabates

Here are some rules of thumb:

  • Nothing that looks at all like SQL should go into a controller, view, or helper.
  • Try to avoid code that causes a database query (even through a shielded API) in views and helpers
  • Never generate HTML in a model
  • Not counting respond_to blocks, shoot for controller actions of 5 lines or less.

11. Configuration Files That Contain Their Own Environment Sections

@stonean

If you create your own configuration file and have to check RAILS_ENV, you’re not using a built-in facility of Rails.

12. Too Much Code

@aaroncampos

OK, so this isn’t really what he meant. But it’s a good thing to think about. If you find yourself writing a lot of code to do something simple, you might be missing something Rails (or a plugin) provides. I’ve seen a whole lot of wheels re-invented inside models, controllers, and helpers. Part of Rails mastery is learning to ask yourself, “Shouldn’t somebody have already done this for me by now?”

13. Messing Up $LOAD_PATH

@drnic

Seems like if you find yourself manipulating Ruby’s load path in your Rails code, you’re doing something strange. If you don’t know you’re doing something strange, then you’re probably doing something wrong.

14. Obfuscated Logic

@sneakin

@pelargir

As Dave Thomas likes to say “Don’t not use positive logic” (or something like that).

Can someone tell me where the use of ”!!true” crept into the Ruby vernacular? Sure, it’s syntactically valid to do:

    !!!!!!!!!!!!!!!!!!ok?
  

But why?

It’s April 1st, so my mind wanders to the hypothesis that someone introduced this and started spreading it as an elaborate joke. If so, well played. Is there a good use of this idiom I’m missing?

15. Seed Data in Migrations

@lifo

ActiveRecord migrations define a simple API/DSL for doing schema manipulation. But when they run, they’re just Ruby classes and methods executing within the Rails environment. So you can do anything you like in that context.

Sometimes people use migrations to load seed data. Pratik doesn’t like this.

I’m on the fence on this one. In small doses it doesn’t strike me as a horrible practice. That being said, I don’t tend to do it. I’d be interested in hearing opinions.

16. Sending Data on GET Requests

@Adkron

I guess it depends on what you’re doing with the parameters. Sometimes long parameter lists on GET requests are a sign that there are two actions’ worth of work happening in a single action. Or that you’re doing something that belongs behind a POST or PUT. This one doesn’t bother me as much as it does @Adkron.

17. Not Using Transactions

@sbfaulkner

    if foo.save && bar.save
  

if bar fails to save, foo doesn’t. Oops. I’ve seen this more than once in the wild.

18. Bad Use of Javascript

@leandroico

@RobotDeathSquad

Obtrusive Javascript and RJS are the themes here.

What’s the worst use of RJS you’ve seen? I love RJS. I may be one of the offenders. Doesn’t feel like it (usually) though.

19. Long Methods

@mikesax

Smalltalk people, as a collective culture, seem to get this right. Kent Beck documents a simple pattern in his Smalltalk Best Practice Patterns called “Compose Method”. He says that one way to determine whether a new method is required is whether all of the code in a given method operates at the same level of abstraction. That’s a simple but powerful rule. Think about it next time you’re coding and I think you’ll agree.

20. Chatty Comments

@mikesax

I agree with Mike on this one. I don’t tend to write any comments, so I may be on the anti-comment side to a fault. My goal is always to write code that is clear enough that comments don’t add anything. If you name everything well and keep your classes, modules, and methods short, you’re already going to make comments redundant in a lot of cases.

Whenever I see a comment inside a method definition, I consider it a bad sign. In most cases, whenever you encounter a comment inside a method, it’s a marker for where code should be extracted into a new method.

If you’re writing a framework, the rules are different. But most of the time as a Rails developer, you shouldn’t be writing a framework.

Mephisto 0.8.2 released

Posted 4 months back at Mephisto - Home

Mephisto 0.8.2 is now available on the download page!

Mephisto’s JavaScript is in much better shape, and most of the remaining “tainted string” errors should now be fixed. The default article and comment filter is now Textile (instead of raw HTML), and our gem management has been cleaned up.

Many thanks to the Mephisto contributors brought you this release: Chris Cummer, James McCarthy, Matthias Lüdtke, Sean O’Brien and Gustavo Sales (who wrote the first version of the theme homepage fix).

Thanks also go to Chris Cummer for investigating Mephisto multisite caching issues. For information on setting up multisite, please see Mika Tuupola’s blog post and the thread on the MephistoBlog group. Alternatively, you can disable multisite support in config/initializers/custom.rb.

We’re actively working on a simpler solution for multisite caching. In particular, we’re looking into writing a custom Rack module under Rails 2.3. If you’re interested in helping, please join us on #mephisto. Contributors are always welcome!

A full list of patches appears after the jump.

Chris Cummer (2):

  • Fixes ‘attempted to output tainted string’ error when rendering email address for mailto
  • Changed user login to send user to admin section on succesful login instead of the blog homepage since users have the ability to post to the blog

Eric Kidd (23):

  • Unbundle tzinfo gem
  • Fix theme controller bugs
  • Change default comment filter to Textile
  • Change default user article filter to Textile
  • Rename *.rhtml files to *.html.erb
  • Rename *.rxml files to *.xml.builder
  • Modernize rjs: admin/articles
  • Added some notes about fixing JavaScript
  • Begin updating to latest Prototype
  • JavaScript: Fix asset search
  • JavaScript: Fix authenticity_token problems
  • JavaScript: Rename admin/assets/*.js -> *.js.rjs
  • Remove RSpec StoryRunner files
  • Write login integration tests using Webrat
  • Add integration test for “reset password”
  • Upgrade to interim release of Webrat from github
  • Add version numbers to config.gem statements
  • Allow newer versions of these gems
  • Add TODO item for explaining how to make Unicode work
  • Merge branch ‘master’ of git://github.com/technoweenie/mephisto
  • Merge branch ‘master’ of git://github.com/mat/mephisto
  • Require test gems in development environment, not test
  • Fix display of theme homepage links

James McCarthy (2):

  • escaped link in _page.html.erb
  • Added some brackets

Matthias Lüdtke (4):

  • Fixed typo.
  • Moved test gems from environment.rb to environments/test.rb.
  • Added missing config.gem ‘ruby-debug’ to environments/test.rb.
  • Added info: install test gems before testing.

Sean O’Brien (1):

  • missing tainted string in cache listing

jQuery on Rails: Why Bother?

Posted 7 months back at RailsTips.org - Home

In which I explain why I use jQuery at times and how you can as well. Oh, and I provide a wealth of links. Links are fun!

A few people have suggested that I post about how to use jQuery with Rails. I thought about it and felt that others have already covered it quite well but why not collect their posts here for you to enjoy, right? Plus, I do all my JavaScript from scatch so I do not really ever use the helpers Rails provides and as such could not post intelligently on them.

So John, When Did You Quit Prototype?

I haven’t! I do not intend to ever quit using Prototype. Honestly, I have used jQuery quite a bit less than Prototype. I have found that jQuery and Prototype are both great and in different situations I will use a different library. The one thing I will say is even if you don’t actually switch to jQuery, I think it is important to learn new things and stretch yourself. It is good to feel frustrated and like a beginner. Also, jQuery takes a very different approach which has actually helped me write better Prototype code. Hope this is helpful and not overwhelming. :)

Creating A Plugin

Addicted to New jQueryToday, I wrote an article on How to Create a jQuery Plugin From Scratch over on my Addicted To New site. I picked out the most basic thing a plugin could do and explained each step in a lot of detail. Give it a read if you are into Prototype but are curious about jQuery.

Live Search and Fancy Zooming

Ordered List jQueryAfter creating my live search with quicksilver for prototype example, I decided to port it to jQuery (view demo). Then, humbly, I was corrected by the jQuery man himself, John Resig, who re-ported my port in a more jQuery-ish functional style. For those that are curious, I also massaged the AJAX-RDoc project to use quicksilver searching. This is really helpful when you can’t quite remember a method name.

Likewise, when I created fancy zoom for prototype, my partner in crime, Steve Smith, created a port of fancy zoom for jQuery (view demo). Fancy Zoom is great for showing text and images with an Apple-esque, in page zoom transition or even Flash if you have a video you would like to feature.

jQuery Railscast

RailsCasts jQueryRyan Bates did an awesome job showing how to use the jQuery on Rails plugin with Rails in a recent screencast. He also gave a really quick example on how to create a plugin. I would recommend watching this and subscribing to his Railscasts, which are great.

jRails Plugin

RailsCasts jQueryjRails is a drop-in jQuery replacement for Prototype/script.aculo.us on Rails. Using jRails, you can get all of the same default Rails helpers for javascript functionality using the lighter jQuery library. Ryan shows how to use it in the screencast mentioned above, but I thought I would also mention it separately. If you are a fan of the Rails javascript/ajax helpers, this plugin is for you. It makes each of them work with jQuery and has some nice demos on the site.

Link Love

While dispelling the myth that Rails is tied to Prototype, DHH gave some jQuery examples.

Brandon showed how he includes the authenticity token using prototype and the pug automatic shows how to do the same using jQuery.

Ben Curtis has a tutorial on how to do drag and drop sorting with jQuery and Rails.

Yehuda Katz has a year old presentation on jQuery and Rails that is still worth a look.

Nutrun has a more full post on how to do unobtrusive ajax with jQuery and Rails

ErrTheBlog (errtheblog is dead. long live errtheblog!) gave jQuery some serious love a while back in their jSkinny article. Chris also created a plugin named Facebox that is used extensively on GitHub and has a short post that shows how to get jQuery working with respond_to.

If you are a fan of Low Pro, Dan Webb has created a port of Low Pro for jQuery. (article #1, article #2)

In some Rails Rumble observations, it was noted that jQuery was more widely used than Prototype.

Don’t forget that “jQuery UI provides abstractions for low-level interaction and high-level, themeable widgets, built on top of the jQuery JavaScript Library, that you can use to build highly interactive web applications.” Be sure to check out the demos.

If you are a fan of Twitter, you can follow jQuery for links to articles and such.

Nathan Smith gave a crash course on jQuery that includes a sweet airline seat demo.

jQuery does not come with all of Prototype’s functionality out of the box, but you can usually find a plugin that does what you need if you are too lazy to make something yourself.

Lastly, one of my favorite jQuery resources is Visual jQuery. I found this site a blessing when I was trying to learn jQuery.

Feel free to post your favorite jQuery/Rails resources as a comment below.

jQuery on Rails: Why Bother?

Posted 7 months back at RailsTips.org - Home

In which I explain why I use jQuery at times and how you can as well. Oh, and I provide a wealth of links. Links are fun!

A few people have suggested that I post about how to use jQuery with Rails. I thought about it and felt that others have already covered it quite well but why not collect their posts here for you to enjoy, right? Plus, I do all my JavaScript from scatch so I do not really ever use the helpers Rails provides and as such could not post intelligently on them.

So John, When Did You Quit Prototype?

I haven’t! I do not intend to ever quit using Prototype. Honestly, I have used jQuery quite a bit less than Prototype. I have found that jQuery and Prototype are both great and in different situations I will use a different library. The one thing I will say is even if you don’t actually switch to jQuery, I think it is important to learn new things and stretch yourself. It is good to feel frustrated and like a beginner. Also, jQuery takes a very different approach which has actually helped me write better Prototype code. Hope this is helpful and not overwhelming. :)

Creating A Plugin

Addicted to New jQueryToday, I wrote an article on How to Create a jQuery Plugin From Scratch over on my Addicted To New site. I picked out the most basic thing a plugin could do and explained each step in a lot of detail. Give it a read if you are into Prototype but are curious about jQuery.

Live Search and Fancy Zooming

Ordered List jQueryAfter creating my live search with quicksilver for prototype example, I decided to port it to jQuery (view demo). Then, humbly, I was corrected by the jQuery man himself, John Resig, who re-ported my port in a more jQuery-ish functional style. For those that are curious, I also massaged the AJAX-RDoc project to use quicksilver searching. This is really helpful when you can’t quite remember a method name.

Likewise, when I created fancy zoom for prototype, my partner in crime, Steve Smith, created a port of fancy zoom for jQuery (view demo). Fancy Zoom is great for showing text and images with an Apple-esque, in page zoom transition or even Flash if you have a video you would like to feature.

jQuery Railscast

RailsCasts jQueryRyan Bates did an awesome job showing how to use the jQuery on Rails plugin with Rails in a recent screencast. He also gave a really quick example on how to create a plugin. I would recommend watching this and subscribing to his Railscasts, which are great.

jRails Plugin

RailsCasts jQueryjRails is a drop-in jQuery replacement for Prototype/script.aculo.us on Rails. Using jRails, you can get all of the same default Rails helpers for javascript functionality using the lighter jQuery library. Ryan shows how to use it in the screencast mentioned above, but I thought I would also mention it separately. If you are a fan of the Rails javascript/ajax helpers, this plugin is for you. It makes each of them work with jQuery and has some nice demos on the site.

Link Love

While dispelling the myth that Rails is tied to Prototype, DHH gave some jQuery examples.

Brandon showed how he includes the authenticity token using prototype and the pug automatic shows how to do the same using jQuery.

Ben Curtis has a tutorial on how to do drag and drop sorting with jQuery and Rails.

Yehuda Katz has a year old presentation on jQuery and Rails that is still worth a look.

Nutrun has a more full post on how to do unobtrusive ajax with jQuery and Rails

ErrTheBlog (errtheblog is dead. long live errtheblog!) gave jQuery some serious love a while back in their jSkinny article. Chris also created a plugin named Facebox that is used extensively on GitHub and has a short post that shows how to get jQuery working with respond_to.

If you are a fan of Low Pro, Dan Webb has created a port of Low Pro for jQuery. (article #1, article #2)

In some Rails Rumble observations, it was noted that jQuery was more widely used than Prototype.

Don’t forget that “jQuery UI provides abstractions for low-level interaction and high-level, themeable widgets, built on top of the jQuery JavaScript Library, that you can use to build highly interactive web applications.” Be sure to check out the demos.

If you are a fan of Twitter, you can follow jQuery for links to articles and such.

Nathan Smith gave a crash course on jQuery that includes a sweet airline seat demo.

jQuery does not come with all of Prototype’s functionality out of the box, but you can usually find a plugin that does what you need if you are too lazy to make something yourself.

Lastly, one of my favorite jQuery resources is Visual jQuery. I found this site a blessing when I was trying to learn jQuery.

Feel free to post your favorite jQuery/Rails resources as a comment below.

Episode 136: jQuery

Posted 7 months back at Railscasts

How do you use jQuery with Rails? In this episode I redo episode #43 using jQuery instead of Prototype/RJS.

This Week in Edge Rails

Posted 7 months back at Riding Rails - home

Rails, as you probably know, is under active development. So, for those of you who don’t have time to read every commit to the source, we’ve decided to revive this section of the weblog. This time around, I’m covering 3 weeks of commits: the time since Rails 2.2 RC1 (otherwise known as Rails 2.2.0) was released. Though there aren’t any major new features being added as Rails drives towards the 2.2 release, that doesn’t mean the source has been completely quiet: there have been about 75 commits in that three-week period. Here’s a look at some of those changes.

In the run-up to 2.2, we’re seeing a batch of little bug fixes, as people try to ensure quality in the release. These include:

  • Squashing a binary data corruption bug that surfaced in the PostgreSQL adapter. commit
  • The regex behind redirect_to can now accept a wider variety of URL schemes, making it possible to redirect to some destinations that were previously inaccessible. commit
  • A regression in date_select and datetime_select that could raise a Null Pointer Exception under some circumstances has been fixed. commit
  • The sanitize helper has been fixed to avoid double escaping already properly escaped entities. commit
  • FormTagHelper has been stopped from generating illegal HTML if the name contains square brackets. commit
  • A memory leak was squashed in Active Record scoped methods. commit

Some of the major features for 2.2 have been getting fine-tuned as well. There’s been work to clean up some loose ends in the thread safety department, and changes to make the I18n backend reload its translations in development mode. The included Prototype bits were bumped to the latest 1.6.0.3 release. The code for configuring, loading, and vendoring gems has had some attention, and the code for maintaining database connection pools has come in for some fine-tuning as well.

Just because we’re in feature freeze doesn’t mean that a few new features can’t sneak in:
  • The current_page method is a bit more reliable now in that it ignores options you don???t explicitly supply (making it more friendly to URLs that use the query string for pagination and the like). commit
  • The default logging has been cleaned up to be less chatty: you???ll see fewer duplicate log messages as Rails goes about its business. commit
  • The render method now takes a :js option to allow you to directly render inline JavaScript without using RJS. commit
  • If you???ve got a current (Ruby 1.8.7 or greater) version of Ruby, Action Mailer turns on STARTTLS if the server supports it; this makes Action Mailer compatible with GMail without the need for plugins. commit

One final note: I’m deliberately not trying to cover every single commit here; just those ones that struck me as most interesting. But if I left out something that you think is highly significant, feel free to add a pointer in the comments!


1 2 3 4