Monday, January 23, 2012

Tip of the day

On my current project I had to calculate date of Wednesday in nth week in mth year.

Here is the trick:
date-extension

Friday, December 23, 2011

Rails upgrade from 3.0.7 to 3.1 and asset pipe-lining

Following my previous blog, I happen to work on another rails upgrade at the beginning of my new project. This time rails 3.0.7 to 3.1. I though, I should document these steps, as it might help myself or someone else in future.

I googled and found a good discussion on stack-overflow. As Forrest Ye gave the right answer, I began the migration step by step, as it is written:
"Edit Gemfile, change Rails gem version

gem 'rails', '3.1.0'

Also adds new gems introduced in 3.1.0

group :assets do
  gem 'sass-rails', "~> 3.1.0"
  gem 'coffee-rails', "~> 3.1.0"
  gem 'uglifier'
end
gem 'jquery-rails'
run

bundle update rails
Then run rake rails:update and resolve conflicts."

I found few conflicts and before accepting them, I tried to understand:

1. config/application.rb:
I paid attention to:
config.assets.enabled = true
config.assets.version = '1.0'
which means you are enabling assets pipe-lining  which is one of the feature of rails 3.1, I accepted the changes.
2. config/environments/development.rb:
config.action_view.debug_rjs = true
which has been deprecated, so this line should be deleted, if you are using rjs in views, debugging is not supported now.
config.assets.compress = false
which means assets compression is off in development, I accepted the changes.

config.assets.debug = true
it means, you can see the assets being loaded in logs. I accepted this change.
3. config/environments/production.rb
I saw again configuration related to asset pipeline:
config.assets.compress = true
config.assets.compile = false
config.assets.digest = true
Simply, accept these changes.

Once this is done, move all assets from public/images, public/javascripts, public/stylesheets to app/assets/ directory. Again, you have to make sure, that you
Include css/javascript links in your layout file like this

<%= stylesheet_link_tag "application" %>
<%= javascript_include_tag "application" %>
Again, it is important to understand the behavior of asset pipeline and how it works. For example, in application.js file, you will have:
//= require_tree .
that means, all the files from assets/javascripts directory will be loaded automatically, as application is being loaded, in hierarchical format. If you do need js files in sequence, mention that above this line, e.g.:
//= require jquery 
//= require jquery_ujs
//= require highcharts
//= require_tree .

Similarly you have application.css file, which will load assets in hierarchy, so override it if needed. 

One important thing I noticed is about images, which are embedded in stylesheets. I had stylesheet.css as:
/*
*= require_self
*= require_tree .
*/
#header { height:20px; }
body {background-image:url(../images/mainBack.png) !important; background-repeat:repeat-x;}
 So, after moving images to app/assets/images directory, I have to remove the relative path of the image:
body {background-image:url(mainBack.png) !important; background-repeat:repeat-x;}
Similarly for all other styles and that is it!

Sunday, September 11, 2011

Rails upgrade from 2.3.5 to 3.0.9

Few weeks back I did rails upgrade for my current project from rails 2.3.5 to rails 3.0.9 (on Windows 7).

I began with rails 3 upgrade guide. So, first step was to install ruby 187, which I already had on my system with pik

There is a good series on rails on upgrading to rails 3 from Ryan Bates:
http://asciicasts.com/episodes/226-upgrading-to-rails-3-part-1
http://asciicasts.com/episodes/226-upgrading-to-rails-3-part-2
http://asciicasts.com/episodes/226-upgrading-to-rails-3-part-3

Some how the rails-upgrade-plugin did not work for me (as I was working on Windows 7) .

I then followed the-path-to-rails-3-approaching-the-upgrade step-by-step and I got application 80% upgraded, the rest 20% was a tough part.

In this blog, I am writing about challenges I faced in this process.


  • Installing rails 3.0.9 gem:
    Somehow gem install rails shown errors:
    C:\myapp>gem install rails
    Successfully installed rails-3.0.9
    1 gem installed

    Installing ri documentation for rails-3.0.9...
    file 'lib' not found
    Installing RDoc documentation for rails-3.0.9...
    file 'lib' not found

    I used,
    C:\myapp>gem install rails --no-rdoc --no-riSuccessfully installed rails-3.0.9
    1 gem installed
  • routes.rb
    I had to update the routes.rb file and I found one really helpful link: http://stackoverflow.com/questions/3103765/routing-in-rails-3-map-with-options
  • Deprecation warning for cookie_store:
    DEPRECATION WARNING: ActionController::Base.session= is deprecated. Please configure it on your application with config.session_store :cookie_store, :key => '....'. (called from C:/myapp/config/initializers/session_store.rb:7)

    So, I did:
    module Myapp   class Application < Rails::Application     config.session_store :cookie_store, :key => '_myapp_session', :secret => 'some-secret-string-very-long'
    Also, I removed C:/myapp/config/initializers/session_store.rb file.
    Reference: http://stackoverflow.com/questions/3720379/sqlsessionstore-in-rails-3 and http://apidock.com/rails/ActiveRecord/SessionStore
  • Logging the deprecation warnings
    I saw another warning:
    You did not specify how you would like Rails to report deprecation notices for your development environment, please set config.active_support.deprecation to :log at config/environments/development.rb

    So, I updated development.rb (and other .rb files):
    Myapp::Application.configure do     config.active_support.deprecation = :log
  • consider_all_requests_local warning
    DEPRECATION WARNING: ActionController::Base.consider_all_requests_local= is deprecated. Please configure it on your application with config.consider_all_requests_local=.

    So, I added this snippet in config/environments/development.rb
    Myapp::Application.configure do config.consider_all_requests_local = true
  • Some easy once
    1. DEPRECATION WARNING: RAILS_ENV is deprecated. Please use ::Rails.env.
    So, wherever I was using RAILS_ENV, I replaced with Rails.env

    2. DEPRECATION WARNING: RAILS_ROOT is deprecated. Please use ::Rails.root.to_s.
    So, wherever I was using RAILS_ROOT, I replaced with Rails.root.to_s
  • ActionMailer warnings
    1. When you need to set character set for action mailer, you specify in initializer.rb, which throws this warning:
    DEPRECATION WARNING: ActionMailer::Base.default_charset=value is deprecated, use default :charset => value instead

    I passed hash to the default method in application.rb:
    Myapp::Application.configure do default :charset => 'utf-8'
    2 Similarly the mime version we set in initializers:
    DEPRECATION WARNING: ActionMailer::Base.default_mime_version=value is deprecated, use default :mime_version => value instead.

    I passed hash to the default method in application.rb:
    Myapp::Application.configure do default :mime_version => '1.0'

    3. For multipart emails the setting has to be adjusted:
    DEPRECATION WARNING: ActionMailer::Base.default_implicit_parts_order=value is deprecated, use default :implicit_parts_order => value instead
    This is again can be passed to default method:
    Myapp::Application.configure do   default :parts_order => [ "text/plain", "text/enriched", "text/html" ]
  • html_safe in view?
    For 2-3 hours I struggled to find the reason, why the select tag was not producing the tags. When I found it I understand that this is again a security addition to convert strings into html safe form. So, all your '&lt;' will be converted to '<' and all '&gt;' will be converted into '>'. I actually added .html_safe at the end of each string in view and that showed all the tags finally.

    Reference: rails-3-select-tag-not-producing-dom-elements
  • Removed config.action_view.cache_template_loading, use config.cache_classes instead
    Reference: https://github.com/rails/rails/commit/83e29b9773ac113ceacb1e36c2f333d692de2573
  • Rspec
    I was using rspec and here is the deprecation warning I got:
    *****************************************************************
    DEPRECATION WARNING: you are using a deprecated constant that will be removed from a future version of RSpec.
    C:/cit/spec/controllers/activity_logs_controller_spec.rb:1:in `require'
    * Spec is deprecated.
    * RSpec is the new top-level module in RSpec-2
    ***************************************************************
    ***************************************************************
    DEPRECATION WARNING: you are using deprecated behaviour that will be removed from a future version of RSpec.
    C:/cit/spec/spec_helper.rb:17
    * Spec::Runner.configure is deprecated.
    * please use RSpec.configure instead.

    So, I have to use rspec-rails-2 which supports rails 3.
    Reference: http://groups.google.com/group/cukes/browse_thread/thread/40c4c2aea1c07afe/cb63eb7f0b733646?lnk=raot
  • Ajax stopped working
    I was using jQuery as javascript library, and I found somehow the ajax calls stopped working after the upgrade. I later found that there is a security threat and a fix for that is available
    Here is what I had to do:

    Step#1. In application.html.erb, I had to include csrf_meta_tag:
    <%= javascript_include_tag :defaults %> <%= csrf_meta_tag %>
    Step#2. I added this snippet to application.js:
    $(document).ajaxSend(function(e, xhr, options) {   var token = $("meta[name='csrf-token']").attr("content");
    xhr.setRequestHeader("X-CSRF-Token", token); });


    Reference: csrf-protection-bypass-in-ruby-on-rails
  • RackBaseURI instead of RailsBaseURI
    I was using RailsBaseURI in apache, but after upgrade to Rails 3, I had to update it to RackBaseURI
    Reference: RackBaseURI
  • Last but not least, I was using valid? method in helper to check if the object is valid or not and based on that I was displaying certain fields, which was working fine in Rails 2.  In Rails 3 valid? method will trigger validations as well, which caused field_with_errors div to show-up all the time (even when the validation should not happen). I changed the logic to not use valid? method to display other fields and it solved the problem.

Thursday, March 24, 2011

development on Windows deploying to Linux with cruise and bundler?

In my previous post, I set-up bundler with rails-2.2.2 application. Soon after that, I found myself in another trouble.

When I set-up bundler, I had to create Gemfile for the gems required by my rails application. Also, when I run bundle install command, it creates Gemfile.lock file, this file holds various information:
  • Gem repositories (sources)
  • Which version of gem the application is using (gem specification)
  • If there is any dependency of any gem, then what they are
  • Platform details
In my current project, I use Windows 7 as development machine, there is a cruise server on linux machine, I am committing my code to a subversion repository and once the build passes on cruise it deploys to a linux server. Every time I run bundle install, it creates a Gemfile.lock with windows version of gems and platform details for windows. If I commit Gemfile and Gemfile.lock, it fails the build and I have to manually login to cruise box and remove those files and re-run bundle install command, so that it generates the Gemfile and Gemfile.lock for linux environment, so that on integration and production servers, the Gemfile and Gemfile.lock will remain with linux version and there is no failures there. This was a pain.

I wrote a ruby script to do this job for me. With this script, I removed everything windows specific in Gemfile and Gemfile.lock I can think of. Here is what I did (look at: https://github.com/gouravtiwari/windows_linux_fix_for_bundler for source code)
  • I extended cruise:init rake task(created fix.rake in lib), to include my ruby script.
  • In the script, I am removing windows traces, updating the platform details, running bundle command and then committing the latest Gemfile and Gemgfile.lock toSVN.
This way, if by mistake I am committing Gemfile and Gemfile.lock to SVN, I don't need to go to cruise and re-generate Gemfile and Gemfile.lock.

Friday, March 4, 2011

Bundler with rails-2.2.2

I am working on a rails application, which is on rails-2.2.2. I have used bundler on rails-3 application, but never tried bundler for rails-2.2.2. The benefit of bundler is huge, it is gem manager for rails application. So, now no pain of vendoring/localizing gems in rails application.

gembundler.com gives step-by-step process on how to install/configure bundler for rails-2.3.x and rails-3.x applications. So, I wanted to find out how does it work with rails-2.2.2 application.

So, here is how I did.
  • First of all I have installed bundler
    gem install bundler // installed bundler 1.0.10
  • Updated rubygems
    gem update --system // rubygems > 1.3.6
  • Created config/preinitializer.rb file with below content:
    begin
      require "rubygems"
      require "bundler"
    rescue LoadError
      raise "Could not load the bundler gem. Install it with `gem install bundler`."
    end

    if Gem::Version.new(Bundler::VERSION) <= Gem::Version.new("0.9.24")
      raise RuntimeError, "Your bundler version is too old for Rails 2.3." +
       "Run `gem install bundler` to upgrade."
    end

    begin
      # Set up load paths for all bundled gems
      ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", __FILE__)
      Bundler.setup
    rescue Bundler::GemNotFound
      raise RuntimeError, "Bundler couldn't find some gems." +
        "Did you run `bundle install`?"
    end
     
  • Created Gemfile with something similar:
    require 'rubygems'
    source 'http://rubygems.org'
    source 'http://gemcutter.org'
    source 'http://gems.github.com'

    gem 'rails', '2.2.2'
    gem 'hpricot', '0.6.0'
    gem "composite_primary_keys", '1.0.8'
    gem 'javan-whenever', '0.3.7'
    gem 'mysql', '2.8.1'
    gem 'activerecord-oracle_enhanced-adapter', '1.1.9'
    gem 'ruby-oci8', '1.0.3'

    group :test do
      gem 'mocha', '0.9.5'
      gem 'rspec',             '1.3.1', :require => 'spec'
      gem 'rspec-rails',       '1.3.3'
      gem 'database_cleaner',  '0.5.0'
      gem 'capybara'
      gem 'ruby-debug'
      gem 'factory_girl'
    end
  • From the application root, I ran:
    bundle install
That is it and I have my application up and running with bundler. Once I tested my application, I removed gems folder from /vendor (no need for localized version of gems now.)

Friday, January 28, 2011

mongodb with Rails 3

Few days back, I did introspection and thought, as a developer:
  1. How many languages I know?
  2. How many databases I have worked with?
  3. Which frameworks I am comfortable working with?
  4. Do I know the latest technologies in my field?
I then realized that working on PHP 4, PHP 5, Ruby 1.8.6 doesn't mean that I know the latest cutting edge technologies. I should try learning may be Ruby 1.9.2, or may be a new language. I have worked with MySQL, Oracle, but what's new? I should try working with some other database, may be Mongodb. I did work on Drupal 4.7.x, 5.7.x and also on Rails 2.0.x to 2.3.x, but may be I should try Rails 3.

Then I downloaded Ruby 1.9.2, with pik, so I can continue work on the project work(ruby 1.8.6), as well as try out rails 3. Needless to say Rails 3.x is far better than it's predecessor Rails 2.x. bundler  is just awesome! But I was so used to use ActiveRecord (with mysql and oracle), I was not able to think how would I work without it on a Rails project. 

I first tried mongodb online (Try it out section) and felt it different, but complete. Whatever basic operations you can perform in mysql/oracle, you can do it in that tutorial.

I installed Rails 3.0.3 without ActiveRecord and installed mongodb to give it a try. It is really different and it amazes you by the fact that how easy to use it with rails. ActiveRecord syntax will not work, but mongo mapper has it's own syntax. In two-three hours I had my basic application with Rails 3 and mongodb on windows7 machine up and running (including learning curve and thanks to mongodb and mongo mapper asciicast and Ryan Bates for nifty_generators)

Once I was done with my rails3-mongodb test application, I realized that MySQL and Oracle are not end of the world. There are better and different things that I should learn. It is much faster to install and configure Ruby 1.9.2 + mongodb + rails 3 and get the application up and running as compared to Ruby 1.9.2 + MySQL/OracleXE (10g) + rails 3 from scratch.

I would love to hear comments/similar experiences :)