#Ruby Class 2: Why Attribute Accessor?

In class 1 we defined the instance variables and know how difficult to accessing it. We managed to access it via calling methods that initializing it.
So we can simplify it by defining access methods.

class Test
 def initialize
  @one = 1
 end 
 def get_one
   @one
 end 
end

The ‘get_one’ method is the reader method for reading the instance variable value.

Ruby has shortcut for this.

class Test
 attr_reader :one
 def initialize
  @one = 1
 end 
 
end

These accessor methods are identical to the methods we wrote by hand earlier.

Sometimes we need to modify the value of these variables from outside. how we do that?

At first we can do this by hand:

class Test
 def initialize
  @one = 1
 end 
 def one=(new_value)
   @one = new_value
 end 
end

The above code allows us to call ‘equal to’ sign on the objects method. This is the setter method. We can set a value to @one like:

t = Test.new
t.one = 3
t.one
=> 3

Ruby also provides a shortcut for this. It is: ‘attr_writer’, so rewrite the above code:

class Test
 attr_writer :one
 def initialize
  @one = 1
 end 
end

Most of the cases we needed ‘attr_reader’ and ‘attr_writer’. So the code becomes:

class Test
 attr_reader :one
 attr_writer :one

 def initialize
  @one = 1
 end 
end

We can again simplify the above code!

class Test
 attr_accessor :one

 def initialize
  @one = 1
 end 
end

How is it? Nice. is n’t it?

#Ruby Class 1: Ruby’s instance variable and initialize method simplified

We read so many documents about ruby but do you think about some facts that we really don’t know. See below.

1. Instance variables are accessible across the class for that instance

Example:

class Test2
 def one
  @one = 1
  @two
 end
 def two
  @two = 2
  @one
 end
end

Here

t = Test.new
=> 
t.one is what ?
t.two is what ?

Can you guess?

t.one is nil why? t.one will return @two, but it is not initialized yet. We have to call t.two for intitializing it (the variable gets a value).

t.two is what?
Ans: 1
Why? because we already initialized @one by calling t.one above. If not it will also return nil.

So what is the purpose of instance variable if we are not getting its value when initializing the Class (say t = Test.new)

Here is the importance of ‘initialize’ method. Lets change the method named ‘two’ to ‘initialize’

class Test3
 def one
  @one = 1
  @two
 end
 def initialize
  @two = 2
  @one
 end
end

then you try:

t = Test.new
=>    ### See here already declared the variable @two

t.one
=> 2

Nice. So we can access that instance variable anywhere in the class. How is that? 🙂

Mongodb how to Import / Export in Linux/Mac

For Importing a mongodb use the following command

$ mongodump --db database_name

This will dump the json/bson files into dump/db_name folder
Or specify a directory with -o option

$ mongodump --db database_name -o path_to_folder

By specifying username and password

$ mongodump --db database_name -o /path/to/folder/ --username=my_user --password="my_password"

For Exporting a mongodb use the following command

$  mongorestore --db database_name path_to_the_json_bson_files

path_to_the_json_bson_files => That we already imported and stored before.

Import one document

$ mongodump --db=db_name --collection=collection_name --out=path_to_folder_to_import
$ mongorestore --db=new_db_name --collection=collection_name path_to_folder_to_import/db_name/collection_name.bson

Sending Gmail calendar events in Rails 4

How to send gmail calendar events to user emails in Rails? Lets see how we can do this. Here we use Rails 4.2 and Ruby 2.2.1 versions.

For this we can use the best available package the ‘icalnder’ gem.

Icalender Github

In Gemfile add:

gem 'icalendar'

We have a user_mailer.rb for sending emails to User. And suppose we are sending emails to manager (User type 1) and a participant (User type 2) when a conversation is scheduled between them.

Create a method as below:

in user_mailer.rb

   def conversation_scheduled(conversation_id, opts={})
      @conversation = Conversation.find_by_id(conversation_id)
      @manager = @conversation.try(:manager)
      @participant = @conversation.try(:participant)
      @base_url = opts['base_url']

      if opts[:send_to] == 'manager'
        cal = calender_event(@conversation, @manager, "Conversation is scheduled with #{@participant.full_name}", "You have scheduled a conversation with Mr/Mrs #{@participant.full_name} on #{@conversation.starting_time}")  
        attachments['conversation_sheduled.ics'] = { :mime_type => 'text/calendar',
                              :content => cal.to_ical }

        mail(to: @manager.try(:email),
             subject: "Conversation is scheduled with #{@participant.full_name}",
             template_name: 'scheduled_manager')
      elsif opts[:send_to] == 'participant'
        cal = calender_event(@conversation, @manager, "Conversation is scheduled with #{@manager.full_name}", "A conversation is scheduled with Mr/Mrs #{@manager.full_name} on #{@conversation.starting_time}")  
        attachments['conversation_sheduled.ics'] = { :mime_type => 'text/calendar',
                              :content => cal.to_ical }

        mail(to: @participant.try(:email),
             subject: "Conversation is scheduled with #{@manager.full_name}",
             template_name: 'scheduled_participant')
      end
    end
private 

def calender_event(conversation, manager, summary, description)
      cal = Icalendar::Calendar.new
      cal.event do |e|
        e.dtstart     = Icalendar::Values::Date.new(conversation.startime.to_date.strftime("%Y%m%dT%H%M%S%Z"))
        e.dtend       = Icalendar::Values::Date.new(conversation.end_time.strftime("%Y%m%dT%H%M%S%Z"))
        e.summary     = summary
        e.description = description
        e.ip_class    = "PRIVATE"
        e.organizer = Icalendar::Values::CalAddress.new("mailto:#{manager.try(:email)}", cn: manager.try(:full_name))
      end
      cal
    end

All we need to do is send an attachment to the email setting the proper mime type to ‘text/calendar’ and the content by calling the ‘to_ical’ method on the event and it returns the calender object.

With proper email templates I do receive the emails with Calendar events and I can add this event to my google calendar and I can update the event details etc.

#Rails 4.2 #Ruby2.2 How to find association class and other info from an object and its association name

When I was working on a Rails project, I encountered a situation where I needed to find the association class of an association object. I have the object and its association name as inputs. How can I find the association class?

Suppose we have Student class that belongs to a school

class School
  has_many students
end

class Student
  belongs_to :school
end

and suppose so many other relations like this in our project.

So we have

s = Student.last
:school symbol 

I can use

s.school.class and s.school.class.name

But what if the school is blank? The result is ‘NilClass’ From the above code.

Basically for has_many associations now we get the class name as

"ActiveRecord::Associations::CollectionProxy"

because recently in new rails version a change of the Array of objects as associations to its own ‘CollectionProxy’ collections.

So we can use ‘ActiveRecord::Reflection::ClassMethods’ for finding all the association info.

Note that this Rails module is so useful to find all the association related information.

In the above situation we can use ‘reflect_on_association’ method for finding association reflection info. And it returns ‘ActiveRecord::Reflection’ Object.

In the most recent version of Rails, there has been a change where Array of objects as associations have been replaced with their own ‘CollectionProxy’ collections. As a result, we can now use ‘ActiveRecord::Reflection::ClassMethods’ to find all the association information we need. This module is extremely useful in finding all association-related information.

To find association reflection information in the situation described above, we can use the ‘reflect_on_association’ method. This method will return an ‘ActiveRecord::Reflection’ object.

http://api.rubyonrails.org/classes/ActiveRecord/Reflection/ClassMethods.html#method-i-reflect_on_association

Check the following code:

> s.class.reflect_on_association(:school)
=> ##}, @scope_lock=#
, @class_name="Topic", @foreign_key="school_id">

#Rails Validation: belongs_to association, How to validate effectively?

Hi guys, how to validate a Rails belongs_to association in most effective way? Did you ever think about that? I am asking this question because there is something that most of the people will not notice. I can explain.

Suppose we have 2 Models ‘User’ and ‘Group’

Condition:
Every ‘User’ must belongs to one of the ‘Group’.

So how we validate this? A simple way of doing this is:

Validate foreign key

class User
  belongs_to group
  validates :group_id, presence: true
end

What this code actually does? Lets find out.

> Group.last.id # => 80
> User.new(group_id: 100).valid? # => true
> Group.exists?(100) # => nil

Oops… Is that true? Not at all. So rails make us fool? Ha. The presence validator will only check a foreign key is provided to it. That’s it. And it will not check the existence of that record. So what we can do in this case? Lets check the other way of doing this.

Validate associated record

class User
  belongs_to group
  validates :group, presence: true
end

Here what the validator does is it checks the record exists or not. If record not exists it returns false for valid? method.

> Group.last.id # => 80
> user = User.new(group_id: 100)
> user.valid? # => false
> Group.exists?(100) # => nil
> user.errors.full_messages # => ["Group can't be blank"]

Wahh..great! But wait, think.. What it actually does in the background? Whenever a user record goes through the .valid? call, rails fire a database query to find this record exists or not. Is that really good? In one way. In other way it’s bad. It affects performance.

But we have to consider database integrity. So the second approach wins even though it is firing an extra query in the background. Cheers!

PostgreSQL 9.3 : Installation on ubuntu 14.04

Hi guys, I just started installing postgres on my ubuntu VM. I referred some docs, and followed this one: https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-14-04

Its pretty much explained in this page. But just explaining here the important things.

You can install postgres by ubuntu’s own apt packaging system. Update local apt repository.

$ sudo apt-get update
$ sudo apt-get install postgresql postgresql-contrib

Postgres uses role based access for the unix users. After the installation a default role called ‘postgres’ will be created. You can login to postgres account and start using or creating new roles with Postgres.

Sign in as postgres user

$ sudo -i -u postgres

Access the postgres console by

$ psql

But i cannot enter into the console and I got the following error:

postgres@8930a29k5d05:/home/rails/my_project$ psql
psql: could not connect to server: No such file or directory
        Is the server running locally and accepting
        connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?

What could be the reason for this error?

So just gone through Postgres doc (http://www.postgresql.org/docs/9.3/static/server-start.html). You can see the same error under the section 17.3.2. Client Connection Problems. But the solution is not mentioned.

Original Reason: PostgreSQL Server was not running after the installation.

I tried rebooting the system and via init script the server should run automatically. But the server is not running again. I understood that something prevents postgres from running the server. What is it?

Just check your postgres server is running or not

$ sudo -aux | grep post
postgres@8930a29k5d05:/home/rails/my_project$ ps -aux | grep postgres
root       136  0.0  0.2  47124  3056 ?        S    06:10   0:00 sudo -u postgres -s
postgres   137  0.0  0.3  18164  3220 ?        S    06:10   0:00 /bin/bash
postgres   140  0.0  0.2  15572  2192 ?        R+   06:10   0:00 ps -aux
postgres   141  0.0  0.0   4892   336 ?        R+   06:10   0:00 grep post

The server is not running.

Run the server manually by

root@8930a29k5d05:/home/rails/my_project#  /etc/init.d/postgresql start
 * Starting PostgreSQL 9.3 database server
                                                                                                                                                         [ OK ] 
root@8930a29k5d05:/home/rails/my_project# ps aux | grep postgres
postgres   158  0.1  2.0 244928 20752 ?        S    06:28   0:00 /usr/lib/postgresql/9.3/bin/postgres -D /var/lib/postgresql/9.3/main -c config_file=/etc/postgresql/9.3/main/postgresql.conf
postgres   160  0.0  0.3 244928  3272 ?        Ss   06:28   0:00 postgres: checkpointer process

postgres   161  0.0  0.4 244928  4176 ?        Ss   06:28   0:00 postgres: writer process

postgres   162  0.0  0.3 244928  3272 ?        Ss   06:28   0:00 postgres: wal writer process

postgres   163  0.0  0.5 245652  6000 ?        Ss   06:28   0:00 postgres: autovacuum launcher process

postgres   164  0.0  0.3 100604  3336 ?        Ss   06:28   0:00 postgres: stats collector process

root       178  0.0  0.0   8868   884 ?        S+   06:28   0:00 grep --color=auto post
root@8930a29k5d05:/home/rails/my_project#

Now the server starts running. If still not works, then try to reconfigure your locales as mentioned here

$ dpkg-reconfigure locales

It is strange that, after installing such a popular database software, it doesn’t provide any information regarding the failure of its own server. It should give the developers some clue so that they can save their precious time.

The reason of this failure, what I concluded is
1. After installation we have to run the server manually
OR
2. I tried resetting the locales (So if no locales set in the machine may prevented the postgres from starting automatically?)

Namespaced classes in Ruby

We can write namspaced classes in ruby in two ways.

Normal way we can wrap the class inside a module. Lets say the module name as ‘MyModule’.
And the constants we define inside this module are accessed as follows:


module MyModule
    CONST1 = 1
    class Myclass
       CONST2 = 2
       def name
          "This is my name"
       end

       def const_1
         CONST1
       end

       def const_2
          CONST2
       end
    end
end

p MyModule::Myclass.new.name
p MyModule::Myclass.new.const_1
p MyModule::Myclass.new.const_2

The other way of doing this is the short way of writing the class name with module name and two columns.
As you can see, the const_1 is accessed as prefixing the module name with two columns.

module MyModule
    CONST1 = 1
end

class MyModule::Myclass
    CONST2 = 2
    
    def name
       "This is my name"
    end
    
    def const_1
        MyModule::CONST1        
    end
    
    def const_2
        CONST2
    end
end

p MyModule::Myclass.new.name
p MyModule::Myclass.new.const_1
p MyModule::Myclass.new.const_2

There is an another way of doing this, that may looks strange to most of the people. Nested classes.

class Myclass
  def name
     "This is my name"
  end

  def my_class_2_name
     Myclass2.new.name
  end

  class Myclass2
    def name
       Myclass.new.name
    end
  end
end

> p Myclass.new.name
> "This is my name"
> p Myclass.new.my_class_2_name
> "This is my name"

The two printing works. So what is the use of these nested classes? Hmmm. It is just namespacing the second class and it tells, somehow it relates to first class even though there is no relation between these two classes.

> p Myclass2.new.name
> uninitialized constant Myclass2

We cannot access Myclass2 without specifying the namespace ( Myclass )

> p Myclass::Myclass2.new.name
> "This is my name"

Set up capistrano deployment for Ruby On Rails

STEP 1:
Install capistrano gem

group :test, :development do
  gem 'capistrano'
end

Install capistrano with rvm

gem 'rvm-capistrano'

STEP 2:
Prepare your Project for Capistrano
Capify your project. The following command initialise your project with Capistrano.

$ capify .

STEP 3:
Do proper modificatons in Capistrano Recipe (config/deploy.rb)
http://guides.beanstalkapp.com/deployments/deploy-with-capistrano.html

Lets do the deployment for staging environment.
Create a ruby file under config/deploy/ folder named staging.rb
Copy the following content

set :domain, "mydomain.in"
role :app, domain
role :web, domain
role :db, domain, :primary => true
role :resque_worker, domain   # if you are using workers in your project, set role for them if needed
role :resque_scheduler, domain # if you are using workers in your project

set :deploy_to, "/home/my_deploy_path/"  # the deployment directory
set :environment, "staging"
set :rails_env, "staging"
set :branch, "staging"
set :previous_environment, "develop"

STEP 4:
Setup capistrano in deployment server

$ cap staging deploy:setup

This will Create folder structure that capistrano uses in the process.

Make sure that everything is set up correctly on the server by the command

$ cap staging deploy:check

Now you can see a message like:
“You appear to have all necessary dependencies installed”

Create shared/config folder in your deploy_to path
and copy database.yml and other config files as you written in the symlink_shared task in cap recipie (if any)

STEP 5:
Deploy your project:

cap staging deploy

How to categorise a blog posts data by month in Ruby On Rails

Suppose we have created a ‘BlogPost’ Model in Rails and it have the following fields in a blog post:

title – title of the blog post
posted_on – date posted
permalink – a permanent link of each blog post (act as a primary key)
publish – a boolean field which decides the post need to show or not

Lets write a method in ‘BlogPost’ Model to get a recent list of posts.
Pass a ‘months_old’ parameter to determine how much months old posts we wanted to list.
Just select the required columns to show the details of the post (by ‘:select => ‘). And Group each post by posted month.

  def self.get_recent_months_post(months_old)
    @blog_posts = where("publish = ? AND posted_on > ?", true, Date.today - months_old.months).all(:select => "title, posted_on, permalink", :order => "posted_on DESC")
    (@blog_posts.group_by { |t| t.posted_on.beginning_of_month }).sort.reverse
  end

We successfully written the method above. Now lets write a method to get the archives (old posts).

  def self.get_archives(old)
    @blog_posts = where("publish = ? AND posted_on  "title, posted_on, permalink", :order => "posted_on DESC")
    (@blog_posts.group_by { |t| t.posted_on.beginning_of_month }).sort.reverse
  end