Translate

December 18, 2013

What is the difference between save and save! in Rails?

Save! performs all validations and callbacks. If any validation returns false, save! throws an error and cancels the save.

Save does not throw any error in the case above, but cancels the save. Also, the methods for validations can be bypassed.

October 16, 2013

What is the difference between delete and destroy in Rails?

The delete method essentially deletes a row (or an array of rows) from the database.
Destroy on the other hand allows for a few more options. First, it will check any callbacks such as before_delete, or any dependencies that we specify in our model. Next, it will keep the object that just got deleted in memory, this allows us to leave a message saying something like “ 'Object_name' has been deleted.” Lastly, and most importantly, it will also delete any child objects associated with that object!

September 24, 2013

Case equality operator === in ruby

To enable developers to write neat, compact code, Many classes take advantage of implementing their own versions of '==='. The '===’ operator is known as the case equality operator. The '===’ operator is used when testing cases in case statements.
def test_object number 
  case number
    when Fixnum
      case number 
        when 1  
          puts "It's One"
        when 2..10  
          puts "Between two and ten"
        else
          puts "-- #{number} -- is not between one and ten"
      end
    when String 
      puts "You passed a string"
    else "I have no idea what to do with -- #{number} --"
  end
end
for each 'when' statement the '===' operator is called on the when argument (1,2..10,String) and the case argument (number) is used for the comparison. For line 5 the comparison done shall be '1 === number'. For most classes ‘===’ is just an alias to ‘==’ however some classes redefine ‘===’ to allow for better functionality in case statements. In Ruby a Proc is a block of executable code, an anonymous function which can be passed around as if it were data. Like ‘===’, a Proc can map a number of arguments to either a true or false value.
is_weekday = lambda {|day_of_week, time| time.wday == day_of_week}.curry  
      
    sunday    = is_weekday[0]  
    monday    = is_weekday[1]  
    tuesday   = is_weekday[2]  
    wednesday = is_weekday[3]  
    thursday  = is_weekday[4]  
    friday    = is_weekday[5]  
    saturday  = is_weekday[6]  
      
    case Time.now  
    when sunday   
      puts "Day of rest"  
    when monday, tuesday, wednesday, thursday, friday  
      puts "Work"  
    when saturday  
      puts "Happy"  
    end  
Simple Factorial lambda function in Ruby
factorial = lambda do |n|
  n <= 1 ? 1 : (n * factorial.call(n - 1))
end

factorial.call 3

July 24, 2013

SQL Injection in rails

How to avoid SQL Injection in rails

How to avoid SQL Injection in rails

SQL injection is a problem that every web developer needs to be aware of when accepting parameters that will during the life of the request be converted into SQL statements. Rails historically has done what it can to mitigate this risk for the developer by providing vehicles for sanitizing parameter inputs at the points when they are being converted for use inside of a SQL statement, however with Rails 3 there are numerous ways to execute a SQL statement against the database and some of these methods are safer than others.
Consider two cases where valid Rails code is vulnerable to SQL injection:

user inputed parameters

params[:query] = "'username'; DROP TABLE EMPLOYEE;"

CASE 1 - find_by_sql

User.find_by_sql("SELECT * FROM users WHERE (name = '#{params[:query]}'")

(Not Good)

generated SQL

SELECT users.* FROM users WHERE (email = 'user@example.com'); DROP TABLE EMPLOYEE; ')
(THIS STATEMENT WILL DROP TABLE EMPLOYEE)
The example above shows how find_by_sql can allow parameters submitted by a user to be directly entered into a SQL statement and how an attacker might use the vulnerability to wreak havoc. These types of find_by_sql statements used to be more commonly used in earlier versions of Rails (1.0 - 2.0) and it was through these statements that the Rails community realized that SQL injection was a problem that needed addressing. Here's another example prominent in the early Rails days:
User.find :first, :conditions => "(name = '#{params[:query]}')" ##(BAD BAD BAD) produces this SQL statement:

generated SQL

SELECT users.* FROM users WHERE (email = 'user@example.com'); DROP TABLE EMPLOYEE;')
(THIS STATEMENT WILL DROP TABLE EMPLOYEE)
The above example shows a common Rails idiom for performing an ActiveRecord query, as with the previous find_by_sql example the find query here is piping the param in directly and generating the exact same tainted SQL.
Fortunately, Rails core decided to make it easier to just do the right thing and provided ways to pass in parameters by using built-in filters that handle special SQL characters, which will escape ’ , " , NULL character and line breaks. Instead of passing in the parameter directly as a raw string, you can pass in an array to sanitize the tainted strings using the built-in filters:
User.find_by_sql(["SELECT * FROM users WHERE (name = ?)", params])
(GOOD)
User.find :first, :conditions => ["(name = '?')", params]
(GOOD)

generated SQL

SELECT * FROM users WHERE (name = 'user\'); DROP TABLE EMPLOYEE; ') (RETURNS NIL)
The distinction in the filtered SQL statement is the escaped single quote right after the t in Robert which prevents the name parameter from terminating and allowing the DROP TABLE EMPLOYEE from being executed since it remains a part of the string parameter. Additionally, Rails also included these built-in filters automatically when AR queries were called from find_by_something or a conditions hash:
User.find_by_name(params[:query])

(GOOD)

generated SQL

SELECT * FROM users WHERE users.name = 'username\'); DROP TABLE EMPLOYEE; ' (RETURNS NIL) User.find :first, :conditions => {:name => params}

(GOOD)

SELECT users.* FROM users WHERE users.name = 'username\'); DROP TABLE EMPLOYEE;' (RETURNS NIL)
Rails 3 introduced AREL, which is another way to perform ActiveRecord queries and with it came as well, another way to make the exact same SQL injection mistakes that are already listed above. However having gotten accustomed to looking for SQL injection vulnerabilities in the AR query formats above you might be lulled into thinking that the new and improved ActiveRecord query methods would just magically handle the tainted strings for you and you'd be dead wrong:
User.where("name = '#{params}'") (BAD) SELECT users.* FROM users WHERE (name = 'username'); DROP TABLE EMPLOYEE; ##') ##(THIS STATEMENT WILL DROP TABLE EMPLOYEE)
The nice thing is that the same fix can also be applied:
User.where(["name = ?", params]) SELECT users.* FROM users WHERE (name = ''username\'); DROP TABLE EMPLOYEE;
(RETURNS NIL)

July 9, 2013

Rails way web caching and caching

A web cache is a mechanism for the temporary storage (caching) of web documents, such as HTML pages and images, to reduce bandwidth usage, server load, and perceived lag. So that future requests for that data can be served faster.

Rails provides three types of caching techniques by default without the use of any third party plugins.
   
1) Page caching
2) Action caching
3) Fragment caching


1) Page Caching:

Page caching is a Rails mechanism which allows the request for a generated page to be fulfilled by the webserver (i.e. Apache or nginx), without ever having to go through the Rails stack at all. Obviously, this is super-fast. Unfortunately, it can't be applied to every situation (such as pages that need authentication) and since the webserver is literally just serving a file from the filesystem.
   
To enable page caching, you need to use the caches_page method.

class ProductsController < ActionController

  caches_page :index

  def index
    @products = Products.all
  end

  def create
    expire_page :action => :index
  end

end


By default, the page cache directory is set to Rails.public_path (which is usually set to the public folder) and this can be configured by changing the configuration setting config.action_controller.page_cache_directory.

In order to expire this page when a new product is added we could extend our example controller like above.


2) Action Caching:

One of the issues with Page Caching is that you cannot use it for pages that require to restrict access somehow(such as pages that need authentication). This is where Action Caching comes in. Action Caching works like Page Caching except for the fact that the incoming web request does go from the webserver to the Rails stack and Action Pack so that before filters can be run on it before the cache is served. This allows authentication and other restriction to be run while still serving the result of the output from a cached copy.
   
class ProductsController < ActionController

  before_filter :authenticate
  caches_action :index

  def index
    @products = Product.all
  end

  def create
    expire_action :action => :index
  end

end

You can also use :if (or :unless) to pass a Proc that specifies when the action should be cached. Also, you can use :layout => false to cache without layout so that dynamic information in the layout such as logged in user info or the number of items in the cart can be left uncached.

Action Caching and Page Caching runs in an after filter. Thus, invalid requests won't generate spurious cache entries as long as you halt them. Typically, a redirection in some before filter that checks request preconditions does the job.


3) Fragment Caching:

Sometimes you only want to cache a section of a page instead of the entire page. Fragment caching is the answer of this.
Fragment Caching allows a fragment of view logic to be wrapped in a cache block and served out of the cache store when the next request comes in.

As an example, if you wanted to show all the orders placed on your website in real time and didn't want to cache that part of the page, but did want to cache the part of the page which lists all products available, you could use this piece of code:
   

<% Order.find_recent.each do |o| %>
  <%= o.buyer.name %> bought <%= o.product.name %>
<% end %>

<% cache do %>
  All available products:
  <% Product.all.each do |p| %>
    <%= link_to p.name, product_url(p) %>
  <% end %>
<% end %>
   
The cache block in our example will bind to the action that called it and is written out to the same place as the Action Cache, which means that if you want to cache multiple fragments per action, you should provide an action_suffix to the cache call:
   
<% cache(:action => 'recent', :action_suffix => 'all_products') do %>
          All available products:

June 4, 2013

install_name_tool reporting malformed object in Mountain Lion

Problem:

Every-time I try to use install_name_tool on my machine it reports the following

install_name_tool: object: xxxxx.x.x.x.dylib malformed object (unknown load command 4) 


I observed that this error could be generated when building the binary.
Whenever I try to change something using install_name_tool. It produces the same result about malformed object (unknown load command 4)

Currently I have XCode Version 4.6.2 running on Mac OSX 10.8.3

I found the solution for this.

Solution:
After wasting lots of time trying different things finally I found that install_name_tool is not updated when XCode is updated. You need to install the Command Line Tool from XCode > Preferences.

install_name_tool on Mac OS X Mountain Lion.

This resolved the same error for me.

April 18, 2013

Install ssh on ubuntu

Install ssh with
sudo apt-get install ssh

Say yes to everything it asks you to install.
Note, you will now have an /etc/ssh/ directory under which you will find a ssh_config and sshd_config file you may have to uncomment a few lines in later.
You then want to run this command:
ssh-keygen -t rsa 

On safer side, it is a good idea to throw a pass phrase in there. For little security.  Make sure it is difficult to guess and NOT the same as your log in password.
Note, it should default to generating 2048 bit encryption which is always better than 1024. You will get a public and private file i.e.
id_rsa and id_rsa.pub
You put the id_rsa which is the private key, in the ~/.ssh directory. You put the public key one up on the server you are remotely connecting too. You can cut and paste it in usually. Make sure you do not introduce any unwanted white space in it. DO NOT put the private key one up on the server you are connecting too.

Troubleshooting:
You may need to restart the service/deamon with
sudo service ssh restart 

This would be necessary if you changed anything in one of the config files. Make sure your permissions are right on the ~./.ssh directory and the files in there.
drwx------ # for .ssh directory
-rw------- # id_rsa for the private key 


Now type from your Ubuntu prompt:
ssh username@yourhost.com

April 15, 2013

Pymongo - TypeError: index 'password' cannot be applied to Cursor instances

In the 10Gen course I am taking of Mongo-db, we are using python to access mongo via pymongo.

I received this "TypeError : index … cannot be applied to Cursor instances" error while attempting to do the following:

user = self.users.find({'_id' : username})
...
salt = user['password'].split(',')[1]



where the "self" variable gave a connection to the mongo db, "users" was a collection on that db, and "username" was a string variable passed into a function containing this code. Initially I didn’t realize that the find() method will always return a full cursor rather than a single document, even if the where clause specifies the primary key field, _id. I’m currently working with iplbeats right now, which when retrieving a "cursor" (users) will always return a single "document" (sObect) if the primary key is supplied in the where clause.

The solution was clear: replace the find() method with the find_one() method to return a document rather than a cursor.

 

April 9, 2013

How to avoid SQL Injection in Rails

SQL injection is any situation in which a user can manipulate a database query in an unintended manner. Consequences of SQL injection vulnerabilities range from data leaks, to authentication bypass, to root access on a database server.

Most Rails applications interact with a database through ActiveRecord, the default and convenient Object Relational Mapping (ORM) layer which comes with Rails. Generally, use of ORMs is safer. ORM can provide abstraction and safety and allow developers to avoid manually building SQL queries. ORM can incorporate best practices and prevent loosely handling of user input.

sqlquery = "SELECT * FROM users WHERE name = '#{name}' AND password = '#{password'} LIMIT 1"
results = DB.execute(sqlquery)

Safer, simpler code like
User.where(:name => name, :password => :password).first

Rails framework will protect them as long as they avoid the "obviously dangerous" methods, like find_by_sql.
ActiveRecord does provide parametrization of queries or some methods. But for some methods it does not provide parametrization of sql queries, these methods are not intended to be used with user input.
Here is an example of using exists?
User.exists? params[:user_id]
However, there is no guarantee params[:user_id] is a string.
Hacker could send a request with ?user_id[]=some_hack_string, which Rails will turn into an array ['some_hack_string']. Now the argument is an array, the first element of which is not escaped.

To avoid this problem, we need to convert the user input to the expected type:
User.exists? :id => params[:user_id]
OR
User.exists? params[:user_id].to_i
This should be the approach for all uses of user input.

April 2, 2013

How to Install PostgreSQL on a Mac

This is a quick guide for installing PostgreSQL (Postgres) on a Mac with Homebrew. If you are planing to use Postgres in your Ruby on Rails App, this tutorial will get you up and running in no time.
I am assuming that you have Homebrew, Ruby on Rails, Xcode, git, rvm etc installed in your mac.

Step 1: Update Homebrew
Before you install anything with Homebrew, you should always make sure it's up to date and that it's healthy by executing following command
brew update
brew doctor

Step 2: Install Postgres

brew install postgresql

When you install Postgres, you will see a bunch of output in your Terminal. There are few instructions like, creating first database, migrating existing database, start/stop PostgreSQL etc. Keep this instructions aside for future reference if you want.

Step 3: Create/Upgrade a database
If this is fresh installation of Postgres with Homebrew, you’ll need to create a database with:

initdb /usr/local/var/postgres -E utf8

I copied this from Terminal output.

Step 4: Create a user
If you want a new user for your new rails app, you can create new user by using createuser command. This will ask few questions.

createuser username 

Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) y
Shall the new role be allowed to create more new roles? (y/n) n

Step 5: Create a database for new user
Create the two databases you will need, development and test. With option -O we can specify the owner of the database.
createdb -Ousername -Eutf8 newapp_development
createdb -Ousername -Eutf8 newapp_test

Done.....
To Verify the installation and database users we can use shell similar to MySQL
psql -U username newapp_development

You will get following prompt

newapp_development=>

Type "help" for help.

April 1, 2013

How to turn off ri and rdoc installation

Most often we never refer to ri and rdoc for all the gems installed on our system.
Sometimes duplicate ri and rdoc are installed on our system when we use ruby version manager (rvm). These documentation takes up few MB of your harddisk. Even space is not a BIG issue.
These ri and rdoc took considerable time while installation. We can increase gem installation time 8x by turning off the ri and rdoc installation.
Turn off ri and rdoc installation. Sure, you can do this on the command-line, like so:

sudo gem install haml --no-ri --no-rdoc

If, like me and most developers, you would rather read the documentation online and have your gems install quickly, then you can disable the documentation generation by creating a file called ".gemrc" in your user's home directory

Better, though, is to set this up as the default in your ~/.gemrc file.

---
:verbose: true
:sources:
- http://gems.rubyforge.org/
- http://gems.github.com/
:update_sources: true
:backtrace: false
:bulk_threshold: 1000
:benchmark: false
gem: --no-ri --no-rdoc

March 18, 2013

Run RhoMobile Apps With XCode Version 4.6.1

I started building Rhodes application on my mac book pro. I had followed every step for building the mobile application using Rhodes. I did configured the Rhodes using rhodes-setup command. On my machine I didn't installed android and blackberry sdk so I skipped those settings.
When I run my application by using following command:

rake run:iphone

I am getting following error;

xcodebuild: error: SDK "iphonesimulator5.0" cannot be located. 

I simply solved this issue by changing the configuration settings of Rhodes.
I found that the invalid SDK is pointed in BUILD.YML

I changed iphone simulator sdk in iphone section in build.yml like this

sdk: iphonesimulator6.1

After this my application could run on the iPhone simulator!

March 3, 2013

How to Install ruby 2.0 with RVM

Ruby 2.0 was released on 24th February 2013, on the 20th birthday of Ruby.
Get the newest version with favorite ruby version manager rvm.
You must install libyaml because Ruby 2.0 deprecated syck in favor of psych.

Make sure you have the latest RVM:
rvm get stable

Execute following command from terminal after installing RVM:

# For Mac with Homebrew
brew install libyaml

# For Ubuntu systems
apt-get install libyaml-dev
rvm pkg install openssl
rvm install 2.0.0 --with-openssl-dir=$HOME/.rvm/usr  --verify-downloads 1
rvm use 2.0.0
rvm use 2.0.0

OR Simply use following
rvm get stable && rvm install ruby-2.0.0

January 21, 2013

Easy google currency conversion gem

When your app wants to convert local currency to any other currency using current exchange rate, then you can convert it using Google API. like http://www.google.com/ig/calculator?hl=en&q=100USD=?INR. This will give you a json string with the converted value. You need to parse the result and get the converted currency value in your app. You can use USD to Yen, EURO to USD etc .. using Google API.

There is a simple interface to handle this using Google API.
Convert any currency to any other currency using easy to use goog_currency gem
A simple Ruby interface for currency conversion using Google API.

How to use:
Add gem file in Gemfile

gem 'goog_currency'

Use bundle to get this gem installed on your system.
Now in your app code you can use functions like follows:
To Get pounds from usd simply use usd_to_gbp

amount = 223
pounds = GoogCurrency.usd_to_gbp(amount)

Get yen from ponds using gbp_to_jpy

amount = 223
yen = GoogCurrency.gbp_to_jpy(amount)

Similarly ....
pounds = GoogCurrency.jpy_to_gbp(amount)
usd = GoogCurrency.gbp_to_usd(amount) 

etc...

You have to pass the amount to those functions.

This will throw an exception in case of any error.
Throws GoogCurrency::Exception in case of any error. And,
Throws GoogCurrency::NoMethodException if conversion method syntax is invalid.

You can find the Source Code here
And Gem here

goog_currency License
MIT License This software is provided as is, use it your own risk.
Copyright (c)  Girish Sonawane

January 17, 2013

How to installing gems when no network

If you have a system with no network connection or you have very restricted firewall connection then its very difficult to install gems.Here is simple work around to solve such problem. You at least need a way to move the files on system.
  • Step 1: Install the required gem on internet connected computer. You can disable the document generation if you desire.
    $ gem install gem_name -i dir_name --no-rdoc --no-ri
    

  • Step 2:  RubyGems has downloaded all the .gem files and placed them in dir_name/cache. You need to Copy this directory to a USB pen drive or some thing else to move directory to the target system. you can use a secure network to transfer it.
  • $ cp -r dir_name/cache /path_to/usb_pen_drive/gems
    

  • Step 3: Install the gems on the target system from the local files
  • $ cd /path_to/usb_pen_drive/gems
    $ gem install --force --local *.gem
    
Thats it ... Your system has a required gem installed