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.

Tuesday, March 2, 2010

My Top 5 on that RightJS vs. jQuery Question

During the last several months of RightJS promotion, the absolute hit among the questions of 'what?' and 'why?' was understandable the question of what is the difference between RightJS and jQuery.

There were lots of talks about RightJS speed and then more about speed, and then we had some abstract talks about its philosophy and its way among the others and we also have that simple comparison page.

And what I find important in a brainwashing process is systematicness and methodicalness. We did some talks on an abstract matter, we did some talks on the opposite side of scale with performance tests, now lets touch something real. Something in the middle. And probably summarize some previous talks.

So here it is, your next session; my top 5 as I see it at this morning.


1. Syntax

When I'm saying "jQuery is like PHP", first of all I mean the nature of its syntax. When you boil it down to the essence, both of them are just collections of helper functions. And as PHP defines a new kinda language upon C, almost the same way jQuery defines a new language upon JavaScript.

RightJS on the other hand is built right into JavaScript itself. In 90% it is the good old JavaScript, where we bring features from later JavaScript specifications and spice it with some standard features from more serious dynamic languages like Ruby and Python.

As the result, when you learn jQuery, you mostly learn jQuery, I've seen many nice fellas around, who know jQuery quite well, but stuck when they needed to do simplest things in pure JavaScript.

When you learn RightJS, you learn the actual JavaScript, yes we have some funny shortcuts and features that make mature web-developers happily giggling like school girls, but all of them are built upon JavaScript standards.

RightJS makes you do the things in JavaScript and do them right. And because of that, whatever the future brings, your knowledge and skills will remain with you.


2. The Actual STL

When I read someone saying "jQuery is the JavaScript STL", it usually makes me laughing so much, that my neighbors probably think that I've finally went nuts and going to blow off the Kremlin.

Now, don't get me wrong, I have no problems with jQuery's popularity and I respect that. Well, at least, as long as it keeps me away from people who doesn't know the difference between popularity and standards.

jQuery is a DOM DSL at best. First of all it doesn't have anything to do with JavaScript itself, because it's a DOM wrapper, secondly there is nothing standard about jQuery in terms of JavaScript. Take for example a look at the .each() function where the arguments are in just the opposite order than they are in the JavaScript own Array#forEach method.

If you need something that actually follows the standards, you should take a look at RightJS. It brings many standard features from later JavaScript specifications, plus many other none the less standard features from server-side programming languages, for example methods like String#startsWith or Array#random.

The DOM interfaces are just one part of RightJS and it has much more. We even have a build of RightJS without DOM features which you can use on the server-side with Node.js or say writing scripts in Qt.


3. Multiple Paradigms

As jQuery is simply a wrapper over DOM interface, it doesn't give you any alternatives but use its own way of dealing with the things. Yes, you might imagine that you're practicing Lisp in JavaScript, but the reality is that 99% of jQuery code (including jQuery itself) is just a spaghettish pieces of crap.

RightJS on the other hand is not just a DOM wrapper, it is a multi-paradigm framework. We have an advanced OOP stack that allows you to write clean and properly designed applications that are easy to support and refactor. We also have most of the standard FP features, like binding, curring, chains and stuff. We also have some standard native units extensions that are most helpful in procedural programming.

RightJS gives you options and flexibility, so that you could deal with your work in the most effective way.


4. Open Sandbox

Maybe jQuery forces you to write a spaghetti code, but there is a bigger problem. Most of jQuery and its plugins code are closed behind anonymous scopes that makes it impossible to change them part by part.

You know, people are actually already invented OOP, inheritance, functionality injection and other fancy stuff to deal with those sort of things. And that's why in RightJS we have radically opposite architecture.

RightJS is built using proper OOP structures and modules and it represents an open sandbox where virtually everything is accessible and customizable. You can easily bend and tune RightJS for your needs, changing and replacing its parts, adding your own features, methods and so one.

And because of that it is super easy to write any sort of plugins and extensions for RightJS. Take for example a look at the right-rails plugin; couple of dozens of lines of code and RightJS API was completely transformed to have the naming system of Ruby, with underscored syntax and other features.

RightJS gives you the same flexibility and hacker's joy as Ruby or Python.


5. Official Plugins

I'm sure you know what they say "jQuery has a gazillion of plugins that will do everything for you". It kinda reminds me other folks who was saying "Everything in Java has already been done".

Normal people usually add on that "badly".

That gazillion of plugins has actually a pretty nasty back side. The problem is in the closed architecture and inflexibility. For every case there are usually half a dozen of implementations, and quite often the choice is like "bad, bad or bad?". At the end you might spend more time looking for a proper plugin than you could spend writing it yourself, and at the finish your app will look like a Frankenstein, all stitched of different parts.

Yes I know, I know, Frankenstein is a romantic figure in gothic culture, but there is so few romantic in supporting such an app.

With RightJS we don't have the luxury of too many plugins, but we have several good points on that matter too. First of all, many common and frequently used features that you have as plugins for jQuery, are already baked into the RightJS core, like for example, additional form features, Ajax via iframes functionality, cookies and stuff.

Then we have all the standard plugins, like D'n'D, JSON, Behaviors, plus most of the standard UI elements like Calendar, Autocompleter, Tabs, Lightbox, etc. already implemented and served in the official plugins repository.

And what's different about RightJS plugins is that all of them are implemented in the same way, using the same set of rules. All events handling, options, usage principles all are the same. So that if you had experience with one plugin, you will be familiar with the rest of them too.

Then all the plugins follow the open-sandbox principles of the RightJS Core. All of them are implemented using proper OOP approach and can be easily extended using inheritance, functionality injection or even monkey patching if you will.

This way you don't need a dozen of variations of the same plugin, you can easily tweak any standard one to do exactly what you need.