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>

Saturday 21 April 2012

Deploying Rails App with Passenger and NGINX

All the ROR begineer every wonder about how the so called ROR expert set and deploy there application in no time. Feeling sorry don't be because after this post you dont have too.

First of all you may like to pause a minute or so and decide the which server you want to use (nginx , apache) depending on your need.

We would be using the awesome nginx server for out post but dont worry if you have apache in your stack hooking up the same is not much different from nginx.

You can download nginx from here or build the nginx based upon distributor package

For Ubuntu it fairly straight forward
sudo apt-get install nginx
(Note: please check your distribution provider for downloading)

but I recommend you to download the nginx source code as one can customized the nginx while configure it with passenger.

Phusion Passenger - a.k.a. mod_rails or mod_rack -- makes deployment of Ruby web application, such as those built on revolutionary Ruby on Rails web framework

Next we can confidently go ahead and install the phusion-passenger gem using
gem install passenger
Once passenger install

Now it time to go ahead and install configure your nginx to work with passenger just go ahead and ran the below command on your favorite shell
passenger-install-nginx-module
(if you have source code of nginx point it when asked by passenger during the above process) 

Now passenger will popup a customized configuration depending upon your environment

Here what passenger displayed me.

Please edit your Nginx me configuration file (probably /opt/nginx/conf/nginx.conf ) ,
  http {
    ...
    passenger_root  /usr/lib/ruby/gems/1.8/gems/passenger-3.0.11;
    passenger_ruby /usr/lib/ruby1.8;
    ...
   }
   server {
     listen 80;
     server_name www.yourhost.com;
     root /somewhere/public;   # <--- be sure to point to 'public'!
     passenger_enabled on;
   }
Copy the above content in your nginx.config
(dont worry if your unaware where is your nginx.conf file located passenger will come to rescue in that too)
 as it would be required you to set up your application now replace 'somewhere' from the above with absolute path for your application

Here how the final configuration look like
worker_processes  1;
events {
  worker_connections  1024;
}

http {
  passenger_root /usr/lib/ruby/gems/1.8/gems/passenger-3.0.11;
  passenger_ruby /usr/bin/ruby1.8;
  include       mime.types;
  default_type  application/octet-stream;
  sendfile        on;
  keepalive_timeout  65;
  server {
    listen       80;
    server_name  myapplication.com;
    root /home/root/application/public;
    passenger_use_global_queue on;
    passenger_enabled on;
    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
      root   html;
    }
  } 
}
Set you Database environment and restart the nginx server
/etc/init.d/nginx restart
(you might want to run this as sudo)

Voila, that it congratulation you have successfully deployed your rails application

Go ahead pat yourself in back for this. :) :) :)

Now enter your application url in your favourite browser you should find it working.
If you can't find it or you land up in error page check nginx error.log
(can be found in nginx.log file) or your application log file for more information it could probably
because you would be missing certain gem or you just missed something from the above list

Hope it help you in someway or other.

Thanks You.

Friday 20 April 2012

process => process in CarrierWave

Well this one is for all those who ever used CarrierWave for uploading there files(no matter which files). Now how many of us had actually extended Carrierwave to process a file (i.e writing you own processing for the file e.g In term of image reducing or increasing the quality of image)

I happen to stumble upon this as all I want was to process a csv file which is suppose to be stored in Amazon S3(on upload) using CarrierWave .

Now the aim was to extract all the information from the CSV (sound simple right ) . Yes it is but I resist the thought of putting the file in Amazon S3 server(first) and then downloading the file and to my server and then extract the data from the CSV file and dump it into database. I want it to be more real time(since the file are small size file) I want user to know that the data in CSV is proper or not and can or cannot data in the CSV can be dumped into database citing validations.

So I realized back when I used to consider PaperClip as my first options, paperclip used to provide me options for processing the file here the link if you want to do it for paperclip Good Luck.

Yes I knew now I have to achieve something of this sort ,but how

Well looking at the uploader file generated by CarrierWave I found out that there is process method ,ok now what how do you apply it.
Inspecting the CarrierWave source code ( for default resize process ) I found out that all you need is to define a method wrapped inside a module .

Now it got it.

So to define a custom processing all you need is to define method wrapped in module and include that module in CarrierWave and pass your process method as an argument to CarrierWave process method define in uploader file
Here how I achieve this.
Inside CarrierWave Uploader
class AssetUploader < CarrierWave::Uploader::Base
   include CarrierWave::CSVProcessor
   process :process_csv
end

That it that all you need to do to define your own file processing.
Just go ahead an define your process_csv method inside module define in file inside config/initializers Voila mission accomplished.
Here how I did it (my file config/initializers/csv_processor.rb)
module CarrierWave
  module CSVProcessor
    def process_csv
      ....
      ....
      ....
    end
  end
end
Go hack now with CarrierWave.

By the way if you want to explore the thought of providing custom error message for CarrierWave here a link that you might want to look at

Hope that it help you in someway or other

Saturday 14 April 2012

Auto Login from Iphone Home Screen Shortcut using LocalStorage and Rack

If you ever worked on Mobile Application and if you have been ever asked to design a web auto login for iOS Home Screen Desktop every
time a user click the Home Screen Shortcut  then you might want settle down and read this post bcoz this can help you

The first that I came across when implementing the home screen shortcut how to manage the cookie and how to store in browser
(even when browser is closed)

Thank full to HTML5 as it provide a localStorage I quickly got the insight how where to store the cookie

For any one how aren’t aware of  HTML5 localStorage. HTML5 localStorage  provide API  for storing data locally on browser which can be
access any time  by your application in near future.

Now with clear insight of where to store the cookie the next task is how to access it and wrap it in request.

That when Rack Hit me

The idea is to mount a rack application on top rails middleware and then play around with Rails request/response cycle . Let me Hook
up the code to then explain you everything bit by bit
CODE = %{
  <script type="text/javascript">
    (function(){
      var RESEND_REQUEST = {{RESEND}};
      function isFullScreen() {
        return navigator.userAgent.match(/WebKit.*Mobile/) && !navigator.userAgent.match(/Safari/);
      }

      if(isFullScreen()) {
        if(!document.cookie.match(/{{REGEX}}/)){
          var storedValues = localStorage.getItem('__cookie__');
          if(storedValues){
            var values = storedValues.split(';');
            for(var i=0; i < values.length; i++)
              document.cookie = values[i];
          }
          document.cookie = '_cookieset_=1';

          if(RESEND_REQUEST){
            window.location.reload();
          }
        }
      }
    })()
  </script>
}

COOKIE = %{
  <script type="text/javascript">
    (function(){
      var COOKIE = "{{COOKIE}}";
      var lastCookie = null;
      setInterval(function(){
        if(lastCookie != ''+COOKIE){
          lastCookie = ''+COOKIE;
          localStorage.setItem('__cookie__', ''+COOKIE);
        }
      },1000);
    })()
  </script>
}  

  def initialize(app)
    @app = app
  end

  def call(env)
    if iphone_web_app?(env)
      if new_session?(env)
        [200,{'Content-Length' => code(true).length.to_s, 'Content-Type' => 'text/html'}, code(true)]
      else
        status, headers, body = @app.call(env)
        request = Rack::Request.new(env)
        response = Rack::Response.new([], status, headers)
        cookie = String.new
        request.cookies.each_pair do |key,value|
              cookie += "#{key}=#{value};"
        end
        body.each do |part|
          part.gsub!(/<\/head>/, "#{set_cookie(cookie)}")
          response.write(part)
        end
        response.finish
      end
    else
      @app.call(env)
    end
  end

  protected

  def code(resend=false)
    regex = "_session_id"
    if Rails.configuration.session_store.name == "ActionDispatch::Session::CookieStore"
      regex = Rails.configuration.session_options[:key]
    end
    CODE.gsub('{{RESEND}}', resend.to_s).gsub('{{REGEX}}',regex.to_s)
  end

  def set_cookie(cookie)
    COOKIE.gsub('{{COOKIE}}',cookie.to_s)
  end

  def new_session?(env)
    request = Rack::Request.new(env)
    if request.cookies['_cookieset_'].nil?
      true
    else
      false
    end
  end

  def iphone_web_app?(env)
    if env['HTTP_USER_AGENT']
      env['HTTP_USER_AGENT'] =~ /WebKit.*Mobile/ && !(env['HTTP_USER_AGENT'] =~ /Safari/)
    end
  end
Now the idea is to trap the request def new_session? which has no cookie associated with it return the code javascript in response body and extract the cookie from localStorage localStorage.getItem(‘__cookie__’);
associate it with document using document.cookie syntax and re-request the page using window.location.reload()

Voila there you have it next time you open your Home screen shortcut you would not be thrown to login screen citing no active session available.

Hooking  all of this in one gem called rack_iphone

Note : There are other way you can achieve the same using parameterized URL (where a URL will be identify with the parameter in it) something like GOOGLE does I Guess.

Providing few links which will further help you so that you don’t stumble upon any roadblocks when building the same
LocalStorage Issue

Hope that it help you in some way or other

Thanks

Viren Negi

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...