Ruby on Rails

RailsConf RubyAZ Presentation Slides

by Irish on May 16, 2012

This past Tuesday evening I presented to the RubyAZ user group. The talk covered useful libraries and gems that I saw at Rails Conf 2012 that I thought others might find helpful in their day to day work. I’ve made the presentation slides available as a pdf. Enjoy!

{ 0 comments }

Got burned by two things today in one of my apps by upgrading to Rails 3.1. The first thing was a few nested forms stopped working when editing an existing record that had child records. None of the children were getting rendered. For briefity, the form basically was like:

<%= form_for @meal do |meal_form| %>
  <table>
    <tbody>
      <% meal_form.fields_for :meal_items do |item_form| %>
        <%= render :partial => 'meal_item_fields',
                   :locals => { :f => item_form } %>
      <% end %>
    </tbody>
  </table>
<% end %>

Can you spot the error? Once I spotted it I felt rather dumb myself. It’s the following erb tag

<% meal_form.fields_for :meal_items do |item_form| %>

Ya even when they’re nested you HAVE to use the <%= form... doh!

<%= meal_form.fields_for :meal_items do |item_form| %>

The second problem I ran into, and which I still don't have an answer for, though if you do answer my StackOverflow question. Basically, in Rails 2.3 if you needed to get at an instance of the Template Builder you could use @template, but then they changed it in Rails 3 to a special method called "view_context". Far enough, so I was using view_context in Rails 3.0.X to create nested forms (other than the one above) dynamically using jQuery ajax and js.erb partials. Using view_context allowed me to call fields_for off of it so that I would get nicely named form_fields when I didn't have the parent FormBuilder handy. Like this

In some_view.js.erb

<% fields =
    view_context.fields_for :meal_items, Meal.new.meal_items.new do |f|
      render :partial => 'meal_item_fields', :locals => {:f => f}
    end %>

$("#meal-items").append("<%= escape_javascript(fields) %>");

But once I upgrade to 3.1, I started getting the following error

ActionView::Template::Error (undefined local variable or method `view_context' for #<#:0x1057b9f70>):

Perhaps this was removed as the Core team figured, why do you need the view_context available when you're in a view template already... but I don't know. I was able to workaround it though by moving my code up into the controller. Which does seem to be a violation of the MVC separation, but I couldn't find any other way to make it work like pre Rails upgrade. So instead of creating a local variable "fields", this became an instance variable that was set in the controller action. And render needed to become render_to_string with an html_safe call tacked on the end.

In controller

def some_ajax_action
  @fields =
    view_context.fields_for :meal_items, Meal.new.meal_items.new do |f|
      render_to_string(:partial => 'fields', :locals => {:f => f}).html_safe
    end
end

I don't like this, but it'll do for now I suppose. And now in some_view.js.erb

$("#meal-items").append("<%= escape_javascript(@fields) %>");

{ 2 comments }