Friday, December 10, 2010

Read an article on rake tasks

It’s about Dependencies

This may be a bit of a stretch to say but build tools are about dependencies. One file or set of files depends on another set to get compiled, linked, or other fun things before the next set can be processed. The same idea exists in rake with tasks and task dependencies. Let’s look at a simple rake task. Save the following as “Rakefile” in any directory:

directory "tmp"

file "hello.tmp" => "tmp" do
sh "echo 'Hello' >> 'tmp/hello.tmp'"
end

What we’re saying here is that the file named “hello.tmp” depends on the directory "tmp". When rake runs across this, it’s going to create the directory "tmp" first before running the "hello.tmp" task. When you run it, you’ll see something like the following:

[jason@brick:~/src]$ rake hello.tmp
(in /Users/jason/src)
echo 'Hello' > 'tmp/hello.tmp'

If you were to look at the "hello.tmp" file you would see the phrase "Hello". What happens if you run it again? You’ll see the same output again. What’s going on? Rake is generating the file again. It’s doing this because it can’t actually find the file tmp/hello.tmp from that definition. Let’s redefine the task:

directory "tmp"

file "tmp/hello.tmp" => "tmp" do
sh "echo 'Hello' > 'tmp/hello.tmp'"
end

Now if you were to run it twice you would see something like this:

[jason@brick:~/src]$ rake "tmp/hello.tmp"
(in /Users/jason/src)
mkdir -p tmp
echo 'Hello' > 'tmp/hello.tmp'
[jason@brick:~/src]$ rake "tmp/hello.tmp"
(in /Users/jason/src)

Rake now knows that the file task has been run.
Running Other Tasks

Rake tasks can take the form of having prerequisites and can depend on another task. Let’s say I wanted to get ready in the morning. My process would be something like this:

1. Turn off alarm clock.
2. Groom myself.
3. Make coffee.
4. Walk dog.

Let’s further assume that I have OCD and have to do all of these in order. In rake I might express my morning as follows:

task :turn_off_alarm do
puts "Turned off alarm. Would have liked 5 more minutes, though."
end

task :groom_myself do
puts "Brushed teeth."
puts "Showered."
puts "Shaved."
end

task :make_coffee do
cups = ENV["COFFEE_CUPS"] || 2
puts "Made #{cups} cups of coffee. Shakes are gone."
end

task :walk_dog do
puts "Dog walked."
end

task :ready_for_the_day => [:turn_off_alarm, :groom_myself, :make_coffee, :walk_dog] do
puts "Ready for the day!"
end

If I were to run this as is I would type rake ready_for_the_day and I’d see the following:

[jason@brick:~/src]$ rake ready_for_the_day
(in /Users/jason/src)
Turned off alarm. Would have liked 5 more minutes, though.
Brushed teeth.
Showered.
Shaved.
Made 5 cups of coffee. Shakes are gone.
Dog walked.
Ready for the day!

By running the ready_for_the_day task it notices that the turn_off_alarm, groom_myself, make_coffee, and walk_dog tasks are all prerequisites of the ready_for_the_day task. Then it runs them all in the appropriate order. You’ll notice that we can pass something in to the make_coffee task. If we were having a really tough day we could pass in a value to the COFFEE_CUPS environment variable and be more prepared:

[jason@brick:~/src]$ rake COFFEE_CUPS=5 make_coffee
(in /Users/jason/src)
Made 5 cups of coffee. Shakes are gone.

Namespaces

Rake supports the concept of namespaces which essentially lets you group together similar tasks inside of one namespace. You’d then specify the namespace when you call a task inside it. It keeps things tidy while still being quite effective. In Rails, you might notice the db:migrate task. In that example, db is the namespace and migrate is the task. Using the above example, we might put everything in to the morning namespace:

namespace :morning do
task :turn_of_alarm
....
end

Now if you were to run rake COFFEE_CUPS=3 morning:ready_for_the_day you would have the same output as above, only it only took 3 cups of coffee today. Score!
The Default Task

Rake has the concept of a default task. This is essentially the task that will be run if you type rake without any arguments. If we wanted our default task to be turning off the alarm from the example above, we’d do this:

task :default => 'morning:turn_off_alarm'

Running rake now produces the following:

[jason@brick:~/src]$ rake
(in /Users/jason/src)
Turned off alarm. Would have liked 5 more minutes, though.

Describing Your Tasks

You can use the desc method to describe your tasks. This is done on the line right above the task definition. It’s also what gives you that nice output when you run rake -T to get a list of tasks. Tasks are displayed in alphabetical order. We’ll define some descriptions in our Rakefile (abbreviated for brevity):

...
desc "Make coffee"
task :make_coffee do
cups = ENV["COFFEE_CUPS"] || 2
puts "Made #{cups} cups of coffee. Shakes are gone."
end
...

Now when we run rake -T for our list of tasks we get the following output:

[jason@brick:~/src]$ rake -T
(in /Users/jason/src)
rake afternoon:make_coffee # Make afternoon coffee
rake morning:groom_myself # Take care of normal hygeine tasks.
rake morning:make_coffee # Make coffee
rake morning:ready_for_the_day # Get ready for the day
rake morning:turn_off_alarm # Turn off alarm.
rake morning:walk_dog # Walk the dog

You can add in a string to get tasks matching that displayed. Running rake -T af would show just the afternoon task.
Redefining Tasks

Let’s say you want to add on to an existing task. Perhaps you have another item in your grooming routine like styling your hair. You could write another task and slip it in as a dependency for groom_myself but you could also redefine groom_myself later on (shortened for brevity but you get the idea):

namespace :morning do
....
task :groom_myself do
puts "Brushed teeth."
puts "Showered."
puts "Shaved."
end
....
end
...
namespace :morning do
task :groom_myself do
puts "Styled hair."
end
end

[jason@brick:~/src]$ rake morning:groom_myself
(in /Users/jason/src)
Brushed teeth.
Showered.
Shaved.
Styled hair.

Invoking Tasks

You may at some point want to invoke a task from inside another task. Let’s say, for example, you wanted to make coffee in the afternoon, too. If you need an extra upper after lunch you could do that the following way:

namespace :afternoon do
task :make_coffee do
Rake::Task['morning:make_coffee'].invoke
puts "Ready for the rest of the day!"
end
end

Which outputs:

[jason@brick:~/src]$ rake afternoon:make_coffee COFFEE_CUPS=1
(in /Users/jason/src)
Made 1 cups of coffee. Shakes are gone.
Ready for the rest of the day!

A real world example of this is the rcov:all task. I use this in Genius Pool for aggregate rcov data. It’s shamelessly stolen from Clayton Lengel-Zigich. Go check out that post for a good example of invoking other tasks from rake.
Refactoring

You’ll notice in the example above we’re delegating most of the work to already defined methods and tasks in the RSpec and Cucumber classes. As a general rule, try to keep your methods already defined other places and call them from rake with your specific options and use cases. Let’s say I had a Rails application that e-mailed all accounts in the system that their account was expiring in a certain number of days. Here’s one way to write it:

namespace :accounts do
desc "Email expiring accounts to let them know"
task :email_expiring => :environment do
date = ENV['from'] ? Date.parse(ENV['from']) : Date.today
accounts = Account.find(:all, :conditions => ["expiration_date = ?", date]
accounts.each do |account|
Notifier.deliver_account_expiration(account)
end
end
end

A better way, that would let you test it more thoroughly would be to do the following:

namespace :accounts do
desc "Email expiring accounts to let them know"
task :email_expiring => :environment do
date = ENV['from'] ? Date.parse(ENV['from']) : Date.today
Account.notify_expiring(date)
end
end

This lets you unit test your notify_expiring method on the account class and make sure that it’s doing what it’s supposed to do. This is a small, made up example, but you get the idea. Here’s an example from Resque:

desc 'Restart redis'
task :restart do
RedisRunner.stop
RedisRunner.start
end

Notice the delegation to the RedisRunner class methods? This is a great rake task
Rails

You can get access to your models, and in fact, your whole environment by making tasks dependent on the environment task. This lets you do things like run rake RAILS_ENV=staging db:migrate. Rails will autmatically pick up tasks in lib/tasks. Any files named with the .rake extension will get picked up when you do rake -T.
Scheduling Rake Tasks

You can use cron to schedule rake tasks. Let’s say you wanted to run the account email expiration task every night at 12:15 on your production server, you might have something like this:

15 * * * * cd /data/my_app/current && /usr/bin/rake RAILS_ENV=production accounts:email_expiring

Misc

Rake.original_dir gives you the directory that the original rake task was run from.

Derivatives

* Thor is a more class based approach to solving some of the things rake does as far as actual tasks go.
* Capistrano is the de facto standard for deploying rails apps. Its syntax is inspired pretty heavily by Rake, but it is definitely not rake.

Source http://jasonseifer.com/2010/04/06/rake-tutorial

Paperclip issue " is not recognized by the 'identify' command."

I tried to upload an image an image (paperclip plugin and windows 7) and then i received the following errror
Avatar C:/Users/machine~1/AppData/Local/Temp/stream20101210-2576-p7vfu8-0.png is not recognized by the 'identify' command.

This was the error obtained as i had not installed imagemagick in my new machine. To fix this i download image magick from http://www.imagemagick.org/script/binary-releases.php
Installed it and then restarted my machine.

Saturday, October 30, 2010

Installing nokogiri for rails 3 app on Heroku

I wanted to install nokogiri gem defined in gemfile of my application on windows platform and i can see them installed when i do a git push heroku master.
But still i get an error saying no such file to load --nokogiri. My application on heroku gets crashed.

After many hours of research then i found these things below:

The problem was with Bundler gem and Bundler 1.0 Will Not Install Compiled Gems in UNIX When `bundle install` is Run in Windows.

When I run bundle install for my project under Windows, Bundler will generate a Gemfile.lock with the following for Nokogiri:

nokogiri (1.4.3.1-x86-mingw32)
nokogiri (1.4.3.1-x86-mswin32)

However, Gemfile.lock does not list the UNIX version nokogiri (1.4.3.1). I then checkin my Gemfile.lock into git and deploy a release to our Linux server. As part of our Cap script, the server runs bundle install --deployment. Upon doing so, there are four problems.

1. Bundler will not install the Nokogiri gem on the Linux server.
2. Bundler will list every other gem in its output, except for Nokogiri.
3. Bundler will say Your bundle is complete!, even though the Nokogiri gem was not installed.
4. Because Bundler does not exit with an error, Cap will deploy the app without Nokogiri being built, and the app errors out when a user tries a page that uses Nokogiri.

I believe this may also affect other compiled gems that have native mingw or mswin builds.

Solution: Remove your Gemfile.lock file and then do a repush.

Thursday, October 21, 2010

ERROR: Failed to build gem native extension whenever we install a gem on windows

When i tried to install a hpricot (gem install hpricot) then i received the following error

Building native extensions. This could take a while...
ERROR: Error installing hpricot:
ERROR: Failed to build gem native extension.

C:/Ruby187/bin/ruby.exe extconf.rb
checking for stdio.h... no
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers. Check the mkmf.log file for more
details. You may need configuration options.

Provided configuration options:
--with-opt-dir
--without-opt-dir
--with-opt-include
--without-opt-include=${opt-dir}/include
--with-opt-lib
--without-opt-lib=${opt-dir}/lib
--with-make-prog
--without-make-prog
--srcdir=.
--curdir
--ruby=C:/Ruby187/bin/ruby


Gem files will remain installed in C:/Ruby187/lib/ruby/gems/1.8/gems/hpricot-0.8
.2 for inspection.
Results logged to C:/Ruby187/lib/ruby/gems/1.8/gems/hpricot-0.8.2/ext/fast_xs/ge
m_make.out

---------------

To fix this all i did was gem install (gemname) --platform=mswin32 (gemname is hpricot in my case)

Friday, September 17, 2010

:select, joins, where parameters in ActiveRecord find of rails

Extracting distinct records from a table can be done using

@players = Player.find(:all).map{ |player| player.name }.uniq

Here it queries and gets all the records from the table and a ruby method is executed to get the distinct records which makes it a bad solution as far as performance is concerned.

A better way to do this is to use the :select parameter of the ActiveRecord find method

@players = Player.find(:all, :select => 'DISTINCT name')

few other examples of using :select

@players = Player.find(:all, :select => ‘name, sur_name, date_of_birth’)

instead of @players = Player.find(:all) if the table data is huge.
However Player.find(:all) will be faster for short lists because of the Rails cache.

Player.find( :all,
:select => Player.column_names.select {|col| col != "sur_name"})

Using "where" for join tables
@users = User.joins(:roles).where(:roles => { :name => [Role::ADMIN, Role::CLIENT_ADMIN]})

Friday, August 27, 2010

Mate Framework diagrams

One-way communication: from views to business logic

































Thursday, August 12, 2010

Few useful links to learn flex with mate framework

http://cookbooks.adobe.com/post_Simple_MVC_For_Flex___Air_using_Mate_Framework-17018.html
http://livedocs.adobe.com/flex/3/html/help.html?content=projects_7.html
http://mate.asfusion.com/page/downloads
http://mate.asfusion.com/page/documentation/getting-started

Wednesday, August 11, 2010

Read an article which was inspiring.

Don’t just have career or academic goals. Set goals to give you a balanced, successful life. I use the word balanced before successful. Balanced means ensuring your health, relationships, mental peace are all in good order.
There is no point of getting a promotion on the day of your breakup. There is no fun in driving a car if your back hurts. Shopping is not enjoyable if your mind is full of tensions.

"Life is one of those races in nursery school where you have to run with a marble in a spoon kept in your mouth. If the marble falls, there is no point coming first. Same is with life where health and relationships are the marble. Your striving is only worth it if there is harmony in your life. Else, you may achieve the success, but this spark, this feeling of being excited and alive, will start to die. ……………….

One thing about nurturing the spark - don't take life seriously. Life is not meant to be taken seriously, as we are really temporary here. We are like a pre-paid card with limited validity. If we are lucky, we may last another 50 years. And 50 years is just 2,500 weekends. Do we really need to get so worked up? …………….

It's ok, bunk a few classes, scoring low in couple of papers, goof up a few interviews, take leave from work, fall in love, little fights with your spouse. We are people, not programmed devices..... ...." :)

Wednesday, August 4, 2010

How to get the logged in user ip address in rails

ip_address = request.env['REMOTE_ADDR']

M4v format videos on Ubuntu Linux

Running railscasts videos in ubuntu linux

Go to system > Adminsitration > Synaptic package manager
search for gsstreamer and install them.

Friday, July 23, 2010

Few useful links for pdf generation in rails

http://www.accesspdf.com/pdftk/#packages

http://wiki.github.com/sandal/prawn/using-prawn-in-rails
http://railscasts.com/episodes/153-pdfs-with-prawn
http://wilsoncolab.com/blog/bryan/2008/11/30/writing-pdfs-with-ruby-on-rails-using-prawn-and-prawnto/
http://prawn.majesticseacreature.com/
http://www.cracklabs.com/prawnto/use

http://rdoc.info/rdoc/sandal/prawn-layout/blob/bcfac3efffb68a0b3c9f1007c1c1193443470afc/Prawn/Document

Thursday, July 15, 2010

Modifications in rails auto_complete plugin to pass id as param.

The auto_complete plugin explain in railscasts passes the selected name as param.
Rails Autocomplete
In most cases we want to pass the select value id instead of name.
To pass the id instead of name in the above link all we need to do is


<!-- categories/index.js.erb -->
<%= auto_complete_values @categories, :name, :id %>
<%= text_field_with_auto_complete :product, :category_name, { :size => 15 }, { :url => categories_path(:js), :method => :get, :param_name => 'search', :after_update_element => "function(text_field, li_element){$('product_category_id').value = $('text_' + li_element.id).value;}"}) %>
<%= hidden_field "product", "category_id" %>
 
<!-- application_helper -->
  def auto_complete_values(entries, text_field, value_field, phrase = nil)
    return unless entries
    items = entries.map do |entry|
      content_tag("li", phrase ? highlight(entry[text_field], phrase) : h(entry[text_field]), {:id => entry[value_field]}) +
      hidden_field_tag("text_#{entry[value_field]}", entry[value_field])
    end
    content_tag("ul", items.uniq, {:style=> "height: 150px; overflow:auto;"})
  end

Note: In case you want to trigger an event on select of autocomplete list then all you want to do is modify after_update_element
Ex: <%= text_field_with_auto_complete :company, :number, {:class => "title"}, {:url => autocomplete_company_numbers_path(:js), :method => :get, :param_name => 'search', :after_update_element => "function(text_field, li_element){window.location.href='/company__numbers/show/' + $('text_' + li_element.id).value;}"} %>

Tuesday, July 13, 2010

Using Clockwork and Delayed Job gem to send event reminder emails.

code below run a background process to send an event reminder emails.
Install clockwork and delayed_job gem. You might want to upgrade ruby gem version too
commands:
gem install clockwork
gem install delayed_job

Create Reminder model with event_id, reminder_at fields

class CreateReminders < ActiveRecord::Migration
  def self.up
    create_table :reminders do |t|
      t.integer :event_id
      t.datetime :reminder_at
      t.timestamps

    end
  end

  def self.down
    drop_table :reminders
  end
end


Add the association into Reminder model
belongs_to :event

Now create clock.rb in the lib folder of your application and add the following.

  require 'rubygems'
require 'clockwork'
include Clockwork

require 'config/boot'
require 'config/environment'
every(2.minutes, 'reminder.deliver') {
reminders = Reminder.find(:all, :conditions => ["reminder_at <= ? and reminder_at > ?", Time.now.advance(:minutes => 2), Time.now])
#reminders = Reminder.find(:all, :conditions => ["reminder_at <= ?", #Time.now.advance(:minutes => 2)])
unless reminders.nil?
UserMailer.send_later( :deliver_event_reminder, reminders )
end


Now using command prompt go to the root directory of the application and run the command
clockwork lib/clock.rb
If you are using delayed_job then you will have to  rake jobs:work in another command prompt
This will trigger an event every 2 minutes which will get all the reminders that needs to be send in the next two minutes and delivers it.

How to make your pc run as fast a new

STEP 1

For those who believe their computer lags at start up, a quick look at the MSConfig would be the place to start. MSConfig can be accessed by hitting the Windows button on keyboard along with R key.

This will bring up the 'Run' dialog. Type 'MSConfig' and you will get the 'Start Up' tab with a list of programs and executables that are launched when the computer starts up.

Starting up of too many programs when the computer boots could be a reason why the boot time is so long. The remedy would be to go through the entire list and uncheck the unnecessary items.

If there are entries you are not sure about, check them on the internet, as unchecking the wrong entries could potentially mess up the functionality of some of your programs.

STEP 2

Defragment the hard drive once a month. It's like changing your car's oil - it should be the one thing on your list even if you don't do anything else. Windows stores information about your programs in the Registry.

This can get cluttered and affect performance. The solution is to download free registry cleaners from the internet (eg CCleaner) to remove redundant program entries.

STEP 3

Indexing Services is a nifty little program that uses a large amount of RAM. This processes indexes and updates lists of files on your computer. This is done so that when you search for something, it can search faster by scanning the index lists.

So, if you don't search your computer often, turn it off would better performance. Simply go to 'Start' button on taskbar, click on 'Control Panel' and select 'Add/Remove Programs'. Find the tab 'Add/Remove Window Components' and uncheck 'Indexing Services'. Click Next.

Also, if there is a delay every time you open 'My Computer' to browse folders, try this.

Open 'My Computer', click on 'Tools', select 'Folder Options', click on the 'View' tab to uncheck the 'Automatically search for network folders and printers' box.

Click 'Apply' and then reboot your computer for changes to apply.

STEP 4

Hard drive performance plummets as you near the drive's maximum capacity.

Assuming you don't have an additional drive to move the content to, your choices are slim. But before you take a machete to your files, you may want to compress them.

Use the built-in compression tool in Windows, which makes accessing the files no different from it currently is. Go to 'Disk Cleanup' and make sure 'Compress Old Files' is checked.

Click 'Options' and specify the age of the files you want Windows to compress - Windows will compress only the files you haven't accessed in more than six months (or as specified).

STEP 5

An important feature of Windows is its ability to return system files to the state they were in earlier. Before tweaking, users can create a new 'Restore Point'.

Go to Control Panel>Performance and Maintenance>System Restore or Start-All Programs > Accessories > System Tools>System Restore and select 'Create a restore point'.

If it is left alone, this can consume a good portion of your disk space with unnecessary restore points.

By default, it uses up to 12 per cent of each of your drives and, even if you have a big hard drive, many extra restore points can slow down processes like virus checking, disk-defragmenting, etc.

Typically, how much space you should allot to system restore depends on your system (200 MB - the minimum allowed - will hold 5 or 6 restore points) and should suffice for average users.

STEP 6

Also, the Windows XP (and Windows Vista) computers have features like smooth animated menus and transparent windows.

These use processor resources, too, which means they can cause slowdown. Right-click the 'My Computer' icon and click 'Properties'.

Click the 'Advanced' tab and under 'Performance', click 'Settings'. Choose to switch off some of these effects and see the improvement in your PC's performance.

STEP 7

Accumulated dust in computer cases a reason for over-heated PCs. Dust gets into the ball bearings in the fan and cause the fan to stop working. This may lead to overheating of processor and permanent hardware failure.

It is less common, but static charges from dust can also be a threat. A layer of dust on a memory chip can cause static electricity to build up.

This can amount to electric charge, which discharges on to your motherboard or memory chip. The best way to stop dust from building up is to open the case on your PC and vacuum it.

We recommend never tweak without knowing how to return where you began

Wednesday, July 7, 2010

Monday, June 28, 2010

Integrate Rails with CouchDB using ActiveCouch

This document assumes you have CouchDB 0.8.1 + as well as Rails 2.1.1 + installed.
To install CouchDB please refer Installing CouchDb on windows
.
So a lot of the evolution of ActiveCouch correlates with the level of frustration with the library and making it better implies making our lives better. There are maybe better/more-lightweight wrappers for CouchDB out there.

Install ActiveCouch as a Rails Plugin

The biggest advantage of ActiveCouch v0.2.x is that it can be used as a Rails plugin as well as, as a standalone gem. You can install activecouch gem by the command
$ gem install activecouch

ActiveCouch uses the JSON gem for fast JSON serialization/deserialization, so install that first:

$ gem install json
Then, create your Rails project

$ rails couchify
Then, install ActiveCouch as a plugin:


$ cd couchify
$ ./script/plugin install git://github.com/arunthampi/activecouch.git
This installs ActiveCouch in RAILS_ROOT/vendor/plugins

Follow up – Get it started

You need to create a file called activecouch.yml in RAILS_ROOT/config which looks something like this (Of course, depending on your deployment strategy, your test and production sites will be something else)

development:
  site: http://localhost:5984/
test:
  site: http://localhost:5984/
production:
  site: http://localhost:5984/ 

Create your ActiveCouch model

This is now very simple in ActiveCouch. At the root of your Rails project, simply enter
$ ./script/generate activecouch_model cat
This generates a cat.rb file in RAILS_ROOT/app/models which looks something like this:

class Cat < ActiveCouch::Base
    site YAML::load(File.open(File.join(Rails.root,
                  'config', 'activecouch.yml')))[Rails.env]['site']
end
All set to use CouchDB database depending on your Rails environment. Now ActiveCouch assumes that you already have a database called ‘cats’ created in CouchDB, so that you can start creating all your CouchDB documents. No matter, Rake tasks to the rescue:

Creating your database

If you goto RAILS_ROOT of your app, and enter the following:

$ rake --tasks
You will see some of the following:

rake activecouch:create_db           # Creates a database in CouchDB
rake activecouch:delete_db           # Deletes a database from CouchDB
rake activecouch:delete_view         # Deletes a view in CouchDB
rake activecouch:save_view           # Saves a view in CouchDB
So to create your database, just enter

$ rake activecouch:create_db db=cats
And boom, you have your database called cats created in ActiveCouch.
If for some reason, you need to delete your database, the answer is simple:

$ rake activecouch:delete_db db=cats
Awesome, now you can go ahead and edit your model to have various fields, for example a cat should probably have a name, so your model will look something like this:

class Cat < ActiveCouch::Base
    site YAML::load(File.open(File.join(Rails.root,
                  'config', 'activecouch.yml')))[Rails.env]['site']

    has :first_name
    has :last_name
end

Creating your first ActiveCouch Objects

To see if this works, open up ./script/console and type in the following:

> cat = Cat.new(:first_name => "Mr.", :last_name => "Jinks")
> cat.save
Or

> cat = Cat.create(:first_name => "Mrs.", :last_name => "Jinks")

Extract db data

CouchDB lets you query your database using something called Views. The CouchDB wiki has a lot of information on how views work. You should also probably consider watching Jan Lenhardt’s awesome talk on CouchDB , which explains a lot of the differences between Relational Databases and Document-Oriented Databases.
ActiveCouch tries to abstract a lot of the view behaviour from you (some people have said it is inelegant , so I’m hoping for some better ideas from people reading this). For example, for the Cat model above, suppose you want to query for all cats by their last name, you can create a view at /cats/design/by_last_name/by_lastname and ActiveCouch lets you query your CouchDB database like so:

cats = Cat.find(:all, :params => {:last_name => "Jinks"})
The price you pay for the somewhat unwieldy view names, is that you get very convenient find methods. Of course if you have created your custom views, you can always use the find_from_url method which works something like this:

cats = Cat.find_from_url("/cats/_view/by_last_name/by_last_name?key=%22Jinks%22")
Ok, back to views. ActiveCouch lets you create your views using a very simple generator. So from your RAILS_ROOT again,

$ ./script/generate activecouch_view ByLastName
This creates an ActiveCouch::View class in RAILS_ROOT/app/models. You can edit the view as given below, so that you can start querying by last name:


class ByLastName < ActiveCouch::View
  define :for_db => 'cats' do 
    with_key 'last_name'
  end
end
Done. But this view is not yet in the CouchDB database, so you need to save it into the database.

Saving your view

To save your view, you can use the built-in Rake task to save your views:

$ rake activecouch:save_view db=cats view=ByLastName
And boom, your view is saved.
Now suppose you want your view to be saved in many databases inside CouchDB. i.e. you have databases such as dogs, people, etc. and all of them need to be queried by their last name. No matter, you can use db=_all_dbs as part of your Rake task and this will save the view into all databases.

$ rake activecouch:save_view db=_all_dbs view=ByLastName
Now you are ready to start querying your database and finding objects.

Installing CouchDB

CouchDB for windows is available at
http://shockdragon.com/couchdb/couchdb-0.9-windows.zip
Simply download it and then extract the zip and execute 'couch_start.bat' from the bin directory, then Futon will be available at
http://127.0.0.1:5984/_utils
 
For more information refer the links:
http://wiki.apache.org/couchdb/Installing_on_Windows
http://wiki.apache.org/couchdb/Windows_binary_installer
http://people.apache.org/~mhammond/dist/snapshots/
http://people.apache.org/~mhammond/dist/0.11.0/

Thursday, June 24, 2010

Prawnto to generate pdf documents.

You need to install the following
gem install prawn
ruby script/plugin install git://github.com/thorny-sun/prawnto.git

Now add a link in your view

<%= link_to "Printable Invoice (PDF)", order_path(@order, :format => 'pdf') %>

Your controller

prawnto :prawn => { :top_margin => 75 }

def show
  @order = Order.find(params[:id])
end
 
create show.pdf.prawn in your views and add
 
pdf.text "Order ##{@order.id}", :size => 30, :style => :bold

pdf.move_down(30)

items = @order.cart.line_items.map do |item|
  [
    item.product.name,
    item.quantity,
    number_to_currency(item.unit_price),
    number_to_currency(item.full_price)
  ]
end

pdf.table items, :border_style => :grid,
  :row_colors => ["FFFFFF","DDDDDD"],
  :headers => ["Product", "Qty", "Unit Price", "Full Price"],
  :align => { 0 => :left, 1 => :right, 2 => :right, 3 => :right }

pdf.move_down(10)

pdf.text "Total Price: #{number_to_currency(@order.cart.total_price)}", :size => 16, :style => :bold
 
For more information refer: http://railscasts.com/episodes/153-pdfs-with-prawn
For more information on prawnto refer: http://www.cracklabs.com/prawnto 

Wednesday, June 16, 2010

Using Faster CSV to parse txt files

You can parse txt files using the following code
count = 1
    ActiveRecord::Base.connection.execute("TRUNCATE your_table")
    @parsed_file = FasterCSV.parse(params[:import][:file].read).each do |row|
      if count == 0              
        unless row[0].nil?
          data = row[0].split "\t"
          self.create(:attribute1 => data[0], :attribute2 => data[1], :attribute3 => data[2])
          table_data << data
        end
      end
      count = 0
    end

Tuesday, June 1, 2010

Paperclip plugin Errno::EACCES Permission denied on windows

If you get the following error on windows while using paperclip plugin
[paperclip] Saving attachments.
[paperclip] deleting C:/Documents and Settings/Sandeep/My Documents/NetBeansProjects/logicare/trunk/public/system/datas/208/original/WLHBSITEAM.csv
  [4;36;1mSQL (0.0ms) [0m   [0;1mROLLBACK [0m

Errno::EACCES (Permission denied - C:/Documents and Settings/Sandeep/My Documents/NetBeansProjects/logicare/trunk/public/system/datas/208/original/WLHBSITEAM.csv):
  c:/ruby/lib/ruby/1.8/fileutils.rb:1297:in `unlink'
  c:/ruby/lib/ruby/1.8/fileutils.rb:1297:in `remove_file'
  c:/ruby/lib/ruby/1.8/fileutils.rb:1305:in `platform_support'
  c:/ruby/lib/ruby/1.8/fileutils.rb:1296:in `remove_file'
  c:/ruby/lib/ruby/1.8/fileutils.rb:771:in `remove_file'
  c:/ruby/lib/ruby/1.8/fileutils.rb:549:in `rm'
  c:/ruby/lib/ruby/1.8/fileutils.rb:548:in `each'
  c:/ruby/lib/ruby/1.8/fileutils.rb:548:in `rm'
  app/controllers/nhs_datas_controller.rb:54:in `update'
  app/controllers/nhs_datas_controller.rb:53:in `update'

Steps to fix the problem
1) create patches.rb in lib folder and add these lines
require 'tempfile'
class Tempfile
  def size
    if @tmpfile
      @tmpfile.fsync
      @tmpfile.flush
      @tmpfile.stat.size
    else
      0
    end
  end
end
2) Add require "patches.rb" in environment.rb inside Rails::Initializer.run
3)Make sure you have installed http://www.imagemagick.org/script/binary-releases.php#windows
4) Restart the server and you should be able to add, delete and update files.

 There is another possibility why you will get permission denied error. This is when u have the file related data saved in associated tables. Say users table has data_id and there is files table has the related data i.e data_file_name, data_content_type etc.
In this scenario when you try you update the file then you will get permission denied errors. One possible way to fix this issue is.
1) first upload the new file
2) Then update the related table i.e users table with data_id . Now the link to old data is lost.
3) You have the old file id as params while submit. so using the get the file and the delete it.
Sample code
@data = Data.new
    @data.data = params[:data][:data]
    @data.save
    @user = User.find_by_data_id(params[:id])
    @user.data_id = @data.id
    @user.save
    @old_data = Data.find(params[:id])
    @old_data.destroy
Let me know if there is any better way to fix this issue.

Monday, May 31, 2010

How to get file extension in ruby and jquery

To get the file extension excluding the "." then do the following
@file_extension = file_name.split('.').pop()

To get the file extension along with "." then do the following
@file_extension = file_name.scan(/\.\w+$/)

Using Jquery
var ext = $('#file_field_id').val().split('.').pop().toLowerCase();

Thursday, May 27, 2010

Access to /etc/hosts denied while modifying host file

This problem occurs when you  do not have the administrative rights.
You get an error when you try to edit the LMHOSTS or HOSTS file under Windows Vista.
Access to C:\WindowsSystem32\drivers\etc\ hosts was denied
or
Cannot create the C:\Windows\System32\drivers\etc\hosts file.
Make sure that the path and file name are correct.

To solve this problem:
1. Click Start–>All Programs–>Accessories–>Notepad–>Run as administrator.
If you are prompted for an administrator password or for a confirmation, type the password, or click Allow.
2. Open the Hosts file or the Lmhosts file, make the necessary changes, and then click Save on the Edit menu.

Friday, May 21, 2010

How to make dynamic on focus popup in the grid.

If you have a data table and need to display a on focus popup which shows the related columns content then you can do the following:
<% @objects.each do |object| %>
           
                   <%=h object.name%>                 
                  Show
                   
                       
           
<% end %>
<% end %>

Friday, April 23, 2010

Using annotate_models plugin

download or install annotate_models plugin (http://github.com/ganeshprasad/annotate_models) into vendor/plugins folder.
Now whenever you run the command rake annotate_models it will update the models with the schema.
Schema is also defined in ActiveRecord models whenever rake db:migrate is done.


Add a comment summarizing the current schema to the top or bottom of each of your…
* ActiveRecord models
  * Fixture files
  * Tests and Specs
  * Object Daddy exemplars
  * Machinist blueprints
The schema comment looks like this:
# == Schema Info
   #
   # Table name: line_items
   #
   #  id                  :integer(11)    not null, primary key
   #  quantity            :integer(11)    not null
   #  product_id          :integer(11)    not null
   #  unit_price          :float
   #  order_id            :integer(11)
   #

    class LineItem < ActiveRecord::Base
      belongs_to :product
     . . .

Thursday, April 22, 2010

Reading huge csv or xls file and importing the data into database tables.

To implement this we need to gems fastercsv (gem install fastercsv) and ar-extensions ( gem install ar-extensions)

FasterCSV is intended as a replacement to Ruby‘s standard CSV library. It was designed to address concerns users of that library had and it has three primary goals:
  1. Be significantly faster than CSV while remaining a pure Ruby library.
  2. Use a smaller and easier to maintain code base. (FasterCSV is larger now, but considerably richer in features. The parsing core remains quite small.)
  3. Improve on the CSV interface. 
Advantages:

  • FasterCSV has a stricter parser and will throw MalformedCSVErrors on problematic data.
  • FasterCSV has a less liberal idea of a line ending than CSV. What you set as the :row_sep is law.
  • CSV returns empty lines as [nil]. FasterCSV calls them [].
  • FasterCSV has a much faster parser. 

ar-extensions

ActiveRecord::Extensions provides extensions to:
  • mass import data
  • convert ActiveRecord models and arrays to CSV format
  • work with temporary tables
  • control foreign keys
  • to include extensible features for better and custom finder support
Sample code to implement :
require 'rubygems'
require 'fastercsv'
require 'ar-extensions'
table_columns = [:attribute1,:attribute2, :attribute3, :attribute4, :attribute5 ]
table_data = Array.new


FasterCSV.foreach("#{RAILS_ROOT}/public/data/yourcsvfile.csv") do |row|
  row.delete_at(14)   #this can be used incase you want to delete any unnecessary column from any row of csv data

  table_data << row
end
options = { :validate => false }
CareHomeHq.import table_columns,table_data

Here insert of data will also be faster because we are not creating a new instance of CareHomeHq everytime a new row is fetched. Instead all the rows are saved in an array first and then we use ar-extensions to import the data.


PARSING FROM TEMP FILE
In case you want to parse from temp file then all you need to do is
  @parsed_file = FasterCSV.parse(params[:data_import][:file].read).each do |row|   
       puts row.inspect
      #your code here     
   end

Monday, April 5, 2010

Conditional validations in rails

By default, validations will take place every time the model is saved. Sometimes you only want a validation to happen when certain conditions are met. See how to do that in this episode.

# models/user.rb
validates_presence_of :password, :if => :should_validate_password?
validates_presence_of :country
validates_presence_of :state, :if => :in_us?
attr_accessor :updating_password

def in_us?
country == 'US'
end

def should_validate_password?
updating_password || new_record?
end

# in controller
@user.updating_password = true
@user.save

# or...
@user.save(false)

Monday, March 1, 2010

Ruby: Large xml files Parsing With SAX

SAX is an event-driven parser for XML.

It sequentially reads the xml and generates special events. So, if you want to use SAX, you should implement the code to handle them. It's quite different from the DOM model, where the whole xml is parsed and loaded in an tree.

The Ruby XML Library

The Ruby core library has a built-in XML parser (both DOM and SAX) called REXML, but it's terribly slow, it's highly advisable to use libxml. It's a binding to the popular library from Gnome and it was released as gem.

Installing libxml is simple by running the following command.

gem install libxml-ruby

Refer the following example which reads a large xml file and inserts the data into the corresponding database table.

require 'xml/libxml'
CombinationPackInd.benchmark("Truncating look up tables and inserting new records") do
#truncate combination_pack_ind table
ActiveRecord::Base.connection.execute("TRUNCATE combination_pack_ind")
#truncate combination_prod_ind table
ActiveRecord::Base.connection.execute("TRUNCATE combination_prod_ind")
############################# ---TRUNCATING ENDS--- ########################

class Lookuphandler
include XML::SaxParser::Callbacks
def on_start_element_ns (name, attributes, prefix, uri, namespaces)
@tag_name = name
@main_tag_name = "" if @main_tag_name.nil?
@main_tag_name = case name
when "COMBINATION_PACK_IND"
then "COMBINATION_PACK_IND"
when "COMBINATION_PROD_IND"
then "COMBINATION_PROD_IND"
else
@main_tag_name
end
end

def on_end_element_ns (name, prefix, uri)
@end_element = name


#saving combination pack ind
if @main_tag_name == "COMBINATION_PACK_IND"
if @tag_name == "CD"
@cd = @value
elsif @tag_name == "DESC"
@desc = @value
end

if @end_element == 'INFO'
@comb_pack_ind = CombinationPackInd.new(:DESC => @desc)
@comb_pack_ind.CD = @cd
@comb_pack_ind.save
# clear the variables so that it wil not carried to the next instance.
@cd, @desc = ""
end
end
#saving combination prod ind
if @main_tag_name == "COMBINATION_PROD_IND"
if @tag_name == "CD"
@cd = @value
elsif @tag_name == "DESC"
@desc = @value
end

if @end_element == 'INFO'
@comb_prod_ind = CombinationProdInd.new(:DESC => @desc)
@comb_prod_ind.CD = @cd
@comb_prod_ind.save
# clear the variables so that it wil not carried to the next instance.
@cd, @desc = ""
end
end

##################################### CLEARING VARIABLE CONTAINING TAG INFO AFTER INSERTING RECORD ##################################
@tag_name = ""
@main_tag_name = "" if @end_element == ( "COMBINATION_PROD_IND" || "COMBINATION_PACK_IND")
end

def on_characters(s)
@value = s
end

end
################# ---LOOKUP PARSING BEGINS--- #########################################################
file_path = RAILS_ROOT + "/data/file.xml"
parser = XML::SaxParser.file(file_path)
parser.callbacks = Lookuphandler.new
parser.parse
end

Thursday, February 25, 2010

Using REXML to read small xml files and load into database table

Save the following code in lib folder of your application as read_xml_file.rb . using command prompt run " ruby script/runner lib/read_xml_file.rb". The following code is possible to read only small xml files ( usually in kbs).


require 'rexml/document'
require 'rubygems'
include REXML
#def import_xml(tag)
file= File.new(RAILS_ROOT + "/file.xml")
doc= Document.new(file.read)

Ingredient.benchmark("Truncating ingredient table and inserting new records") do
#truncate ingredient table
ActiveRecord::Base.connection.execute("TRUNCATE ingredient")
# read table contents
XPath.each( doc, "//INGREDIENT_SUBSTANCES//ING" ){|ingredient|
ingredient_params = {}
#if there are more than one attributes for table then create a hash.
ingredient.children.each do |child|
key = "#{child.name}".to_sym
if key.to_s == "ISID"
@isid_value = child.text
else
ingredient_params[key] = child.text
end
#@desc_value = child.text if key.to_s == "DESC"

end
#create new instance
ingredient = Ingredient.new(ingredient_params)
#set the primary key if mass assigning of primary key is not possible.
ingredient.ISID = @isid_value
#save
ingredient.save
}
end

TRUNCATE All Tables in a Ruby on Rails

There might be a case where you need to delete all the rows from all the tables in the database to end up with just the structure(a bare DB). The right thing to do is to run the TRUNCATE command on all the tables. It will delete all the data and also reset the auto increment value. But the only current way to get a bare DB in rails now is to run rake db:reset. This will run rake db:drop, rake db:create and rake db:migrate. The downside of this is that if you have a reasonable number of migrations this command can take quite some time to run which is really not efficient when you are iterating fast. Hence following rake task will
TRUNCATE all the tables.

namespace :db do
task :load_config => :rails_env do
require 'active_record'
ActiveRecord::Base.configurations = Rails::Configuration.new.database_configuration
end

desc "Create Sample Data for the application"
task(:truncate => :load_config) do
begin
config = ActiveRecord::Base.configurations[RAILS_ENV]
ActiveRecord::Base.establish_connection
case config["adapter"]
when "mysql"
ActiveRecord::Base.connection.tables.each do |table|
ActiveRecord::Base.connection.execute("TRUNCATE #{table}")
end
when "sqlite", "sqlite3"
ActiveRecord::Base.connection.tables.each do |table|
ActiveRecord::Base.connection.execute("DELETE FROM #{table}")
ActiveRecord::Base.connection.execute("DELETE FROM sqlite_sequence where name='#{table}'")
end
ActiveRecord::Base.connection.execute("VACUUM")
end
rescue
$stderr.puts "Error while truncating. Make sure you have a valid database.yml file and have created the database tables before running this command. You should be able to run rake db:migrate without an error"
end
end
end


Just create a file named db_truncate.rake in your lib/tasks directory
with this code in it. Save the file and then run rake db:truncate. Your
database now should have no data now. Before you run the task make sure
that you have a valid database.yml file and have created the database
tables before running this command. You should be able to run rake
db:migrate without an error

In case you want to truncate a single table from database all you have to do is
ActiveRecord::Base.connection.execute("TRUNCATE table_name")



Monday, February 15, 2010

Avoid validations on create or update in rails

There might be several situations where we might have to avoid the default validations defined in the model when we update or create a record.
a.)One solution to avoid validation is by doing something like this
@something = Something.find(params[:id])
@something.column_save = 'your data'

respond_to do |format|
if @something.save(false) #save without validation
b.)Another solution is to write a separate method to validate in the model
please see the example below
validate :validates_uniqueness_of_name

def validates_uniqueness_of_name
return if deleted == true
num_duplicates = self.class.count(:conditions => ["name = ? AND deleted = ?",self.name, false])
if num_duplicates > 0
errors.add(:name, :taken)
end
end

How to delete a many-to-many association with Rails

One solution is to create a new model for the association. It should be the case
if you add attributes to the association (because push_with_attributes is now deprecated).
You can then simply find the association given the ids of your linked object and call destroy.

However, when you don't have any attribute in your liaison, the has_and_belongs_to_many
is nicer to work with. (you don't need a rails model for the liaison.)
Here is a link to the methods has_and_belongs_to_many adds where we can read :


"collection.delete(object, …) - removes one or more objects from the
collection by removing their associations from the join table.
This does not destroy the objects."

Let's assume we dispose of 2 models 'Post' and 'Category' with a N-N association :

class Post < ActiveRecord::Base
has_and_belongs_to_many :categories
end

class Category < ActiveRecord::Base
has_and_belongs_to_many :posts
end

To delete an association (remove a post from a category) you can use this method :

  def remove_post_from_category
post = Post.find(params[:post][:id])
category = post.categories.find(params[:category][:id])

if category
post.categories.delete(category)
end

end

This function will destroy the association but won't destroy the category.

You can also removes all the categories from the posts by using :


collection.clear - removes every object from the collection.
This does not destroy the objects.
In our case its

post.categories.clear