[Rails] Check request is_bot or not

def is_bot?(request)
 agent = request.env["HTTP_USER_AGENT"]
 # agent = request.user_agent
 matches = nil
 matches = agent.match(/(facebook|postrank|voyager|twitterbot|googlebot|slurp|butterfly|pycurl|tweetmemebot|metauri|evrinid|reddit|digg)/mi) if agent
 if ( agent.nil? or matches)
   return true
   return false

Another code:

def is_bot?
  http_user_agent = request.env["HTTP_USER_AGENT"] || ""

    ua = ""
    ua = URI.decode(http_user_agent)

  browser = Browser.new(ua: ua)
  return browser.bot?


1 example Googlebot smartphone user-agent

Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) 
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.96 
Mobile Safari/537.36 (compatible; Googlebot/2.1; +

We use agent.match(/(facebook|twitterbot|googlebot)/mi), it will search in user-agent string, find text match googlebot. 

/mi: search downcase and upcase

without /mi: search exactly with googlebot (Googlebot is not match)


[Ruby] Why should we use symbol for key in Hash

Using symbols not only saves time when doing comparisons, but also saves memory, because they are only stored once

1. Symbol and String

– Symbols in Ruby are basically “immutable strings” .. that means that they can not be changed, and it implies that the same symbol when referenced many times throughout your source code, is always stored as the same entity, e.g. has the same object id.

– Strings on the other hand are mutable, they can be changed anytime. This implies that Ruby needs to store each string you mention throughout your source code in it’s separate entity, e.g. if you have a string “name” multiple times mentioned in your source code, Ruby needs to store these all in separate String objects, because they might change later on (that’s the nature of a Ruby string).

2. Use in Hash

– If you use a string as a Hash key, Ruby needs to evaluate the string and look at it’s contents (and compute a hash function on that) and compare the result against the (hashed) values of the keys which are already stored in the Hash.

– If you use a symbol as a Hash key, it’s implicit that it’s immutable, so Ruby can basically just do a comparison of the (hash function of the) object-id against the (hashed) object-ids of keys which are already stored in the Hash. (much faster)

Downside: Each symbol consumes a slot in the Ruby interpreter’s symbol-table, which is never released. Symbols are never garbage-collected. So a corner-case is when you have a large number of symbols (e.g. auto-generated ones). In that case you should evaluate how this affects the size of your Ruby interpreter.


If you do string comparisons, Ruby can compare symbols just by their object ids, without having to evaluate them. That’s much faster than comparing strings, which need to be evaluated.

If you access a hash, Ruby always applies a hash-function to compute a “hash-key” from whatever key you use. You can imagine something like an MD5-hash. And then Ruby compares those “hashed keys” against each other.

Refer: http://stackoverflow.com/posts/8189435/revisions

[Docker] Error: Can’t not access internet from container in Ubuntu 14.04

When I use Docker, I create container from image (Ex: Ubuntu:14.04) and ssh to this container by command:

docker run -it <image_id> bash

When I ssh to container, I used command ping google.com 

but I get error:  ping: unknown host google.com

To fix it, I have 2 solutions, but first, you must get DNS of your machine by command


Result in my machine:


=> I’ll use DNS:

1. Solution 1

– Go to file sudo nano /etc/docker/daemon.json and add your DNS to this file

    "dns": ["", "", ""]

Save it and restart docker by command: sudo service docker restart

2. Solution 2

solution 1- Go to file sudo nano /etc/default/docker, uncomment and add your DNS to this row:

DOCKER_OPTS="--dns --dns --dns --ip-masq=true"

Save it and restart docker by command: sudo service docker restart

If when restart, you get error:

docker stop/waiting
start: Job failed to start

or error:

stop: Unknown instance: 
start: Job failed to start

– You shoud go to file sudo nano /etc/default/docker, and comment row

DOCKER_OPTS="--dns --dns --dns --ip-masq=true"

and try again with solution 1.

==> After you try adding DNS successfully, you can ssh to container and run

ping google.com once again. And this is my result after try fixing with solution 1

root@2beb109bc7b3:~# ping google.com
PING google.com ( 56(84) bytes of data.
64 bytes from static.vnpt.vn ( icmp_seq=1 ttl=56 time=1.06 ms
64 bytes from static.vnpt.vn ( icmp_seq=2 ttl=56 time=1.51 ms
64 bytes from static.vnpt.vn ( icmp_seq=3 ttl=56 time=2.32 ms
64 bytes from static.vnpt.vn ( icmp_seq=4 ttl=56 time=1.19 ms
64 bytes from static.vnpt.vn ( icmp_seq=5 ttl=56 time=1.55 ms

That’s all. Thank you for reading. 🙂

[Docker] Error Cannot connect to the Docker daemon. Is the docker daemon running on this host?

In Ubuntu, when I install Docker successfully, I try running with command:

docker images #show all images in local

but it has error

Cannot connect to the Docker daemon. Is the docker daemon running on 
this host?

because it doesn’t have permission of root. I can run it by command

sudo docker images

Another way, we can config it to needn’t use sudo

  • Step 1: go to /var/run

    cd /var/run
  • Step 2: Add permission for file docker.sock
    sudo chmod -R 776 docker.sock

And now, we can use command docker images for shorter code


Error: AbstractController::DoubleRenderError when render in Rails

When work, I’ve had bug when use 2 render error 404 and 422. 

When I go to link: http://localhost:3000/products/cloths.js. Firstly, controller will understand params {name=cloths.js} and will select in database with name=cloths.js and not found any record with that name, then the website will use function render_404.

After that, website will check 422 error because the link has .js and use function render_422. At this time, this error will appear:

AbstractController::DoubleRenderError (Render and/or redirect were called multiple times in this action. Please note that you may only call render OR redirect, and at most once per action. Also note that neither redirect nor render terminate execution of the action, so if you want to exit an action after redirecting, you need to do something like “redirect_to(…) and return”.)

To fix error, I use this code in function render after

self.response_body = nil

It will

# Clear the previous response body to avoid a DoubleRenderError
# when redirecting or rendering another view

Example for my problem:

In function 404, which render before:

def render_404
   if request.xhr? || request.format.json?
     render json: { meta: { message: "404 not found" } }, status: :not_found, layout: false
     render file: path_to_error_file(404), status: :not_found, layout: false

And in function 422, which render after and has error  AbstractController::DoubleRenderError

def render_422
  self.response_body = nil
  if request.xhr? || request.format.json?
    render json: { meta: { message: "422 Error" } }, status: :422_error, layout: false
   render file: path_to_error_file(422), status: :422_error, layout: false, 
      content_type: 'text/html'

Paperclip AV Transcoder can not upload video

When use gem paperclip-av-transcoder to upload video and get error:

Av::UnableToDetect - Unable to detect any supported library:
  av (0.9.0) lib/av/cli.rb:10:in `initialize'
  av (0.9.0) lib/av.rb:24:in `cli'
  paperclip-av-transcoder (0.6.4) lib/paperclip/paperclip_processors/transcoder.rb:14:in `initialize'

=> May be your computer missing ffmpeg and libav-tools

To install them:

// libav-tools
sudo apt-get install libav-tools

// ffmpeg
sudo add-apt-repository ppa:mc3man/trusty-media
sudo apt-get update
sudo apt-get install ffmpeg gstreamer0.10-ffmpeg


And if after install them, we get error:

Av::CommandError - error while running command avconv -loglevel quiet -i

Let’s uninstall them and reinstall ffmpeg static build

// Uninstall  
sudo apt-get remove ffmpeg  
sudo apt-get purge libav-tools

// install ffmpeg static build
wget http://johnvansickle.com/ffmpeg/builds/ffmpeg-git-64bit-static.tar.xz
tar xf ffmpeg-git-64bit-static.tar.xz
cd ffmpeg-git-64bit-static
sudo mv ff* qt-faststart /usr/bin/

[ActiveAdmin] Conditionally show buttons on show page

For customize buttons in page show in ActiveAdmin, we use:

First, we remove the default buttons from the show page:

# Remove the buttons from the show page
config.action_items.delete_if { |item| item.display_on?(:show) }

Then, add Edit button with conditions

# Add Edit Button with conditional, in show page
action_item :edit,  only: [ :show ] do
  if condition # (Ex: product.is_published?)
    link_to "Edit Product", edit_product_path(resource)

And, add Delete button

# and our Delete Button
action_item :delete,  only: [ :show ] do
  link_to "Delete", resource_path(resource), method: :delete, 
      data: { confirm: I18n.t('active_admin.delete_confirmation') }