Archive for the 'Ruby on Rails' Category

RMagick::RVG : outputting an inline image (or the horrid no decode delegate for this image format `' error)

Thursday, March 8th, 2007

Ruby is all nice and all, but some things are just either very poorely documented or just don't work very seamlessly sometimes. I have spend over an hour today trying to identify what is going on with RMagick::RVG not wanting to output an inline image for me.

The error I was getting was:

no decode delegate for this image format `'

And the code was as simple as contents of my brain in the early morning:

Magick::RVG.dpi = 72

rvg = Magick::RVG.new(320, 320).viewbox(0,0,320,320) do |canvas|
canvas.background_fill = 'red'
end

img = rvg.draw

send_data img.to_blob,
:filename => "woohoo.png",
:disposition => 'inline',
:quality => 90,
:type => 'image/png'

Everything seems to be fine and as I'm setting the image type in the to_blog thingy, I somehow assume there should be no problems decoding the image. Well I was wrong! In order to get rid of the bloody no decode delegate for this image format `' you have to specify the image format you want to image to be in, manually.

Behold the magic!

Magick::RVG.dpi = 72

rvg = Magick::RVG.new(320, 320).viewbox(0,0,320,320) do |canvas|
canvas.background_fill = 'red'
end

img = rvg.draw

img.format = "png" #FORGET THIS LINE AND DIE A HORRIBLE DEATH!! :)

send_data rvg.draw.to_blob,
:filename => "woohoo.png",
:disposition => 'inline',
:quality => 90,
:type => 'image/png'

Well.. that's it :) Hopefully it will help someone to save an hour or two ;)

Moving to Rails 1.2.2

Thursday, February 8th, 2007

Well today I have FINALLY moved all my three current Rails projects (the third one is still in development though) to Rails 1.2.2.

There were some quirks I had to resolve during the transition though.

First of all, I have installed the latest version of rails onto the server by typing:

gem install rails –include-dependencies

Then I have updated all of the gems to their latest versions:

gem update

Some changes had to be made to the source code of my Ruby apps:

  • @params and @headers are deprecated now, so I have renamed them to params and headers
  • in environment.rb I have replaced the old RAILS_GEM_VERSION = '1.6' to RAILS_GEM_VERSION = '1.2.2' unless defined? RAILS_GEM_VERSION
  • there was a problem links generated by image_tag / FlexImage's flex_image generated image formatting function not resolved by Rails routing because image_tag attached the ".png" extension (and Rails 1.2 has a stricter checking for filenames in routes, so /image/show/123 was resolved just fine, but /image/show/123.png was getting unknown_action , though it was not a problem with Rails 1.1.6). As a simple solution I have added the following to routes.rb :
    map.connect 'image/:action/:id.:ext', :controller => 'image'
  • I have removed "vendor/plugins/engines", "vendor/plugins/unicode_hacks" as they seem not to be compatible with Rails 1.2 (everything worked fine in development mode, but was giving errors in production)
  • as the last step, I ran "rake rails:update" to update JS libs and stuff to their latest version

Everything works fine nice, and feels a bit snappier even. Cool :)

Another Rails project reaches beta :)

Wednesday, January 31st, 2007

Well finally after 2 weeks of caffeine-powered crazy coding, I have a nice new project running locally on my computer, waiting to be released into the wilderness :)

The project is a full-fledged CMS/blogging system, based on my previous, already released Rails-based skinnable blog system. I have used the same basis (and the basis was multi-user blog system), and have added pages-based CMS system into the mix - so now it is a site with multiple-users blog.

There are several types of pages a user can add to the site, including normal page with editing based on TinyMCE with some custom plugins I have wrote (notably the plugin for easier images uploads). There are also special pages for products categories and products page, as well as special page with handling links to Google maps, implemented in the same way my WordPress Inline Google Maps plugin works. You can also upload different banners for site's front page, as well as all custom pages of the site. There's a ping going to Google when a blog is updated, and Google sitemap, which is generated automatically. Overall, I have a built a system I can be proud of (to a degree :)
Rails definitely rules and I can't imagine even in my happiest dreams to create such feature set in just 2 small weeks (that includes layout coding!).

Now, what is even more exciting (at least for me) is that the system is actually designed to support multiple sites running on different domains, but using the exact same Rails codebase. What I mean is that same servers, same Mongrel clusters will be serving different sites depending on the URL by which a user accesses the system (meaning different content, different design, different everything, without duplicating scripts and clusters!!). Now, that being set, I didn't try to setup the whole multiple-sites system yet - the testing is performed against single site.

If things go well, the site will go online next month. Let's keep fingers crossed though :)

Some pics..

First of all, the site (keep in mind that the design overall is copyrighted, but some images used as placeholders were taken from devianart.com).

untitled.jpguntitled0.jpguntitled-2.jpg

And here are some pics of admin interface.

untitled-5.jpguntitled-4.jpguntitled-3.jpg

Phew..

"Hidden" problems with inheritance in Rails (noob prob? :)

Tuesday, January 23rd, 2007

Yesterday I have discovered a pretty annoying mistake in my own projects design.

As I have wrote previousely (simple caching in Rails) , I had simple front page caching implemented for my site's front page. The caching code was defined in ApplicationController, which in turn was responsible for generating the front page content.

To put it simple, it looked like this:

class ApplicationController < ActionController::Base

caches_action :index
before_filter :index_cache_expirer, :only => [:index]

The code caches (and expires) action named :index. But, there is a may be invisible at first glance, but very big problem with this code.

The problem is that "caches_action :index" directive will propagate to all other pages on the site, effectively making all :index actions in all controllers to cache their content in the same way as the front page.

Even pages which must be avoided to be cached (like /admin area on multiuser sites). Here's a simple example - a multiuser blog with /admin/posts action, showing a list of blog posts for each user, depending on who is logged in. So, say, user "mike" logs in, and watches his posts list (which gets caches, since the caches_action :index gets propagated from ApplicationController to Admin::PostsController). Soon after that, a user "jane" logs into the same admin/posts trying to have a look at her posts list - only to get served a cached page containing lists of posts of user "mike"! The page will expire eventually and "jane" will get her list of posts, but think about the next user - he or she will get Jane's posts list instead, and so on, and so on.

One of the biggest probs is that this scenario doesn't work if you are working in development mode, because caching is only active in production mode by default! So it looks like that - you happily debug your code in development mode, deploy to public server, and the caching problems begin to appear.

Now, I didn't tell why exactly this gets propagated. But that's very easy to notice if you just look at, say, PostsController definition:

class Admin::PostsController < ApplicationController

See how PostsController inherits from ApplicationController, which in turn has caching to action :index implemented? Therefore, PostsController will have the same exact set of functionality as ApplicationController, including caching of its own :index action!

So, the point is - putting too much stuff into ApplicationController is definitely not a good idea, as well as it seems to be now very wise to use ApplicationController to render site's front page (in case this page has alot of custom functionality, caching and stuff like that).

Solution? It's pretty simple, at least for the caching problem I've been having. You just have to make a separate controller for front page only, and define all these front page specific stuff inside of that controller.

So, watch out for the "hidden" inheritance problems. And happy coding :)

Securing your sleep when running Mongrel

Wednesday, January 17th, 2007

Mongrel, which, along with Apache 2.2 & load balancer & mongrel cluster, I run for hosting my Rails site - is a very nice piece of software. But there is a problem. It crashes.

I found about it the hard way - by a phone call at 0:30 in the morning, saying "the server seems to be down". "Doh", I though - and got out of my comfy bad.. Got to my computer, logged in to the server, restarted Mongrel cluster and got back to sleep (you can always check the logs later in the morning, right? :) (more…)

Online finally!

Friday, January 12th, 2007

My first Rails project finally went online today! Imported over 500Mb of blog data from the old blog, set up a simple caching on the front page, and made a prayer ;) Let's see how it will hold up :D

gakuenbbiglogo.gif

Check it out: MediaJapan Gakuen blog

And here's the old version of the blog: old version of Gakuen blog

Simple and fast caching in Rails

Thursday, January 11th, 2007

I've been setting up some Rails caching code today and found a pretty simple and easy way to implement caching for index page which was taking too much time loading due to some pretty expensive DB queries (accesses, polls counts etc etc).

First of all, there is a very nice article on the subject written by Robert Evans - "Rails Caching" - and you can read about the ways to implement caching of pages, actions and also find a link to a very cool cached.rb gem for model-level caching.

The problem in my case was that Robert's approach (and this approach of of course Rails-recommended) for expiring cached actions is to install a cache sweeper, and in my case, index page was using data from several controllers and installing cache sweepers for all of them is needless overkill. What I wanted is just to add time-expiring action_cache for my site's top page's :index action.

So, here's the bits of code I had to add to my ApplicationController (inside application.rb) in order to make it done:

class ApplicationController < ActionController::Base

@@indexLastCached = Time.now #initializing the last-cached timer
before_filter :index_cache_expirer, :only => [:index] #installing cache-expirer action
caches_action :index  #turning on action cache for action :index

#….. controller code and stuff like that ….. #
def index_cache_expirer
if Time.now-@@indexLastCached>60 # expiring index page every 60 seconds
expire_action :action => :index
@@indexLastCached = Time.now
end
end

Well, now, I'm sure there are much better approaches to caching actions with complicated content (tell me about it?), but the above code works just fine for me and dutifully expires cached action every 60 seconds. Thanks to that, my requests-per-second count increased from 0.61 req/sec to value near 36 req/sec. Pretty cool huh?

Rails are ready to go wild, at last

Wednesday, December 27th, 2006

Well it took me almost.. how much.. 3-4 months to learn Ruby on Rails from scratch, to the point when 2 of my Rails-based projects are ready to go wild in January, 2007 :)

And if you want some teasers, here you are

Gakuen blog project

Nagoya Talent Navi project

Both projects a blog-based systems, written from scratch, in Web 2.0 style (where it was necessary, of course), skinnable, using Akismet for blog spam filtering, lots of nice features including TinyMCE text editing (with custom image-upload plugin), very easy to use, and ready to be translated into any language since GetText facility was used to localize them into Japanese. Gakuen blog is actually a renewal of our company's Media Japan Gakuen blog project, so initially it will feature pretty much articles (5000+ articles, 10000+ images, 500+ Megs of data overall). I wonder how our (not very powerful) server will handle the multiple connections in the wild :) Anyways, looking forward for the January, 5th.  I'll post more info then.

In other news, since our company will change the ownership from privately-held company to stock-company, I've got a new name cards today. Well the design sucks I know but oh well I don't have many chances to hand them out to anybody, anyway :D

old one is to the left, new is to the right

Hopefully, after finishing with the forementioned two big projects I'll have some more time to spend blogging (there's pretty lots of things I have learned along the way and would love to share if only I had enough time to spare ;)

Adding :class parameter to link_to_remote in Rails

Monday, November 27th, 2006

Well, this is mostly a note to myself, since I have spend almost half an hour trying to figure how to add class parameter to a link generated by link_to_remote in Rails.

Well here is the code (with all bells and whilstles):

<%= link_to_remote "Vote on it",
{
:url => { :action => 'vote', :id => post_dig.id },
:update => 'thevote',
:before => visual_effect(:opacity, 'thevote', :duration => 0.2, :from => 1.0, :to => 0.1),
:complete => visual_effect(:opacity, 'thevote', :duration => 0.5, :from => 0.1, :to => 1.0)
},
:class => "vote"
%>

This code updates the contents of an element with id='thevote', and adds nice fade-out/in during the update. Most important that it also adds class "vote" to the generated link so it can be used for a nice CSS rollover.

ROR-style Flash alerts in PHP

Monday, June 12th, 2006

Although I didn't get to use Ruby on Rails in my job due to various factors I had to consider, I took some interesting concepts for the framework, namely the ROR-style flash alerts. These alerts are stored in cookies and are transferred between pages even on redirects. Pretty cool idea, so I wrote a replicate for this functionality in PHP.

Demo and the source code can be viewed here

Have fun :)