Apr 29, 2011

We have to use Full-text indexing at some point

I have found that the blog describes very well about Full-text indexing modules:

http://locomotivation.squeejee.com/post/109279130/simple-ruby-on-rails-full-text-search-using-xapian

http://locomotivation.squeejee.com/2008/07/15/mulling-over-our-ruby-on-rails-full-text-search-options

Database design for tag-based search

Ref: http://incarnate.ru/post/1439084341/database-design-for-tag-based-search#disqus_thread

Apr 26, 2011

Delayed Job cheatsheet

To add email sending to background job, use:


# NotificationMailer.deliver_welcome_user(@user)
# We do not use the above line anymore
NotificationMailer.send_later(:deliver_welcome_user, @user)


Or you can use a more customizable version:



# put this in lib/delayed_notification.rb
class DelayedNotification
attr_accessor :user_id
def initialize(user_id)
self.user_id = user_id
end

def perform
NotificationMailer.deliver_welcome_user(User.find(@user_id))
end
end

# Add this where you were sending the mail earlier
Delayed::Job.enqueue DelayedNotification.new(@user.id)


Ref: http://8raystech.com/2009/2/28/background-job-processing-in-rails-with-delayed_job

Stop Aptana RadRails from generating .tmp (for HTML previewing)

It's quite annoying for us that Aptana RadRails keeps generating .tmp__... for HTML and ERB files that are previewed.

Therefore, in order to disable it:

1. Go to Preferences
2. Aptana->Editors->HTML->Preview
3. Uncheck 'Generate temporary files for browser previews'

Apr 20, 2011

A service to start at boot time

We have to build a shell script with this line

# chkconfig: - 85 15

(Please google to see what it means)

Then we type


chkconfig <your_service_file_name> on


That's it.

Run background process with Capistrano

To run a background process with Capistrano is so difficult. I have tried few different ways and I found the working one.

It turns out that you need to use a command, nohup together with &, which is put in a shell script file.

Then in Capistrano file (deploy.rb), you'll need to use run the shell script with >/dev/null 2>&1.

And that's it.

-------

I have tried use :pty=>true option on the Capistrano's run command. It produces a very strange behavior. Sometimes the background process is started and sometimes it is not...

And without >/dev/null 2>&1, there will be an output, which blocks Capistrano from proceeding forward...

Fix: msvcr90.dll is either not designed to run ... error

Out of nowhere, my beloved Vaio has the error on msvcr90.dll. It just corrupted. Just like that.

The fix is really simple. Just replace the DLLs file.

mscvr90.dll is the files of Visual Studio 2008 redistributable.

Go to C:\Program Files\Microsoft Visual Studio 9.0\VC\redist\x86\Microsoft.VC90.CRT...

Copy all 3 DLLs to the destination folder. and that's it.. it works like a charm.

Apr 16, 2011

Full error reporting on Rails production

Just comment all these lines:


# The production environment is meant for finished, "live" apps.
# Code is not reloaded between requests
config.cache_classes = true

# Full error reports are disabled and caching is turned on
config.action_controller.consider_all_requests_local = false
config.action_controller.perform_caching = true
config.action_view.cache_template_loading = true


And add these lines, instead:


config.cache_classes = false

# Log error messages when you accidentally call methods on nil.
config.whiny_nils = true

# Show full error reports and disable caching
config.action_controller.consider_all_requests_local = true
config.action_view.debug_rjs = true
config.action_controller.perform_caching

Apr 15, 2011

Bad URI with oauth token

Bad URI error occurs when we do OAuth verification. (I found it because of Facebook connect)

This is because the OAuth token contains a special character, precisely, |. I think there can be other characters that cause Bad URI error.

Moreover, I have found that the Bad URI only occurs with WEBRick, a webserver provided by Ruby.

Therefore, in order to fix it, I had to modify Ruby source code.

Here is what I have done:

In the file httpresponse.rb, which resides in C:/Ruby187/lib/ruby/1.8/webrick (This depends on where you installed Ruby)

Around the line 164:

# Location is a single absoluteURI.
if location = @header['location']
if @request_uri
@header['location'] = @request_uri.merge(location)
end
end


Add URI.encode() around location before @request_uri.merge()


# Location is a single absoluteURI.
if location = @header['location']
if @request_uri
@header['location'] = @request_uri.merge(URI.encode(location))
end
end


And that's it.

I'm gonna fix this in the Ruby open source project also. This will be my first open source participation, yeahhhh.

Apr 13, 2011

Communications link failure (MySQL)

When you find this exception:

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The cause is that you cannot to MySQL server. Simply, try:


telnet 127.0.0.1 3306


in order to verify that it does not work.

My problem is that I bind MySQL server to a specific address.

I fix it by binding MySQL server to 0.0.0.0 (all network interface).

Apr 12, 2011

Get POST parameters from Java HTTP Server

It turns out that it is not very simple to do so.

First, Create a class name ParameterFilter


/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/

package friendposter;

import com.sun.net.httpserver.Filter;
import com.sun.net.httpserver.Filter.Chain;
import com.sun.net.httpserver.HttpExchange;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
*
* @author Tanin
*/
public class ParameterFilter extends Filter {

@Override
public String description() {
return "Parses the requested URI for parameters";
}

@Override
public void doFilter(HttpExchange exchange, Chain chain)
throws IOException {
parseGetParameters(exchange);
parsePostParameters(exchange);
chain.doFilter(exchange);
}

private void parseGetParameters(HttpExchange exchange)
throws UnsupportedEncodingException {

Map parameters = new HashMap();
URI requestedUri = exchange.getRequestURI();
String query = requestedUri.getRawQuery();
parseQuery(query, parameters);
exchange.setAttribute("parameters", parameters);
}

private void parsePostParameters(HttpExchange exchange)
throws IOException {

if ("post".equalsIgnoreCase(exchange.getRequestMethod())) {
@SuppressWarnings("unchecked")
Map parameters =
(Map)exchange.getAttribute("parameters");
InputStreamReader isr =
new InputStreamReader(exchange.getRequestBody(),"utf-8");
BufferedReader br = new BufferedReader(isr);
String query = br.readLine();
parseQuery(query, parameters);
}
}

@SuppressWarnings("unchecked")
private void parseQuery(String query, Map parameters)
throws UnsupportedEncodingException {

if (query != null) {
String pairs[] = query.split("[&]");

for (String pair : pairs) {
String param[] = pair.split("[=]");

String key = null;
String value = null;
if (param.length > 0) {
key = URLDecoder.decode(param[0],
System.getProperty("file.encoding"));
}

if (param.length > 1) {
value = URLDecoder.decode(param[1],
System.getProperty("file.encoding"));
}

if (parameters.containsKey(key)) {
Object obj = parameters.get(key);
if(obj instanceof List) {
List values = (List)obj;
values.add(value);
} else if(obj instanceof String) {
List values = new ArrayList();
values.add((String)obj);
values.add(value);
parameters.put(key, values);
}
} else {
parameters.put(key, value);
}
}
}
}
}



Then, when start a server, please add ParameterFilter as a filter:


HttpServer server = HttpServer.create(new InetSocketAddress(PORT),100);

HttpContext context = server.createContext("/", new FriendPosterServer());
context.getFilters().add(new ParameterFilter());

server.setExecutor(null); // creates a default executor

server.start();


Then, in the handler, you may obtain parameters like this:


public void handle(HttpExchange t) throws IOException
{
...
Map params = (Map)t.getAttribute("parameters");
...
}

Java to do HTTP Post and read response's content


public void postToCallbackUrl()
{


int retry_count = 0;

while (retry_count < 3)
{
try
{
// do HTTP request
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
formparams.add(new BasicNameValuePair("print_image_url", printImageUrl));
formparams.add(new BasicNameValuePair("signature_image_url", signatureImageUrl));
formparams.add(new BasicNameValuePair("order_key", orderKey));

UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, "UTF-8");

HttpPost httppost = new HttpPost(callbackUrl);
httppost.setEntity(entity);

HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(httppost);

logger.debug("Got response:" + IOUtils.toString(response.getEntity().getContent(), "UTF-8"));

break;
}
catch (Exception e) {
retry_count++;

logger.error("Post error",e);
}
}
}

How to migrate database in production environment


rake db:migrate RAILS_ENV="production"