aku-aku: v.. To move a tall, flat bottomed object (such as a bookshelf) by swiveling it alternatively on its corners in a "walking" fashion. [After the book by Thor Heyerdahl theorising the statues of Easter Island were moved in this fashion.] source: LangMaker.com. Aku Aku also has another meaning to the islanders: a spiritual guide.
« Why I Microwaved My Passport | Main Page | login sugar for the salted hash login generator »
in_place_editor_field and blank values
Posted by dav at 2006 August 16 12:20 AM
File under: Geek
Updated to add the :nil_content_replacement option

One of the nice features in Rails is the in_place_editor_field view helper which wraps script.aculo.us's Ajax.InPlaceEditor and displays your model attributes in a nice ajaxy editor. However a major problem with it is that when the attribute is blank the editor effectively disappears and you are not able to set a value for it through the browser.

This seemed like a common problem but I wasn't able to find a nice solution to it after 20 minutes of googling. There were some kludgy fixes that required poor interface design on the web page, adding special handling code to my models [shudder], or else hacking the script.aculo.us code. What I wanted was for blank values to be replaced with a series of blank spaces (which would then give the user something to click on). It took a bit of poking around in the rails source, but I was able to pull it off by over-riding some of the default behavior. Here it is.

file RAILS_ROOT/lib/extensions.rb:

class Extensions

  ActionView::Helpers::JavaScriptMacrosHelper.class_eval do
    def in_place_editor_field(object, method, tag_options = {}, in_place_editor_options = {})
      tag = ::ActionView::Helpers::InstanceTag.new(object, method, self)
      tag.nil_content_replacement = in_place_editor_options[:nil_content_replacement] || 'Unknown'
      tag_options = {:tag => "span", :id => "#{object}_#{method}_#{tag.object.id}_in_place_editor", :class => "in_place_editor_field"}.merge!(tag_options)
      in_place_editor_options[:url] = in_place_editor_options[:url] || url_for({ :action => "set_#{object}_#{method}", :id => tag.object.id })
      tag.to_content_tag(tag_options.delete(:tag), tag_options) +
      in_place_editor(tag_options[:id], in_place_editor_options)
    end
  end

  ActionView::Helpers::InstanceTag.class_eval do
    attr_writer :nil_content_replacement

    def value
      unless object.nil?
        v = object.send(@method_name)
        if @nil_content_replacement.nil?
          return v
        else
          (v.nil? || v.to_s.strip=='') ? @nil_content_replacement : v
        end
      end
    end
  end

end

And put this line at the end of RAILS_ROOT/config/environment.rb:

require 'extensions'
Comments:

It works perfectly. You should submit this to the dev team!

Posted by: Matteo Vaccari on September 11, 2006 01:55 AM

This solution worked well, sans one issue. When using in_place_edit_for any field whose value was cleared by the edit would no longer be editable. So, I cracked open the code and made use of the (unused) options parameter to pass in a value to be used when the update results in an empty value. The new parameter is :empty_text. Here's the code:

  ActionController::Macros::InPlaceEditing::ClassMethods.class_eval do 
    def in_place_edit_for(object, attribute, options = {})
      define_method("set_#{object}_#{attribute}") do
        @item = object.to_s.camelize.constantize.find(params[:id])
        @item.update_attribute(attribute, params[:value])
        display_value = params[:value].empty? && options[:empty_text] ? options[:empty_text] : @item.send(attribute)
        render :text => display_value
      end
    end
  end
Posted by: jfoxny on October 26, 2006 08:12 AM

I am also trying to do this in_place_edit and have also found that after it is blanked and updated the field becomes unclickable. I tried jfoxny code but couldn't get it to work. jfoxny can you post an example of it being used... or where you placed this snippet also inside extensions.rb?

Julian (not a noob, but not an expert either)

Posted by: Julian Guppy on November 29, 2006 01:42 PM

Hey Julian, I am sure you figured this out, but for others, like myself, who did not "get" what to do with jfoxny's addition right off the bat, all you need to do is add the :empty_text parameter to the in_place_edit_for call in your controller...

class UsersController 
    in_place_edit_for :user, :name, :empty_text => '...'
end

His snippet also lives within the extension class. I hope this helps... only a month late :)

Posted by: rjb on December 28, 2006 03:57 PM

this code no longer works with rails 1.2.2...does anyone have a patch?

Posted by: deezzer on February 25, 2007 08:20 PM

For 1.2.2

  ActionView::Helpers::InstanceTag.class_eval do
    attr_writer :nil_content_replacement

def value(object)
unless object.nil?
v = object.send(@method_name)
if @nil_content_replacement.nil?
return v
else
(v.nil? || v.to_s.strip=='') ? @nil_content_replacement : v
end
end
end
end

Posted by: Cussen on February 26, 2007 05:34 PM

Does not work for me, i get following error:

wrong number of arguments (1 for 0)
Extracted source (around line #87):
...
87:
...

#{RAILS_ROOT}/lib/extensions.rb:16:in `in_place_editor_field'

in extensions.rb i have at this line:

tag.to_content_tag(tag_options.delete(:tag), tag_options) +

Same if I change this line to:
tag.to_content_tag(tag_options.delete(:tag), tag_options) + in_place_editor(tag_options[:id], in_place_editor_options)
or
tag.to_content_tag(tag_options.delete(:tag), tag_options)

What could be the problem?

Posted by: mkezys on March 8, 2007 01:33 PM

mkezys: I had the same problem. Turns out the implementation of value() in the post is incorrect. It should be

def value(object)

not

def value

Cussen's comment above has it defined correctly. That's why you get the "wrong number of args" error

Posted by: joe on February 27, 2008 10:30 AM

Nothing suggested in this thread worked for me (Rails 2.0.2) but after much hair-pulling, I had an AHA! moment. I put a bit of CSS at the top of my template:


.in_place_editor_field:after {
content: url(/images/edit_entry_12.png)
}

Basically, CSS dynamically inserts the a small image into the , giving you something to click on when the is otherwise empty. You can also use "content:'some text'" instead of an image, but that looks ugly.

Posted by: doppler on April 22, 2008 11:12 AM

Post a new comment:

Thanks for signing in, . Now you can comment. (sign out)

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)


Remember me?