Hexa's Blog

Phoenix and using multiple layouts

26/01/2016 Phoenix

1. How to specify the layout when render() in controllers

There is an option in render/3 method, source In the below example, I did specify the layout, the layout will be located at @conn.assigns[:layout], so as :id

defmodule ImageQuickShare.ImageController do
  use ImageQuickShare.Web, :controller
  def show(conn, %{"id" => id}) do
    render(conn, "show.html", id: id,
           layout: {ImageQuickShare.ImageView, "empty_layout.html"})
  end
end

The directory which locate layout look like:

templates
├── image
│   ├── empty_layout.html.eex
│   └── show.html.eex
├── layout
│   └── app.html.eex
└── page
    └── index.html.eex

2. Setup a default layout for all method within a controller

We have to use plug :put_layout.

defmodule ImageQuickShare.ImageController do
  use ImageQuickShare.Web, :controller
  plug :put_layout, {ImageQuickShare.ImageView, "empty_layout.html"}  #<--- HERE

  def show(conn, %{"id" => id}) do
    render(conn, "show.html", id: id)
  end
end

3. Get advanced from PLUG.

Because of using plug, we can also specify the defaul layout in router. In route.ex we can define an extra pipeline.

pipeline :empty_layout do
  plug :put_layout, {ImageQuickShare.ImageView, "empty_layout.html"}
end

And then, within scope, add the pipeline via pipe_through. Here is an example.

scope "/", ImageQuickShare do
  pipe_through [:browser, :empty_layout] # Use the default browser stack
  get "/", PageController, :index
  get "/image", ImageController, :show
end

REFERENCE

Tweak to ssh quickly any server

24/01/2016 Linux

To ssh to server, I used to type ssh --flags, the command line too long and replication. Here is a solution reduce the pain.

Go to file ~/.ssh/config, and add the following configuration. If the file is not exist, you can make a new one.

Host server-dev1
Hostname  xxx.xxx.xxx.xxx
Port 1022
User nguyenvinhlinh

Host server-dev2
Hostname  xxx.xxx.xxx.xxx
Port 1023
User nguyenhoangson

Right after that, you can use ssh with server alias name.

$ ssh server-dev1
$ ssh server-dev2

Devise, generate hash password

04/01/2016 Ruby on Rails 4

The question is that you are using devise and you want to get hash password from raw password. Here is your solution:

password = 'the secret password'
new_hashed_password = User.new(:password => password).encrypted_password

Rails, How to set redirect path after devise updating password

22/12/2015 Rails

This post is all about how to change redirect url after devise update password (or any?). By default, devise after change password successfully, it will redirect to the root url. There are step you have to do to change the redirect path.

  1. Make devise controllers Or generate using command rails g devise:controllers user

  2. After generating, because I want to change the redirect url after changing password. The only file I concern is passwords_controller.rb, the method you have to override is after_resetting_password_path_for, within this method, you have to declare your favorite redirect url.

for example:

class User::PasswordsController < Devise::PasswordsController
  protected
  def after_resetting_password_path_for(resource)
    change_password_success_path
    #OR "http://google.com"
  end
end

Rails, configuring view path of controller

22/12/2015 Rails

This is a solution to configure the view path of any controller in Rails web framework. The only method you have to concern is self.controller_path

class User::HomeController < ApplicationController
  def self.controller_path
    "users/home"
  end
end

With this configuration, all view of User::HomeController will be located in app/users/home/

How to add new public directory in Phoenix framework

15/12/2015 Phoenix

In Phoenix web framework, there is a share directory /priv. By default, it will only public css,js,images,fonts directory. However, If you want to share a new directory to save upload image for example, you have to end_point file at

/lib/app_name/end_point.ex . Look at plug Plug.Static, the only: macro declares which directory, files could be public. Simply, you have to append your directory name at only:line.

This is my configuration to add a directory named avatar public. This directory is under /priv/static.

plug Plug.Static,
    at: "/", from: :blog_phoenix, gzip: false,
    only: ~w(avatars css fonts images js favicon.ico robots.txt)
    ### Other no need configuration
end

Your tree should look like below

priv
├── repo
│   ├── migrations
│   └── seeds.exs
└── static
    ├── avatars
    │   ├── abc.text
    │   ├── Screenshot\ from\ 2015-12-04\ 22-31-39.png
    │   ├── Screenshot\ from\ 2015-12-11\ 01-49-29.png
    │   └── Screenshot\ from\ 2015-12-14\ 22-21-56.png
    ├── css
    │   ├── app.css
    │   └── app.css.map
    ├── favicon.ico
    ├── images
    │   └── phoenix.png
    ├── js
    │   ├── app.js
    │   └── app.js.map
    └── robots.txt

Rails, how to export excel files

07/12/2015 Ruby on Rails 4

On the front-end, instead of using Ajax(post, get). I uses window.location

$("#export-quote-button").click(function(){
  var encoded = $.param(getQuoteParams(), true);
  var url = "/quotes/tran_stats/export_search_result?" + encoded;
  window.location = url;
});

On the back-end, I uses a gem named spreadsheet

def export_search_result
    require 'spreadsheet'
    require 'stringio'
    Spreadsheet.client_encoding = 'UTF-8'
    book = Spreadsheet::Workbook.new
    sheet1 = book.create_worksheet
    #YOUR DATA PROCESSOR HERE
    file_name = "abc.xls"
    spreadsheet = StringIO.new
    book.write spreadsheet
    send_data(spreadsheet.string, :filename => file_name,
              :type => "application/vnd.ms-excel")
end

Comparison of LinkList,Tuples, Maps, HashDict and Keyword Comparison in Elixir

01/12/2015 Elixir

1. Tuples It’s an order collection of values. There is a tip for using Tuples, a typical tuples has two to four elements

  • Once created, a tuples cannot be modified, the only thing we can do is matching(assigning) variable with new tuple.
  • If the number of tuple element is great,(probably greater than 4 elements), programmer should use Map

2. List (LinkList) The list of Elixir is link-list, there are some features/specification that you should noted.

  • It is easy to travel from head to tail, but expensive to get to particular element for example a[22]. You will have to loop via 21 elements.
  • It’s easy to add an new element to a link-list to the head or tail.

3. Keyword List Keyword list is a list of tuples of pair values. An example below explain the keyword list.

[name: "Linh", age: 2]
[{:name, "Linh}, {:age, 2}]
  • Keyword list allows duplicated key value, because in fact, it’s a list

4. Map Map is used to save collection with a pair of key and value. Unlike keyword list, Map does not allow duplicated keys. Accessing a map by:

states = %{ "AL" => "Alabama", "WI" => "Wisconsin" }
states["AL"]

Excel file, replace special character single quotes which besides numbers

27/11/2015 etc

I have work with spreadsheet gem on ruby, Sometime I do realize that in the LibreOffice, the content is something like '24%, the character single quote refers to a string. However, I want a number instead. A possible way to convert them without programming is Find and Replace. However it does not easy as I say because the character ' is a special character in LibreOffice, you have to use regular expression to work with this.

There is a solution to convert string to number in such case is using replace function name Find and Replace C-h in LibreOffice. In the Search for text, type ^.; in the Replace with, type $. In the other options, please tick on Regular expressions. Finally, you can choose replace or replace all.

Elixir Cheatsheet

20/11/2015 cheatsheet

This is cheatsheet for Elixir, it’s a not a summary of this language, this article all about tweak, remember note for Elixir language.

1. For loop Given that, we we a list of map

people = [
  %{name: "Linh", age: 22},
  %{name: "Son", age: 18},
  %{name: "Long", age: 15},
]
for person <- people, do: (
  IO.inspect person
)

Elixir supports a for conditional loop.

for person = %{age: tuoi}<- people, tuoi < 20, do: (
  IO.inspect person
)

2. Update a map

old_map = %{attr1: 1, attr2: 2 }
new_map = %{old_map | attr1:  3}

3. Struct Generate Struct

defmodule Subscriber do
  defstruct name: "", paid: false, over_18: true
end

sub1 = %Subcriber{}
sub2 = %Subcriber{name: "sub2", paid: true, over_18: false}

Use Struct attribute

sub1.name
sub2.name
sub2[:name]

Update attr in a struct

sub2 = %Subcriber{name: "sub2", paid: true, over_18: false}
sub2 = %{sub2 | name: "Another sub2"}

#alternative solution:
put_in(sub2.name, "new_name")