codedecoder

breaking into the unknown…


Leave a comment

ruby installation with rvm

I have installed RVM in this post. make sure that RVM is installed with below command

$ type rvm | head -1 # below message will show that, your rvm is working fine and you are ready to move to ruby installation

rvm is a function

So, our RVM is up and working fine, we will now proceed to install ruby

$ rvm list known # it will list all the available type of ruby(ruby, ree,, jruby etc) with there corresponding version. choose whatever you want. I prefer ruby

# MRI Rubies
[ruby-]1.9.3-rc1
[ruby-]1.9.3-p0
[ruby-]1.9.3-p125
[ruby-]1.9.3[-p194]
[ruby-]1.9.3-head
ruby-head

# JRuby
jruby-1.6.6
jruby-1.6.7
jruby[-1.6.7.2]
jruby-head
jruby-1.7.0.preview1

# Rubinius

rbx-1.2.4
rbx[-head]
rbx-2.0.testing

# Ruby Enterprise Edition
ree-1.8.6
ree[-1.8.7][-2012.02]

$ rvm requirements # it will list the prerequisite for installing a particular type of ruby. you can something like below

Additional Dependencies:
# For Ruby / Ruby HEAD (MRI, Rubinius, & REE), install the following:
ruby: /usr/bin/apt-get install build-essential openssl libreadline6 libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev automake libtool bison subversion

$ sudo apt-get install build-essential openssl libreadline6 libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev automake libtool bison subversion # it will install the requirement mention above

$ rvm install ruby-1.9.3 #it will install ruby-1.9.3 for you. install any other ruby also if you want as below

$ rvm install ree-1.8.7 # it will install 1.8.7 version of ree for you

$ rvm list #it will show you all the installed rubies

rvm rubies

=* ruby-1.9.3-p194 [ i686 ] # see the meaning of symbol =* below, thus ruby-1.9.3 is our current ruby. also it is default one i,e will be loaded if none other is specifed
ree-1.8.7-p358[ i686 ]
# => – current
# =* – current && default
#  * – default

$ ruby -v # It will show you the current ruby version in use by your system
ruby 1.9.3p194 (2012-04-20 revision 35410) [i686-linux]

$ rvm use ree-1.8.7-p358 # so now this will become your current ruby
Using /home/arun/.rvm/gems/ree-1.8.7-p358

$ rvm list #check the difference in symbol before the listed rubies

rvm rubies

= ruby-1.9.3-p194 [ i686 ] # the default ruby
* ree-1.8.7-p358[ i686 ] # the currently used ruby. Note that you have made it current ruby in the last command

$ rvm –default ree-1.8.7-p358 # it will change the default to ree-1.8.7-p358 i,e unless you specify which ruby to use with rvm use command, this ruby will be used by your system


Leave a comment

Rails metrics : load, performance and code quality

Sometime, we need some evaluation of our code to see its robustness, performance, quality etc. These can be gather into a metrics, we will call it Rails Metrics. Fortunately, gems are available to provide all these metrics. A good detail of available metrics can be found here . I personally, feel that at start of your project, we should also set up tools to provide us with metrics under below category.

Metric 1: Code Quality

This will track our code quality in terms of best practice. Best Practices can be found on this site.  it will show error in the metrics when we deviate from the best practices. The rails_best_practices gem can be used for this.

Metric 2: Code test coverage.

This metric will tell you, how much of your code is covered under different test cases and how much is left out. You can then add test cases for those piece of code. A no of tools are available for this on ruby tool box. The gem I preferred is simplecov . If you are using below ruby 1.9.x, you can also use rcov. rcov  do not support ruby 1.9.x.

Metric 3:  Code Performance

It will provide metrics about, your active record calls, method replication, query optimisation etc. newrelic provide performance testing service. Though, it is paid service. In Development mode you can use it for free. The newrelic rpm gem is available here

Metric 4: load metrics

This metric is generally needed for production. I have discussed in detail about various tools available for this in this post

NOTE : There is a no of other metrics also available. metric_fu is the gem which integrate a no of other tool metrics like Flog, Flay, RCov, Saikuro, Churn, Reek, Roodi etc.  So , You can install it directly to get all the metrics at once or keep installing other metric gem as per your need.


Leave a comment

json parsing in ruby

Sometime we want to convert json response to  Hash or array , so that we can easily use it. Ruby provide, json parsing as its core feature. The detail documentation is available here. Let us assume that our json response is stored in sample_json file at  /db/data/sample_json of your project root. Some sample data is available here.  Add one of the sample data to this file, I used the first one. Now, we will parse it on the console

$rails c #move to the console

1.9.3p194 :005 >json_file = File.open(Rails.root.join(“db”, “data”, “sample_json”)) # It will open the json file

1.9.3p194 :006 > json_data = json_file.read # file value is read and stored in json data, this is basically our response, which you will get from some API cals, some methods etc.

1.9.3p194 :007 > a=JSON.parse(json_data) # your response wil be as below

=> {“glossary”=>{“title”=>”example glossary”, “GlossDiv”=>{“title”=>”S”, “GlossList”=>{“GlossEntry”=>{“ID”=>”SGML”, “SortAs”=>”SGML”, “GlossTerm”=>”Standard Generalized Markup Language”, “Acronym”=>”SGML”, “Abbrev”=>”ISO 8879:1986”, “GlossDef”=>{“para”=>”A meta-markup language”, “GlossSeeAlso”=>[“GML”, “XML”]}, “GlossSee”=>”markup”}}}}}

You can also pass, different option to the parser as below

1.9.3p194 :023 > b=JSON.parse(json_d, :max_nesting => false,:allow_nan => true, :symbolize_names => true)
=> {:glossary=>{:title=>”example glossary”, :GlossDiv=>{:title=>”S”, :GlossList=>{:GlossEntry=>{:ID=>”SGML”, :SortAs=>”SGML”, :GlossTerm=>”Standard Generalized Markup Language”, :Acronym=>”SGML”, :Abbrev=>”ISO 8879:1986″, :GlossDef=>{:para=>”A meta-markup language”, :GlossSeeAlso=>[“GML”, “XML”]}, :GlossSee=>”markup”}}}}}

The complete list of option for parse method is as below

parse(source, opts = {}) #Parse the JSON document source into a Ruby data structure 
and return it.

opts can have the following keys:

max_nesting: #The maximum depth of nesting allowed in the parsed data structures. 
Disable depth checking with :max_nesting => false. It defaults to 19.

allow_nan: #If set to true, allow NaN, Infinity and -Infinity in defiance of RFC 4627
to be parsed by the Parser. This option defaults to false.

symbolize_names: #If set to true, returns symbols for the names (keys) in a JSON object.
Otherwise strings are returned.Strings are the default.

create_additions: #If set to false, the Parser doesn't create additions even if a matching class 
and ::create_id was found.This option defaults to true.

object_class: #Defaults to Hash

array_class: #Defaults to Array


Leave a comment

rails on ubuntu with rvm nginx passenger

I have explained deploying rails app with mina in this post. But the script just deploy my source code to the server and set my rvm, gemset and run the bundle. Though, that is great and good enough feature provided by the mina gem, I’ am still short of configuring my deployment with apache or nginx. It was, my first trial with nginx and passenger configuration. I tried a lot of things, get into a no of trouble, which I will post some other day. Here, I will list down the things which worked for me.

To get it work, I surfed a lot of blogs, read original documentation at nginx , nginxwiki and passenger, tried out a no of things myself and realized that what work for other may not work for you, simply because they are on some other environment, using different machine, different version of gem or rvm or ruby or so on. But, no doubt all these reading clear a lot of concepts and give you a direction to proceed.

NOTE : The rails+rvm+nginx+passenger configuration and installation using passenger gem is explained in this post.

STEP 1: Prerequisite

So, first thing first. I have used my friend suresh’s machine as server and deployed my source code using mina script. This is the detail of my overall environment.

-> ubuntu 12.04 # the version of Ubuntu determine which version of certain thing get installed in your system through apt-get install command, say older version of ubuntu may install older version of nginx as compared to this one. generally repository installation is always outdated. example it install nginx 1.1.9 for me when current available version is 1.2.3. don’t worry, I have uninstalled it and manage to install the latest version

-> rvm 1.13.8 (stable) # my rvm is installed as non root user and located  in /home/suresh/.rvm , don’t worry if you have installed as root user, infact many have suggested that it is better to have all server installation as root user. You may have any other version of .rvm, but that version must provide wrappers support i,e there should be wrappers folder in your rvm folder. for example: Iam having  /home/suresh/.rvm/wrappers. If you do not find this in your rvm, the implementation here will not work for you, so upgrade your rvm

-> ruby 1.9.3 # You may have any other ruby version. The thing is that passenger in common case work with only one ruby(though, you can make it work with multiple ruby), which you should able to provide it in its configuration file

-> using gemset : myapp # you may have different name for your gemset

-> my source code is present at /var/www/my_app.com/current # it may be present at any location, but as a common practice put it here. mina deploy my code to current folder  in /var/www/my_app.com and back up the older code to releases folder

-> I have set my application environment to staging # You need to specify the environment in server configuration of nginx, else it will run the default production environment

STEP 2: Understanding the approach

-> You need to have nginx installed on your server

-> You need to have passenger installed on your server

-> You need to configure nginx to load your app and suites your other need

-> You need to tell nginx to work with passenger as application server

-> You need to tell passenger, where is your ruby and gemset

STEP 3: installing nginx and passenger

There is a no of methods available for installing both of them like: from source code, through debian i,e apt-get install , gem install etc. I tried all of them and find that, installing through debian is the best as it do a lot of configuration for you itself and place everything at the default locations. It is almost like, you have run the command and you are done when it is finished. But, its drawback is that, it install from system repository which is always outdated, for example recent ubuntu version (12.04) will install nginx 1.9.1 for you when the recent available version is 1.2.3. So people prefer to install from the source code. I have tried it here. But it give you a lot of configuration headaech and you may mess up thing many a time if missed something.

But, the good thing is that brightbox provide a updated passenger repository with nginx and apache mod which you can install as debian. Thus, you will get the updated versions as well as all the automatic configuration done by debian. For, nginx with passenger just run the below command
$ sudo apt-add-repository ppa:brightbox/passenger-nginx #it will add passenger-nginx repository to your system
$ sudo apt-get update # update the debian of the new repository.
$ sudo apt-get install nginx-full # not down the last few line of the log as will tell you where some file are installed, which will help you in understanding the configuration in general

Unpacking replacement nginx-common …
Preparing to replace nginx-full 1.1.19-1ubuntu0.1 (using …/nginx-full_1%3a1.2.3-1~36~precise1_i386.deb) …
Unpacking replacement nginx-full …
Processing triggers for man-db …
Processing triggers for ufw …
Processing triggers for ureadahead …
Setting up libreadline5 (5.2-11) …
Setting up libruby1.8 (1.8.7.352-2ubuntu1.1) …
Setting up ruby1.8 (1.8.7.352-2ubuntu1.1) …
update-alternatives: using /usr/bin/ruby1.8 to provide /usr/bin/ruby (ruby) in auto mode.
Setting up ruby (4.8) …
Setting up ruby-rack (1.3.5-1) …
Setting up librack-ruby1.8 (1.3.5-1) …
Setting up passenger-common (3.0.17+110~precise1) …
Setting up nginx-common (1:1.2.3-1~36~precise1) …
Installing new version of config file /etc/nginx/nginx.conf …
Installing new version of config file /etc/nginx/sites-available/default …
Installing new version of config file /etc/nginx/uwsgi_params …
Installing new version of config file /etc/init.d/nginx …
Installing new version of config file /etc/logrotate.d/nginx …
Setting up nginx-full (1:1.2.3-1~36~precise1) … # so it installed the most current version for you

NOTE : It will also install passenger at /usr/lib/phusion-passenger

STEP 4: Testing nginx
$ sudo /etc/init.d/nginx start # this will start nginx
full list of the available options are {start|stop|restart|reload|force-reload|status|configtest}

Now, go to browser and type localhost or ip address of your system 192.168.173.52 in my case. I got

500 internal server error

I checked the /var/log/nginx/error.log file for error, which show the below error
rewrite or internal redirection cycle while internally redirecting to /index.html nginx

Solution: edit the default file in site-enabled folder as below

$ sudo su – # change to root user
$ gedit /etc/nginx/sites-enabled/default # it will open the default file for editing

There you will find a no of lines, but most of them are commented out and it just for instruction how to write different type of configuration. They are worth reading, infact you can read them as reference when needed,so better backup it, if you want to change it considerably. For now, just find the below line in the opened file.
root   /usr/share/nginx/www;
try_files   $uri $uri/ /index.html;

Replace, them with below line
root   /usr/share/nginx/html; # the www folder is not there, instead html folder is present so corrected the default root
try_files   $uri $uri/ /index.html =404; # some one suggested it here

Again, Restart the server and type localhost in browser. Yepieee…..nginx is up. You will see

Welcome to nginx!

STEP  5: Configuring your app with nginx
All nginx configuration goes to nginx.conf file. It follow nested block structure(http -> server -> location),with configuration in higher block passing to lower one

http{

server{

locations{

}

}

}

But, since you have installed, nginx through debian, it has structured your thing such that in nginx.conf file you write only http block where as server and location blocks goes to file in site-enabled and conf.d folder. all these files are loaded within http block of nginx.conf with below line, already there.
include /etc/nginx/conf.d/*.conf; #it load all file within sconf.d folder with .conf extension.
include /etc/nginx/sites-enabled/*; # it load all file in site-enabled folder. site related configuration should be placed in individual file in this folder

We will add my_app file within /etc/nginx/sites-enabled folder and add below configuration

server {

listen 8080; #port at which our server will listen
server_name my_app.com; #name of our server
root /var/www/my_app.com/current/public; # <— be sure to point to ‘public’!
passenger_enabled on; # it will set passenger as our application server
rails_env staging; # set the environment. default is production

}

STEP 6: configuring passenger

We will add passenger.conf file in /etc/conf.d folder and add below line to this

passenger_root /usr/lib/phusion-passenger; # it will tell where passenger is present, modify it if it is at some other location
passenger_ruby /home/suresh/.rvm/wrappers/ruby-1.9.3-p194@myapp/ruby; # the ruby path must be from wrappers folder, otherwise will throw error no such file to load — rubygems (LoadError) . I find this blog useful in clearing some of my concept

When, you see the wrappers folder, you will find a separate folders for every ruby you installed and gemset you have created within them. the folder name is combination of ruby_name@gemset_name. within them you can find files for gem, ruby, rake etc. What I feel that, these wrapper automatically, load correct gemset for passenger

STEP 7: Test Your App running

restart the server with the below command
$ sudo /etc/init.d/nginx start # this will start nginx

Go to browser and type IP_of_server:8080 for me it is 168:192:173:52:8080

Yepieeee…. My Home Page is UP  🙂


					
		
	


Leave a comment

toolbar search with jqgird

In my earlier post I have explained, how to implement jqgrid in rails. The detail on enabling toolbar search for jqgird is well documented here

To introduce toolbar we just need to add below script to our view file, displaying our jqgrid. See complete steps in this post. I am rewriting step 5 of that post, which needs the modification.

<div>

<table id=”unsigned_documents_list”></table>
<div id=”unsigned_documents_pager”></div>
<%= raw(unsigned_documents_jqgrid) %>

</div>

Add below lines to enable the toolbar search for the grid

<script type=”text/javascript”>

$(“#unsigned_documents_list”).jqGrid(‘filterToolbar’, { pass options available here } ); #toolbar will get attached to each column of table

</script>

An example of passing the available options is as below. note that the option can be a string, boolean or function

<script type=”text/javascript”>

function set_search(){alert(“Hi”)} # the function passed to beforeSearch option

$(“#unsigned_documents_list”).jqGrid(‘filterToolbar’, {{ searchOnEnter: true, enableClear: false, beforeSearch: set_search} }}); #see that to beforesearch I have  passed set_search function which just alert hi for demo

</script>

Note That, By deafult the above line will add toolbar search to all the column of the grid. But say you do not want search on any column say for status column, then just pass  :search => false to it in step 4 of last post

{name: ‘applied_at’, index: ‘applied_at’, width: 130) # old one

{name: ‘applied_at’, index: ‘applied_at’, width: 130, :search => false} # passing false to search will remove toolbar from the applied_at column


Leave a comment

Sample json data

Sometime, I want to experiment with json data and feel the need of some rough data to work on. I used to generate the data myself while creating array or hash or array of hash and then converting that to json data by using ruby to_json method which basically convert array or hash object to a json object. However, I come across some sample data here and copied here for my future use.

SAMPLE JSON DATA 1 :

{
    "glossary": {
        "title": "example glossary",
		"GlossDiv": {
            "title": "S",
			"GlossList": {
                "GlossEntry": {
                    "ID": "SGML",
					"SortAs": "SGML",
					"GlossTerm": "Standard Generalized Markup Language",
					"Acronym": "SGML",
					"Abbrev": "ISO 8879:1986",
					"GlossDef": {
                        "para": "A meta-markup language",
						"GlossSeeAlso": ["GML", "XML"]
                    },
					"GlossSee": "markup"
                }
            }
        }
    }
}

SAMPLE JSON DATA 2 :

{"web-app": {
  "servlet": [   
    {
      "servlet-name": "cofaxCDS",
      "servlet-class": "org.cofax.cds.CDSServlet",
      "init-param": {
        "configGlossary:installationAt": "Philadelphia, PA",
        "configGlossary:adminEmail": "ksm@pobox.com",
        "configGlossary:poweredBy": "Cofax",
        "configGlossary:poweredByIcon": "/images/cofax.gif",
        "configGlossary:staticPath": "/content/static",
        "templateProcessorClass": "org.cofax.WysiwygTemplate",
        "templateLoaderClass": "org.cofax.FilesTemplateLoader",
        "templatePath": "templates",
        "templateOverridePath": "",
        "defaultListTemplate": "listTemplate.htm",
        "defaultFileTemplate": "articleTemplate.htm",
        "useJSP": false,
        "jspListTemplate": "listTemplate.jsp",
        "jspFileTemplate": "articleTemplate.jsp",
        "cachePackageTagsTrack": 200,
        "cachePackageTagsStore": 200,
        "cachePackageTagsRefresh": 60,
        "cacheTemplatesTrack": 100,
        "cacheTemplatesStore": 50,
        "cacheTemplatesRefresh": 15,
        "cachePagesTrack": 200,
        "cachePagesStore": 100,
        "cachePagesRefresh": 10,
        "cachePagesDirtyRead": 10,
        "searchEngineListTemplate": "forSearchEnginesList.htm",
        "searchEngineFileTemplate": "forSearchEngines.htm",
        "searchEngineRobotsDb": "WEB-INF/robots.db",
        "useDataStore": true,
        "dataStoreClass": "org.cofax.SqlDataStore",
        "redirectionClass": "org.cofax.SqlRedirection",
        "dataStoreName": "cofax",
        "dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver",
        "dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon",
        "dataStoreUser": "sa",
        "dataStorePassword": "dataStoreTestQuery",
        "dataStoreTestQuery": "SET NOCOUNT ON;select test='test';",
        "dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log",
        "dataStoreInitConns": 10,
        "dataStoreMaxConns": 100,
        "dataStoreConnUsageLimit": 100,
        "dataStoreLogLevel": "debug",
        "maxUrlLength": 500}},
    {
      "servlet-name": "cofaxEmail",
      "servlet-class": "org.cofax.cds.EmailServlet",
      "init-param": {
      "mailHost": "mail1",
      "mailHostOverride": "mail2"}},
    {
      "servlet-name": "cofaxAdmin",
      "servlet-class": "org.cofax.cds.AdminServlet"},

    {
      "servlet-name": "fileServlet",
      "servlet-class": "org.cofax.cds.FileServlet"},
    {
      "servlet-name": "cofaxTools",
      "servlet-class": "org.cofax.cms.CofaxToolsServlet",
      "init-param": {
        "templatePath": "toolstemplates/",
        "log": 1,
        "logLocation": "/usr/local/tomcat/logs/CofaxTools.log",
        "logMaxSize": "",
        "dataLog": 1,
        "dataLogLocation": "/usr/local/tomcat/logs/dataLog.log",
        "dataLogMaxSize": "",
        "removePageCache": "/content/admin/remove?cache=pages&id=",
        "removeTemplateCache": "/content/admin/remove?cache=templates&id=",
        "fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder",
        "lookInContext": 1,
        "adminGroupID": 4,
        "betaServer": true}}],
  "servlet-mapping": {
    "cofaxCDS": "/",
    "cofaxEmail": "/cofaxutil/aemail/*",
    "cofaxAdmin": "/admin/*",
    "fileServlet": "/static/*",
    "cofaxTools": "/tools/*"},

  "taglib": {
    "taglib-uri": "cofax.tld",
    "taglib-location": "/WEB-INF/tlds/cofax.tld"}}}

SAMPLE JSON DATA 3 :
If some value is not there, you can put them as NULL, they are equivalent to <separator/> in XML
{"menu": {
    "header": "SVG Viewer",
    "items": [
        {"id": "Open"},
        {"id": "OpenNew", "label": "Open New"},
        null,
        {"id": "ZoomIn", "label": "Zoom In"},
        {"id": "ZoomOut", "label": "Zoom Out"},
        {"id": "OriginalView", "label": "Original View"},
        null,
        {"id": "Quality"},
        {"id": "Pause"},
        {"id": "Mute"},
        null,
        {"id": "Find", "label": "Find..."},
        {"id": "FindAgain", "label": "Find Again"},
        {"id": "Copy"},
        {"id": "CopyAgain", "label": "Copy Again"},
        {"id": "CopySVG", "label": "Copy SVG"},
        {"id": "ViewSVG", "label": "View SVG"},
        {"id": "ViewSource", "label": "View Source"},
        {"id": "SaveAs", "label": "Save As"},
        null,
        {"id": "Help"},
        {"id": "About", "label": "About Adobe CVG Viewer..."}
    ]
}}


Leave a comment

editing file on remote server

Recently, I want to change database.yml file manually on server. This file is not versioned in git due to security reason and we are creating it directly on the server. I tried with gedit but it do not worked . I think gedit will not work for remote server, though I have not confirmed it  🙂 Anyway, I have used below Editors.

Virtual Editor – vi

STEP 1:  login to your server
$ ssh your_server_root_path
your_server_root_path’s password:
$ cd to_your_project

STEP 2: open the file to edit
$ vi your_file_path #this will open your file in the terminal

STEP 3: edit the file
-> press i on you keyboard #it will activate the insert option so now you can change the file
-> use up down left right keys of keyboard to reach the line you want to edit
-> make the changes as you want

STEP 4: exiting the opened file
Now, you have done your changes and want to go back
-> press Esc on your keyboard # it will take you to bottom of the file
-> type below from your keyboard depending on you want to save or not
:q! #you will exit the file without saving the change you made
:wq! # it will write and quit i,e will save your changes

 

NANO EDITOR – nano

STEP 1:  login to your server
$ ssh your_server_root_path
your_server_root_path’s password:
$ cd to_your_project

STEP 2: open the file to edit
$ nano your_file_path #this will open your file in the terminal

STEP 3: edit the file
-> use up down keys to reach the point to make chages

STEP 4: exiting the opened file
Now, you have done your changes and want to go back
-> press ctr+x

-> It will ask you option Y or N. press Y if you want to save the changes or N if you do not want to save