April 30th, 2011 No Comments »
While there’re multiple tools available for monitoring, ranging from Dan Bernshtein’s daemontools to God, I found that Monit is a pretty balanced solution. On one hand, it’s quite powerful, and on the other – it’s not resource hungry. The only drawback that I found, is that for monitoring a process, the process must have a pid-file saved somewhere. The Monit FAQ states that the programs which don’t have pid-file support should be run with some wrapper which will create it on their behalf.
I wanted to use Monit to monitor Rails’ instances, so if they grow too fat, Monit will take care of that. The problem is that the pid file that the Passenger creates a) doesn’t have a predictable location (there’s something called “generation” or something like that), and b) doesn’t have children, as those processes are detached.
Of course there exists a possibility of patching Passenger for providing such pid files. But, luckily, Passenger provides extension points in form of callbacks which are fired when the application instance is created and when it’s taken down.
It was trivial to use this API to provide pid-file managing. The result of this work was the “passenger_monit” plugin.
So, go ahead, add ‘gem “passenger_monit”‘ to your Gemfile and give it a try!
The source is available from:
https://github.com/romanbsd/passenger_monit
April 5th, 2011 No Comments »
Logging line numbers in Ruby Logger can be done with a simple decorator:
class LoggerDecorator
def initialize(logger)
@logger = logger
end
%w{debug info warn error fatal}.each do |method|
eval(<<-eomethod)
def #{method}(msg)
@logger.#{method}(position) {msg}
end
eomethod
end
private
def position
caller.at(1).sub(%r{.*/},'').sub(%r{:in\s.*},'')
end
end
March 6th, 2011 3 Comments »
In order to make ExtJS play nicely with Rails, the following tweaks are needed:
On the ExtJS javascript side, the following things are needed:
1. Ask server to server JSON:
Ext.Ajax.defaultHeaders = {'Accept': 'application/json'};
2. RailsJsonStore:
Ext.data.RailsJsonStore = Ext.extend(Ext.data.JsonStore, {
constructor: function(config) {
Ext.data.RailsJsonStore.superclass.constructor.call(this, Ext.applyIf(config, {
messageProperty: 'message', //for store.reader.getMessage()
restful: true,
url: '/'+ config['root'] + 's',
writer: {encode: false}
}));
}
});
Ext.reg('railsjsonstore', Ext.data.RailsJsonStore);
3. XSRF protection:
Ext.Ajax.on('beforerequest', function(o) {
var csrf = Ext.select("meta[name='csrf-token']").first();
if (csrf) {
o.defaultHeaders = Ext.apply(o.defaultHeaders || {}, {'X-CSRF-Token': csrf.getAttribute('content')});
}
});
On Rails side:
config.active_record.include_root_in_json = false
November 23rd, 2010 No Comments »
I forked the livejournal ruby gem (http://neugierig.org/software/livejournal/ruby/) which seems to be abandoned.
It fixes the well known errors like:
livejournal/entry.rb:174:in `load_prop': unknown prop
which are due to new properties.
It also has some new functionality.
The fork can be found here.
I tried to contact the author, but haven’t heard from him yet.
February 18th, 2009 13 Comments »
Simple, but nice replacement for open-uri library (which uses rather slow Net::HTTP library) which uses libcurl (via curb).
It’s easy to swap the original one just by replacing ‘require open-uri’ with ‘require curb-openuri’. Should work as the original, even with better defaults (which, of course, can be changed).
http://github.com/romanbsd/curb-openuri/tree
February 9th, 2009 7 Comments »
Several months back I needed to compute NMF of some relatively larges matrices.
Since the native Ruby code was painfully slow, and for some reason even failed to work for some matrices, I decided to write a C implementation which will leverage the GNU Scientific Library (GSL) and then wrap it for using in Ruby application.
It was a neat add-on to the rb-gsl ruby library. What it does is adding NMF module under the GSL::Matrix, and there you have a method nmf which receives a GSL::Matrix and number of columns as a parameter and then returns two matrices.
Since this is an iterative algorithm, the number of runs is limited to 1000, and the desired difference cost metric is set to 10-6.
I tried to contact the author and even posted my code in the issue tracker, but haven’t received any response at the time of writing.
So I decided to create a git-svn mirror on Github and add my changes there.
http://github.com/romanbsd/rb-gsl
You can install the gem using this command:
$ gem sources -a http://gems.github.com/ # (you only have to do this once)
$ gem install romanbsd-gsl
February 8th, 2009 2 Comments »
This simple fix uses the fact, that if the second argument to the ‘add’ method is a symbol, then a generate_message is called, which does all the voodoo of Rails 2.2 I18n.
I tried to contact the original author to no avail, therefore I’ll post it here, hoping that if anyone needs it, it’ll surface on a Google search.
The fix itself is quite simple:
Index: lib/validates_date_time.rb
===================================================================
--- lib/validates_date_time.rb (revision 403)
+++ lib/validates_date_time.rb (working copy)
@@ -114,7 +114,7 @@
if options[:before]
options[:before].each do |r|
if r.value(record) and value >= r.last_value
- record.errors.add(attr_name, options[:before_message] % r)
+ record.errors.add(attr_name, :before, :default => options[:before_message] % r)
break
end
end
@@ -123,7 +123,7 @@
if options[:after]
options[:after].each do |r|
if r.value(record) and value <= r.last_value
- record.errors.add(attr_name, options[:after_message] % r)
+ record.errors.add(attr_name, :after, :default => options[:after_message] % r)
break
end
end
I’ve a fork of the git-svn mirror here:
http://github.com/romanbsd/validates_date_time/tree/master
Then, for using it, you’ll just need to have the following path in your locale yml files (for example):
activerecord:
errors:
models:
user:
attributes:
birth_date:
before: 'is wrong'
after: 'is wrong'
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.