Rails 3 in place editing problems

I’ve been following the examples used in the Learning Rails podcasts to get up to speed on rails.  I was impressed with how they quickly built a very basic CMS using Rails, so decided to try to emulate it in my first Rails site (a loot management system for EverQuest 2).  As mentioned in my previous post, I’ve been having some issues with the in place editing.  Being a little stubborn, I’ve decided to push on and try to get this functionality working the way I want it to (and the way I think it should).

One of the main things I’ve noticed in going from a language like Delphi to Ruby, is how quickly things change and how much those rapid changes can bite you.  Some of the things that worked in their tutorial under Rails 2.02 no longer apply in Rails 3.0.3 (which I’m using).  Coming from a language background where things are fairly stable, it’s a little disconcerting.

The first hurdle was actually prior to getting the “in place editing” working.  The HTML is being generated from Textile entered in by the user and stored in the database using the Page model.  Putting the line: “<%= @page.body %>” in viewer/show.html.erb
would escape the HTML leaving me with the HTML source, instead of rendering the HTML.  It appears this is something that was added to Rails 3.

I was able to resolve this issue by using “<%= @page.body.html_safe %>”.  It feels like a nasty hack, but I think it should be safe enough in this instance.

Once I got that working, implementing the “in place editing” quickly broke it and I was back to square one.

I tried using the following line as discussed here, but that causes the contents of viewer/show.html.erb to not be rendered at all.

render :text => @page.body, :layout => true

At this point, I got the debugger out and traced the code through the following path:

helper_methods.rb - InPlaceMacrosHelper.in_place_editor_field
tag_helper.rb - TagHelper.content_tag

After looking at the tag options inside tag_helper.rb, I decided to hide the “in place editing” control and always display @page.body.  This also gave me more control over where the “edit” link would be.

To do this, I simply set hidden to true for in the tag options in my view: “viewer/show.html.erb”:

<%= @page.body.html_safe %> 
<% if logged_in? %>
    <a href='#' id='edit'>Edit This Page</a></br>
    <%= in_place_editor_field :page, 'body',{:hidden => true},
                              {:rows => 20, :cols => 80, 
                               :external_control => 'edit',
                               :external_control_only => true,
                               :load_text_url => {:controller => 'viewer',
                                                  :action => 'get_unformatted_text',
                                                  :id => @page.id
                                                 }
                              } %>
<% end %>

Now when I click on the “edit” link, the control is still displayed and I can edit the text.  Clicking Ok, would save the text and hide the control again.

At this point, I thought I was done and went to bed.  But further testing the next day highlighted another issue.  After editing the Textile it was rendering the old version, and not my changes.  I made the “control” visible again, and the control did render the changes correctly upon saving, but rendering @page.body didn’t.  I tried changing my controller code to cause it to re-render the page after the update, but that still didn’t work.  My view_controller.rb code is:

class ViewerController < ApplicationController
  in_place_edit_for :page, :body

  def show
    @page = Page.find_by_name(params[:name])
    login_required if @page.admin?
  end

  def set_page_body
    @page = Page.find(params[:id])
    if @page.update_attribute(:body, params[:value])
      flash[:notice] = 'Page was successfully updated.'
      redirect_to view_page_path(@page.name)
    else
      render :text => @page.body
    end
  end  def get_unformatted_text
    @page = Page.find(params[:id])
    render :text => @page.body(:source)
  end
end

When I debug through set_page_body, I can see the “new” version of the Textile as I have entered it in @page.body, but when watching through firebug, there is no HTTP GET request being called causing the old version of HTML is rendered. If I un-hide the “in place editing” control, the text is rendered correctly in that control, but it doesn’t render it correctly when just navigating to the page.

Even worse, I start getting some funky behavior when repeatedly editing the same page.  The first time it’s fine, but the second time I get two “in place edit” controls.  The third time, I get three controls, etc, etc.

At this point, I feel like I’ve wasted way too much time on this and I’m going to move onto the next task.  Googling around only finds more people with similar issues using various versions of Ruby and Rails.  Searching for solutions to this on various Ruby forums (including http://www.learningrails.com) and Stackoverflow yields similar results.

I find it annoying that something many people consider to be “simple” to do in Ruby on Rails is turning out to be so painful to get working.  While I have this functionality “working”, it’s not in a way that is elegant.  And not in a way that I’d be happy to deliver to a “client”.  At this point, this is going to be put on the back-burner until I have implemented some more functionality.

Advertisements

~ by Catharz on 03/10/2011.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: