Showing posts with label Ruby and Rails. Show all posts
Showing posts with label Ruby and Rails. Show all posts

Monday, April 4, 2011

Making Tags With Rails And RightJS

As the tags widget appeared recently on the RightJS UI list, I'd like to write a simple how-to about tags in case of using RubyOnRails.

You can see the tags widget in action on this demo page, and over here you can find a demo rails application that has the tags feature implemented, along with some other right-rails features.

Let's start

The Initial Model

When you need to add a tags feature in a ruby-on-rails project, a standard model would look kinda like that

class Article < ActiveRecord::Base
has_and_belongs_to_many :tags, :uniq => true
end

class Tag < ActiveRecord::Base
has_and_belongs_to_many :articles, :uniq => true

validates_presence_of :name
validates_uniqueness_of :name
end

As you can see, it's a pretty much straightforward m2m association, articles have many tags and tags have many articles.


Tags To Strings Conversion

The next standard step is usually to add a couple of methods to convert the list of tags into a coma separated string back and forth. The basic reason is that tags are data-base records and it's not much of user-friendly to use integer ids

class Article < ActiveRecord::Base
has_and_belong_to_many :tags, :uniq => true

def tags_string
tags.map(&:name).join(', ')
end

def tags_string=(string)
self.tags = string.split(',').map do |tag|
unless tag.blank?
Tag.find_or_create_by_name(tag.strip)
end
end.compact
end
end

After that you can use this proxy property in forms directly, like that

<%= form_for @article do |f| %>
<p>
<%= f.label :tags_string %>
<%= f.text_field :tags_string %>
</p>
<% end %>

This way the user will always manipulate the tags list as a simple string and your app will automatically create the tag records and associations on fly


Hooking Up RightJS

At this point your rails app will present a kind of a standard and simple case of tags handling. Time to make it look nice and friendly with a bit of javascript.

To hook up RightJS into your Rails application all you need is just add the right-rails gem into your Gemfile

gem 'right-rails'

And run the following code generator

rails g right_rails

Don't worry when you see a tall list of scripts it copies into your public/javascripts directory, right-rails handles most of them automatically, so you won't really need to look inside of those.


Adding The Tags Widget

Ironically, the actual RightJS part of this enterprise is the shortest one. Once you added right-rails into your application, all you need to do is replace 'f.text_field' with 'f.tags_field' in your form

<%= form_for @article do |f| %>
<p>
<%= f.label :tags_string %>
<%= f.tags_field :tags_string %>
</p>
<% end %>

RightRails handles everything else automatically, it generates all necessary html, includes javascript/css modules, it even switches between minified and source builds of javascript libraries depending on the working environment.

More of that, it can automatically use the google hosted rightjs cdn-server for a superfast, shared scripts delivery.


Adding Autocompletion

By default the f.tags_field will make you a pretty looking tags-field, if you want to add the tags autocompletion feature to it, all you need is to specify a list of known tags in it

....
<%= f.tags_field :tags_string, :tags => Tag.all.map(&:name) %>
....


There is also a few additional options you can use with tags widgets, you can find them at the rightjs.org documentation


Conclusion

This is a good example to show how RightJS is build with server-side developers in mind. As you have noticed we didn't write a single line of javascript in our little exercise, not like we couldn't, just we don't have to bother with those routine things every time we need a simple form with a bunch of standard widgets.

More of that, if you take a look into your HTML code, you'll see that RightRails didn't write a single line of script either, all it did is added the data-tags attribute to your input field.

<input data-tags="{tags: ['one','two','three'}" value="one, two"
id="article_tags_string" name="article[tags_string]" />

This way, even if something will go wrong, the user will still see the standard input field with coma separated tags. All your styles and content will remain were it was.


--
Well, this is pretty much the whole story. If you're interested, go check the RightJS UI collection, it has many more useful widgets that you can use in your applications.

Tuesday, March 15, 2011

Ruby + Gosu = Fun

Gosu is a nice simple 2D games engine for Ruby, which I used to work on this little game called pentix.rb. And I'd like to put in some good words for the folks who maintain the project.

What's particularly cool about Gosu is that it doesn't try to jump over its head and do everything by themselves. Gosu is a very small framework specifically made for 2D games, it will help you make things like windows, handle graphics, fonts, sounds and some basic animations. But it also easily integrates with Chipmunk to handle physics and with ImageMagic/OpenGL modules if you need some seriously looking graphics.

If you think about it, Gosu is a very cool thing, you leave all the rendering and heavy stuff to the native modules and use Ruby for what it's good for, for describing logic, units, interactions and so on. And Gosu does it right, it doesn't force you to inherit it's classes all the time, quite on contrary actually. Gosu itself has just a few basic classes to handle media things, like fonts and images, and for the actual units you can write plain Ruby classes, which certainly makes it much easier to implement, test and maintain.

And one more thing. Gosu is not just a Ruby toy. It also has all the C++ bindings, which kinda makes it a pretty interesting choice. You can use the power of Ruby to prototype and do all the R&D things. And later, if you actually make it to the investors, it will be relatively simple for you to port everything to C++ and make it running anywhere. Yup, iPhone is on the list :)

This is basically it. If you ever wanted to write some simple 2D games, but didn't want to deal with C++ check out Gosu, it's pretty awesome!

UPD: Check out also this simple ruby tutorial they have

Saturday, October 2, 2010

Making Pretty CLI Applications In Ruby

Sometimes we need to process large amount of data in Ruby, convert things from one format to another, process a large database, etc. And when you start implementing those things as rake tasks or something like that you need some feedback, say to see the progress and so one. Normally people would use puts

index = 0
count = things.size
things.each do |thing|
do_something_about thing

puts "#{index +=1} of #{count}"
end

But when you have several thousands or millions things to process this approach doesn't work, because it will just blow into the console, which is ugly and well... there are ways to do it much better, prettier and more professionally looking.

There are gems and libs that will help you to do it properly, but in this article I'd like to show how it actually works internally.


Strings Rewriting

One of the first things you might want to learn in order to make seriously looking CLI app is how to rewrite strings all over. It is a bit tricky in Ruby so here how it looks like. First of all you need to learn the "\r" symbol, which is called "caret return" and well it returns the caret. A simple example will demonstrate. Say you have a line of code like that

puts "one\ranother"

when you run it, you will see in the console a string like "another" and what's happening is that ruby will print "one" then return the caret and print "another" over it, so that you see the last one only. But the trouble is that if you'll write something like that

puts "one"
puts "\ranother"

It won't work and you'll see two strings in the console "one" and "another", and because of that if you'll put into your loop something like that

puts "\r#{index += 1} of #{count}"

it won't work either and you will see the same ugly roll of strings. To make it working you have to use the a combination of the print and STDOUT.flush calls, kida like that

8.times do |i|
print "\r#{i}"
STDOUT.flush
sleep 0.1
end

In this case it will print a string and stay on it. STDOUT.flush dumps the current stdout into the console, and on the next iteration, it will normally go to the beginning of the string and write it over as you needed.

But it is still not everything. If you run a piece of code like this one

%w{looooong short}.each do |str|
print "\r#{str}"
STDOUT.flush
sleep 0.5
end

You will see that on the second iteration, the previous line won't be entirely overwritten and instead of "short" you will see "shortong", to make it work properly you need to write a long enough string that contains spaces at the end, for example

%w{looooong short}.each do |str|
print "\r#{str.ljust(80)}"
STDOUT.flush
sleep 0.5
end

String#ljust makes a string of the given length by filling the remaining places with spaces. This way you will always overwrite 80 symbols of the line in the console.

To wrap it up nicely you might create a simple function and your loop will look like that

def print_r(text, size=80)
print "\r#{text.ljust(size)}"
STDOUT.flush
end

index = 0
count = things.size
things.each do |thing|
do_something_about thing

print_r "#{index +=1} of #{count}"
end
puts "\n" # <- a final new line



Displaying the progress

With the trick above you will be able to show a constantly updating status line, but there are still some meat on this bone. Showing the user things like "345 of 87654" is not particularly user friendly, because it might be a bit annoying to calculate the actual progress in your head all the time. Would be nice to show the progress in percents as well. Happily it is very simple to do using placeholders

print_r(
"%d of %d (%d%%)" %
[index+=1, count, (index.to_f/count * 100)]
)

The other usual problem with status reports is that you might have particularly large set of things, say several millions of them and your script might process several thousands of them per second. In this case hitting your console several thousands times per second will seriously slow the process down, so you might need a way to skip some steps and print reports in some periods of time. You can do that the following way

index = 0
count = things.size
step = count / 1000 # 1/10th of a percent

things.each do |thing|
if (index += 1) % step == 0
print_r "....."
end
end

As you can see we defined the step variable and then skip all the non-round iterations. In this particular case it will make the script to update the report every 1/10th of a percent of the job done. Which is in most cases is not a big drawback and still provides the user with progress updates.

You also might think of ETA calculations, but you probably can figure it out on your own now, it's very simple.


Add Some Colors

And the last thing I'd like to show is how to make colors in the console, which might make your application look even cooler. Some developers already know how to do that, but some don't. So here it is.

Basically it is very simple and in some ways similar to HTML tags. You use things called escape sequences which are just some markers like tags, you have an opening one, and you have a closing one, like that

puts "\e[32mGREEN TEXT\e[0m"
puts "\e[31mRED TEXT\e[0m"
puts "\e[36mBLUE TEXT\e[0m"

As you can see, the closing sequence is always the same and the opening one differs only by a number, and this number is basically describes the properties of the following text. It might be a color, or a blinking effect, you can nest them just like normal HTML tags and so one. You can find full list of options on wikipedia

The only trouble with those things is that the format of escape sequences differs from a platform to platform. The example above is for OSX terminal. How to make those things working in DOS and Linux you can find that on the same wikipedia page.


This is about it. Now go and make the world prettier!

Thursday, September 23, 2010

Easy Way Out of The STI Hell

I like the idea of STI (single table inheritance), it is cheap, dodgy but it works and allows you to play with all sorts of sub-types in a civilized way. For example you can redefine things in subclasses, use strategies and so one.

But when you try STI with Rails, you immediately fall into the polymorphic routes hell. Because you have new types, Rails tries to find routes for them, and it doesn't want to use the base model as a fallback. And here, people start to do all kinds of things (I did), define controller level helpers, generators, modules and so one. But then, someone adds a new custom method or a new subtype and it all falls down like a house of cards.

Well, you know what they say, the exit from a hell lays at the very bottom of it. And in Rails it will be routes. Say I want to handle all sorts of User model subclasses, like User::Admin, User::Manager, User::Blocked.

Trololo::Application.routes.draw do
# here I collect all the User subtypes
user_types = Dir["#{Rails.root}/app/models/user/*.rb"].map do |name|
"user_" + File.basename(name).gsub('.rb', '').pluralize
end

# and then I put all of them one by one
(['users'] + user_types).each do |name|
resources name, :controller => 'users', :path => '/users' do
member do
get 'stats'
end

resources :comments # we can define nested resources too
end
end
end

I use the Rails 3 notation in this case, but I suppose you can figure how to make it work under Rails 2 as well.

It is still a bit dodgy, but it is better and more stable than defining those type-specific routes manually in controllers, you also can automatically handle all the nested routes as well.

That's it, hope that will help

Tuesday, May 18, 2010

Automatic Records Search in Rails

There is one neat trick I'd like to share. In many cases, especially when you work on intranet applications, you need say to check some security settings against the data-records before you let the request to access the actual method in your controller. Normally, most folks do that by adding before filters to find the records, like that

before_filter :find_this
before_filter :find_that

def find_this
def find_that

When your application grows and starts having something like a dozen models, plus you might have nested routes where you need to check the security against the nested elements too, those things tend to get really messy.

So here is a simple method which I use on my projects

before_filter :find_restful_units
def find_restful_units
params.each do |key, value|
if key == 'id' || key.ends_with?('_id')
unit_name = key == 'id' ? controller_name.singularize : key.gsub('_id', '')
unit_class = Object.const_get(unit_name.camelize)
instance_variable_set("@#{unit_name}", unit_class.find(params[key]))
end
end

rescue NameError # just hung up if there is no such unit
nil
end

You put this in your ApplicationController and it will automatically find and assign all your models, the actual and the nested ones.

This makes controllers much cleaner and you always have your models extracted and ready to use in the standard way.

Monday, March 29, 2010

RightJS + Rails = Love

As the right-rails (the Ruby On Rails plugin for RightJS) was updated recently, lets have another brainwashing session. This time for Rails people.

If you're a kind of a pragmatic developer, you're probably asking yourself "why would I fall in love with this new thing? I already know Prototype and jQuery why would I need something else?", and believe me, I know precisely what you mean.

But ask yourself, being a Rails developer, were you ever happy of doing AJAX features in Rails? No, I mean, not like first two weeks on rails, or things like "it's working". I mean really happy, did you feel funny about Prototype or jQuery? Did they make the butterflies in your stomach fly? Literally.

Think about it. The Prototype support on Rails was always a kind of a flimsy hack and most serious developers don't really use those RJS stuff. And with jQuery you were always left alone to deal with all those kinky JavaScript stuff. That's good if you are a JavaScript guru and know your magic. But what if you are not, and what about the actual Rails business anyway? Did any of the frameworks really helped you in any way to be an actual Ruby/Rails developer?


How Is RightJS Different?

First and most important thing you should know about RightJS is that it was written by a Ruby/Rails developer for Ruby/Rails developers. And despite the fact that from time to time we have all those arrogant promotions and we mock jQuery folks constantly. RightJS is not really about JavaScript itself. It is something quite opposite.

RightJS is all about getting JavaScript off your hair. RightJS is made to help Ruby developers to deal with JavaScript tasks, it reflects Ruby way of handling things, has mostly Ruby syntax and many of its key features are copies of Rails features.

RightJS civilizes JavaScript and brings it closer to Ruby developers.

But we didn't came here to talk about JavaScript, right? What about Rails itself?


Lets Make The Butter Fly

How much time does it take to make a date-time field with a calendar in your framework?

Let me spare you the calculations time and show how it looks like in RightJS + RightRails.

<% form_for(@zing) do |f| %>

<%= f.calendar_field :dead_line %>

<% end %>

Nope. I didn't forget nothing. `calendar_field` is all what it takes. RightRails automatically includes all necessary JavaScript, CSS and I18n modules on your page and initializes the fields, so you don't need to worry about a thing.

More of that, it will automatically swap between builds and source code for JavaScript in production and development modes.

So, would you like some rater or slider on your form?

<%= f.rater_field :rating %>
<%= f.slider_field :completeness %>

Oh, I know! You'd like some autocompleter, right?

<%= f.autocomplete_field :category, :url => categories_path %>

Would you like the autocompleter to be RESTful design and hard-caching friendly? No problem!

<%= f.autocomplete_field :category, :url => "/categories/%{search}.js" %>

Here you go.


And That's Not All

The fun is not over, not by a long shot. The next feature is that RightRails comes with a brand new RJS generator, and that's not just a collection of dummy functions like in the case of the Rails original RJS templates.

The new generator lets you literally write JavaScript in Ruby and more of that it allows you to mix Ruby and JavaScript calls in one flow escaping and transforming variables on fly.

For example this is how the annoying nested forms look like when you make them with RightRails.

<% form_for(@zing) do |f| >

<div id="categories">
<%= render @zing.categories %>
</div>

<%= link_to_function 'add' {|page|
page[:categories].insert(render(Category.new))
} %>

<% end %>

See, the `insert` method is a JavaScript function, the `render` is the ActiveView method, `Category` is your model. All in one flow with automatic types conversion. And it is not just a list of predefined functions, you can literally do whatever you want.

update_page do |page|
page[:todos].update render(@todos)

page[:todos_count].innerHTML = @todos.size + ' Items'

page[:todos].select('li').each do |item|
item.onClick('toggleClass', 'marked')
end

page.json_variable = @todos.to_json
page.items_count = @todos.size
page.list_updated = true

page.alert "There are #{@todos.size} items left on the list"
end

There are no limiatations.

Mommy Look, More Fancy Stuff!

Oh yes mommy, there are! On top of all RightRails has a conventional interface to cover the most common AJAX CRUD operations. Let me show you.

Say here's your remote form

<% remote_form_for(@zing) do |f| %>

<%= f.text_field :name %>
<%= f.file_field :picture %>

<%= f.submit 'Create' %>
<%= image_tag 'spinner.gif', :class => :spinner %>

<% end %>

And here is your controller method

dev create
@zing = Zing.new(params[:zing])
if @zing.save
render rjs.insert(@zing)
else
render rjs.replace_form_for(@zing)
end
end

The `rjs` method provides access to the new RJS generator from the controllers, and `insert` and `replace_form_for` are the AJAX operations interface.

It all works over the Rails conventions, the `insert` method looks for the class of the `@zing` model, finds related partial, renders it and generates a piece of JavaScript that inserts the HTML into an element with the `zings` ID.

The `replace_form_for` method will render a new form with all the error messages for the @zing model and generate JavaScript that will update the form on the page.

RightRails has a collection of such methods for all CRUD operations.

Note also that I've put a file field and a spinner image on the form. RightRails automatically and transparently processes files uploading too, basically there is no difference whether your form has files or not, it all has the same API. And the RightJS when submits a form via AJAX, automatically searches for images with the `spinner` class and uses them as spinners, you don't need to hook them up with callbacks manually.

Summary

I'm not going to indulge you with obvious conclusions, I'll just tell you that I've already used RightJS + RightRails on two production projects and it saved me hell of a lot of time and nerves on JavaScript and AJAX development.

Well, it was designed to.

Saturday, March 27, 2010

Supervisor Mode With Authlogic

Supervisor mode is a feature that allows site admins to quickly switch to any other user (say customers) and take a look at the site the same way the customers see it, may be perform some actions from this user, etc.

So here is a simple tip how you do that using the Authlogic plugin for Rails.

First of all you'll need couple new routes, one to switch to some user, another to get back to the admin mode.

map.super_login '/login/:id', :controller => 'user_sessions', :action => 'super'
map.back_login '/login/back', :controller => 'user_sessions', :action => 'back'

I used two new methods named 'super' and 'back', which are not exactly RESTful, but you can use 'edit' and 'update' if feel particularly evil about it. They are normally not used in the 'user_sessions' controller.

After that on the list of customers you add links to switch under this user, for example like that

....
%td= link_to 'Supervision', super_login(user)
....

And finally you'll need those two methods in your `UserSessions` controller

class UserSessions
.....
# switches under this user
def super
raise AccessDenied if !admin?
session[:original_admin_id] = @current_user_session.user.id
@current_user_session = UserSession.create(User.find(params[:id]))
redirect_to '/'
end

# switches back to the admin -mode
def back
raise AccessDenied unless @current_user_session && session[:original_admin_id]
@current_user_session = UserSession.create(User.find(session[:original_admin_id])
session[:original_admin_id] = nil
redirect_to '/'
end
.....
end

The idea is simple, in the first method you stash the original user_id in a session variable, then create new user session with that specific user. And in the second one we restore the original user in the session.

You also might consider to add two methods like `current_user` and `current_user=` in your application controller they are pretty useful and will make your code cleaner.

class ApplicationController
...
# returns the currently logged in user
def current_user
@current_user_session.user if @current_user_session
end

# assigns the currently logged in user
def current_user=(user)
@current_user_session = UserSession.create(user)
end
...
end


That's all. Have fun!

Friday, March 5, 2010

Mechanize and MultiSelect fields

Mechanize is a little handy tool that allows you to perform all sorts of HTTP requests in Ruby. It automatically emulates all sorts of browsers, handles cookies, headers and stuff, which is really useful when you need to harvest some data from sites that don't have any computer friendly feeds.

I'm using it on my current project and run into a small problem. It doesn't work nicely with array data, like for example multiselect fields emulation, so when you do something like that

agent = Mechanize.new

agent.post('http://boo.boo/boo', {
'param[]' => ['one', 'two', 'three']
});

In the reality it sends the 'one' value only. I've sent a little patch to the devs, but it seems like it will take time before they do something about it. So here is how you fix it in your rails app.

In any initializers in your `config/initializers/` directory add the following lines.

class Mechanize::Form::Field
def query_value
if @value.is_a?(Array)
@value.collect{ |v| [@name, v || '']}
else
[[@name, @value || '']]
end
end
end

After that it will be just fine.

Sunday, December 27, 2009

Making a gem out of your ruby-on-rails plugin

Generally, now, when we have the gemcutter service, making a gem is not a brainer. Just find a similar project on github, copypaste its gemspec, then say gem build my.gemspec and gem push my.gem and you're basically done.

But there are some options you might want to know about.

First of all to that gemspec business, as I said, if you never did that before, you'd better just find a famous plugin on github that is more or less close to your project, copy its spec in a file named my-plugin.gemspec in the root of your plugin and fill it up with descriptions of your project.

You might find the gemspec option descriptions here and here. For example if you need to show the user some post install message, use the post_install_message option like that

spec.post_install_message = %Q{
Warning! Warning! Annoying message!
}

And one more, some gemspecs on github use plain lists of files that should go into the spec, sometimes with several dozens of entries. Don't do that. First of all, it will be pain in the ass for you, because you might just forget to update the list when you create a new file, second of all it will be pain for another people who might be interested in evolving your project. Ruby is a nice language and has everything you need to process those stuff automatically. For example like that

spec.files = Dir['lib/**/*'] + Dir['spec/**/*'] + %w{
README
LICENSE
CHANGELOG
}

For the second thing, you need to understand how rails hooks up plugins and gems.

When you create a ruby-on-rails plugin there is a file called init.rb in the plugin directory. When rails fires up, it adds your plugin lib/ directory to the load-path and then includes this init.rb file. Basically that's a good idea, you can keep the actual code clean in one place, and the dirty monkey patching script in another. This way you can test them separately and use separately, like say you want your module be available as is, outside of the rails stack, say with Rack apps or something.

But when it comes to a gem, it's a bit different story. Gem supposed to be just a standalone piece of code which you require from your application. It doesn't know anything about initialization, and when ruby-on-rails hooks it up, it just requires a file with the same name as the rubygem.

Say you have a plugin named super_duper then you will have a file lib/super_duper.rb, which rails will include when the gem is specified in the config. So, if you want to convert your plugin into a gem, you basically have two options. Include your init script into the super_duper.rb file, probably with some additional dirty conditions, or create another file like lib/super_duper_lib.rb and make your user define the gem in rails config like that

conf.gem 'super_duper', :lib => 'super_duper_lib'

Both are quite dirty and yet pretty common.

But, there is another, nicer option that lets you avoid disadvantages of those two approaches.

The trick is simple. All you need is to name your ruby-gem in a dashed style. Like say you have a plugin super_duper, so you create a ruby-gem named super-duper, after that you just create a file named lib/super-duper.rb with one simple line of code in it

require File.dirname(__FILE__) + '/../init.rb'

When ruby-on-rails hooks up the gem it will load the dashed file, which will load your init script. This way you can share your initialization script between plugin and gem, and you still keep your actual code clean and easily available outside of the rails stack with the standard require 'super_duper' call.

Sunday, December 13, 2009

FrontCompiler With Rubygem And Console Tool

FrontCompiler is a Ruby based JavaScript/CSS/HTML compressing tool of mine. It can create albeit packed JavaScript, works with DRYed CSS, can inline css in javascript, works as a Rails plugin, etc.

And as I use it quite a lot on my projects, finally, I've created a rubygem for it. It's available at the gemcutter service now.

http://gemcutter.org/gems/front-compiler

So if you use the project, you might just install it from there.

gem sources -a http://gemcutter.org
gem install front-compiler

Along with the rubygem I've added a simple console tool to work with the compressor

$ frontcc file1.js file2.js ....

It will automatically recognize the file type by its extension, so you can feed it with javascript or css or html. It will read them all, compress in a single string and spit it in the stdout. You also can mix javascript and css in one command to make the css be inlined in javascript.

Enjoy!

Friday, November 20, 2009

RightRails The RubyOnRails Plugin For RightJS

In case you don't know, some time ago I started a ruby-on-rails plugin for RightJS called right-rails, which was just updated to the next version 0.3.0

There are actually quite a lot of interesting and fancy stuff going on and it tries to solve many of usual headache of ajax applications development.

Like say it transparently handling files uploading for remote forms, so that there is no difference if you have or have no files on your form. Plus there is a simple javascript interface for the most common ajax operations which is super easy in use.

Then there is a new much more powerful RJS scripting replacement, that allows you write javascript in ruby and more of that mix in one flow the serverside and browserside contexts, it has automatic types conversion and lots of other things.

Then small things like transparent Prototype/Scriptaculous helpers replacement for RightJS, plus various helpers for the RightJS own features and modules, plus automatic scripts including handler, etc. etc.

If you like RightJS and do ajax stuff in rails, check it out, you'll find many helpful stuff.

Saturday, September 19, 2009

Ajax Files Uploading With RightJS And Rails

I kinda stuck with the RightJS project for now and mostly write articles for the site.

But there is another interesting articles that lights up some details over the remote forms with files handling using Ruby on Rails and RightJS. There is also a link to a complete ajax photo gallery application that uses the featues.

Please take a look it is over here. I'm sure you might find some interesting stuff over there.

Thursday, August 13, 2009

FrontCompiler Updates

FrontCompiler is a Ruby based JavaScript compression tool of mine. And I've just updated the self-builds feature of it.

Formerly it used a literal based hashes and special markers, and I've reworked it the way it used numbers and arrays, similarly how the Base62 encryption algorithm works.

Anyway. Now both, compression and decompression processes work faster, and the result builds are slightly (3-8%) smaller.

This is pretty much it. Enjoy!

Thursday, July 23, 2009

Transparent Dates and Times Internationalization in Rails

The basic internationalization approach in Ruby on Rails supposes that you translate the dates and times like that

Created at: <%= I18n.localize @model.created_at, :format => :short %>

But most of us use the "to_s" method to format times, like that

Created at: <%= @model.created_at.to_s :short %>

Mostly because you usually don't think much about i18n when a project is just starting up, and then it's kinda sweet, nice and short way of doing that.

So, usually when it comes to the internationalization, the project is already pretty much covered with the to_s methods. If you were lucky you might had created a single helper method which processes all the dates and times in your project and then it's simple, but if you didn't you might think about highjacking the "to_s" method of the Time class. Like that.

class Time
def to_s(format=:default)
I18n.localize self, :format => format
end
end

But if you do so, you will probably broke the things. Because first of all the "to_s" method supposed to work like an alias for the "strftime" method, secondly this method is used to convert times and dates in the :db format and if it was not translated properly it will break your models, thirdly it's naughty when you completely replace such a method.

Okay here is a better way of doing that

[Date, Time, ActiveSupport::TimeWithZone].each do |klass|
klass.instance_eval do
define_method :to_s_with_i18n do |*args|
format = args.first || :default
if format.is_a?(Symbol) && format != :db
I18n.localize(self, :format => format)
else
to_s_without_i18n(*args)
end
end
alias_method_chain :to_s, :i18n
end
end

It keeps the original method and doesn't touch the custom and database formats. The ActiveSupport::TimeWithZone class is the Rails class for the UTC times you need to process it too.

Monday, July 20, 2009

Inline IE hacks with SASS

SASS is a nested css engine written in ruby. It's a pretty powerful and handy tool with lots of features inside, http://sass-lang.com

I'm using it on my current project and find it quite useful. The only thing which was bugging me is that I tend to use inline IE hacks in my css, like that

div.box {
cursor: pointer;
* cursor: hand;
}

And it seems like sass doesn't support such a feature, at least I haven't found it in their documentation.

But in reality it does actually has support of the feature, just it is not documented. It looks like that

#my-block
:cursor pointer
*cursor: pointer

Note, there should be no space betwen '*' sign and the property name

Friday, July 17, 2009

Customizing The Rails Forms Builder

The word "customer", usually means someone who come and say "I wanna custom stuff". And because it is their nature they do it all the time. Sometimes several times a day.

I'm skipping here the obvious question "why would I need to customize a forms builder?" and get straight to the point.

So you need to customize your forms. Big time. And if the first what comes on your mind are helper methods and partial templates, this article is for you.

And please don't think about monkey patching rails form-builder. Don't behave like a php developer thinking he can use rails. Lord save their poor souls.

There are better way of doing that.

First of all you should realize that in 99.99% of cases you should not change the default rails templates. Meaningly that

<% form_for(@model) do |f| -%>
<%= f.error_messages %>
<p>
<%= f.label :name %>
<%= f.text_field :name %>
</p>
<% end -%>

Despite that it is a simple structure, with a little bit of imagination and css magic you can make it look like anything you need.

Secondly you really should pay a dollar of penalty every time you think about monkey patching. Ruby is not just a monkey patching language it is object oriented too, and rails form builder is a quite well organized structure.

Instead of patching, we will create our own form-builder using advantages of the inheritance and then swap the default builder from the built-in to our own one. This way we can change the logic of the forms building transparently for the templates, you even can have several form-builders which behave differently and swap them depend on the context.

The basic example would look like this. You create another helper module called FormsHelper and save it along with the other helpers in your application

module FormsHelper
def self.included(base)
ActionView::Base.default_form_builder = CustomFormBuilder
end

class CustomFormBuilder < ActionView::Helpers::FormBuilder
# your custom methods go here
end
end

Inside the class you will have access to the form builder context with all its built in methods and variables. For the beginning you should know about the following ones

  • @template - the template context, you call this variable if you need to call the basic helpers

  • @object - the current model of the form

  • @object_name - the string name under which the form knows the model


Okay now lets play with the thing a little. Say the customer says "don't like the <h2> header on the error reports, the one with the number of errors on the form". No problem, we just override the built in method

def error_messages(options={})
super options.reverse_merge(:header_message => nil)
end

Then say you as many other developers usually put your forms in a partial and then depends on the model state change the submit button caption. something like this

form_for(@model) do |f|
f.submit @model.new_record? ? "Create" : "Save"

This is a little bit annoying. Say I'd like just call it <:%= f.submit %> and want the form automatically set the caption. Here is the code

def submit(caption=nil, options={})
super(caption || @object.new_record? ? "Create" : "Save"), options
end

Then I got completely lazy and started to want my form builder to build a block of label + text-field in a single call, like this

form_for(@model) do |f|
f.labeled_text_field :name

# this should build the thing like that
<p>
<%= f.label :name %>
<%= f.text_field :name %>
</p>

# you could do it like this
def labeled_text_field(name, options={})
@template.content_tag(:p, label(name) + text_field(name, options))
end

Then, all the sudden, your customer comes back and says a scary thing "I like this, but I want for this particular controller, there actually was the h2 header saying 'Oh noooo!'. Yes, just for this special case".

No, my friend we are not going to the monkey patchers hell! We just define another form-builder over our own builder, and automatically swap it in the particular controller

class SpecialFormBuilder < CustomFormBuilder
def error_messages(options={})
super options.reverse_merge(:header_message => "Oh noooo!")
end
end

class ParticularController < ApplicationController
before_filter :swap_form_builder

def swap_form_builder
ActionView::Base.default_form_builder = SpecialFormBuilder
end
end

Think you understand the idea. If you do the things in a serious way, lord will love you and grand you a big deal of flexibility and rapidness.

This is pretty much it. Have a good one!

Saturday, June 20, 2009

How Not To Create Rails Plugin

Another day I needed to handle some task which included communication with a SPARQL service. Quick google search gave me a reference to the ActiveRDF project, which claims to be the thing for ruby and rails.

But the thing is that the darn thing ain't work. As the matter of fact, you won't be able even run the example from the official site. I'm not complying, used the python sparql-wrapper to accomplish the task, but this project is a good example how you should not create a Rails plugin.

And here some tips and lessons you can learn out of it.

1. Location and Versioning Control System

The project was started at the https://launchpad.net service, under the bazaar versioning control system. That's probably a progressive thinking, but still a big mistake.

All the Rails crowd currently, more or less lives on git and github. The reason is obvious, all the people in one place, it is easy to participate in the projects using quick forking and merging. No need to register and set up your account. You do it once and have them all.

I had some experience with launchpad, it's a pretty good system, and if I would start some specific project for Ubuntu, I would probably thought about launchpad, but for Rails related project, if you want the people to participate you should go to github.

2. Implementation

The implementation as well a good example how not to write ruby code.

First of all when you creating an actual plugin or gem, global classes is the last thing which you should do. There should be the only one global name and this is the name of your project. All the rest of the things should be under the namespace.

The second is the API and what the users need to write in order to make it working in their application. With such a beautiful and powerful language as Ruby is, it is quite a shame to make people call the factory method directly. None of the actual rails part do that. There so much opportunities for all the meta-programming magic and you end up calling classes creation manually.

They should do it simultaneously to the existing things, like ActiveRecord or ActiveResource. As the matter of fact they probably should not start a standalone project in the first place and create some extension for the ActiveRecource project, they might make it to the rails codebase and that's huge. Much better than having another rails plugin.

But anyway, with a badly structured project, even if someone would like to participate and help it, that would be really hard and usually almost impossible to change anything, because there are already people who use the project as is, and people don't like to update their application code.


3. Support

I don't think I should mention such basic things, that when you have year and a half old bugs in your bug-tracker, even bugs where people already posted solutions and patches and you still didn't fix the problem, that's quite suck. As well as I should not mention such simple thing like keeping your code actually working, at least with the examples you have got on the front page.

The thing is that despite the fact that you are creating an open-source project and by the license you are not responsible for anything, you actually creating a project for people. Yes I know 90% of OOS just show-off projects by rookies just out of the university. But if you want the people to take you seriously you should support your projects.

Even if you don't want to work on the project anymore and there are no one else, you probably should say something, like "sorry guys the thing didn't fly and I have better things to do". Yes that suck, but that's understandable, and responsible.

If you didn't do that, people will still come and kill their time with your buggy code and will be left pretty much alone. You should warn your customers about such things, because everyone has different situations, someone probably would be happy to spend some hours to make a dead thing walking, but someone might be on a deadline and would expect your project actually working and probably would switch to something else if was warned.


The End

So the thing is simple. Bad location, bad implementation and bad support. This is more than enough to kill almost any project in any area. Think about it when you start your own.

Tuesday, June 9, 2009

Integers To Binary Or Hex Conversion In Ruby

There are some tips on how you convert integers to binary or hex numbers forth and backwards.

irb(main):019:0> 30.to_s(2)
=> "11110"
irb(main):020:0> 30.to_s(10)
=> "30"
irb(main):021:0> 30.to_s(16)
=> "1e"

irb(main):027:0> '11110'.to_i(2)
=> 30
irb(main):028:0> '30'.to_i(10)
=> 30
irb(main):029:0> '1e'.to_i(16)
=> 30

Saturday, November 22, 2008

Mommy Look, new Plugin!

I've launched new simple plugin for Rails/ActiveRecord.

This one extends the belongs_to associations between models and allows you to assign related units by one (or several) fields for the model. Say you have got a message which belongs to a user, and you would like to assign the user to the message by his login name. That's our case. Use the plugin and everything will be fine! 8)

http://github.com/MadRabbit/assign_by/tree/master

Thursday, November 6, 2008

SearchableBy, the ActiveRecord plugin

I've created some simple plugin for Rails/ActiveRecord, which you can use for search methods definitions.

It is a simple stuff which just creates some named_scopes which you case use as various search methods.

Take a look at the README file at the repository http://github.com/MadRabbit/searchable_by there are some examples.