January 30th, 2009 No Comments »
I just wanted to display reCAPTCHA inside a ModalBox.
This simple task turned out to be quite complicated.
After playing with innerHTML, creating <script> nodes manually and attaching them and other voodoo and black magic and failing to accomplish the desired effect, I settled with displaying the recaptcha inside iframe inside ModalBox.
Modalbox.show('<iframe src="' + this.href + '?iframe=1"></iframe>',
{title: this.title, width: 600});
(The iframe parameter helps to select another layout).
January 30th, 2009 No Comments »
Wouldn’t it be nice to cache some item (e.g. action) for some amount of time, before expiring it? For example, if you’re displaying some page that parts of it change very often, but you don’t want to expire cache every time, since you prefer to serve stale information instead of expiring the page?
The answer is the options[:expires_in] which is supported by the Rails’ ActiveSupport::Cache::MemCacheStore.
The current implementation of ActiveSupport::Cache::FileStore, however, lacks such feature, despite the fact that it’s really easy to implement.
This is the fix accompanied by a unit-test.
cache_fix
And then you can happily add a line like this in your controllers:
caches_action :find, :expires_in => 10.minute
The check, by the way, adds about 7usec to cache read request, which IMHO is negligible.
The Rails core team doesn’t seem to be interested in this patch, though.
January 23rd, 2009 No Comments »
There’s a nice plugin which adds helper for the reCAPTCHA. The downside is that it doesn’t support I18n at the moment.
This is a straight forward approach patch that adds this functionality. (I don’t know what will be the fate of I18n in Rails 3, thus the simple check for version).
The error message path then will be:
activerecord.errors.models.model_name.captcha
diff --git a/lib/recaptcha.rb b/lib/recaptcha.rb
index 87c26e9..44413bc 100644
--- a/lib/recaptcha.rb
+++ b/lib/recaptcha.rb
@@ -65,7 +65,11 @@ module Ambethia
session[:recaptcha_error] = error
if model = options[:model]
model.valid?
- model.errors.add_to_base "Captcha response is incorrect, please try again."
+ if Rails::VERSION::MAJOR >= 2 and Rails::VERSION::MINOR >= 2
+ model.errors.add_to_base I18n.translate("#{model.class.name.underscore}.captcha", :scope => %w(activerecord errors models), :default => "Captcha response is incorrect, please try again.")
+ else
+ model.errors.add_to_base "Captcha response is incorrect, please try again."
+ end
end
return false
else
I wonder if this is the proper way of adding I18n support…
P.S. I reported this on lighthouse.
January 6th, 2009 No Comments »
This trick is great for actions which receive lots of parameters, for example – search controller. Obviously, you wouldn’t want to do that with something that receives a POST, but I omitted the check for it (using :if => Proc.new {|controller| controller.request.get?} , for example), since I think that I know what I’m doing.
So the idea is to map all the parameters to some unique key, and then use that key as an :id for the url_for.
# This caches the find action by the parameters
require 'digest/sha1'
caches_action :find, :expires_in => 10.minute,
:cache_path => Proc.new { |controller|
search_key = Digest::SHA1.hexdigest(controller.params.inspect)
logger.debug "Current search key: #{search_key}"
controller.url_for(:action => 'find', :id => search_key)
}
The only minor issue that might arise, is that if you’re using pagination, the page number 1 when reached from the pagination links will have page=1 parameter, but when it’s initially presented, the parameter is absent. Adding such parameter won’t do any good, since the order of keys in hash in undefined. It’s possible, though, to build the key using some other technique, for example by massaging the request string. But since the case is quite rare, I think that any fix will be a waste of CPU cycles.