読者です 読者をやめる 読者になる 読者になる

spring of life

技術、ときどき日常のブログ(予定)

テストのスキップ判定

RSpec

RSpecで、itのオプションに:ifやら:unlessやらあるらしくて、それを使うことでスキップの判定ができるらしい。知らんかった。。。

ちなみにRSpecのバージョンは3.4.1でした

% bundle exec rspec -v
3.4.1

書き方は普通に条件判定する文を値に持ってくる感じでOK。ブロックになってるのかな〜詳しく調べてないんだけど

it 'hoge test', :if => 1 == 1 do
  expect(hoge).to eq fuga
end

詳しいことは↓のあたりを参考に

www.relishapp.com

jbuilder の使い方2

Rails

前に こういう記事を書いたんだけど、結構見られてるんだよね笑

leonis.hatenablog.com

で、1つ前の記事で多対多の関連を作ったというのを書いて、同時にレスポンスの json の形式も↓のように変えてみた

# 変更前
{
  "payment_type": "income",
  "date": "2017-04-16",
  "content": "hogehoge",
  "category": "fuga",
  "price": 100
}
# 変更後
{
  "payment_type": "income",
  "date": "2017-04-16",
  "content": "hogehoge",
  "categories": [
    {"id: 1, "name": "fuga"}
  ],
  "price": 100
}

もともとカテゴリは複数付くのを想定してたんだが、適当にカンマ区切りの文字列にしてた。。。

で、まぁ今回ちょっとカテゴリをリソース化してみようと思って、ついでにレスポンスも真面目に考えることにした(。-_-。)

ここからが本題↓

途中に関連するモデルの属性を入れる時

↑でいう変更後の json を作ってみる

json.(@payment, :payment_type, :date, :content)
json.(@payment.categories, :id, :name)
json.(@payment, :price)
# payment_type, date, content, price は@payment の属性
# id, name は@payment に関連しているカテゴリ情報の属性

単純に上から順番に属性を書いていけばいいだけなんですね。。。わかりやすい。。。

多対多の関係のモデル作成

Rails

今回はhas_and_belongs_to_manyを使う方法で実装してみた

  • 例として、というか自分が家計簿のアプリで実装したのは、収支情報(payment)とカテゴリ(category)の関連の作成
  • まずはスキーマの作成
    • 中間テーブルのファイル名はアルファベット順という規則(categories → payments )らしい
bundle exec rails g model payment
bundle exec rails g model category
bundle exec rails g migration create_categories_payments
  • payments と categories は好きに属性を追加するとして、中間テーブルの設定を以下のようにする
    • インデックスの設定とかはご自由にどうぞ、みたいな感じで
class CreateCategoriesPayments < ActiveRecord::Migration
  def change
    create_table :categories_payments, :id => false do |t|
      t.references :category, :index => true, :null => false
      t.references :payment, :index => true, :null => false
    end

    add_index :categories_payments, [:category_id, :payment_id], :unique => true
  end
end
  • モデルに関連を追加する
# app/models/payment.rb
class Payment < ActiveRecord::Base
  has_and_belongs_to_many :categories
  ...
end

# app/models/category.rb
class Category < ActiveRecord::Base
  has_and_belongs_to_many :payments
  ...
end

これでincludesとかjoinsとかが使えるようになる
例えば、カテゴリで検索をかける場合、

# app/models/payment.rb
class Payment < ActiveRecord::Base
  has_and_belongs_to_many :categories
  ...
  scope :category, ->(category) { joins(:categories).where('categories.name = ?', category) }
  ...
end

みたいな感じで書いといて、コントローラー側とかで

def index
  ...
  Payment.category('食費')
  ...
end

と書けば、name属性が食費のカテゴリが付いてる収支情報が取れる


問題はここからなんだよなぁ。。。
ビューにはどう書くとキレイなんだろ?
カテゴリとか今入力してるとこを選択するようにしたいし、リストの先頭を空欄にして、そこに新しいカテゴリを入力して登録すればカテゴリが新規作成されるようにしたい

.tar.gz の作成(圧縮)

Ruby

ruby で圧縮処理しようと思ったんだが、あんまり記事がなかったので自分でメモ

唯一(と言ってもいいくらい無かった)見つかったのが↓の記事

d.hatena.ne.jp

まぁでもこれもけっこう古い記事で、今は gem の名前が変わってるっぽい。

今は minitar という gem と、あと minitar-cli っていうのも一緒にインストールする(bundle installしたらメッセージが出てくる)

# Gemfile

gem 'minitar'
gem 'minitar-cli'

で、使い方はだいたい↑の記事といっしょで、Archive::Tar::MinitarのとこをMinitarに直すくらいかな。

require 'zlib'
require 'archive/tar/minitar'

Zlib::GzipWriter.open('foo.tar.gz', Zlib::BEST_COMPRESSION) do |gz|
  out = Minitar::Output.new(gz)
  Dir['/path/to/dir/*'].each do |file|
    Minitar::pack_file(file, out)
  end
  out.close
end

NFS を使ったマウント

Linux

前にこっちでCIFSを使ってWindowsサーバーのフォルダをマウントする方法を書いたけど、今度はNFSを使って別のLinuxのサーバーのディレクトリをマウントする機会があったから方法をメモ

ちなみに、OSは

  • サーバー側: CentOS 6.6
  • クライアント側: CentOS 7.2

です

マウントするディレクトリがある側(サーバー側)の設定
  • nfs-utils をインストール
    • サービスを起動する時は、rpcbind→(nfs, nfslock)の順番でないとエラーになる
# yum install nfs-utils
# service rpcbind start
# service nfs start
# service nfslock start
  • /etx/exportsにマウントするディレクトリの設定を書く
    • 書き方とかはこちらを参考に
    • exportfs -aで更新しておくことも忘れずに
  • iptables を使っている人は111, 875, 2049番ポートを開けておく
# /etc/sysconfig/iptables

...
-A INPUT -p tcp -m tcp --dport 111 -j ACCEPT
-A INPUT -p udp -m udp --dport 111 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 875 -j ACCEPT
-A INPUT -p udp -m udp --dport 875 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 2049 -j ACCEPT
-A INPUT -p udp -m udp --dport 2049 -j ACCEPT
...
別サーバーのディレクトリをマウントする側(クライアント側)の設定
# yum install nfs-utils
  • マウント実行(123.456.789.012にある/home/nfs_test/mnt/nfs_testにマウントする場合)
# mount -t nfs 123.456.789.012:/home/nfs_test /mnt/nfs_test
  • mountコマンド実行してmount.nfs: access denied by server while mounting ...とか出た場合はサーバー側のiptablesの設定がうまくいってないかも

emacs の json-mode の設定

Emacs

しばらく書いてなかった。。。

ネタがなかったというとウソだがけっこう細かいリファクタみたいなことをいろいろしてた。

まぁ今回書くのも細かいけどw



chef のコードを書いてると json を書くことが多くて、 emacsjson の設定を変えたのでメモ

  1. まず json-mode をインストール
    • M-x package-install [ret] json-mode [ret]
  2. .emacs.el か何かの設定ファイルにインデント設定を記載
    • 自分は2スペースが好みなので↓のような設定
(add-hook 'js-mode-hook
          (lambda ()
            (make-local-variable 'js-indent-level)
            (setq js-indent-level 2)))

chef で jenkins 環境構築

jenkins chef

jenkins の環境構築を chef でできないかな〜といろいろ調べてある程度できたのでメモ

jenkins のインストール

remote_file node[:jenkins][:rpm_path] do
  source node[:jenkins][:rpm_url]
  owner 'root'
  group 'root'
  mode 0755
  not_if { File.exists?(node[:jenkins][:rpm_path]) }
end

package 'jenkins' do
  source node[:jenkins][:rpm_path]
  not_if 'rpm -q jenkins'
end

アカウント作成

  • ここからが少し面倒だった。。。
  • jenkins には WebAPI とか CLI があるみたいで、今回は CLI を使った
  • chef の中でコマンド実行することでアカウントを作成
  • まず、jenkins-cli.jar をダウンロード( http://localhost:8080/jnlpJars/jenkins-cli.jar にアクセス)
  • groovy を使ってアカウントを作成
    • groovy = とすることで標準入力を受け付けれる
  • 最初は管理者しかいないので、ユーザー名とパスワードは管理者のものを使用
    • パスワードは/var/lib/jenkins/secrets/initialAdminPasswordに書かれている
    • --passwordオプションもあるが、インストール前だともちろんファイルはなく、chef でインストールから始める場合にファイルがなくエラーになるのでファイルを指定するようにしておく
remote_file node[:jenkins][:cli_path] do
  source node[:jenkins][:cli_url]
  owner 'root'
  group 'root'
  mode 0755
  not_if { File.exists?(node[:jenkins][:cli_path]) }
end

execute 'create account' do
  command <<-"EOF"
echo 'jenkins.model.Jenkins.instance.securityRealm.createAccount("<id>", "<password>")' |
java -jar #{node[:jenkins][:cli_path]} -s #{node[:jenkins][:host]} groovy = --username=admin --password-file=</path/to/password-file>
  EOF
  user 'root'
end

プラグインインストール

  • これも CLI を使ってインストール
  • install-pluginというコマンドを使う
execute 'install plugin' do
  command <<-"EOF"
java -jar #{node[:jenkins][:cli_path]} -s #{node[:jenkins][:host]} install-plugin <プラグイン名(git とか)> --username=<ユーザー名> --password=<パスワード>
  EOF
  user 'root'
end

ジョブ作成

  • これは1度config.xmlを作っとかないと無理。。。
  • 自分の場合は既に手作業で作った jenkins があったので、/var/lib/jenkins/jobs/<ジョブ名>/config.xmlをコピーして chef のリポジトリの中に入れておくことにした
    • まぁこうしとけば、あとは別のサーバーで作る時は自動で作れるので一応便利、かな。。。
execute 'create job' do
  command <<-EOF
cat /path/to/config.xml |
java -jar #{node[:jenkins][:cli_path]} -s #{node[:jenkins][:host]} create-job <ジョブ名> --username=<ユーザー名> --password=<パスワード>
  EOF
  user 'root'
end

とりあえず今回はここまで自動化した!

おまけ

  • jenkins でパスワードなしで sudo 権限を使いたい場合は/etc/sudoers.d以下に↓みたいな設定ファイルを追加しておく
jenkins        ALL=(ALL)        NOPASSWD: ALL