Monday, 23 April 2012

What I missing in Rails 2.3+

Well 3.1 and 3.2 is been out for quite a while now so I intend to dedicate this post is for all those fellow coder who still believe or want to maintain there code with rails 2.3+ to let them know that what actually they are missing

If I happen I go about and write the all new feature of rails 3.1 or rails 3.2 then I guess I will run out of word but still I ensure that I cover most important one though

1. Unobtrusive Javascript :
              Before I move ahead and announcement ,Rails 3+ has default javascript framework as jQuery instead of Prototype as opposed to rails 2.3+ and older version (+1 on this) and by adapting HTML standard Rails 3+ encourage developer to write unobtrusive javascript and give them the ability to work seemless of javascript frameworks in our case its jquery(default) so all you need is to install the gem jquery_ujs( you dont have to do this for rails-3.2).If your a prototype support dont get dishearten there is a piece of cake for you too just install the prototype-rails gem and your ready to go

Now all by developer folks would agree with me saying that  back in rails 2.3+ days writing erb code server side would turn up looking one big mess in HTML
here what I meant

a simple delete link in rails 2.3+ would look like this
<%= link_to 'Destroy', user, :confirm => 'Are you sure?',:method => :delete %>
under the hood create such a big mess in HTML

<a href="/users/1" onclick="if (confirm('Are you sure?')) { var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href;var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var s = document.createElement('input'); s.setAttribute('type', 'hidden'); s.setAttribute('name', 'authenticity_token'); s.setAttribute('value', 'FqAHj1L667xA8SmeQjHvVncy8WJz0shaoKjiLHbhQT0='); f.appendChild(s);f.submit(); };return false;">Destroy</a>
same is true if your writing and ajax related code using using any of Rails 2.3+ ajax helper (e.g link_to_remote,remote_form_for etc)

Now with Rails 3+ you can just clean all this mess let me show you how .
link_to_remote is replace  with  normal link_to syntax with once extra parameter remote => true  providing this  help in rails understand to create a link that under hood fire an ajax request (identified by jquery_ujs on click)which is basically achieve by creating a custom data-attribute data-remote => true . same is true with confirm

In Rails 2.3+ a normal link_to_remote would look like this.

<%= link_to_remote 'Edit', :url => edit_user_path(user)  %>
this will produce html on browser like this.
<a href="#" onclick="new Ajax.Request('/users/1/edit', {asynchronous:true, evalScripts:true, parameters:'authenticity_token=' + encodeURIComponent('FqAHj1L667xA8SmeQjHvVncy8WJz0shaoKjiLHbhQT0=')}); return 
false;">Edit</a>
not so clean let see the same in Rails3+ with slightly different syntax.
<%= link_to 'Edit' ,edit_user_path(user) , :remote => true %>
would produce the below underlying HTML code in browser
<a href="/users/3/edit" data-remote="true">Edit</a>
Totally unobtrusive Javascript 


So now hence forth the both server side and client side code is much cleaner now hooray !!


2. ActiveRelation (AREL - CHAINING QUERY)
       I must admit this the  first time I heard this it just blew me the ActiveRelation original created by and written nkallen before rewritten by many especially one person Aaron Patterson citing performance issue thankfully it done now.
(want to know more about ActiveRelation please go through this )

What ActiveRelation basically mean is back in Rails 2.3+ if you want to retrieve record from a database you basically would do use any of this
Model.find(:all,:conditions => {} )
 e.g (list all user that are admin right in the application)
User.find(:all,:conditions => {:admin => true} )
Now in Rails 3+ you could achieve this using
Model.where('your conidtion')
e.g
User.where("admin =?",true)
Now the basic difference between the above two query interface apart from  syntax is that earlier one (Model.find() ) return you all records  against your query
but the latter(Model.where) one return you with a relation object which is cool
because this mean I can just chaining the query to every relation object returned

like 
Model.where().order().select()
Now the actual query is fired only when you enumerate over your object or  you supply a '.all' syntax to end of Query

like
Model.where().order().select().all
So what Rails 3+ essential does is it kind of lazy load all of records only when you actually need it. Simply Awesome

Here list of method that Rails 3+ ActiveRecord provide
 - where
 - select
 - group
 - order
 - reorder
 - reverse_order
 - limit
 - offset
 - joins
 - includes
 - lock
 - readonly
 - from
 - having
Which such Awesome feature Rails 3+ also has support for old syntax to so as to help migrating Rails 2.3+ application to 3+

Just in inline what used to named_scope in rails-2.3+ is 'scope' in rails 3+ hence worth you like to use named scope something like this
scope :admin , where("admin =?",true)
User.admin

3. Action Dispatcher (New Route API)
   Yes with all the this amazing changes there are changes in Rails 3+ routing too.In Rails 3+ the Routing API is much more cleaner and sound a bit more Rubyish here I will list the difference between rails 2.3+ and newest syntax


i.Now the routes is laid all under your app name
something like
RentHouse::Application.routes.draw do
  ... 
  ...
  ...
end

(RentHouse is your app name)
instead of ActionController in Rails 2.3+

ActionController::Routing::Routes.draw do |map|
  ...
  ...
  ...
end

ii.Get rid of block parameter(map). Now you see map is now more an options in rails3+  

iii. nested resources

 In rails2.3+
 map.resources :products do |products|
  products.resources :comments
  products.resources :sales, :collection => { :recent => :get }
 end
     
Same can be achieve using Rails 3+
  resources :products do
    resources :comments
    resources :sales do
      collection do 
        get 'recent'
      end
    end
  end
  or
 resources :products do
   resources :comments
     resources :sales do
       get 'recent' :as => "collection"  
     end
   end
 end

Sound more rubuies right I dont know about you guys I feel Rails 3+ simple act like DSL where you define Domain logic  

iv . Regular Routes

 Rails 2.3+
map.connect 'product_describe',:controller => "products",:action => "describe" 

 In Rails 3+
match 'product_describe', :to => "products#describe"

Look a bit cleaner right

v. Named Routes 

 In Rails 2.3+  
map.describe 'product_describe',:controller =>"products",:action =>"describe"
In Rails 3+
match 'product_describe', :to => "products#describe", :as => :describe

Now there quite a lot more changes in Routes I recommend refer Rails 3+ routing API for more information

vi. Here an announcement coming
  "Rails has never been so Rack friendly as Rails3+ is"

Now you can just plug and play any of your rack app in Rails3+ and it way to easy and Routes too is no exception (as rails3+ routes embrace so beautifully just like that whole rails)

mount your rack app all you need is point it in your routes
 match '/rack_it_up',:to => RackItUp
(RackItUp is rack app (sinatra,cramp,or anything else)

So Awesome <3 Rails3+


4. ActionMailer API Rewritten.

      This is brand( I mean rewritten) new by Mike Lindsaar I guess we all knew that in Rails 2.3+ ActionMailer use tmail gem well I guess in Rails 3+ it been rewritten with mail gem      

Apart from mail gem ActionMailer has separate directory now for all your mailer code. Which I guess I was missing in Rails 2.3+ where one just would write there mailer code inside model. the syntax too is bit change now here a user_creation_mail

Now in Rails 2.3+ you would have code written like this
class DeliveryMailer
  def user_creation_email(user_created,password)
    subject   "User Registration Mail"
    recipients user_create.email
    from 'myapp@test.com'
    body :user => user,:password => password
  end
end
To sent the mail we would call
DeliveryMailer.deliver_user_creation_email(user,"SECRET")
Same in Rails 3+ with mail gem would be written as
class DeliveryMailer
  def user_creation_email(user_created,password)
    @user     = user_created
    @password = password
    @from     = 'myapp@test.com'
    mail(:to => user_created.email,:subject => "User Registration") 
  end
end
Now to deliver this mail all you need to do is  call
DeliveryMailer.user_creation_email(user,"SECRET").deliver
Kind of look neat isn't it

Note that we are passing object in instance variables so that we can use them in the email template.


5. ActiveModel

        Shout loud if you feel in rails-2.3+ managing tableless model or using some noSQL with model was so much pain

First you need to uncomment -active_record from your environments file asking it(rails) not to be loaded AciveRecord in Rails(really), as if that was not enough.you happen to stumble upon all the errors that you never encounter
(if you want to achieve this in Rails2.3+ here a link .)

Now if you want to associate callbacks or validations with your model. You probably think of writing your own(and there goes DRY ideology) , wasn't there something that has all the underlying ActiveRecord API where all the validation and callbacks would be defined which would help in better managing of noSQL or tableless model easy

Now a step ahead .You think Rails 3+ has it.

ActiveModel is the place where all the validation and callbacks of ActiveRecord are define now we could integrate ActiveModel in your models and you could have all validation and callbacks in a snap.

Great work Guys Love you Rails3+ for this.



6. Faster Development ActiveReload
   I guess this was integrated in Rails 3.2 . How activereload gem created by Robert Pankowecki which basically started as project to speed up development environment quickly became the most downloadable library to speed up your development environment insanely fast close 300% faster . Now the good new is that active_reload in merge in Rails 3.2 here the story you may want read .Written by Robert about how his gem active_reload

As his word  "Die ActiveReload long live Rails "

All Hail Rails


7. Asset Pipeline
    I guess this feature was introduce in Rails 3.1 what it basically means a better management of your assets (images,stylesheets,javascript) for your applications.

As of Rails 3.1 provide you a bunch of assets directory under 'app' ,'lib', 'public', 'vendor' Now you would place any of your assets any where in the assets directory listed under ('app','lib' .. ) and it would be loaded in application .

Also Rails 3.1 has a support for coffeescript and sass default you could write your javascript or stylesheet in coffee or sass and rails would compile the same for you on run time.
(Note that you don't want to do this production as you don't need you asset to compile on every request) 
You could also precompile your assets but I recommend you to do this only on production using rake asset:precompile:all

What basically precompile do is consider that you have a application.js
//= require 'jquery'
//= require 'jquery_ujs'
//= require 'basic'

precompile would basically club all the three file 'jquery,jquery_ujs,basic' and compress to a single with md5 hash of content in filename application[md5hash].js something like this 
application-908e25f4bf641868d8683022a5b62f54.css 

It also create a gzip version of your assets in case if you need to allow web server to render gzip version of your asset to improve transmission

Now back in rails 2.3+ to cache your asset you would do something like this.
<%= javascript_include_tag :application ,:cache => true %>
And rails would create a script tag
<script src=”/javascript/application.js?1335015587” type=”text/javascript” >
(where 1335015587 is the last modified time.)

Now I have read and face many time that the web server dont treat the latter one so gracefully (webserver doesnot treat '?' so gracefully )

great step taken by rails 3 team in fixing this . 

Asset pipeline has also support for preprocessor

which mean you could chain your application.css or application.js with application.css.sass.erb or application.js.coffee.erb
and can write sass or coffee and erb code in css or js and Rails would do all the necessary compiling.

Now this is basically done using Sprockets as it drill down for each set of processors and compile the file with respect to processor (.erb,.coffee)


8. Template Inheritance
     This one I badly needed it I remember how many time I  wanted more level of layouting thankful to Rails  team we have  template inheritance hooked in rails 3+ but I wish rails 2.3 has this although there where gem like rails-template-inheritance to achieve the same.

Here what I meant with Template Inheritance

consider an application where I have login page and internal pages each having different navigation (like About Us,Contact Us, etc) . Now there are several way you can achieve this segregation but using template inheritance you can achieve this by simple define navigation for each controllers in there respective view directory  

e.g  my application layout preview
 <html>
   <head>
      ..
   </head>
 <body>
   <%=  render 'top-navigation' %>
   <%= yield %>
 </body>
</html>
Now we could define top-navigation partials specific to any controller in there respective directory and rails would render it.

e.g
For UserController Rails will first look for top-navigation partial in the current controller view directory(app/views/users over here) if it can find one it will look for the partial in the application directory defined in view.

hence the name template inheritance as just like controllers where all controller inherit from application_controller all view inherit from application

9. Erubius support
  To be fair I was  expecting this I knew sooner or later Rails team will have default erubius support. there are benchmark laid on erubius website that show how fast
erubius is which regard to erb check here Now basically with hardly any noticeable syntactical change you get faster template compiling.If you want to read the path of integration for erubius in rails3+ I must recommend you read this by Yehuda Katz
 

Thanks to Rails team


10. Dependency Management
    Dependency management was and is major headache in rails2.3+ application unless you are using your application with bundler I still remember getting error like

can load activesupport 2.3.5 already activated activesupport 2.3.11 or some other sort now which bundler already hooked in rails 3 I guess my life is more peaceful

now with Rails 3+ all need do is  'bundle install' that it bundle will manage all your dependency for you ( bundler gem is crafted by highly advance ruby programming) It basically achieve this a DFS (depth first server)


There other list of command like bundle pack , bundle list , bundle exec etc I advice to follow bundle website for more on bundler .


11.  Logging Slow Query
        Everyday I used to inspect Rails3+ commit and I used to ask myself what next ,what next. Well we have this amazing framework what next now and I seem to get surprise everytime,this one is no exception reading through rails commit in (Rails3.2) I was made aware that hence forth I can log slow query for my application . Awesome man now I dont need to config my mysql to log one


All you need is new configuration parameter.
config.active_record.auto_explain_threshold_in_seconds

determines what's to be considered a slow query. Setting that to nil disables this feature.

Default are 0.5 in development mode nil in test and production modes

Rails 3.2 supports this feature in SQLite , MYSQL(mysql2 adapter) and PostgresSQL

12 . Simpler Code and Better Documentation

     All of this but still simpler code management and better documentation ( I wont believe you) I guess I would have said the same but when I looked at rails 3+ code I was wrong far more simpler and modular code and way better documentation than rails2.3+.

Love Rails3+  Keep growing 3> 3> 3> 3> 3> 3>

No comments:

Post a Comment

What did I learn today?

Welcome to the what did I learn today series. The intention of this blog spot is to compose the stuff that I learnt day-to-day basics and jo...