Sukoshi. Fuzoroi

某フリーPGの技術っぽいブログ。

既存のDBをActiveRecordを使ったrubyスクリプトで操作する

すごく久しぶりに書く技術ブログ…前回は去年の8月かぁ(遠い目…

今回は既存のDBの中味を ActiveRecord gem で操作するときの手順などを書いてみたいと思います。ActiveRecord のバージョンは 4.1.8 です。

環境構築

DB接続情報

まずは接続情報をYAMLで用意しておきましょう。別にスクリプト中に直接書いてもかまいませんが、YAMLで別ファイルにしておくと複数接続先を切り替えたいときに便利です。

database.yml
db:
  local:
    adapter:  mysql2
    host:     localhost
    username: sample_user
    password: samplesample
    database: sample_db

スクリプト

実際のスクリプトは下記のようになります。

test.rb
require 'active_record'
require 'yaml'

#DB接続情報を読み込み
conf = YAML.load_file('./database.yml')

#接続情報を渡しDBへ接続する
ActiveRecord::Base.establish_connection(conf['db']['local'])

# ユーザモデルを定義
class User < ActiveRecord::Base

  # 使用するテーブル名を指定
  # テーブル名がActiveRecordの命名規約に沿っていない場合のみ
  self.table_name = 'user'

end

# 全ユーザを出力
p User.all

既存カラム名ActiveRecord予約語とバッティングした場合の対処

スクリプトも書けて、さぁバリバリ操作しようと意気揚々と実行させたら…下記のようなエラーメッセージが…

`instance_method_already_implemented?': hash is defined by Active Record. Check to make sure that you don't have an attribute or method with the same name. (ActiveRecord::DangerousAttributeError)

既存DBのカラム名の中にActiveRecord予約語とバッティングするものがあったため例外が発生しています。(この場合は hash というカラム名が問題ですね)

このような場合はカラム名を変更するのがベストなんですが、既存DBのためそれも困難…

しかしこれに対処するための safe_attributes というgemが存在します。

そのgemを使用したサンプルコート

require 'active_record'
require 'safe_attributes/base'
require 'yaml'

#DB接続情報を読み込み
conf = YAML.load_file('./database.yml')

#接続情報を渡しDBへ接続する
ActiveRecord::Base.establish_connection(conf['db']['local'])

# ユーザモデルを定義
class User < ActiveRecord::Base

  # SafeAttributesをinclude
  include SafeAttributes::Base

  # 予約語と重複しているカラム名を指定
  bad_attribute_names :hash
  
  # 使用するテーブル名を指定
  # テーブル名がActiveRecordの命名規約に沿っていない場合のみ
  self.table_name = 'user'

end

# 全ユーザを出力
p User.all

これでバッチリ回避できました!

Jekyll で HAML - SASS 環境を構築

じわじわ人気がでてきている静的サイト&ブログのファイルジェネレーターの jekyll ですが、今回 HAMLとSASSのコンパイルをできるように環境構築してみました。

jekyll インストール

まずは jekyll を運用したいディレクトリを作成

$ mkdir jekyll_site
$ cd jekyll_site

今回は Bundler で gem を管理したいので Gemfile を書きます。
(Bundler の事前インストールが必要です。)

$ vi Gemfile
source 'https://rubygems.org'

gem 'jekyll'

gem 'jekyll-sass'
gem 'jekyll-haml'

そして Bundler でインストールを実行。

$ bundle install

Using fast-stemmer (1.0.2) 
Using classifier (1.3.3) 
Using colorator (0.1) 
Using highline (1.6.19) 
Using commander (4.1.4) 
Using directory_watcher (1.4.1) 
Using tilt (1.4.1) 
Using haml (4.0.3) 
Using kramdown (1.0.2) 
Using liquid (2.5.1) 
Using syntax (1.0.0) 
Using maruku (0.6.1) 
Using posix-spawn (0.3.6) 
Using yajl-ruby (1.1.0) 
Using pygments.rb (0.5.2) 
Using redcarpet (2.2.2) 
Using safe_yaml (0.7.1) 
Using jekyll (1.1.2) 
Using jekyll-haml (0.1.1) 
Using sass (3.2.10) 
Using jekyll-sass (1.1.0) 
Using bundler (1.3.5) 
Your bundle is complete!
Use `bundle show [gemname]` to see where a bundled gem is installed.

システムを汚したくない場合や権限がない場合には、下記コマンドでカレントディレクトリに配下にインストールできます。
その場合にはコマンドを bundle exec jekyll **** のように実行する必要がありますので注意してください。

bundle install --path _vendor/bundle

プラグインの記述

jekyll のインストールが完了したら、次は Bundler でインストールした gem を 適用するようプラグインを記述します。

_plugins ディレクトリを作成して、下記内容のファイルを作成します。
ファイル名はなんでもいいですが、今回はわかりやすいように bundle.rb という名前で保存しています。

require "rubygems"
require "bundler/setup"
Bundler.require(:default)

jekyll 設定ファイルの記述

次に jekyll の設定ファイル _config.yml を YAML で記述します。
必要最低限の内容として下記のようにしました。

# Bundler 関連ファイルをコンパイル対象から除外
exclude: ['Gemfile', 'Gemfile.lock']

# Sassの設定
sass:
  syntax: sass     # scss|sass
  style: compact   # nested|expanded|compact|compressed

ここまでのファイル構成

$ tree
.
├── Gemfile
├── Gemfile.lock
├── _config.yml
└── _plugins
   └── bundler.rb

ハマった点

configを書き終わったら jekyll のお作法に則って作り始めていけば大丈夫ですが、Sassのコンパイルではまったので備忘録として書き残しておきます。

jekyll ではファイルの先頭に Front-matter と呼ばれる YAML の書式があるものがコンパイル対象となります。下記の例でいうと --- で囲まれた部分が Front-matter です。

---
  layout: default
  title: index
---

%h1 これはJekyllで生成したファイルです。
%p ページの名前は {{ page.title }} です。

この Front-matter をsassのファイルでも書いたのですが、これを書くとsassをコンパイルしてくれないようでした。
なのでsassファイルを書くときには普通に書き始めればOKです。

参考サイト

Jekyll • Simple, blog-aware, static sites
http://jekyllrb.com/

Jekyllいつやるの?ジキやルの?今でしょ!
http://melborne.github.io/2013/05/20/now-the-time-to-start-jekyll/

noct/jekyll-sass
https://github.com/noct/jekyll-sass

samvincent/jekyll-haml
https://github.com/samvincent/jekyll-haml

OpenPNE3 通知センターの新着コメント通知を日記ごとにまとめて表示する

OpenPNE3.8系で運用されている某地域SNSで、通知センターの新着コメント通知の挙動についていまいち使いづらいとの議論が。


通知センターは javascript で実装されており、データは JSON API から取得していました。
自分が調べた結果、分かる範囲での既存の仕様は以下のとおり。

・通知対象は自分で書いた日記及びコメントした日記
・他のユーザからコメントが付くと新着コメントとして通知される
・通知単位はコメント毎
・通知欄(リンク)をクリックすることにより該当の日記に飛び、その通知が既読となる


仕様としては問題なさそうですが、一括既読にする機能などの既読管理機能がないために、1件の日記に複数の新着コメントがある場合、すべて既読にするには1件1件リンクをクリックして同じ日記を何度も開く必要があります。


また、どの通知も同じメッセージなのでどの日記のどのコメントか実際にリンクで開いてみるまでわかりません。


修正案としてはいろんなアプローチがあると思いますが、自分は運用側でなく1ユーザとしての立場ですので、クライアント側で取得データを加工するモンキーパッチを書いてみました。


CentOS 6.3 (64bit) に JS Bin をインストールする

CentOS 6.3 (64bit) に JS Bin をインストールする際にいくつかハマったので記録しておきます。

基本的なインストールの流れは Running a local copy of JS Bin の通り。
いかにも「ね、簡単でしょ?」的に書いてありますが…ハマりましたw

Node経由で一気に入れるかとPHPのソースを展開して入れるか…
正直どちらでもよかったんですが、Node環境も作りたかったのでNode経由で入れることにしました。


まずNodeのインストール。

yum install npm

yum install node ではないんですねw
npmを入れて依存でnodeも入るという雰囲気です。けっこうたくさん依存パッケージがあります。

nodeを入れたらあとは簡単♪npmでjsbinをサクッと入れてしまいましょう♪

npm install -g jsbin

そう…サクッと…さく…s…

サクッといかないね!
で、原因を最初にバラしてしまうと…サーバー時間が大幅に遅れていたために様々なビルトが失敗してたんでした…

時間あわせは大事だよ…ローカル環境だから気づかなかった。



そんなこともいざ知らず…

いくつか抜粋してエラーを調べてみると node-gyp.js のビルドに失敗している模様。

gyp ERR! command "node" "/usr/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /usr/lib/node_modules/jsbin/node_modules/sqlite3
gyp ERR! node -v v0.10.12
gyp ERR! node-gyp -v v0.9.5
gyp ERR! not ok 

(中略)

gyp ERR! command "node" "/usr/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild"
gyp ERR! cwd /usr/lib/node_modules/jsbin/node_modules/bcrypt
gyp ERR! node -v v0.10.12
gyp ERR! node-gyp -v v0.9.5
gyp ERR! not ok 

node-gyp.js でいろいろググってみると、pythonのバージョンが古いとダメっぽいという記事を見つけたので、python のバージョンアップ。
でもyumでは既存の ver 2.6.6 までしかないので、ソースから。下記のサイトを参考にしました。

忘れるためのメモ: CentOS 6.2 に Python 2.7.2をインストールする

で、結構高スペックの開発環境なのに Python の make がいつまでたっても終わらない。よく見てみるとログがループしている。

make[2]: ディレクトリ `/root/src/Python-2.7.5' に入ります
make[2]: 警告: ファイル `Makefile.pre.in' の修正時刻が 3.1e+06 秒分未来の時刻です

この段階で時刻ズレに気づきました。あぁ!

ともかく時刻を直して、Python インストール完了。
あとは npm をアップデートして…

npm update -g

もう一度 JS Bin のインストール。

npm install -g jsbin

(中略)

jsbin@3.2.17 /usr/lib/node_modules/jsbin
├── soak@0.3.0
├── commander@1.0.0
├── flatten.js@0.1.0
├── async@0.1.22
├── grunt-contrib-concat@0.1.3
├── asyncjs@0.0.7
├── hogan.js@2.0.0
├── less@1.3.0
├── lynx@0.0.11 (mersenne@0.0.3, statsd-parser@0.0.4)
├── jade@0.26.3 (commander@0.6.1, mkdirp@0.3.0)
├── stylus@0.28.2 (debug@0.7.2, mkdirp@0.3.5, cssom@0.2.5)
├── grunt-contrib-uglify@0.1.2 (uglify-js@2.2.5, grunt-lib-contrib@0.5.3)
├── bcrypt@0.7.5 (bindings@1.0.0)
├── mysql@0.9.6 (hashish@0.0.4)
├── grunt-contrib-jshint@0.1.1 (jshint@0.9.1)
├── grunt@0.4.1 (which@1.0.5, dateformat@1.0.2-1.2.3, colors@0.6.0-1, hooker@0.2.3, eventemitter2@0.4.12, coffee-script@1.3.3, underscore.string@2.2.0-rc, nopt@1.0.10, iconv-lite@0.2.10, lodash@0.9.2, glob@3.1.21, minimatch@0.2.12, rimraf@2.0.3, findup-sync@0.1.2, js-yaml@2.0.5)
├── nodemailer@0.3.20 (simplesmtp@0.3.3, mailcomposer@0.2.0)
├── express@3.0.6 (methods@0.0.1, fresh@0.1.0, cookie-signature@0.0.1, range-parser@0.0.4, buffer-crc32@0.1.1, cookie@0.0.5, debug@0.7.2, commander@0.6.1, mkdirp@0.3.3, send@0.1.0, connect@2.7.2)
└── sqlite3@2.1.7

インストール完了。あっけないです。はい。
…ね、簡単でしょ?

あとは設定ファイルのひな形を config.local.json としてコピーして設定。最低限hostのURLさえ指定していれば確認はできます。

cd /usr/lib/node_modules/jsbin
cp config.default.json config.local.json

起動。

$ jsbin
JS Bin v3.2.17 is up and running on port 3000. Now point your browser at http://local-dev:3000

「サービス」>「辞書で調べる」にショートカットを設定する

Macの「プレビュー」アプリで英語のPDFを読んでいるとき、分からない単語があっても「辞書で調べる」が右クリックメニューにないのでとっても面倒でした。

じゃあどこにあるのかというと… 「プレビュー > サービス > 辞書で調べる」 と2階層もメニューをたどった先にあります。んー面倒!しかもキーボードショートカットも設定されていません。

ならしてやろう!ということでw

環境は MacOSX 10.8.4 です。
環境設定から「キーボード > キーボードショートカット > サービス」とたどって…

「辞書で調べる」のショートカット追加をクリックして設定します。


うん!これで快適♪

ん?…ん??あああーーーー!!!
右クリックメニューに「調べる」あるじゃん…

まぁ…サービスメニューにショートカットを設定する方法の記事ということで;;;
オチが付いてしまった。

Pow のアプリケーションアイドル時間を変更する

Powを使って開発していると、よくアプリケーションインスタンスがKillされていて再読込に時間がかかり不便なのでデフォルト時間(5分)を変更してみました。

Pow User's Manual によると…

~/.powconfig を作成し、export POW_TIMEOUT=xxx で必要な秒数を記載すればOKとのこと。

自分の場合、まず.powconfigがなかったので作成し、アイドル時間を1時間に設定してみました。

$ cd ~
$ echo 'export POW_TIMEOUT=3600' > .powconfig 

そして.powディレクトリにrestart.txtを配置、Powを再起動して設定反映。

$ touch ~/.pow/restart.txt

なかなか快適になりました。