Facebookとのアプリの連携を解除する

調べてみたら自分所のDBからFacebookの情報を消すだけのものが多くて、大元のFacebookのアプリ設定から削除するのがあんまり載ってなかったようなきがするので

以下の感じで、連携解除ができます。

1
2
3
4
5
6
$facebook = new Facebook(array(
'appId' => アプリのapp_id,
'secret' => アプリのapp_secret
));

$facebook->api("/me/permissions", "delete", array('access_token' => ユーザーのアクセストークン));

珍しくPHPでした。


s3からcliでファイルをまとめて落としたり、正規表現で落とせたりするツール

s3 getter.rbとか名前つけて保存して
ruby s3
getter.rbとかで起動すると

最初にbucket選ぶ選択肢が出てきて選択すると、bucketのディレクトリかファイルか、ファイル全てダウンロードが選べ。
ディレクトリを選ぶと再帰的にまたディレクトリかファイルかファイル全てをダウンロードが選べます。

ファイルもしくは全てダウンロードを選ぶと、ダウンロードと同時に解答するか選べ(すいません。現状gzの解凍のみ)
また抽出するファイル名を正規表現で絞り込めるかを選べます。

動くの重視で片手間に作ったのでノー例外処理でございます。
gz圧縮以外にも対応したいとかあれば、ご自由に改変してお使いください。

Gist
https://gist.github.com/YoshitsuguFujii/349069b2e74c28153a17

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# coding: utf-8

require "aws-sdk"

S3_SAVE_DIR = "s3/"
ALL_FILE_DOWNLOAD = "全てのファイルを落とす"

s3 = AWS::S3.new(
  access_key_id: "YOUR AWS ACCESS KEY"
  secret_access_key: "YOUR AWS SECRET"
)

def show_item_with_pointer(iterator, console_print = true)
  rtn_hash = {}
  iterator.each_with_index do |value, idx|
    rtn_hash[idx.to_s] = value
    if console_print
      p "[" + (idx).to_s + "] " + value.inspect.to_s
    end
  end

  rtn_hash
end

def ls(tree)
  ls = []
  directories = tree.children.select(&:branch?).collect(&:prefix)
  files = tree.children.select(&:leaf?).collect(&:key)

  #all_select = files.length > 1 ?  [ALL_FILE_DOWNLOAD] : []
  all_select = [ALL_FILE_DOWNLOAD]
  ls = all_select.concat(directories.concat(files))
end

def get_or_into_directory_recursive(tree)
  file_and_directories = show_item_with_pointer(ls(tree))

  idx = gets_from_stdin("fileまたはdirectoryを数値で選択")

  file_or_directory = file_and_directories[idx]

  # select dir
  if file_or_directory.end_with?("/")
    tree = @bucket.as_tree({prefix: file_or_directory})
    objs = get_or_into_directory_recursive(tree)
  else
    objs = []
    # select all
    if file_or_directory == ALL_FILE_DOWNLOAD
      objs = get_objects(file_and_directories)
    # select file
    else
      objs << @bucket.objects[file_or_directory]
    end
  end

  return objs
end

# http://qiita.com/riocampos/items/cf71862bf975e13bdb4a
def progress_bar(i, max = 100)
  i = i.to_f
  max = max.to_f
  i = max if i > max
  percent = i / max * 100.0
  rest_size = 1 + 5 + 1 # space + progress_num + %
  bar_size = 79 - rest_size # (width - 1) - rest_size
  bar_str = '%-*s' % [bar_size, ('#' * (percent * bar_size / 100).to_i)]
  progress_num = '%3.1f' % percent
  print "  r#{bar_str} #{'%5s' % progress_num}%"
end


def get_objects(file_and_directories)
  objs = []
  file_and_directories.each do |idx, path|
    next if path == ALL_FILE_DOWNLOAD
    if path.end_with?("/")
      tree = @bucket.as_tree({prefix: path})
      recursive_file_and_directories = show_item_with_pointer(ls(tree), false)
      objs.concat(get_objects(recursive_file_and_directories))
    else
      objs << @bucket.objects[path]
    end
  end

  objs
end

def gets_from_stdin(message = nil)
  print message unless message.nil?
  str = STDIN.gets.chomp
end


def get_y_or_n_from_stdin(message)
  bol = ""
  while !%w(Y N).include?(bol.upcase)
    bol = gets_from_stdin("#{message}(y/n)")
  end
  bol.upcase == "Y"
end

all_buckets = show_item_with_pointer(s3.buckets)

idx = gets_from_stdin("bucketを数値で選択")

@bucket = all_buckets[idx]
tree = @bucket.as_tree

files = get_or_into_directory_recursive(tree)

s3_dir = File.expand_path(S3_SAVE_DIR)

# gz圧縮なら解凍するか問う
extract_bol = if files.any?{|file| file.key.include?("gz")}
                get_y_or_n_from_stdin("解凍を同時に行いますか?")
              else
                false
              end

# 正規表現抜き出しを行うか問う
regexp = nil
if get_y_or_n_from_stdin("正規表現によるファイル名絞り込みを行いますか?")
  regexp = Regexp.new(gets_from_stdin("正規表現を入力してください"))

  files = files.reject do |file|
    file_path = [s3_dir,file.key].join("/")
    File.basename(file_path).match(regexp).nil?
  end

end

# 保存処理
files.each.with_index(1) do |file, idx|
  file_path = [s3_dir,file.key].join("/")
  dir = File.dirname(file_path)
  FileUtils.mkdir_p(dir)

  File.open(file_path, 'wb') do |f|
    file.read do |chunk|
      f.write(chunk)
    end
  end

  if extract_bol
    `gunzip #{file_path}`
  end

  progress_bar((idx.to_f / files.length) * 100)
end

godでThe server is not available (or you do not have

色々と設定をいじっていて、godのプロセスが立ち上がらなくなった。

1
2
rbenv exec bundle exec god terminate
# => The server is not available (or you do not have permissions to access it)

多分rootとかで色々やった時に出きたpidファイルとかが悪さしてるんだろうなー。
って思ったけどどこにあるのか?

とりあえずRAILS _ROOTのtmpを見てみるけど。ない

軽くはまりつつも、/tmpにありました。
/tmp/god.12223.sock

コレを消して無事解決!


jQueryのappendが重かったので対応したこと

railsでチェックボックスで会社を選択して、ajax通信で返すjsの内容がこんな感じだった。

1
2
3
4
5
  <% @company.each do |company| %>
    <% company.member.each do |customer| %>
        $("#customer_area").append("<%= escape_javascript(render("make_customer_area", cid: customer.id)) %>");
    <% end %>
  <% end %>

重い。console.time仕込んで計測したらappendがめちゃめちゃ重い。
一回のappendで1秒ぐらいかかってた。

毎回appendじゃなくて、一回でappendしてみる

1
2
3
4
5
6
7
8
9
10
11
  var html = []
  var customer_area = $("#customer_area")
  <% @company.each do |company| %>
    <% company.member.each do |customer| %>
        html.push("<%= escape_javascript(render("make_customer_area", cid: customer.id)) %>");
    <% end %>
  <% end %>

  if ( html.length > 0 ){
    customer_area.append(html.join(''))
  }

あんまり変わらないなぁ。
というかappendやめよ。もうやめよ。

1
2
3
4
5
6
7
8
9
10
11
  var html = []
  var customer_area = document.getElementById("customer_area");
  <% @company.each do |company| %>
    <% company.member.each do |customer| %>
        html.push("<%= escape_javascript(render("make_customer_area", cid: customer.id)) %>");
    <% end %>
  <% end %>

  if ( html.length > 0 ){
    customer_area.innerHTML = customer_area.innerHTML + html.join('')
  }

約0.5秒ぐらい早くなった。いいね。
でもinnnerHTML使ってるから、何回か会社をクリックするとinnerHTMLにテキストが溜まりすぎてだんだん重くなる。
innnerHTML参照せずにappendChildで追加しよう。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  var html = []
  var customer_area = document.getElementById("customer_area");
  <% @company.each do |company| %>
    <% company.member.each do |customer| %>
        html.push("<%= escape_javascript(render("make_customer_area", cid: customer.id)) %>");
    <% end %>
  <% end %>

  if ( html.length > 0 ){
    var element = document.createElement('div');
    element.innerHTML = html.join('');
    customer_area.appendChild(element);

  }

これで当初の半分ぐらいまでは処理時間が軽減されました。


knexで外部キー制約のマイグレーション

Node.js向けORM Bookshelfの紹介を参照させていただきながら、Bookshelf触ってみている。

ページではsqlite3だけど、自分はmysqlで使っている。

外部キー制約の部分。

1
 t.integer('post_id').notNull().references('id').inTable('posts');

がmysqlではCannot add foreign key constraintが出て動かなかった。

これで動いた。

1
t.integer('post_id').unsigned().notNullable().references('id').inTable('posts');

csvからuserを検索して、データ更新サンプル

例えば外部システムとユーザの情報を持ち合っている時。
外部システムのuser id(コード内ではuser external _id)から、システム内のユーザIDを導き出して、そのデータにパッチを当てるスクリプト。

active _recordとかは単品で扱ってる(database.yml'読み込み)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/usr/bin/env ruby
# coding: utf-8
require 'csv'
require 'optparse'
require "active_record"

params = ARGV.getopts('', 'csv:user.csv', 'ENV:development', 'RAILS_ROOT:./')
p params

config = YAML.load_file( params['RAILS_ROOT'] + 'config/database.yml' )
raise ArgumentError, 'ENVが設定されていません'            if params['ENV'].nil?
raise ArgumentError, 'RAILS_ROOTが指定されていません'     if params['RAILS_ROOT'].nil?
raise ArgumentError, 'database.ymlを読み出せませんでした' if config[params['ENV']].nil?
raise ArgumentError, 'csvファイルが存在しません'          unless File.exists?(params['csv'])

ActiveRecord::Base.establish_connection(config[params['ENV']])
class User < ActiveRecord::Base
end

column = %w(user_external_id  name birthday)
CSV.foreach(params['csv']) do |row|
  # 一行を全部hashに入れる
  row_hash = {}
  row.each_with_index do |r,idx|
    row_hash[column[idx]] = r
  end

  user = User.find_by_external_id(row_hash['user_external_id'])
  if !user.nil?
    user.update_attribute(:name => row_hash['name'])
  end
end

実行はターミナルで

1
2
3
ruby 上記コードのファイル --ENV production
もしくは
bundle exec ruby 上記コードのファイル --ENV production

とかとか

スクリプトのオプションは
–ENVはdatabae.ymlの読み込みたい環境{development|production}
–csv で読み込むファイルパス
–RAILS _ROOT でRailsのapp rootを指定。

さらさらっと書いて本番のrails rootで動かしてパッチを実際に当てましたが。
仕事にかかわる記述は消したり直したり、ロクにテストしていないので動かなかったらごめんなさい。


半角カナが入力されているファイルを抽出

お客様から、半角カナを全角カナにしておくれと依頼がきていたので、railsのrootから半角カナを含むファイルを抜き出したくてスクリプト書きました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/usr/bin/env ruby

require 'find'

except_ext = %w(.log .yml .jpg .JPG .jpeg .png .pid .ttf .woff .md .json .ico .eot .gif)                                                    # 除外するファイル拡張子を設定
except_pattern = %w(.git test .DS_Store migrate hankaku_kana_checker RackMultipart sprockets letter_opener underscore cache)                # 除外するパスに含まれる文字列を指定

# チェックする半角カナの配列
han_kana =  %w{ア イ ウ エ オ カ キ ク ケ コ サ シ ス セ ソ タ チ ツ テ ト ナ ニ ヌ ネ ノ ハ ヒ フ ヘ ホ マ ミ ム メ モ ヤ ユ ヨ ラ リ ル レ ロ ワ ヲ ン ァ ィ ゥ ェ ォ ャ ュ ョ ッ ゙ ゚ 、 。 ー 「 」}

Find.find(File.expand_path('./')) do |path|
  next if File.directory?(path)
  next if except_ext.include?(File.extname(path)) # 調査しない拡張子
  next if path.match(Regexp.new(except_pattern.join("|")))

  begin
    File.readlines(path).each.with_index(1) do |line, idx|
      @idx, @line = idx, line
      # CP932のファイルが混在してたのでダメならCP932で変換
      include_han_kana = begin
                           line.match(Regexp.new(han_kana.join("|")))
                         rescue
                           line.encode("UTF-8", "CP932").match(Regexp.new(han_kana.join("|")))
                         end

      if include_han_kana
        p [idx, path, line].join(": ")
      end
    end
  rescue => ex
    p "####################################################################################################"
    p [@idx, @line].join(": ")
    p [ path, ex.message ].join(":")
    p ex.backtrace.first
    p "####################################################################################################"
  end
end

再帰的にディレクトリをくだって、探します。
含めたくないファイル名やディレクトリ名。拡張子を指定できます。

良かったら使ってみてください。


Terminalでsshするときに、接続先に応じて背景色を変える方法

朝これを見た。

iTermでsshするときに、接続先に応じて背景色を変える方法
http://qiita.com/k_kinukawa/items/3e5665325a4954e33019

いいなと思った。

でも普段僕はMacの標準のTerminalを使っている。
Terminalで同じこと出きないかなとぐぐったらすぐあった。

https://github.com/dlobraico/dotfiles/blob/master/bin/ssh-host-color

でも僕は透過率が75%にしていて透過率を設定したいのだけど。
osascriptで透過率の設定がよくわからない。

というか普段ターミナルの色とかはProの設定を使っているのでProの使いたいなーって思ってググってprofileを切り替えられるようにした。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!/bin/bash
#
# ssh into a machine and automatically set the background
# color of Mac OS X Terminal depending on the hostname.
#
# Installation:
# 1. Save this script to /some/bin/ssh-host-color
# 2. chmod 755 /some/bin/ssh-host-color
# 3. alias ssh=/some/bin/ssh-host-color
# 4. Configure your host colors below.

set_term_bgcolor() {
   local R=$1
   local G=$2
   local B=$3
   /usr/bin/osascript <<EOF
tell application "Terminal"
   tell window 0
      set the background color to {$(($R*65535/255)), $(($G*65535/255)), $(($B*65535/255)), 32767}
   end tell
end tell
EOF
}

set_term_profile() {
   local profile=$1
   /usr/bin/osascript -e "tell application   "Terminal  " to  set current settings of first window to settings set   "$profile  ""
}

# Host-specific background colors.
if [[ "$@" =~ production1.com ]]; then
   set_term_profile "HomeBrew"
elif [[ "$@" =~ production2.com ]]; then
   set_term_bgcolor 0 40 0
fi

ssh $@

# Default background color.
set_term_profile "Pro"

set term profileでプロファイルの名前を渡せばそれに切り替わる。
set bg colorも残してる。



jsでformの取り消す・やり直す

javascript力が弱くて、クラス使って何か書きたくて、しかも coffeescriptで書きたくて、
CTRL + Z というブラウザの標準の機能があるのに、jsで戻る、やり直しを行うことができるプラグインを作りました。
正直使い道がよくわかりません。どのあたりをターゲットにしているのかもちょっとわかりません。

こんな感じでエレメントを指定してformを対象にして

1
form = new FormObserver('form');
1
2
3
4
// 一つ前の操作に戻す
form.undo();
// やり直し
form.redo();

って感じで、操作できます。

IE10とchromeでは動きました。
よくテストはしてません。
バグがあったらすいませんすいません。

使って見たい方はこちらからどうぞ
https://github.com/YoshitsuguFujii/form-undo.js