Restful In Place Editor with CSRF protection and RJS response
It took me quite a while to get the in_place_editing in Ruby on Rails (Rails 2.1.2) to work with RESTful resources and using RJS to handle the data. So I thought I'd share my results and maybe save you some time.
The essential steps to the solutions are two patches:
* http://dev.rubyonrails.org/ticket/10055
* http://www.vaporbase.com/postings/Restful_In_Place_Editor
The first patch mainly takes care of sending the authenticity token with the in_place_editor.
The second patch applies RESTfulness but doesn't play well with the first patch, so a little more tweaking is necessary in in_place_macros_helper.rb by changing the bits displayed in bold face:
The scriptaculous library (controls.js) switches the request method to get in that case, again breaking the RESTful approach. For this I found no other solution than to alter this behaviour in controls.js.
Old:
The essential steps to the solutions are two patches:
* http://dev.rubyonrails.org/ticket/10055
* http://www.vaporbase.com/postings/Restful_In_Place_Editor
The first patch mainly takes care of sending the authenticity token with the in_place_editor.
The second patch applies RESTfulness but doesn't play well with the first patch, so a little more tweaking is necessary in in_place_macros_helper.rb by changing the bits displayed in bold face:
def in_place_editor
[...]
if protect_against_forgery?
options[:with] ||= "Form.serialize(form)"
options[:with] += " + '&authenticity_token=' + encodeURIComponent('#{form_authenticity_token}')"
end
+ if options[:as]
+ options[:with] ||= "Form.serialize(form)"
+ options[:with] += " + '&#{options[:as]}=' + encodeURIComponent(value)"
+ end
[...]
- js_options['callback'] = "function(form,value) { return '#{options[:as]}=' + escape(value) }" if options[:as]
js_options['callback'] = "function(form,value) { return #{options[:with]} }" if options[:with]
Handling the data with RJS still raises the problem that after updating the value, the javascript of the RJS is displayed instead of the updated value. According to the documentation the solution to this is sending the option :script => :true.The scriptaculous library (controls.js) switches the request method to get in that case, again breaking the RESTful approach. For this I found no other solution than to alter this behaviour in controls.js.
Old:
[...]
handleFormSubmission: function(e) {
[...]
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
New:
[...]
handleFormSubmission: function(e) {
[...]
+ if (this.options.restfulResponse)
+ var options = Object.extend({ evalScripts: false }, this.options.ajaxOptions);
+ else
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
For this change to be actually triggered, we need one more line in in_place_macros_helper.rb :
def in_place_editor [...] js_options['htmlResponse'] = !options[:script] if options[:script] + js_options['restfulResponse'] = trueNow, changing a framework library function is tricky as you cannot be 100% sure what the side effects might be and you have to reapply your changes with every update of the framework. So if any of you have a better solution, please tell me in the comments.
McLibboc - 11. Dezember, 13:34
