## How to dynamically assign storage path and url in Paperclip

Thought Paperclip offers storage path and url customization, however, sometimes it just cannot satisfy some situation. For example, when you have a complex path/url generation logic that must be handle outside the model and you don't know the path/url until the last moment before creating model object. In this case, maybe the only way is "PASS" them into the model object, just like passing arguments in C/C++ or Java.

I tried few ways to solve this problem, here I'm going to show you what's NOT gonna work and why and finally what's gonna work it out.

Say there're 2 dependent models
A -> B
which means A owns B. Assume A and B are both literally singular. B has attachement called file. The attachement's path and url will be calculated in controller, in this case, not model .

It works. file was stored in path. Perfect. But when we retrieve from database, e.g.

What the hell are these things happens! Go checkout your disk, file is exactly stored in the location. But you can't find them from the database.

The reason is: @store_path and @store_url are instance variables and they're just not exist in the new object initiated by B.find_by_id(params[:id]). Unless you assign values to them after you create a new object, or it will be nil, thus when you tried to access file.path or file.url, paperclip will send back default value of course. So you got file stored properly but cannot be accessed from database forever. The key for paperclip to use dynamically generated arguments is:

Just save the storage information in database.

It's pretty straight forward. Cost extra 2 columns, which is the price I really don't want to pay at the begining. But well... it's alright.

This phenomenant like the dangling object in C/C++, where a pointer is pointing to some object, then once the pointer's value changes, you could never get a way to access what it was pointed to -- the object.

## 翻.牆.教.學

1. 啟動GoAgent (支援Windows/OSX/Linux，只是啟動方式不一樣)
2. 在瀏覽器設定proxy server

### 檢查是否成功

speedtest.net，或者這裡，看看你的位置是不是來自美國，是的話就成功了！

ps: 日本VPN

## How to take photo from webcam in Linux without official drivers?

### Problem

Few webcams you bought from 3C-market support linux, pretty sad. However there's a way lead you to the heaven:

### Solution

Here is it: fswebcam

It's a light-weight open source program for people to get image from webcams which support V4L or V4L2 protocal. Just install it and type

Try it!

## How to connect PointGrey CCD Fly Capture C/C++ SDK to Java Interface in Netbeans in Ubuntu

### Introduction

This tutorial is about how to use PointGrey's Camera (a CCD vendor from Cadana) by using their FlyCapture SDK(C/C++) as an interface connecting with Java in Ubuntu.

Prepare a PointGrey(PG) camera, Fly Capture SDK, and probably Netbeans IDE. Now here we go.

ps. This tutorial using the C libraries of the SDK, not yet C++, but I believe the setup procedure is similar. If you wanna more powerful features, try C++.

My environment:

• CCD: Chameleon CMLN-13S2C (connect to PC via USB 2.0)
• Fly Capture SDK version: 2.5.2.3 (amd64)
• OS: Ubuntu 12.04 LTS (desktop manager is by default)
• Compiler: gcc 4.6.3
• IDE: Netbeans 7.3
• Java version: 1.6.0_27 OpenJDK Runtime Environment 64-Bit Server VM

### Setting everything up

2. ./install_flycapture.sh

After doing this, you will have C/C++ header files in /usr/include/flycapture/ and dynamic libraries in /usr/lib/, the library you need is libflycapture.so and libflycapture-c.so. Besides, PointGrey also offer you the sample code to use the CCD. Open /usr/src/flycapture you will see bin, lib, src directories.

Now you have some executable program in your computer, try to play with them to see if the connection to CCD via USB is built successfully.

OK, if you could run it without problems, you're on the half of the way. Personally I suggest copy the /usr/src/flycapture folder into another place and play with it. For example:

And try to build the sample code:

Same as it for you to play with another C++ sample codes. Just remember to build FlyCapture2GUI first since all other C++ sample codes here require the GUI interface.

### Now let's connect it to Java

The way for Java connect with C/C++ libraries is called Java Native Interface. You write Java codes and use java compiler auto-generated the C/C++ header interface by include preinstalled jni.h. And then include the auto-generated header interface in your C/C++ code and implement it!

First of all, Fork this project:

It already generate the interface header file for you. Now Craate a Netbean C/C++ dynamic library project, add the FlyCapture2JNI_Interface.c and include PointGreyCameraInterface.h.

You also need to tell Netbeans to include the path of FlyCapture2_C.h, if you're in Ubuntu, it's in /usr/include/flycapture. And you need to add the path of jni.h as well. If you don't know where it is:

Project Property -> C Compiler -> Include Directories -> add:
/usr/include/flycapture
/usr/include/flycapture/C
/path/to/jni/
/path/to/jni/linux

Now the compiler has everything to know: the .c and included .h files. You can compile now but will fail in runtime because you didn't tell where the needed libraries are.

Project Property -> Linker -> Libraries -> select: /usr/lib/flycapture-c.so and /usr/lib/flycapture.so
Project Property -> Linker -> Output -> specify where you want to place the dynamic link library file (.so), this dynamic link library (say, called libInterface.so) will need to be load into your Java project in the future. Remember to name this .so file with prefix "lib". Linux systme recognizes the library in this way. The library file libABC.so will then be include in Java by System.loadLibrary("ABC"), for example.

Now clean and build it, the libInterface.so should be generated, place it into somewhere.

OK, now you got all you need to let Java interact with C/C++ libraries by using libInterface.so. Coding in Java are comfortable but sometimes you need more efficiency, run faster. By this way, you could actually implement some criticle functions in C/C++ and use them in Java. Perfect!

Open a Java application project with Netbeans and add what you just forked, include them in a proper way. One thing to take care: In PointGreyCameraInterface.java, make sure the library you load is just the library you generated.

For this to work, you need to tell where this dynamic library is as usual:
Project Property -> Run -> VM Options -> add:

Done, enjoy =)

## [Rails] How to read EXIF in ActiveRecord with Paperclip

Ref:

Online example
http://regex.info/exif.cgi

migration
rails generate migration AddLatitudeAndLongitudeToModel latitude:float longitude:float
rake db:migrate
https://github.com/alexreisner/geocoder
in case of doing math in the future, datatype is float

model storage
after_attachment_post_process
http://stackoverflow.com/questions/1874851/image-orientation-and-validation-with-paperclip

exiftool api
http://www.sno.phy.queensu.ca/~phil/exiftool/exiftool_pod.html
-d
-c
-j

json to hash
JSON.parse

string to datetime
DateTime.parse

[issue] iOS upload files stripped EXIF

## [Capistrano] Auto Deployment for nginx + thin

Nginx + Thin are greate, but auto deployment makes them even awesome! Here's HOW-TOs by using capistrano:

First assumed that you've set up a Nginx-Thin server, if you don't, please read this post.

Typically, there're few things you will always do after cap deploy:

1. Bundle install: This is most important, otherwise your app might not work at all. This part is included in this post

2. Copy config files: database.yml, thin_config.yml, some scripts... and so on.

3. Precompile assets: This is of course you must do for performance, I think maybe it could be done before deploy but anyway I do this after cap deploy.

4. Migration

5. Restart thin servers and nginx server.

And we're going to make these things done automatically. Here's a sample configuration for deploy.rb

## thin + nginx + rails

### Install

First and of course, install them:

### Configure Thin server

In your rails app, create a thin.yml setting for thin server:

thin.yml:

usage:
thin server -C thin.yml
or if you don't want the config bounded to a specific dir, just don't specify "chdir", then its usage:
cd {some_path}; thin server -C thin.yml

It will create 3 thin servers in port 5000, 5001, 5002

### Connect Nginx with Thin

Now let's set up nginx, insert these code into http{...} section

in /etc/nginx/sites-available create a configure file, or modify default. If you choose to create a configure file, like myApp.com, remember to add it in /etc/nginx/sites-enable as well, make a symbolic link to sites-available.

configure file:

### Worth Notice

1. Remember to run assets pipeline first in your rails app so that nginx could serve the static files (thin is not going to serve static files by default). rake assets:precompile RAILS_ENV=production

2. Create dir "log" and "system" in rails_deployment_dir_path/shared/

#### Problems might face

If you got "413 Request Entity Too Large", that's nginx's setting stuff, in nginx.conf, insert this line of code into http{...}.

### Ref

Ubuntu Hardy - Nginx, rails and thin

Useful command:
sudo service nginx start/stop/restart
sudo service apache2 start/stop/restart
rails db:migrate RAILS_ENV=production
thin start -s 3 -p 5000 -e production
tail -f log/production.log

## [Rails] 如何偵測IP位置來自哪個國家？

### Geocoder

#### Let's Start!

gem geocoder
Then,
bundle install

Geocoder # Module
Geocoder.search("China") # Array
Geocoder.search("China")[0].data # Hash

## deploy Rails to AWS ec2

### local machine

make sure you can ssh host_name connect to your remote server. ssh-add key.pem if neccessary.

Install capistrano, then in your local application dir
capify .
Then
require 'bundler/capistrano'

one more thing:

ok, let's deploy,
git push ec2 master # dont forget push first
cap deploy

Gone for this far, theoretically it should be easy for the rest. However, by my experiences, it's still highly possible to get stucked in any step by any kind of errors.

A command problem might be the shell environment. On one linux machine, there might be different shell environments, sh, bash, cth, ..etc, and different shell environments usually corresponding to different rvm/ruby/rails paths. To solve this problem, one may want to decide the shell environment you want to use in deployment.

By default, capistrano use sh. If you don't want it be your choice, set false in your deploy.rb, ref here:
default_run_options[:shell] = false
or you can specify your favorite, ref here :
default_run_options[:shell] = '/bin/bash' # I haven't test this yet

Once into your favorite shell, there might still be different rvm loading path. Try this, it works for me, ref here:
set :bundle_cmd, 'source \$HOME/.bash_profile && bundle'

good ref: here
this maybe: here, here