コピペコードで快適生活

明日使えるソースを自分のために

minttyのカッコいい設定

minttyは設定次第でカッコいい見た目になるのでとても気に入っています。
僕の.minttyrcは↓のような感じです。

BoldAsFont=no
FontHeight=11
Font=Inconsolata
FontIsBold=no
BackgroundColour=0,0,0
ForegroundColour=245,245,245
Transparency=medium
Columns=160
Rows=40
Black=0,0,0
Red=255,204,153
Green=204,255,204
Yellow=255,255,153
Blue=153,204,255
Magenta=204,153,255
Cyan=204,255,255
White=255,255,255
BoldRed=255,204,153
BoldGreen=204,255,204
BoldYellow=255,255,153
BoldBlue=153,204,255
BoldMagenta=204,153,255
BoldCyan=204,255,255
BoldWhite=255,255,255
CopyOnSelect=no


見た目こんな感じになります。
f:id:comb_8107:20160323151424p:plain


設定はこちらを参考にさせていただきました。感謝です。
Cygwin Terminal (Mintty) の設定 - 計算物理屋の研究備忘録


フォントはこちらを使用しています。
Inconsolata

RubyでUTF-8変換時にUndefinedConversionが出た件

shift_jisで書かれたCSVUTF-8に変換して取り込み処理をするところで、Encoding::UndefinedConversionError が吐かれてた。

str.encode('utf-8', 'shift_jis') # => Encoding::UndefinedConversionError: "\x87@" from Shift_JIS to UTF-8


なんでだと思って調べてたところ、shift_jisでは対応していない①とか㈱とかの機種依存文字を変換しようとしていたからエラー出ていたみたい。なのでCP932(Windows-31J)使えば解決。

str.encode('utf-8', 'CP932') # => ①㈱

Rubyで短縮URL用の文字列生成

短縮URL機能を自前で作らないといけないんだけど、その文字列の生成アルゴリズムをどうするかなーってところで、
Flickrの短縮URL用にRubyでbase58実装 | EasyRamble
こちらで紹介されているソースをほぼそのまま利用させてもらいました。

ただ今回は、ひとつ文字をずらしたら隣接IDの情報が見えてしまう的なことを避けたいので、diff引数で隣接が特定されにくくなるような小細工を仕込んでます。

#
# 短縮URL作成用に使う
#
module Base58
  class Base58Exception < Exception; end

  BASE58_ALPHABET = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"

  def self.encode(row_id, diff = 1)
    id = row_id.to_i * diff
    base = BASE58_ALPHABET.size

    encoded_str = ""
    while id > 0
      mod = id % base
      encoded_str = BASE58_ALPHABET[mod] + encoded_str
      id = id / base
    end

    return encoded_str
  end

  def self.decode(encoded_str, diff = 1)
    encoded_str = encoded_str.to_s
    base = BASE58_ALPHABET.size

    decoded = 0
    multi = 1
    while encoded_str.size > 0
      c = encoded_str.slice!(-1)
      decoded = decoded + BASE58_ALPHABET.index(c) * multi
      multi = multi * base
    end

    if decoded % diff != 0
      raise Base58Exception.new("decode error")
    end

    return decoded / diff
  end
end


使い方はこんな感じで。

require 'base58'

# エンコード
Base58.encode(123) # => "38"

# デコード
Base58.decode("38") # => 123

# 文字列ずらすと隣が分かる
Base58.decode("37") # => 122

# エンコード(diff指定)
Base58.encode(123, 256) # => "amU"

# デコード(diff指定)
Base58.decode("amU", 256) # => 123

# 文字列ずらしても隣は分からない。
Base58.decode("amT", 256)
Base58::Base58Exception: decode error
from /home/kinosuke/my_app/lib/util/base58.rb:36:in `decode'

MySQLのユーザ管理コマンド

ユーザ管理
-- ユーザリスト
SELECT Host, User, Password FROM mysql.user;

-- ユーザ作成
CREATE USER 'kinosuke'@'localhost' IDENTIFIED BY 'some password';

-- パスワード変更
SET PASSWORD FOR 'kinosuke'@'localhost' = PASSWORD('some password');
権限変更
-- 権限確認
SHOW GRANTS FOR 'kinosuke'@'localhost';

-- グローバルレベル:
GRANT 権限 ON *.* TO 'kinosuke'@'localhost';

-- データベースレベル:
GRANT 権限 ON db_name.* TO 'kinosuke'@'localhost';

-- テーブルレベル:
GRANT 権限 ON db_name.table_name TO 'kinosuke'@'localhost';

-- カラムレベル:
GRANT 権限 (カラム1, カラム2, ...) ON db_name.table_name TO 'kinosuke'@'localhost';

rbenvでRubyをインストール~gemsetの設定

Rubyインストー
# rbenv をインストール(clone)する
git clone https://github.com/sstephenson/rbenv.git ~/.rbenv

# bash_profile 設定追加
# vim ~/.bash_profile
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"

# 上記設定の再読み込み
exec $SHELL -l

# rbenvの確認
rbenv --version

# ruby-build を インストール(clone)する
git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build

# ruby の最新版を確認
rbenv install --list

# ruby のインストール
RUBY_BUILD_CURL_OPTS=--tlsv1.2 rbenv install -v 2.0.0-p451

# 再読み込み
rbenv rehash

# installed 確認
rbenv versions

# デフォルト設定
rbenv global 2.0.0-p451

# カレントディレクトリで使う
rbenv local 2.0.0-p451

参考にさせていただきました!感謝!
rbenv を使って ruby をインストールする(CentOS編) - Qiita

gemsetの設定
# ruby-gemset を インストール(clone)する
cd ~/.rbenv/plugins/
git clone https://github.com/jf/rbenv-gemset.git

# gemset 作成
rbnev gemset list
rbenv gemset create 2.0.0-p451 redmine

# 削除するとき
rbenv gemset delete 2.0.0-p451 redmine

# 指定dir以下で gemset使う
cd /var/www/app/redmine/
echo redmine > .rbenv-gemsets
rbenv rehash

# カレントディレクトリで有効なgemset
rbenv gemset active

参考にさせていただきました!感謝!
Redirecting...

Rails×SES バウンスメール(不達メール)対策

「SESで不達メールが多いから、対策してくれなかったらSES止めるよ」って過去にAWSから言われたことがあって、そのときの対応メモを書きだしてみた。

対応の基本的な流れ
SESは不達メールがあった場合に特定のURLに対してリクエストをjson付きで投げてくれるので、それを特定のURLでうけてJSONパースして、そのパースしたJSONの中にメールアドレスがあるので、それをブラックリストテーブルか何か作ってINSERTして、メール送信の時はそのブラックリストテーブルを見て、送っていいメールアドレスいいか判定するって感じ。

AWSの設定はここを参考に。
Amazon SESのBounce SNS通知をRailsで処理する|WEBデザイン Tips

Railsのソースはこんな感じ。

app/controllers/api/aws_controller.rb

#
# AWSから飛んできたリクエストを受け取るAPI
#
require 'json'
require 'open-uri'
class Api::AwsController < ActionController::Base
  skip_before_filter :verify_authenticity_token

  #
  # SESからリクエストされる
  # 不達メールアドレスリストをブラックリストに登録する
  #
  def receive_bounce_notice
    # data = JSON.parse(dummy_raw_post) # debug用
    data = JSON.parse(request.raw_post)

    # Subscription認証用URLを開いて認証を完了する
    if data['SubscribeURL'].present?
      open(data['SubscribeURL'])    

    # ブラックリスト登録する
    else
      data2 = JSON.load(data['Message'])
      type = data2['notificationType']

      if type=='Bounce'
        bounce = data2['bounce']
        bouncerecps = bounce['bouncedRecipients']
        bouncerecps.each do |recp|
          email = recp['emailAddress']
          if BouncedEmailAddress.where(email: email).blank?
            BouncedEmailAddress.create(email: email)
          end
        end
      end
    end

    render text: ""
  end

  private
    def dummy_raw_post
str =<<EOS
{
  "Type" : "Notification",
  "MessageId" : "463fbb0b-63ea-4a6d-90c5-33c8686e3bd1",
  "TopicArn" : "arn:aws:sns:us-east-1:811118151095:suz-lab-ses",
  "Message" : {
      "notificationType":"Bounce",
      "bounce":{
         "bounceType":"Permanent",
         "bounceSubType": "General",
         "bouncedRecipients":[
            {
               "emailAddress":"recipient1@example.com"
            },
            {
               "emailAddress":"recipient2@example.com"
            }
         ],
         "timestamp":"2012-05-25T14:59:38.237-07:00",
         "feedbackId":"00000137860315fd-869464a4-8680-4114-98d3-716fe35851f9-000000"
      },
      "mail":{
         "timestamp":"2012-05-25T14:59:38.237-07:00",
         "messageId":"00000137860315fd-34208509-5b74-41f3-95c5-22c1edc3c924-000000",
         "source":"email_1337983178237@amazon.com",
         "destination":[
            "recipient1@example.com",
            "recipient2@example.com",
            "recipient3@example.com",
            "recipient4@example.com"
         ]
      }
  },
  "Timestamp" : "2012-10-08T13:00:40.691Z",
  "SignatureVersion" : "1", 
  "Signature" : "FDNBWbFhc5MXs+2tjw327zXhiKca3GLHbbVEN8vUmLAmnj60...",
  "SigningCertURL" : "https://sns.us-east-1.amazonaws.com/SimpleN...",
  "UnsubscribeURL" : "https://sns.us-east-1.amazonaws.com/?Action..."
}
EOS
      return str
    end
end


lib/mail/email_interceptor.rb

#
# email_interceptor は、action mailer の
# before action 的な動きをしてくれるヤツ(らしい。。)
#
class EmailInterceptor
  #
  # ブラックリスト宛には送らない
  #
  def self.delivering_email(message)
    _to = message.to
    message.to = probe_email(message.to)   if message.to.present?
    message.cc = probe_email(message.cc)   if message.cc.present?
    message.bcc = probe_email(message.bcc) if message.bcc.present?

    message = set_to(message, _to)
  # rescue => e
  #   binding.pry
  #   Rails.logger.error(e.to_s << "\n" << e.backtrace.join("\n"))
  end

  #
  # ブラックリストに載っていないアドレスだけにする
  #
  def self.probe_email(emails)
    bounced_email_addresses = BouncedEmailAddress.pluck(:email)

    list = []
    emails = [emails] if emails.instance_of?(String)
    emails.each do |email|
      list << email if !(bounced_email_addresses.include?(email))
    end
    return list
  end

  #
  # toがすべて空だった場合
  # 送信処理するとエラーになるため、
  # とりあえず仮で送信先を入れる
  #
  def self.set_to(message, _to)
    return message if message.to.present?

    # ブラックリストに送ろうとしたメールはここに送信する
    message.to = ["sample@gmail.com"]
    # message.subject = "Can not sent to bouced email address"
    return message
  end
end

email_interceptor.rb は、lib/mail の配下とかにおいて、
config/application.rb で読みこむようにすればOK。

  class Application < Rails::Application
  # 略
    config.autoload_paths += %W(#{config.root}/lib/mail)
 # 略


※BouncedEmailAddressというモデルはブラックリスト用テーブル。
 メールアドレスを格納しているだけなのでソースは割愛。

Backlog風のベルト型通知UI

Backlogの課題更新時に表示されるベルト型の通知UI。
あれいいなって思って実装してみた。
Ajaxで更新処理したあとの通知用に使っていこう。

/*
 * Backlog風のベルト型通知UI
 */
function beltNotice(text, type) {
  var bg_color = "#468847";
  if (type == "alert") {
    bg_color = "#b94a48";
  }

  var css = {
    "background-color": bg_color,
    "color": "#FFF",
    "display": "none",
    "font-size": "1.2em",
    "font-weight": "bold",
    "padding": "10px",
    "position": "fixed",
    "text-align": "center",
    "top": "200px",
    "width": window.parent.screen.width + "px",
  }

  var $belt = $("<div></div>", {
    css: css
  });
  $belt.text(text);

  $("body").append($belt);
  $belt.fadeIn("slow");
  setTimeout( function() {
    $belt.fadeOut("slow");
  }, 3000 );
}