[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.

Notes:

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

nm-tool 

Result in my machine:

DNS: 192.168.30.29
DNS: 192.168.30.66

=> I’ll use DNS: 192.168.30.29

1. Solution 1

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

{
    "dns": ["192.168.30.29", "8.8.8.8", "8.8.4.4"]
}

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 192.168.30.29 --dns 8.8.8.8 --dns 8.8.4.4 --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 192.168.30.29 --dns 8.8.8.8 --dns 8.8.4.4 --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 (113.171.239.123) 56(84) bytes of data.
64 bytes from static.vnpt.vn (113.171.239.123): icmp_seq=1 ttl=56 time=1.06 ms
64 bytes from static.vnpt.vn (113.171.239.123): icmp_seq=2 ttl=56 time=1.51 ms
64 bytes from static.vnpt.vn (113.171.239.123): icmp_seq=3 ttl=56 time=2.32 ms
64 bytes from static.vnpt.vn (113.171.239.123): icmp_seq=4 ttl=56 time=1.19 ms
64 bytes from static.vnpt.vn (113.171.239.123): 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
   else
     render file: path_to_error_file(404), status: :not_found, layout: false
   end
 end

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
  else
   render file: path_to_error_file(422), status: :422_error, layout: false, 
      content_type: 'text/html'
  end
 end

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)
  end
end

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') }
end

Gem schedule “whenever”

Whenever is a Ruby gem that provides a clear syntax for writing and deploying cron jobs.

Installation

$ gem install whenever

Or with Bundler in your Gemfile.

gem 'whenever', :require => false

 

Getting started

$ cd /apps/my-project
$ wheneverize .

This will create an initial config/schedule.rb file for you.

Show example code in page: https://github.com/javan/whenever

Notes:

– When add new schedule in schedule.rb file => Update schedule by:

whenever -i
OR
whenever --update-crontab

*** Remmember add RAILS_ENV=production or RAILS_ENV=development

– To show all schedule is active:

crontab -l

– To edit schedule was generated and is active:

crontab -e

edit and save.

Format when define schedule

Ex:

every '4 10 * * *' do
 rake "daily:save_diff"
end
* * * * * *
| | | | | |
| | | | | +-- Year              (range: 1900-3000)
| | | | +---- Day of the Week   (range: 1-7, 1 standing for Monday)
| | | +------ Month of the Year (range: 1-12)
| | +-------- Day of the Month  (range: 1-31)
| +---------- Hour              (range: 0-23, 1 in our example)
+------------ Minute            (range: 0-59, 10 in our example)