proxy: error reading status line from remote server
A few months ago, on Swirrl’s test server, we were seeing errors like this in the Apache error log, about once a day (normally when the server had been idle for a while – i.e. overnight)
proxy: error reading status line from remote server ...The (ruby on rails) application would be non-responsive, and the only way to get it going again would be to restart its mongrels.
After a bit of head-scratching and Googling, we realized that it was because we didn’t have the MySQL gem installed on that server. The MySQL gem installs a MySQL API module for Ruby. It provides the same functions for Ruby programs that the MySQL C API provides for C programs.
(We also made a small change to our Apache config, but I don’t think that this made any difference.)
One small gotcha is that some of the ActiveRecord error messages produced with/without the MySQL gem are different, so if you’re doing any custom error handling (e.g. for database uniqueness violations etc), you might want to check this.
Macports and Ruby 1.8.7 1
Last month, I wrote about how Macports now gives you Ruby 1.8.7 by default (with which Rails has problems), and that I didn’t know how to get back to 1.8.6.
If you’re having the same problem, this post by Robby Russell might help you out.
Lightview for modal dialogs on Rails 20
Long-time followers of this blog will know that I’ve tried various solutions for modal dialogs in rails apps (namely, Prototype-Window, and Redbox).
Prototype-Window worked fine, but uses Prototype 1.5RC3, and I’m using rails 2 with Prototype 1.6. The guys behind Prototype-Window are working on a new open source library, Prototype-UI which uses Prototype 1.6 and Script.aculo.us 1.8, but it’s still just a release candidate at the moment. This is a really exciting development and it will be interesting to see how this project progresses.
Initially, I was a big fan of Redbox, but I uncovered a few problems as time went on (including some cross-browser issues), which meant that it lost favour. To be fair to Craig Ambrose, the developer of Redbox, he did mention to me that he wasn’t currently working on it, and that it was just built to fit the exact requirements he had at the time.
So, to get down to the topic of this blog post… my current modal dialog solution du jour is Lightview by Nick Stakenburg. It’s not free, but relatively cheap, even for commercial use (€49 for one domain – if you compare this cost to the amount of developer-time it would take to write something of equal quality, it’s really a no-brainer). You can download a free-trial so that you can try it out before buying. I can’t comment on the quality of the code because it’s obfuscated but the documentation on the website is great, and the product itself works well across all major browsers.
I thought I would share how i got Lightview working in a rails application, for showing ajax content.
1. Download Lightview from here. (I’m using version 2.2.9.2)
2. Make a lightview folder in your application’s public/javascripts folder, and copy the contents (i.e. the css, images and js folders) of the lightview 2.x folder into your new folder.
3. Create a new file, lightview_helper.rb, in your helpers folder, and add the following code into it.
module LightviewHelper
# A lightview is shown with js like below (example taken from the lightview site:
# (http://www.nickstakenburg.com/projects/lightview/)
# There are 2 levels of arguments:
# top-level 'parameters' (href, rel etc.)
# 2nd-level 'options' (autosize, ajax etc.)
# Lightview.show({
# href: '/ajax/',
# rel: 'ajax',
# title: 'Login',
# caption: 'Enter your username and password to login',
# options: {
# autosize: true,
# topclose: true,
# ajax: {
# method: 'get',
# onComplete: function(){ $('name').focus(); }
# }
# }
# });
# link to a light view.
# name: the text to display in the link
# options: url options for the content to show in the lightview
# html_options: html_options to pass to link_to
# lightview_params: parameters (top-level arguments) for lightview, that differ from or add to defaults
# lightview_options: options (2nd-level arguments) for lightview, that differ from or add to the defaults
def link_to_lightview( name, options = {}, html_options = {}, lightview_params = {}, lightview_options = {} )
# get hold of the js for showing the lightview
show_lightview_js = show_lightview( options, lightview_params, lightview_options )
# merge in the javascipt on the onclick event, keeping any other onclick code intact.
html_options.merge!({
:onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{show_lightview_js} return false;"
})
# return a link which points to #, but has the onclick event in the html options.
link_to( name, "#", html_options )
end
# returns javascript for showing a lightview.
# url_options : hash of options to pass to url_for
# parameters: parameters (top-level arguments) for lightview, that differ from or add to defaults
# options: options (2nd-level arguments) for lightview, that differ from or add to the defaults
def show_lightview( url_options, parameters, options = {} )
# get hold of the default options and merge in what is passed in to this method
lightview_options = get_default_lightview_options
lightview_options.merge!( options )
# get hold of the default parameters
lightview_params = get_default_lightview_params
# merge in any paramters passed in
lightview_params.merge!(parameters)
#merge in the href and options(from above)
lightview_params.merge!(
{
:href => "'#{escape_javascript(url_for(url_options))}'",
:options => options_for_javascript(lightview_options)
}
)
# return js to show the lightview
"
Lightview.show(
#{options_for_javascript(lightview_params)}
);
"
end
# returns js to hide a lightview
def close_lightview_js
"Lightview.hide();"
end
# appends javsascript to hide a lightview to the page
def close_lightview_rjs
page<<close_lightview_js
end
private
# a default set of parameters for showing a lightview
# (top-level arguments -see comments at top of file)
def get_default_lightview_params
{
:rel => "'ajax'",
}
end
# a default set of options for showing a lightview
# (2nd-level arguments -see comments at top of file)
def get_default_lightview_options
{
:autosize => true,
:ajax => options_for_javascript({ :evalScripts => true }) # this is so any js in the displayed page is available (e.g. for autocompleter)
}
end
end
4. Change the get_default_lightview_params and get_default_lightview_options methods to reflect what you want your defaults to be.
5. Add a method to the application helper:
def use_lightview
# Avoid multiple inclusions
@content_for_lightview_css = ""
@content_for_lightview_js = ""
content_for :lightview_css do
stylesheet_link_tag "/javascripts/lightview/css/lightview.css"
end
content_for :lightview_js do
javascript_include_tag "/javascripts/lightview/js/lightview.js"
end
end6. In the application layout (views/layouts/application.rhtml), yield the appropriate contents.
<head>
<!-- ... -->
<%= yield :lightview_css %>
<%= javascript_include_tag "prototype" %>
<%= javascript_include_tag "scriptaculous" %>
<%= javascript_include_tag "effects" %>
<%= javascript_include_tag "controls" %>
<%= yield :lightview_js %>
<!-- ... -->
</head>7. Now, just use the helper methods in your views. e.g.
<% use_lightview -%>
<%= link_to_lightview(
"link text",
{:controller=>'my_controller', :action=>'my_action', :id=>my_id}, #url options
{:class => "whatever"}, # html options
{:title => "'Add type'"}, # lightview params
{:autosize => false, :width => 100, :height => 200} # lightview options
)%> See the Lightview website for details of all the configuration options. Note that the configuration in the lightview.js file (in public/javascripts/lightview/js) is for all lightviews. If you need multiple versions of these settings, just make another lightview folder with a different name, and adapt the helper methods.
If you want to open two (or more) lightviews in succession (e.g. for a wizard), just link to another lightview from inside the first. The lightview will just resize and show the new content.
Update on Rails on OS X Leopard 1
A few months ago I posted an article on how to get rails going on OS X Leopard, in which I advocated using Macports.
MacPorts and Ruby 1.8.7
In order to solve a strange problem with my MacBook Pro, I recently re-installed Leopard from scratch. (Apple said that they had fixed the problem in 10.5.3, but sometimes the problem lingered if you had been running on a non-updated version for a while. So far the problem hasn’t reoccurred, but I’m going to withhold judgment until I’ve run trouble-free for a few weeks – watch this space!).
Anyhow, I followed my own instructions in order to get my development environment back up and running again. However, Macports now installs ruby 1.8.7 by default, and it seems there is a problem with using this version of ruby with rails. When I tried to run my application, I got an error like this:
wrong number of arguments (2 for 1)
/opt/local/lib/ruby/1.8/cgi/session.rb:267:in `respond_to?'
/opt/local/lib/ruby/1.8/cgi/session.rb:267:in `initialize_without_cgi_reader'
/opt/local/lib/ruby/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/cgi_ext/session.rb:39:in `initialize'
...I couldn’t figure out how to get Macports to install a previous version of ruby. Note that this doesn’t work:
sudo port install ruby @1.8.6If anyone knows how to do this, please leave a comment! Maybe I’m being stupid.
UPDATE 19th June 2008: You might want to check out this post by Sho Fukamachi for tips on how to fix Ruby 1.8.7
UPDATE 1 July 2008: Check out my latest blog post for more info on reverting to 1.8.6
Hivelogic
At least with Macports, I could just delete the /opt/local folder and start again. So, I reverted back to using Dan Benjamin’s instructions on HiveLogic so that I could install ruby 1.8.6. Dan’s procedure works a treat, except that I recommend defining the path in ./bash_profile instead of /.bash_login. (See the first comment on his article, and this).
Netbeans 6.1
Since I wrote the original blog article, Netbeans 6.1 has been released. Most of the settings are the same as for version 6.0, but there are few new bits:
For the fast step-through debugging, you need to make sure you have the right versions of ruby-debug installed, i.e. ruby-debug-base 0.10.0 and ruby-debug-ide 0.1.10
You also need to make sure your ruby platform is set up under Tools->Ruby Platforms, and tell Netbeans to use this platform by going to Build->Set Main Project Configuration->Customize.
I’ve noticed a couple of bugs in Netbeans 6.1, such as not refreshing the svn properties every time (work around this by choosing show changes from the Subversion menu before committing), and forgetting some editing preferences. Hopefully these will be fixed soon.
TinyMCE WYSIWYG Text Editor on Rails 31
In Swirrl, we needed users to be able to easily create formatted text. For a time, we toyed with using a markup language such as Textile, but decided that only techies would really be comfortable with writing in a markup language, and we wanted our app to be as accessible as possible.
Basically, what we needed was a WYSIWYG (what you see is what you get) editor. We looked into a couple of options but eventually settled on TinyMCE. This is a really flexible javascript-based text editor, which is already used in many applications on the web. It simply produces html, and provides a way for techie users to edit that html directly if they want, but ‘normal’ users don’t have to worry about any markup.
After reading the rails wiki, the TinyMCE wiki and playing around a bit, I found it quite easy to integrate into our rails application. There’s quite a lot of suggestions on different ways to go about this, so I thought I’d document what worked for me…
2. Make a new folder in your rails app: ‘public/javascripts/tiny_mce’
3. Copy the contents of the ‘jscripts/tiny_mce’ folder from the download into this new folder in your rails app. (So now you should have a folder in your rails app: ‘public/javascripts/tiny_mce/’ which contains the ‘langs’, ‘plugins’ and ‘themes’ folders, amongst other things.)
4. Make a new file: ‘public/javascripts/mce_editor.js’ and add your TinyMCE initialisation code, e.g.
tinyMCE.init({
theme:"advanced",
mode:"textareas",
plugins : "safari",
...
});(Get more information on the TinyMCE API and configuration options from the TinyMCE wiki)
5. Add a method to the application helperdef use_tinymce
@content_for_tinymce = ""
content_for :tinymce do
javascript_include_tag "tiny_mce/tiny_mce"
end
@content_for_tinymce_init = ""
content_for :tinymce_init do
javascript_include_tag "mce_editor"
end
end6. In the application layout (views/layouts/application.rhtml), yield the appropriate contents. According to this TinyMCE wiki page the order of javascript files is important.
<head>
<!-- ... -->
<%= javascript_include_tag "prototype" %>
<%= yield :tinymce %>
<%= javascript_include_tag "scriptaculous" %>
<%= javascript_include_tag "effects" %>
<%= javascript_include_tag "controls" %>
<%= yield :tinymce_init %>
<!-- ... -->
</head>7. Now, to use tinymce in a view or layout, just make a call to the new helper method e.g.
<% use_tinymce -%>
<%= textarea_tag :foo, :bar, ... :class => "mce-editor" %>8. Although TinyMCE does do some tidying up of the html code, you will also want to add white-listing to your implementation to prevent people submitting anything dodgy. (Note that for some of the more advanced TinyMCE formatting, you will need to allow the “style” attribute in your whitelist).
Gotcha: If you want your users to be able to post xml code in their text areas, you will have to use the xml encoding option, and decode that content if you’re showing it outside of a TinyMCE editor anywhere e.g:
<%= white_list(CGI.unescapeHTML(@page.content)) -%>(Note: I found that this option doesn’t work correctly in TinyMCE version 3.0.8 but is fixed in 3.0.9)
I'm Richard Roberts, a developer in the UK working with Ruby on Rails. I'm a founder of: 
