MySQL queries in rails using ‘mysql’ gem


To establish connection to MySQL database and to handle huge databases in an efficient way, try with the following type of code:

require 'rubygems'
require 'mysql'
db_connection = Mysql.new('localhost', 'mysql_username', 'mysql_passwd', 'database_name')
user_result_set = db_connection.query('SELECT id, name FROM users ORDER BY id ASC')
user_result_set.each_hash { |user|
new_sql = "SELECT id FROM profiles WHERE (user_id = '#{user['id']}' "
profile_result_set = db_connection.query(new_sql)
profile_result_set.each_hash { |profile|
db_connection.query("INSERT INTO user_profiles(user_id, profile_id) VALUES (#{user['id']}, #{profile['id']})")
}
puts "PID: #{user['id']} - #{Time.now} updated"
}
db_connection.close

Simple MongoDB model configuration


Here is a simple Model configuration with MongoDB,

class Item
include MongoMapper::Document
key :user_id, ObjectId
key :name, String, :required => true
key :short_description, String
key :liked_by, Array
key :custom_url, String
key :item_url, String
key :category_id, String
key :source_id, String
key :source_name, String
key :points, Float, :default => 0.0
key :item_image_url, String
# Relationships
# Validations.
# methods
end

Fetch birthday and email address – Facebooker plugin – Rails


By default you’d not be getting birthday and email address of users in the facebook_session as response from facebook. To get them you need something like this in your initialization JavaScript in the body tag of the view file.

<%= fb_connect_javascript_tag %>
<%= init_fb_connect "XFBML",{ :app_settings=>" { permsToRequestOnConnect : 'email,user_birthday' }"} %>
<%= authlogic_facebook_login_button %>

We can also extend the permission for publish_stream, offline_access, etc,.

This will work fine.

Arithmetic operations in a different way – Ruby


Usually arithmetic operations will be done using operators(+, -, * or /) between operands.
This can be also be done like

>> 2.send(:+,3)
=> 5
>> 2.send(:-,3)
=> -1
>> 2.send(:*,3)
=> 6
>> 2.send(:/,3)
=> 0
>> 2.send(:%,3)
=> 2

Easy way to fetch data from associations – Ruby on Rails


If you have models and their associations like the case shown below, the needed data can be fetched in much simpler ways:

User Model
class User < ActiveRecord::Base
has_many :articles

Article Model
class Article < ActiveRecord::Base
belongs_to :user
has_many :article_ratings
has_many :ratings, :through => :article_ratings

ArticleRating Model
class ArticleRating < ActiveRecord::Base
belongs_to :article
belongs_to :rating
Rating Model
class Rating < ActiveRecord::Base
has_many :article_ratings
has_many :articles,:through => :article_ratings

Usually we will take the articles for a user by the following type:

user=User.first
user.articles

The case will be simpler if the requirement is articles for the user.

Incase if we need to collect the article_ratings for the particular user,
user.articles.each do |art|
some_arr << art.article_ratings
end

this can be done much simpler like:

user.articles.map(&:article_ratings).flatten

Similarly iff we need the articles for the user based on the article_ratings relationship,

user.articles.map(&:article_ratings).flatten.map(&:article).flatten

Hope this will make the query much simpler.

warning: default `to_a’ will be obsolete – Ruby arrays


Yo may get this warning on some occasions when trying to convert a value to array.

>> hash={"a"=>1,"b"=>2,"c"=>3}
=> {"a"=>1, "b"=>2, "c"=>3}
>> hash.each{|key,value| value.to_a }
(irb):63: warning: default `to_a' will be obsolete
(irb):63: warning: default `to_a' will be obsolete
(irb):63: warning: default `to_a' will be obsolete
=> {"a"=>1, "b"=>2, "c"=>3}

To recover from this warning message try with the following code:

>> hash.each{|key,value| [*value].to_a }
=> {"a"=>1, "b"=>2, "c"=>3}

Merge two hashes without data loss – Ruby


Hashes can be merged by either merge or update options. This will progress with data loss, since the new value will overwrites the old value if both keys are equal. To avoid such data losses try with the following code:

>> hash1={"a"=>1,"b"=>2,"c"=>3}
=> {"a"=>1, "b"=>2, "c"=>3}
>> hash2={"c"=>4, "d"=>5,"a"=>3}
=> {"a"=>3, "c"=>4, "d"=>5}
>> hash1.merge(hash2)
=> {"a"=>3, "b"=>2, "c"=>4, "d"=>5}
#"a"=>1 & "c"=>3 items in hash1 were lost
>> hash1.merge(hash2){|key,oldval,newval| [*oldval].to_a + [*newval].to_a }
=> {"a"=>[1, 3], "b"=>2, "c"=>[3, 4], "d"=>5}

Values with same keys will be converted into Array format ensuring Nil data loss.

Hash merge Vs update – Ruby


Let hash1 & hash2 be two hashes,

>> hash1={"a"=>1,"b"=>2,"c"=>3,"d"=>7}
=> {"a"=>1, "b"=>2, "c"=>3, "d"=>7}
>> hash2={"d"=>4,"e"=>5}
=> {"d"=>4, "e"=>5}

The main difference between the merge and update options for a hash is that the result have to be stored manually in any hash variable for merge and it gets stored automatically in the first hash for update.

For Example:

Merge:
>> hash1.merge(hash2)
=> {"a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5}
>> hash1
=> {"a"=>1, "b"=>2, "c"=>3, "d"=>7}
>> hash2
#the values of hash1 & hash2 remains unchanged
=> {"d"=>4, "e"=>5}
>> hash=hash1.merge(hash2)
=> {"a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5}
>> hash
=> {"a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5}

Update:
>> hash1.update(hash2)
=> {"a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5}
>> hash1
#the result hash is stored in hash1
=> {"a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5}

Common elements from a group of Arrays – Ruby


To extract the common elements(Intersection) from a group of Arrays(say in hashes), try with the following code:

>> h={"a"=>[1,2,3,5], "b"=>[1,3,5], "c"=>[2,4,6,1]}
=> {"a"=>[1, 2, 3, 5], "b"=>[1, 3, 5], "c"=>[2, 4, 6, 1]}
>> h.values.inject{|k,v| k & v }
=> [1]

Similarly, to find the Union of several group of Arrays, the following code works fine,

>> h.values.inject{|k,v| k | v }
=> [1, 2, 3, 5, 4, 6]

Batch processing in rails query


When handling table with huge content we can use batch processing type of find query in rails as follows:

User.find_in_batches(:batch_size=>1000){|users| puts users.collect(&:username)}
#- where users contains 1000 records of each batch.

The above query will process only 1000 records at a time and after the process is complete, it will process the next 1000 records and so on.

For Example:

>> User.find_in_batches(:batch_size=>3){|users| puts "<------------------->"; puts users.collect(&:username)}
pradeep
vatti
udhaya
<------------------->
ukesh
senthil
nagaraj
<------------------->
rajesh
arun
karthick
<------------------->
kumar
selva
pdp
<------------------->
ram
kannan