Bad Spammers! Go Away!

Posted almost 7 years back at Sporkmonger

I finally got annoyed enough by all the comment spam. (Probably upwards of 100 comment spams a day.) To absolutely no one’s surprise, my IP blacklist wasn’t helping much. I’ve now customized the comment submission system in Mephisto to include a CAPTCHA of sorts. Well, really more like a test for an actual Javascript-capable browser. Sadly, the technique requires Javascript to be on, and I was a little too lazy to accommodate people who have it off. If you have Javascript off, and you really, truly can’t turn it on, well, I suppose you can always email me? The rest of site works perfectly fine with Javascript off, and I apologize in advance for letting you become a casualty of the War on Spam. If anyone has trouble commenting, email me, I haven’t tested this thing very well—it was a five minute change.

Update:

I rather like how well this has worked out thus far. Went from 100+ spam comments per day to zero since the code was deployed, with effectively zero chance of false positives. I can live with that.

[RELEASE] Plugems packaging

Posted almost 7 years back at Revolution On Rails

The Plugems runtime is enough to justify their existence, but it does not stop there. Since we already defined our dependencies in a gem-like fashion, it is only a small step to start using them for packaging as well. All that is needed for this is the plugems_deploy gem that can be installed from rubyforge. After the gem is installed, a new plugem command comes up. It piggy-backs to capistrano to provide some plugems-related recipes. The recipe packaged with the initial version is build. This action allows you to package your project as a gem.

Let's take for example our sample application's config:

:version: [1, 0]
:name: "cool_application"
:description: "My First Plugemified Application"
:dependencies:
- ['some_gem', '~> 1.0']
- ['other_gem', '> 2.0']
- ['one_more', '2.0.1']

When we run the plugem build on the top of the application, we get a gem built:

$ plugem build
* executing task plugem_build
rm -rf pkg
mkdir -p pkg
Successfully built RubyGem
Name: cool_application
Version: 1.0.0
File: cool_application-1.0.0.gem
mv cool_application-1.0.0.gem pkg/cool_application-1.0.0.gem

If you looked inside, you would find that the attributes and dependencies from the manifest file were translated to corresponding gem attributes and dependencies.

Where did the build (micro) revision come from?

You might noticed that the manifest defined only major and minor revisions but there was a micro added during the packaging time. The plugem packaging process follows the Rubygem's rational versioning policy giving you full control over the build revision. The full version can be defined in the manifest file a-la-Rakefile (i.e. :version: [1, 0, 1]). You can derive it dynamically from a source like svn revision. You just set the capistrano gem_micro_revision variable in a deployment recipe (like config/deploy.rb). An svn based example is:
set :gem_micro_revision, `svn info`.grep(/^Revision:/).first[/(\d+)/][$1]

And you can always overwrite the full version via the '--version' flag of plugem: plugem build --version 3.2.1

The choice is yours.

You might wonder why would you package your rails application as a gem. The rationale is that it allows you to utilize the only ruby-native packaging and distribution system to distribute and deploy your application. The next plugem_deploy releases and this series installments would provide the tools and guidance how to do that.

But it is not just for packaging...

Since you have you dependencies clearly defined, it is really easy to update them to the latest version. Just run plugem update from the project directory:

$ plugem up
* executing task plugem_update
Updating some_gem (~> 1.0)
* executing task plugem_install
Bulk updating Gem source index for: http://gems.rubyforge.org
Installing [ some_gem, 1.2.2 ]

You also have a full control which gem servers to use. Set the variable in your deployment recipe:
set :gem_servers, [ 'http://gems.mycompany.com:8808', 'http://gems.rubyforge.org' ]

and see the difference:

$ plugem up
* executing task plugem_update
Updating some_gem (~> 1.0)
* executing task plugem_install
Bulk updating Gem source index for: http://gems.mycompany.com:8808
Bulk updating Gem source index for: http://gems.rubyforge.org


To Be Continued ...

[RELEASE] Plugems packaging

Posted almost 7 years back at Revolution On Rails

The Plugems runtime is enough to justify their existence, but it does not stop there. Since we already defined our dependencies in a gem-like fashion, it is only a small step to start using them for packaging as well. All that is needed for this is the plugems_deploy gem that can be installed from rubyforge. After the gem is installed, a new plugem command comes up. It piggy-backs to capistrano to provide some plugems-related recipes. The recipe packaged with the initial version is build. This action allows you to package your project as a gem.

Let's take for example our sample application's config:

:version: [1, 0]
:name: "cool_application"
:description: "My First Plugemified Application"
:dependencies:
- ['some_gem', '~> 1.0']
- ['other_gem', '> 2.0']
- ['one_more', '2.0.1']

When we run the plugem build on the top of the application, we get a gem built:

$ plugem build
* executing task plugem_build
rm -rf pkg
mkdir -p pkg
Successfully built RubyGem
Name: cool_application
Version: 1.0.0
File: cool_application-1.0.0.gem
mv cool_application-1.0.0.gem pkg/cool_application-1.0.0.gem

If you looked inside, you would find that the attributes and dependencies from the manifest file were translated to corresponding gem attributes and dependencies.

Where did the build (micro) revision come from?

You might noticed that the manifest defined only major and minor revisions but there was a micro added during the packaging time. The plugem packaging process follows the Rubygem's rational versioning policy giving you full control over the build revision. The full version can be defined in the manifest file a-la-Rakefile (i.e. :version: [1, 0, 1]). You can derive it dynamically from a source like svn revision. You just set the capistrano gem_micro_revision variable in a deployment recipe (like config/deploy.rb). An svn based example is:
set :gem_micro_revision, `svn info`.grep(/^Revision:/).first[/(\d+)/][$1]

And you can always overwrite the full version via the '--version' flag of plugem: plugem build --version 3.2.1

The choice is yours.

You might wonder why would you package your rails application as a gem. The rationale is that it allows you to utilize the only ruby-native packaging and distribution system to distribute and deploy your application. The next plugem_deploy releases and this series installments would provide the tools and guidance how to do that.

But it is not just for packaging...

Since you have you dependencies clearly defined, it is really easy to update them to the latest version. Just run plugem update from the project directory:

$ plugem up
* executing task plugem_update
Updating some_gem (~> 1.0)
* executing task plugem_install
Bulk updating Gem source index for: http://gems.rubyforge.org
Installing [ some_gem, 1.2.2 ]

You also have a full control which gem servers to use. Set the variable in your deployment recipe:
set :gem_servers, [ 'http://gems.mycompany.com:8808', 'http://gems.rubyforge.org' ]

and see the difference:

$ plugem up
* executing task plugem_update
Updating some_gem (~> 1.0)
* executing task plugem_install
Bulk updating Gem source index for: http://gems.mycompany.com:8808
Bulk updating Gem source index for: http://gems.rubyforge.org


To Be Continued ...

Hobo Recipe Ideas

Posted almost 7 years back at The Hobo Blog

I’m thinking more and more that a great way to document Hobo is with a collection of “Hobo Recipes”. So I’ve created a wiki page where we can capture ideas for recipes. There’s only two there at the moment but I’m sure it will grow fast.

Hobo Recipe Ideas

Posted almost 7 years back at The Hobo Blog

I’m thinking more and more that a great way to document Hobo is with a collection of “Hobo Recipes”. So I’ve created a wiki page where we can capture ideas for recipes. There’s only two there at the moment but I’m sure it will grow fast.

Episode 27: Cross Site Scripting

Posted almost 7 years back at Railscasts

Another common security issue is cross site scripting. In this episode you will see why it is so important to escape any HTML a user may submit.

Focussing on documentation

Posted almost 7 years back at The Hobo Blog

The forums are getting really busy, which is a great sign that Hobo is starting to gain some mind-share. It’s so busy that it’s getting harder for me to keep up. If you look at a few posts, it quickly becomes clear that the main issue is lack of documentation. There’s an obvious conclusion here - writing docs is a better way for me to help you all than answering lots of individual questions.

Up until now I’ve had a kind of “no unanswered questions” attitude to the forum, but I don’t think it’s sensible to carry on like that. I’ve set aside a chunk of time each day to keep the Hobo community ticking along, and for now I’m going to try and focus a bit more on documentation and a bit less on the forums.

I’ll still follow the forums closely of course, and reply to the more challenging questions and bug reports, so you’ll still see lots of posts from me. Those of you that have dived into the source and learnt Hobo the hard way – it would be great if you could help out in the forums with some of the more basic questions.

Focussing on documentation

Posted almost 7 years back at The Hobo Blog

The forums are getting really busy, which is a great sign that Hobo is starting to gain some mind-share. It’s so busy that it’s getting harder for me to keep up. If you look at a few posts, it quickly becomes clear that the main issue is lack of documentation. There’s an obvious conclusion here - writing docs is a better way for me to help you all than answering lots of individual questions.

Up until now I’ve had a kind of “no unanswered questions” attitude to the forum, but I don’t think it’s sensible to carry on like that. I’ve set aside a chunk of time each day to keep the Hobo community ticking along, and for now I’m going to try and focus a bit more on documentation and a bit less on the forums.

I’ll still follow the forums closely of course, and reply to the more challenging questions and bug reports, so you’ll still see lots of posts from me. Those of you that have dived into the source and learnt Hobo the hard way – it would be great if you could help out in the forums with some of the more basic questions.

CSS: CSS Browser Selector

Posted almost 7 years back at Revolution On Rails


Each browser has its quirks. Having a clear way of organizing the work arounds
for those quirks is a challenge. Using CSS selectors is not a new idea, but I thought it might be helpful to others to give an example of the technique and how we've been able to successfully deploy it for revolutionhealth.com.



First, for IE (the browser that usually requires a hack), we can rely on conditional comments. This is good because it means we don't need to depend on Javascript. For other browsers we'll have to rely on a document.write solution. For Safari, Opera, and Firefox, we rely on the script from http://rafael.adm.br/css_browser_selector/ and for IE, conditional comments.


Here's what we include at the top of our document. (The browser_detect_start partial.)



<!--[if lt IE 7.]>
<div class='ie ie6'>
<![endif]-->
<!--[if IE 7]>
<div class='ie ie7'>
<![endif]-->
<script type="text/javascript">//<![CDATA[
var d = browserCSSDetection();
if( d.browser != "ie" ){ document.write( "<div class='" + d.browser + " " + d.os + "'>" ); }
//]]></script>

And here's what we do for the end of the document. (The browser_detect_end partial.)

<!--[if IE ]>
</div>
<![endif]-->
<script type="text/javascript">//<![CDATA[
var d = browserCSSDetection();
if( d.browser != "ie" ){ document.write( "</div>" ); }
//]]></script>


The browser detection in Javascript. This could be enhanced further, but for us this allowed us to get the site working relatively easy in Konqueror. As well it enabled us to fix our menu's so that they float over flash in Linux using this techinque.



function browserCSSDetection()
{
// see: http://rafael.adm.br/css_browser_selector/
var ua = navigator.userAgent.toLowerCase();
var is = function(t){ return ua.indexOf(t) != -1; };
var b = (!(/opera|webtv/i.test(ua))&&/msie (\d)/.test(ua)) ?
('ie ie'+RegExp.$1) :
is('gecko/') ? 'gecko' :
is('opera/9') ? 'opera opera9' :
/opera (\d)/.test(ua) ? 'opera opera'+RegExp.$1 :
is('konqueror')?'konqueror' :
is('applewebkit/') ? 'webkit safari':
is('mozilla/')?'gecko':'';
// see: http://www.mozilla.org/docs/web-developer/sniffer/browser_type.html
var os = (is('x11')||is('linux'))?' linux':is('mac')?' mac':is('win')?' win':'';
var css = {browser:b,os:os};
return css;
}


Finally, to make all this fit nicely into a layout:

<head>
<%= javascript_include_tag 'browser_detect' %>
</head>
<body>
<%= render :partial => "browser_detect_start" %>
<%= @content_for_layout %>
<%= render :partial => "browser_detect_end" %>
</body>


Update:
Here's a simple example of what this enables. The advantage of this over a conditionally included file is it keeps everything about the login box isolated to one place. You don't need to worry about openning up a separate file to make your IE fixes. We do use iefix specific CSS for our site, but only for very large features like menus



#login {
padding:0px;
}
.ie6 #login {
padding: 2px;
}

CSS: CSS Browser Selector

Posted almost 7 years back at Revolution On Rails


Each browser has its quirks. Having a clear way of organizing the work arounds
for those quirks is a challenge. Using CSS selectors is not a new idea, but I thought it might be helpful to others to give an example of the technique and how we've been able to successfully deploy it for revolutionhealth.com.



First, for IE (the browser that usually requires a hack), we can rely on conditional comments. This is good because it means we don't need to depend on Javascript. For other browsers we'll have to rely on a document.write solution. For Safari, Opera, and Firefox, we rely on the script from http://rafael.adm.br/css_browser_selector/ and for IE, conditional comments.


Here's what we include at the top of our document. (The browser_detect_start partial.)



<!--[if lt IE 7.]>
<div class='ie ie6'>
<![endif]-->
<!--[if IE 7]>
<div class='ie ie7'>
<![endif]-->
<script type="text/javascript">//<![CDATA[
var d = browserCSSDetection();
if( d.browser != "ie" ){ document.write( "<div class='" + d.browser + " " + d.os + "'>" ); }
//]]></script>

And here's what we do for the end of the document. (The browser_detect_end partial.)

<!--[if IE ]>
</div>
<![endif]-->
<script type="text/javascript">//<![CDATA[
var d = browserCSSDetection();
if( d.browser != "ie" ){ document.write( "</div>" ); }
//]]></script>


The browser detection in Javascript. This could be enhanced further, but for us this allowed us to get the site working relatively easy in Konqueror. As well it enabled us to fix our menu's so that they float over flash in Linux using this techinque.



function browserCSSDetection()
{
// see: http://rafael.adm.br/css_browser_selector/
var ua = navigator.userAgent.toLowerCase();
var is = function(t){ return ua.indexOf(t) != -1; };
var b = (!(/opera|webtv/i.test(ua))&&/msie (\d)/.test(ua)) ?
('ie ie'+RegExp.$1) :
is('gecko/') ? 'gecko' :
is('opera/9') ? 'opera opera9' :
/opera (\d)/.test(ua) ? 'opera opera'+RegExp.$1 :
is('konqueror')?'konqueror' :
is('applewebkit/') ? 'webkit safari':
is('mozilla/')?'gecko':'';
// see: http://www.mozilla.org/docs/web-developer/sniffer/browser_type.html
var os = (is('x11')||is('linux'))?' linux':is('mac')?' mac':is('win')?' win':'';
var css = {browser:b,os:os};
return css;
}


Finally, to make all this fit nicely into a layout:

<head>
<%= javascript_include_tag 'browser_detect' %>
</head>
<body>
<%= render :partial => "browser_detect_start" %>
<%= @content_for_layout %>
<%= render :partial => "browser_detect_end" %>
</body>


Update:
Here's a simple example of what this enables. The advantage of this over a conditionally included file is it keeps everything about the login box isolated to one place. You don't need to worry about openning up a separate file to make your IE fixes. We do use iefix specific CSS for our site, but only for very large features like menus



#login {
padding:0px;
}
.ie6 #login {
padding: 2px;
}

Plugems - Why views in plugems?

Posted almost 7 years back at Revolution On Rails


When we started to develop Plugems we had multiple applications that all shared a similar look and feel. One concept that emerged recently for me was that layouts can act like objects. In our suite of applications, we have a base layout that each application can derive from to satisfy it's unique set of presentation requirements. For example our UI plugem has the following:



ui/views/layouts/default.rhtml

Using a little magic from fora.pragprog we can extend our default layout writing the following:

<% inside_layout 'default' do -%>
<%= @content_for_layout %>
<% end -%>



As well as with layouts, there are also smaller blocks of UI that make up a page that can be shared. I've always thought of these as widgets, which in many cases can be defined as a set of partials and helpers. An application may place a widget on a view, feeding it the data needed to bring it to life. This is different from components because there is no controller logic. Really the presentation side of a widget can be expressed by a set of partials, Javascript, CSS and a healthy dose of ruby [e.g. helpers]. In this way partials are the basic building block on which many UI components can be built. By themselves they are incomplete, but within the context of an application they are alive...




Plugems enables you to share common UI widgets across multiple applications. Common assets (css, js, images) can live in a plugem, but be shared across applications at deployment time. I hope to post more in depth on this topic in near future.

Plugems - Why views in plugems?

Posted almost 7 years back at Revolution On Rails


When we started to develop Plugems we had multiple applications that all shared a similar look and feel. One concept that emerged recently for me was that layouts can act like objects. In our suite of applications, we have a base layout that each application can derive from to satisfy it's unique set of presentation requirements. For example our UI plugem has the following:



ui/views/layouts/default.rhtml

Using a little magic from fora.pragprog we can extend our default layout writing the following:

<% inside_layout 'default' do -%>
<%= @content_for_layout %>
<% end -%>



As well as with layouts, there are also smaller blocks of UI that make up a page that can be shared. I've always thought of these as widgets, which in many cases can be defined as a set of partials and helpers. An application may place a widget on a view, feeding it the data needed to bring it to life. This is different from components because there is no controller logic. Really the presentation side of a widget can be expressed by a set of partials, Javascript, CSS and a healthy dose of ruby [e.g. helpers]. In this way partials are the basic building block on which many UI components can be built. By themselves they are incomplete, but within the context of an application they are alive...




Plugems enables you to share common UI widgets across multiple applications. Common assets (css, js, images) can live in a plugem, but be shared across applications at deployment time. I hope to post more in depth on this topic in near future.

Episode 26: Hackers Love Mass Assignment

Posted almost 7 years back at Railscasts

Your site may be at risk! When using mass assignment, you are giving the user complete control over that model and its associations. See how a hacker might use this vulnerability and learn how to stop it in this episode.

Plugems, Welcome!

Posted almost 7 years back at Rails Engines News

Revolution on Rails have finally released their solution to shared dependencies between Rails applications, which they have called Plugems (see what they’ve done there?). In their announcement they discuss some of the differences between plugins, “engines” (ahem!) and Plugems, and I think they’ve raised some interesting points.

Continue Reading…

Breaking change, and the ups and downs of FileMerge

Posted almost 7 years back at The Hobo Blog

I forgot to mention – there’s a small breaking change in 0.5.3, object_table@skip_fields has been renamed to just skip (that’s the skip_fields attribute of <object_table> using a syntax that just popped into my head). The reason being that you can now use that attribute to skip both fields and associations.

I blame FileMerge - it neglected to remind me about the change. If you’re a Mac user and you’ve not discovered FileMerge (I didn’t know about it for a good while), you’re missing out. Once you’ve installed Xcode you’ll find it in /Developer/Applications/Utilities. It’s a diff/merge tool for both files and whole directory trees and, in a very Mac-like way, it just works. It’s got the most readable display of any such tool I’ve used.

You can also launch it from the command line, where it goes by the name (somewhat strangely) of opendiff.

So I just do something like

opendiff rel_0.5.2 rel_0.5.3

And document all the changes I see in the changelog.

So why was I not reminded of that breaking change? Well, one of the “just work” features of FileMerge is that it automatically ignores .svn directories – very nice. A quick look in preferences shows that there’s a pre-configured list of filename patterns the tool will ignore. And alas, in that list is “tags” (I believe that’s a ctags thing). Sometimes “just works” just doesn’t :-(.

I’ve removed ‘tags’ from that list now of course, but I’ve probably missed changes within Hobo’s tags directory in several chapters of the changelog. I should go back and fix that I guess. Hmm… :-)

And finally, absolutely free of charge, here’s a groovy FileMerge link for you :-)