ホーム ブログ ページ 42

VirtualBoxを使ってjenkinsを動かした際のメモ

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

以前、railsでスマホ用アプリを作成する際、

rspecテストなどを自動で走らせたいという事で、

rails環境を構築した仮想OS上に、jenkinsを入れて動かそうとし,

ハマった部分についてのメモです。

jenkinsとは

Javaによって書かれた「オープンソース継続的インテグレーションツール」。

様々なプラグインを使用する事によって、継続的にジョブを監視したり、ビルドをしたりすることができます。

railsと合わせて、自動的にrspecのテストを行わせる目的で入れようとしました。

(今回仮想環境にjenkinsを入れる事が目的となる為、詳しい使用方法などは割愛)

 Jenkinsのインストール

仮想環境

・VirtualBox

・CentOS 6.6

# yum -y install java-1.7.0-openjdk wget
# wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
# rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key
# yum -y install jenkins

 Jenkinsの起動

# service jenkins start
# chkconfig jenkins on

以上で、http://サーバーのIPアドレス:8080/(初期設定)にアクセスすればJenkinsのトップ画面が表示されるはずでしたが、ip接続がうまくいかず、表示されませんでした。

 仮想OSのサーバipアドレスを確認する

VirtualBoxの メニュー>環境設定>ネットワーク

で、ネットワーク名が表示される。

各ネットワーク名を右クリック>編集で、IPv4のアドレス/ネットマスクが見れるので、それらをメモします。

そして、CentOS内の/etc/sysconfig/network-scripts/ifcfg-eth0を、メモしたipアドレス・ネットマスクに書き換えます。

例えば、ipアドレスとマスクが「166.166.66.6/255.255.255.0」だったとしたら、以下のように。

IPADDR=166.166.66.6
NETMASK=255.255.255.0

これで再度、networkをリスタートして、ホストOSのブラウザからアクセスすると、

jenkinsのトップ画面が表示されました。。

ブラウザからJenkinsにプラグインがインストールできないとき

上記の操作で、ブラウザでJenkinsが確認出来ても、

ブラウザ上での操作から、プラグインのインストール等が出来ないことがありました。

その場合、仮想環境がネットワークにつながっていない場合があります。

VirtualBoxのアダプターの設定を見直して、

・アダプター1:ホストオンリーアダプタ

・アダプター2:NAT

になっているかを確認します。

自分の場合、アダプタ設定が逆になっていたので、正しく戻したらきちんとブラウザからインストールできるようになりました。

svn moveを試してみる

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

ブランチをトランクにするために、svn moveをローカルで検証してみました。

 svn moveって何?

svn moveコマンドは、作業コピーやリポジトリにある、ファイルやディレクトリを移動することができます。

※内部的には、svn copyの後にsvn deleteを行っている模様

※以下の手順のパス等は、Mac環境のものです。

 事前準備(検証用のデータを作成)

リポジトリ作成

$ cd
$ mkdir -p Documents/svn/repos
$ svnadmin create Documents/svn/repos
$ svn mkdir file://localhost/Users/hoge/Documents/svn/repos/trunk -m "create directory trunk"
$ svn mkdir file://localhost/Users/hoge/Documents/svn/repos/branches -m "create directory branches"
$ svn mkdir file://localhost/Users/hoge/Documents/svn/repos/tags -m "create directory tags"

チェックアウト

$ cd Documents/svn
$ mkdir working-copy
$ cd working-copy
$ svn co file://localhost/Users/hoge/Documents/svn/repos/trunk

コミット

トランク見分けるためファイルをコミットします。

$ cd trunk
$ touch trunk.txt
$ vim trunk.txt
---- ここから ----
trunk!
---- ここまで ----
$ svn add trunk.txt
$ svn ci trunk.txt -m 'create trunk.txt'

ブランチ作成(URL -> URL)

$ svn copy file://localhost/Users/hoge/Documents/svn/repos/trunk file://localhost/Users/hoge/Documents/svn/repos/branches/branch -m 'create new branch'
$ svn ls file://localhost/Users/hoge/Documents/svn/repos/branches
branch/
$ svn ls file://localhost/Users/hoge/Documents/svn/repos/branches/branch
hoge.txt
trunk.txt

ブランチチェックアウト

$ cd ../working-copy
$ svn co file://localhost/Users/hoge/Documents/svn/repos/branches/branch
A    branch/trunk.txt
Checked out revision 5.

ブランチを区別するコミット

$ cd branch
$ touch branch.txt
$ vim branch.txt
---- ここから ----
branch!
---- ここまで ----
$ svn add branch.txt
$ svn ci branch.txt -m 'create branch.txt'

 svn move検証

いよいよ本題のsvn moveの検証です。

①branch -> tagsにコピー

バックアップのためブランチをtagsにコピーします。

$ svn copy file://localhost/Users/hoge/Documents/svn/repos/branches/branch file://localhost/Users/hoge/Documents/svn/repos/tags/branch_snapshot -m 'create tags branch_snapshot'
$ cd ..
$ svn co file://localhost/Users/hoge/Documents/svn/repos/tags/branch_snapshot
$ cd branch_snapshot/
$ ls
branch.txt trunk.txt
$ cat branch.txt
branch!
$ cat trunk.txt
trunk!
$ svn log
------------------------------------------------------------------------
r7 | hoge | 2015-12-24 15:45:45 +0900 (水, 24 12 2015) | 1 line

create tags branch_snapshot
------------------------------------------------------------------------
〜省略〜
→copy時点のbranchのファイルとリビジョン履歴がコピーできている。OK

②trunk -> tagsにmove

バックアップのためトランクをtagsに移動します。

$ svn move file://localhost/Users/hoge/Documents/svn/repos/trunk file://localhost/Users/hoge/Documents/svn/repos/tags/trunk_snapshot -m 'create tags trunk_snapshot'

trunk-snapshotが出来ているか

$ svn ls file://localhost/Users/hoge/Documents/svn/repos/tags/branch_snapshot/
trunk_snapshot/
→OK

trunkが消えていること

$ svn ls file://localhost/Users/hoge/Documents/svn/trunk
svn: Unable to open an ra_local session to URL
svn: Unable to open repository 'file://localhost/Users/hoge/Documents/svn/trunk'
→OK

trunk_snapshotをcoしてファイル(trunk.txtのみ)とリビジョン履歴確認

$ cd ..
$ svn co file://localhost/Users/hoge/Documents/svn/repos/tags/trunk_snapshot
A    trunk_snapshot/trunk.txt
Checked out revision 8.
$ cat trunk_snapshot/trunk.txt
trunk!
$ svn log trunk_snapshot/
------------------------------------------------------------------------
r8 | hoge | 2015-12-24 15:55:16 +0900 (水, 24 12 2015) | 1 line

create tags trunk_snapshot
------------------------------------------------------------------------
r4 | hoge | 2015-12-24 15:36:01 +0900 (水, 24 12 2015) | 1 line

create trunk.txt
------------------------------------------------------------------------
r1 | hoge | 2015-12-24 15:33:03 +0900 (水, 24 12 2015) | 1 line

create directory trunk
------------------------------------------------------------------------
→OK

③branch -> trunkにmove

ブランチをトランクに移動します。

$ svn move file://localhost/Users/hoge/Documents/svn/repos/branches/branch file://localhost/Users/hoge/Documents/svn/repos/trunk -m 'create trunk move branch'

trunkが出来ているか

$ svn ls file://localhost/Users/hoge/Documents/svn/repos/trunk
branch.txt
trunk.txt
→OK

branchが消えていること

$ svn ls file://localhost/Users/hoge/Documents/svn/branches/branch
svn: Unable to open an ra_local session to URL
svn: Unable to open repository 'file://localhost/Users/hoge/Documents/svn/branches/branch'
→OK

trunkをcoしてファイル(trunk.txtとbranch.txt)とリビジョン履歴確認

$ cd ~/Documents/svn/working-copy
$ svn co file://localhost/Users/hoge/Documents/svn/repos/trunk trunk_moved
$ cat trunk_moved/trunk.txt
trunk!
$ cat trunk_moved/branch.txt
branch!
$ svn log trunk_moved/
------------------------------------------------------------------------
r9 | hoge | 2015-12-24 16:06:14 +0900 (水, 24 12 2015) | 1 line

create trunk move branch
------------------------------------------------------------------------
r6 | hoge | 2015-12-24 15:40:30 +0900 (水, 24 12 2015) | 1 line

create branch.txt
------------------------------------------------------------------------
r5 | hoge | 2015-12-24 15:36:56 +0900 (水, 24 12 2015) | 1 line

create branch from trunk
------------------------------------------------------------------------
r4 | hoge | 2015-12-24 15:36:01 +0900 (水, 24 12 2015) | 1 line

create trunk.txt
------------------------------------------------------------------------
r1 | hoge | 2015-12-24 15:33:03 +0900 (水, 24 12 2015) | 1 line

create directory trunk
------------------------------------------------------------------------
→OK

ちゃんとブランチにコミットしたファイルが存在し、ログも問題なさそうですね。

以上です。

Rails ブラウザバックでどうやってもjsのイベントが取れない件

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

ブラウザバックでページ遷移した時に起こる不具合は意外とたくさんあることに気づくポッキーの日。その1つとしてjsのイベントがどうやっても取れない現象に出くわしたので、その時の対処法をメモとして残しておきます。

きっかけ

ブラウザバックした際、デザインが崩れてしまう不具合が報告されたので調査することに。デザイン崩れの原因が2つの特定条件の時に起こるみたい。

・スマホ端末とタブレット端末のみ
・端末を縦横に向きを変えて任意のページからブラウザバックした時に起こる

ちなみにリロードすると元に戻る。デザイン崩れが発生しているのがjsのプラグインを使っている箇所だったのでソースを見ても訳分からない..。なのであまり良くないですが、デザインが崩れるページに戻った際はリロードして崩れないようにしようと思いました。

原因と対応

結論から言うと、この不具合の根本原因はturbolinksによる影響でした。
ページロードの高速化(これしか知らない)などのメリットがあるけど、デメリットの方が多いと言われるturbolinks..。実際にデメリットの部分を実感できたのでまぁぁ良しとしましょう。

turbolinksの影響だと気づいていない時にブラウザバックでイベントを取得する方法をいろいろ探してたら、このイベント(下記に記載)なら取れるよ!って言う記事がたくさんあったのですが、turbolinksの前では全く効果ありませんでした。

$(window).load(function(){});
$(window).onload(function(){});
$(window).unload(function(){});
$(window).pageshow(function(){});
$(window).onpageshow(function(){});

参考: iOS ブラウザバック時にリロードさせる (javascript)

turbolinksを無効にすれば手っ取り早いですが

#app/assets/javascripts/application.js
//= require turbolinks   #これを削除

そうもいかず路頭に迷ってたら見つけました、turbolinksが提供しているイベントが!
ブラウザバック時に以下のイベントを取得することができるみたい。

page:before-unload
page:change
page:update
page:restore

参考: infinite scrollとRails4のTurbolinks

結果としてこの記述でブラウザバックした時にページリロードすることができました。

$(document).on 'page:restore', ->
  location.reload();

他にもturbolinks絡みの不具合を経験したので嫌いになりかけていましたけど(もう使いたくない)、便利なところもあるのでうまく共存していきたいですね..。turbolinksについて、そもそもturbolinksって何?だったりメリットデメリット、使っていく上で気をつけるべきことなのがわかりやすい記事があったので載せておきます。

参考: 今更ながらTurbolinksを初めて仕事で使ってみたので色々調べてみた

記憶の固執 dalli をDBレコードに使ったときのメモ

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Webアプリを高速化するのに memcached を使うことがある。

今回は Ruby on Rails 上で memcached 簡単に行うことができる gem に dalli を使ったときのメモ。

 環境

OS (cat /etc/redhat-release )

CentOS Linux release 7.1.1503 (Core)

kernel (uname -r)

3.10.0-229.1.2.el7.x86_64

memcached

rpm -qa memcached
	memcached-1.4.15-9.el7.x86_6

ruby

ruby -v
	ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-linux]
	rails -v
	Rails 4.2.2
	gem list pry
	
	 LOCAL GEMS ***
	
	pry (0.10.1)
	pry-rails (0.3.4)
	
	gem list dalli
	
	 LOCAL GEMS ***
	
	dalli (2.7.4)

 dalli インストール例

dnf install memcached

gem install dalli

 rails アプリケーションの設定ファイルの記載

config/environments/development.rb に下記行を追記。

※ 本番環境なら config/environments/production.rb

config.cache_store = :dalli_store

 基本的な使い方

キャッシュを作成する

Rails.cache.write(key, obj)

キャッシュを読み込む

Rails.cache.read(key)

キャッシュがあれば読み込み、なければ作成し読み込む

Rails.cache.delete(key)
	Rails.fetch(key, obj,  expires_in: cache_tol_sec) do
	  obj
	end

※ キャッシュの寿命を指定するには write や fetch の第3引数に秒数を指定する。

 気をつけること

ひとつのキーでひとつの値を保持するのでdevlopmentや test など複数環境で使用することを考慮しておく。

テーブル名や引数、sql文などをキーにしているときにテスト実施後に開発環境で表示不具合が発生した。memcache はキーバリューなので不自然でないが rails の開発時に環境ごとの db の切り替えに気を使ったコーディングをすることが少ないので注意。この度はキーに “#{Rails.env.first}_” の接頭辞をつけるようにして解決。

キーはシンボルで指定しても文字列で作成されるので意図せぬ書き換えに注意。

Rails.cache.write(:key_str, obj1)
	Rails.cache.write('key_str', obj2)

Hash と異なる。

DBレコードごとにキャッシュを作成する場合、レコードの更新・削除にあわせてキャッシュも更新すること。

after_save や after_destroy などを使うとよいかも。

【Rails】フォームの要素を動的に追加・削除 〜JSON編〜【jquery】

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

フォームの要素を追加・削除する機能がよくあるので作成方法をまとめます。

例として作る機能

特徴や内容量などにつかいそうなフォーム。今回はプロパティという名前で作成。

Modelにメソッド追加

	    def properties
	      parse_property = JSON.parse(property) # propertyに不正な値が入っていた場合に例外発生する
	      return [] unless parse_property.is_a?(Array) && parse_property.all? { |prop| prop.is_a?(Hash) }
	      parse_property
	    rescue
	      []
	    end
	

Helperにメソッド追加

	      def add_property_button_tag(name)
	        fields = render 'property_fields', property_key: nil, property_value: nil
	        button_tag(name, type: :button, class: 'add_property btn btn-default pull-right', data: { fields: fields.delete("\n") })
	      end
	

View (_form.slim)

	  fieldset
	    .col-md-3
	      legend プロパティ
	
	    .col-md-9
	      .form-group
	        / 入力フィールド
	        table.table#properties
	          - @モデルのインスタンス.properties.each do |property|
	            = render 'property_fields', property_key: property['property_key'], property_value: property['property_value’]
	        / 実際に値が入るフィールド↓
	        = f.hidden_field :property
	
	        / 追加ボタン
	        = add_property_button_tag 'プロパティ追加'
	

View (_property_fields.slim)

	tr.property
	  td
	    = text_field_tag nil, property_key, id: nil, class: :property_key
	  td
	    = text_field_tag nil, property_value, id: nil, class: :property_value
	  td
	    button.btn.btn-default.pull-right.remove_property type="button"
	      = '削除'
	

coffee script

	class クラス名
	  constructor: ->
	    @properties = $('#properties')
	    @add_property = $('.add_property')
	
	    @add_event_to_property()
	
	  # イベント設定
	  add_event_to_property: ->
	    @properties.on('change', 'input', @reset_property)
	    @properties.on('click', '.remove_property', @remove_property)
	    @properties.on('click', '.remove_property', @reset_property)
	    @add_property.click(@adding_property_field)
	
	  # hiddenフィールドに入れる値設定
	  reset_property: =>
	    property_attrbutes = $('.property').map( (_index, property) ->
	      property_key = $(property).find('.property_key').val()
	      property_value = $(property).find('.property_value').val()
	      return unless property_key && property_value
	      {
	        'property_key': property_key,
	        'property_value': property_value
	      }
	    )
	    # JOSN形式で保存
	    @property.val(JSON.stringify(property_attrbutes.get()))
	
	  # 削除
	  remove_property: ->
	    $(this).closest('tr').remove()
	
	  # 追加
	  adding_property_field: ->
	    field_tags = $(this).data('fields')
	    $field = $(field_tags)
	    $('#properties').append($field) # タグを追加
	

保存した値

	$ rails c
	2.2.0 :002 > モデルインスタンス.property
	 => "[{\"property_key\":\"高さ\",\"property_value\":\"10cm\"},{\"property_key\":\"横幅\",\"property_value\":\"20cm\"},{\"property_key\":\"重さ\",\"property_value\":\"100g\"}]”
	
	2.2.0 :003 > モデルインスタンス.properties
	 => [{"property_key"=>"高さ", "property_value"=>"10cm"}, {"property_key"=>"横幅", "property_value"=>"20cm"}, {"property_key"=>"重さ", "property_value"=>"100g”}]
	
	

checkboxとlabelの変な現象

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

railsで、checkboxとlabelの組み合わせで、チェックボックスが反応なしの現象が起こりました。

調査しにくいので、共有したいと思います。

 現象

チェックボックスをクリックしても、チェックされなくて、反応なしです。

 開発環境

Rails 4.1.4

ruby 2.1.2p95

viewテンプレート: erb

 lable forとは

<lable for="ID属性値">タグを使用すると、
<lable>タグの開始タグと終了タグに挟まれた文書が、
ID属性の属性値として「ID属性値」と同じ値が書き込まれた部品と、関連付けされます。

 発生状況

<%= check_box_tag '/feature_ids[]'/, feature.id, feature_ids.include?(feature.id), 
id: "feature_id_1_#{ feature.id }", class: "g_1" %>
<lable for="<%= " feature_id_#{ feature.id }" %>"><%= feature.name %></lable>

checkboxのID:feature_id_1_#{ feature.id }

lableのfor:   feature_id_#{ feature.id }

checkboxのIDを修正し、lableのforを修正し忘れたため、現象が起こりました。

 対処

lableのforの値はcheckboxのidと一致します。

※関連付けるために、値は一致しないのは正しくないですが、

まさかチェックボックス動作に影響するのは思いませんでした。

RailsのViewを自在にカスタマイズするための「Cosme」gem

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

既存のViewに手を加えずカスタマイズするためのRails向けgem「Cosme」を紹介します。

 はじめに

Railsには便利なgemがたくさんあり、この中にはロジックだけでなく画面のデザインであるViewを含んだものが数多くあります(たとえばActiveAdminやDevise、Comableなど)。これらをこのまま利用できれば楽ですが、認証のための項目を増やしたいとか商品価格の横には定価を載せたいとか、やりたいことが増えてくるとその一部に手を加えたくなるケースが少なからずあります。

通常Viewは一部分だけを変更することが不可能で、カスタマイズを行う場合はファイルを丸ごと置き換える形で対応することになります。ただしこの手法には、gemのバージョンアップの際にViewの更新を追うことができなくなってしまう、という欠点があります。

今回はこの欠点を補いつつ既存のViewをカスタマイズするためのgem「Cosme」を紹介します。

 使い方

1. gemのインストール

bundlerを利用している場合は下記の行を Gemfile に追加します。

gem 'cosme'

2. JavaScriptライブラリの読み込み

※ v0.4.0 からこの操作は不要になりました。

`app/assets/javascripts/application.js` に下記の行を追加します。

//= require cosme

3. ヘルパメソッドの組み込み

※ v0.2.0 からこの操作は不要になりました。

`app/views/layouts/application.html.erb` の <body> タグ直下に下記の行を追加します。

<%= cosmeticize %>

4. カスタマイズ内容を定義

カスタマイズ用のViewとメタ情報を記載した設定ファイルを `app/cosmetics` ディレクトリに設置します。

カスタマイズの定義を行うために `Cosme.define` というメソッドを呼び出します。

「target」はカスタマイズ対象で、jQueryのHTMLセレクタと同じ役割を果たします。

「action」はカスタマイズ方法で、「before」「after」「replace」をいずれかを指定します。

# app/cosmetics/after_example.rb
Cosme.define(
  target: '.example',
  action: :after
)
<%# app/cosmetics/after_example.html.erb %>
<h2>After Example</h2>

 結果

これで、すべての `example` というCSSクラスを持つHTML要素の後に「After Example」と表示されるようになりました。

例えば `app/views/layouts/application.html.erb` が下記のように `example` クラスを持つ要素を含んでいたとすると、最終的には「Example」のあとに「After Example」が表示されるようになります。

<%# app/views/layouts/application.html.erb %>
<html>
  <head>
    <title>Example</title>
    <%= stylesheet_link_tag '/application'/, media: '/all'/ %>
    <%= javascript_include_tag '/application'/%>
  </head>
  <body>
    <div class="example">
      <h1>Example</h1>
    </div>
  </body>
</html>

上記の結果、<body> タグ内は下記のようになります。

<div class="example">
  <h1>Example</h1>
</div>
<h2>After Example</h2>

 しくみ

CosmeはHTMLの置換処理を JavaScript 上で行っています。そのため動作速度や非JavaScript環境での動作を求める方にはあまりオススメできません。その一方でとてもシンプルな実装になっているためすべてのテンプレートエンジンに柔軟に対応できます。

同じことを実現できる「deface」というgemがありますが、こちらはActionViewを拡張することで実装されているため対応テンプレートエンジンが限定されており、またその一部にバグがある*1状態です(*1 2015/10/1現在: slimにおいてブロック内の要素がHTMLエスケープされてしまう https://github.com/spree/deface/issues/133 )。ただし、動作速度を求めていてバグにも引っかからない場合はこちらのgemをオススメします。

 おわりに

今回はViewのカスタマイズに便利なCosmeというgemを紹介しました。

追加機能の要望や不具合の報告は こちら にリクエストすると中の人が対応してくれるかもしれません。

 関連リンク

Cosme :: https://github.com/appirits/cosme

Deface :: https://github.com/spree/deface

 改訂

  • 2015/10/18 :: v0.4.0へのバージョンアップに伴い、スクリプトの組み込みが不要になりました。
  • 2015/10/09 :: v0.2.0へのバージョンアップに伴い、ヘルパメソッドの組み込みが不要になりました。

IDCF keepalivedを使用したグローバルIPとローカルIPの紐付け

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

rickNo38です。
IDCフロンティアでhttp/httpsのアクセス先を冗長化するため
keepalivedを使用するために行った設定を記載いたします。

用意するもの

・IDCF契約(仮想サーバ2台以上)
・グローバルIP1個(IDCF管理画面上はIPアドレス)
・実施したOSはCentOS7

冗長化を行う理由

用意されているルーターを使用するとhttpsの場合、アクセス元IPが取得できなくなります。
そのため、ルーターを返さず直接apache等で受け取る必要があります。
また、冗長化していないと安全性が低いため冗長化も必用となってきます。

APIコマンドinstall

keepalivedでの冗長化を実現するためには、
管理画面上の設定では不可能なため、
APIをinstall必要があります。
設定するのはmasterサーバの1台だけです。su – curl -kL https://raw.github.com/pypa/pip/master/contrib/get-pip.py | python
yum -y install libxml2 libxml2-devel libxslt libxslt-devel gcc python-devel
pip install git+https://github.com/idcf/cloudstack-api
cloudstack-api –version
—–
cloudstack-api v0.10.2
—–

API設定

vim ~/.idcfrc
—–
[account]
host=エンドポイント
api_key=API Key
secret_key=Secret Key
—–
chmod 600 ~/.idcfrc
# 下記表示されればok
cloudstack-api listZones
—–
{
“listzonesresponse”: {
“count”: 3,
“zone”: [
{
“allocationstate”: “Enabled”,
“dhcpprovider”: “VirtualRouter”,
“id”: “xxxx”,
“localstorageenabled”: true,
“name”: “tesla”,
etc…
—–

サーバに2個目のIPを付与

# 仮想マシンIDの確認
cloudstack-api listVirtualMachines -t displayname,id
—–
+————–+————————————–+
| displayname | id |
+————–+————————————–+
| test | 1234567890 |
—–
# NICの確認
cloudstack-api listNics –virtualmachineid 1234567890
—–
{
“listnicsresponse”: {
“count”: 1,
“nic”: [
{
“gateway”: “10.3.0.1”,
“id”: “abvdefg”,
“ipaddress”: “10.3.0.2”,
“isdefault”: true,
“macaddress”: “xx:xx:xx:xx:xx”,
“netmask”: “xxx.xxx.xxx.xxx.xxx”,
“networkid”: “xxxxxxx”
}
]
}
}
—–
# サーバにIPを付与
cloudstack-api addIpToNic –nicid abvdefg –ipaddress 10.3.0.3
# secondaryipが指定されているか確認
cloudstack-api listNics –virtualmachineid 1234567890
—–
{
“listnicsresponse”: {
“count”: 1,
“nic”: [
{
“gateway”: “10.3.0.1”,
“id”: “abvdefg”,
“ipaddress”: “10.3.0.2”,
“isdefault”: true,
“macaddress”: “xx:xx:xx:xx:xx”,
“netmask”: “xxx.xxx.xxx.xxx.xxx”,
“networkid”: “xxxxxxx”
“secondaryip”: [
{
“id”: “zxcvasdf”,
“ipaddress”: “10.3.0.3”
}
]
}
]
}
}
—–

NAT設定

# グローバルIPのリスト取得
cloudstack-api listPublicIpAddresses -t ipaddress,id
—–
+—————–+————————————–+
| ipaddress | id |
+—————–+————————————–+
| 210.140.111.111 | aaaaaa |
——
# ローカルIPとグローバルIPのNAT設定
cloudstack-api enableStaticNat –ipaddressid aaaaaa –virtualmachineid 1234567890 –vmguestip 10.3.0.3
管理画面メニューのIPアドレスから「210.140.111.111」がNAT設定されているか確認できます。

keepalived設定

後は普通にkeepalivedの設定をするだけです。

RailsでEnumerizeの使い方

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

railsのModelで列挙型を扱うのに、gemのenumerizeが便利です。

enumerizeについて、幾つかの使い方を紹介したいと思います

 gem

gem ‘enumerize’

 モデル

class User < ActiveRecord::Base
  extend Enumerize

  enumerize :sex, in: [:male, :female]  #配列
  enumerize :role, in: {:user => 1, :admin => 2}  #ハッシュ
end

これだけでsexに対するinclusionのバリデーションがかかる

エラーメッセージ

性別は一覧にありません。

 ja.yml

ja:
  enumerize:
    user:
      sex:
        male: 男
        female: 女
      role:
        user: 会員
        admin: 管理者

 使い方

User.sex.values  # => ["male", "female"]
User.sex.options # => [["男", "male"], ["女", "female"]]

※もしフィールド名はnameの場合、User.nameはUserモデルのメソッドのため、enumerized_attributesを利用する
User.name  # => "User"
User.enumerized_attributes[:sex].values # => ["male", "female"]
User.enumerized_attributes[:sex].values # =>  [["男", "male"], ["女", "female"]]

user = User.new
user.male?   # => false
user.female? # => false
user.sex = 'male'
user.male?   # => true
user.female? # => false
user.sex_value # => "male"
user.sex_text # => "男"

user.role = :user
user.role #=> 'user'
user.role_value #=> 1
user.role_text  #=>  "会員"

User.role.find_value(:user).value #=> 1
User.role.find_value(:admin).value #=> 2

 form_for

<%= form_for @user do |f| %>
  <%= f.select :sex, User.sex.options %>
<% end %>

 SimpleForm

select collection
<%= simple_form_for @user do |f| %>
  <%= f.input :sex %>
<% end %>

radio buttons
<%= simple_form_for @user do |f| %>
  <%= f.input :sex, :as => :radio_buttons %>
<% end %>

 enumerizeを使用する際、モデルのdefault値

マイグレートファイルでdefaultを指定していたとしても、モデルでenumerizeのdefaultを指定しないとnullが挿入される。

enumerize :role, in: [:user, :admin], default: :user

 ActiveRecord scopes

scope: trueを利用して、scopeとして利用できる。

class User < ActiveRecord::Base
  extend Enumerize
  enumerize :sex, :in => [:male, :female], scope: true
  enumerize :status, :in => { active: 1, blocked: 2 }, scope: :having_status
end

User.with_sex(:female)
# SELECT "users".* FROM "users" WHERE "users"."sex" IN ('female')

User.without_sex(:male)
# SELECT "users".* FROM "users" WHERE "users"."sex" NOT IN ('male')

User.having_status(:blocked).with_sex(:male, :female)
# SELECT "users".* FROM "users" WHERE "users"."status" IN (2) AND "users"."sex" IN ('male', 'female')

 参照

https://github.com/brainspec/enumerize

lambda のスコープ

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

lambda というのを使ってみたのでメモです。

使い方は Proc.new と同じです。

※ ブロック内で return したときの挙動が違います。

メソッドを変数のように扱うことができます。

定義時のスコープの変数を参照するところが面白いと思いました。

 使い方

lambda ブロック

※ ブロックというのは雑にいうと do ;end や {} で囲った処理の定義のこと。

 環境

ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]

Pry version 0.10.1 on Ruby 2.2.2

 使ってみました。

ブロック定義時に未定義の変数は未定義のままとなることの確認(変数を定義すると試せないので先に試します)

proc = lambda {puts i}
proc.call
出力
NameError: undefined local variable or method `i' for main:Object
from (pry):1:in `block in __pry__'
i = 3
proc.call
出力
NameError: undefined local variable or method `i' for main:Object
from (pry):1:in `block in __pry__'

標準的な使い方

i = 2
proc = lambda {puts i}
proc.call
出力
2
  • ブロック定義前に使用される変数を定義されていることがポイント

each内での挙動

i = 5
proc = lambda {puts i}
(1..4).each do |i|
  proc.call
end
出力
5
5
5
5

each内で意図した出力を試みる

i = 7
proc = lambda {puts i}
(1..4).each do |j|
  i = j
  proc.call
end
出力
1
2
3
4

for を使って見る

i = 11
proc = lambda {puts i}
for i in (1..4)
  proc.call
end
出力
1
2
3
4

直接引数を渡すときはブロック引数を使う

proc = lambda { |value|  puts value}
proc.call('引数はこれ')
出力
引数はこれ

[scala] [vim] vimでSnakeCaseとcamel_caseとを変換する

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

RailsとPlayで同一のDBを参照した環境で開発している場合には、この変換を機械的にできると便利

 本記事の対象者

・RailsからもPlayからも同一のDBに対してアクセスするモジュールをvimで開発している。

 RailsとPlayのいずれでも開発しているときの問題点

  • Railsの推奨は、キャメルケース(単語間をアンダーバーで区切る)
  • Playの推奨は、スネークケース(単語間の文字の先頭を大文字にする)

特にDBのカラム名を扱うとき、Rails側ではキャメルケースで書き、Play側ではスネークケースで書くことになり、双方のコードの編集を行き来しているとキャメルケースとスネークケースとを機械的に変換したくなる。

 対応方法

vimにはキャメルケースとスネークケースとを機械的に変換するプラグインが存在する。

その1つのoperator-camelizeというプラグインを導入した。

なお、当該プラグインのベースとなるこのプラグインも必要。

 設定

「.vimrc」に

map <leader>c <plug>(operator-camelize-toggle)

と設定しておくことで、VisualModeで選択した後「\c」でキャメルケースとスネークケースとをトグル変換できる。

トグル変換が嫌な場合には、以下のように設定するとよい。

「\c」でキャメルケースへの変換。

「\C」でスネークケースへの変換。

map <leader>c <plug>(operator-camelize)
map <leader>C <plug>(operator-decamelize)

ThinReports使用に関するTips

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Ruby on RailsにてデータをPDF出力できるThinReportsを使用する際のTipsを記載する。

 プログラム的に問題なくデータ転送しているはずなのに出力されない場合に確認すべき点

項目が非表示になっている可能性があるので、確認する。

(PROPERTY => 基本 => 表示 にチェックが入っているか確認)

 レイアウトファイル上にある項目とプログラムの転送項目が一致しない場合の挙動

レイアウト:有、PG:無

レイアウトファイル上にありプログラムで転送していない項目がある場合

=> エラーにならず、項目が配置されている場所には何も表示されない。

レイアウト:無、PG:有

レイアウトファイル上になくプログラムで転送している項目がある場合

=> エラーが発生する。

 値がnilとなる可能性のあるキーを含むハッシュを指定する場合の注意

前提

  1. レイアウトファイルに「tax」という項目が配置されている。
  2. priceの基本書式(PROPERTY => 簡易書式 => 基本書式)に「{value}円」と設定されている。
  3. 「products」(商品)テーブルに「tax」カラムがあり、NULLを許可している(NULLの可能性がある)。
product = Product.find(id)
# product.taxがnilの可能性がある

report.values { price: product.tax }

taxが100の場合:「100円」と表示される。

taxがNULLの場合:「円」と表示される。

対処方法

ハッシュにcompactメソッドを介してから引数に指定する。

report.values { price: product.tax }.compact

taxが100の場合:「100円」と表示される。

taxがNULLの場合:何も表示されない。

【Rails】RailsでAjaxを使用する簡単手順【Ajax】

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

RailsでAjaxを使用する手順を簡単に説明します。

例として作る機能

選択されたユーザーの年齢が表示されるようなものを作成します。

例として使うデータ

	>> User.all
	=>[
	    #<user id: 1, name: “ユーザー1”, age: 11>,
	    #<user id: 2, name: “ユーザー2”, age: 22>,
	    #<user id: 3, name: “ユーザー3”, age: 33>
	]
	

1. routes.rbにajax用のアクションを追加

vim config/routes.rb

	resources :users
	

	resources :users do
	  get :search_user, on: :collection
	end
	

2. controllerにajax用のアクションを追加

	def search_user
	  @user = User.find(params[:user_id])
	  render layout: false
	end
	

3. viewにタグを記述

下記の3つを記述します。

①イベントを走らせるセレクトボックス

②ユーザー名を入れる用のタグ

③jsでpostする用のフォーム

vim app/views/users/index.slim

	#select_user
	  = select :user, :name, [[“ユーザー1", 1], [“ユーザー2", 2], [“ユーザー3", 3]], include_blank: true
	
	p このユーザーの年齢
	p#user_age
	
	div style=‘display: none;’
	  = form_tag(search_user_users_path, remote: true, method: :get) do
	    = text_field_tag :user_id
	    = submit_tag
	

4.フォームをpostするjsを記述

vim app/assets/javascripts/users.coffee

	$ ->
	  # セレクトボックスが変更されたらフォームをsubmit
	  $(‘#select_user select’).change( ->
	    $user_id = $('#user_id')
	    $user_id.val($(this).val()) # 選択されたユーザーのIDをパラメータとして渡す
	    $user_id.closest('form').submit()
	  )
	

4.ajax用のアクションのview(js)を記述

vim app/views/users/search_user.coffee

	$('#user_age’).text(‘<%= @user.age %>')
	

以上で完了です。

これでセレクトボックスを変更するたびにユーザーの年齢が変更されると思います。

誤解しやすいSQL

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

プログラムコードを書く際、書く言語の文法を理解している事は重要であるが、

理解している様で実は意外と誤解しているエンジニアが(比較的)多そうな、SQLのWHERE条件について、挙動と注意点を記述する。

 前提

次の様なデータを持つテーブル「t」があるとする。

+----+------+------+
| id | a    | b    |
+----+------+------+
|  1 | NULL | NULL |
|  2 | NULL | 2222 |
|  3 | 1111 | 2222 |
|  4 | 1111 | 1111 |
+----+------+------+

このテーブルに対して、WHERE句で条件を指定して抽出するSELECT文を考える。

SELECT id FROM t WHERE /* ここに条件を記載 */;

このWHERE句が以下のパターン1-4に記述する様な内容であった場合、どのidが抽出されるか正確に想像できるであろうか。

余談

Oracle, MySQL 等、DUALが使用可能なデータベースでは、次の様に記述すれば簡単に確認ができる。

SELECT * FROM (
SELECT 1 id, NULL a, NULL b FROM DUAL UNION 
SELECT 2 id, NULL a, 2222 b FROM DUAL UNION 
SELECT 3 id, 1111 a, 2222 b FROM DUAL UNION 
SELECT 4 id, 1111 a, 1111 b FROM DUAL
) t
WHERE /* ここに条件を記載 */;

 パターン1 (通常比較)

問題

(1) a = b
(2) a <> b
(3) a < b
(4) a > b
(5) a IS NULL
(6) a IS NOT NULL

結果

(1) 4
(2) 3
(3) 3
(4) なし
(5) 1, 2
(6) 3, 4

結果から言える注意点

=, >, <>, <= を指定した場合、NULLデータはヒットしなくなる。

 パターン2 (パターン1にNOT付加)

問題

(1) NOT a = b
(2) NOT a <> b
(3) NOT a < b
(4) NOT a > b
(5) NOT a IS NULL
(6) NOT a IS NOT NULL

結果

(1) 3
(2) 4
(3) 4
(4) 3, 4
(5) 3, 4
(6) 1, 2

結果から言える注意点

NOTを付けると付けなかった場合に抽出されなかったレコードが抽出されると考えがちであるが、実際にはそうではない。

中身の比較演算子(IS NULL等も含めるとする)が逆の意味を持つ比較演算子に変化したと考えると理解し易い。

= の逆は <>
> の逆は <=
< の逆は >=
IS NULL の逆は IS NOT NULL

※即ち以下と同じになる。

(1) a <> b
(2) a = b
(3) a >= b
(4) a <= b
(5) a IS NOT NULL
(6) a IS NULL

 パターン3 (複数条件)

問題

(1) a = b AND a IS NOT NULL
(2) a = b AND b IS NOT NULL
(3) a = b OR b IS NULL
(4) a < 1111 AND b < 2222 OR a < b

結果

(1) 4
(2) 4
(3) 1, 4
(4) 3

結果から解る点

パターン1で述べた様に、=を用いるとNULLデータはヒットしなくなる(もともとIS NOT NULL を含意している)ので、「AND a IS NOT NULL」等を付け足しても結果に差は出ない。

 パターン4 (パターン3にNOT付加)

問題

(1) NOT (a = b AND a IS NOT NULL)
(2) NOT (a = b AND b IS NOT NULL)
(3) NOT (a = b OR b IS NULL)
(4) NOT (a < 1111 AND b < 2222 OR a < b)

結果

(1) 1, 2, 3
(2) 1, 3
(3) 3
(4) 4

結果から言える注意点

この結果からも解る様に、NOTを付けなかった場合に抽出されなかったレコードがNOTを付けると抽出される訳ではない((1)と(2)はパターン3では同じ結果であるがパターン4は結果が異なる)。

次の様に考えると理解し易い。

ANDやORを含む句にNOTを付けると、それぞれの比較演算子は逆の意味を持つ演算子になり、ANDはORに、ORはANDに変化する。また、ANDとORが複合している場合は、もともとANDであった条件同士の方が結合度が強くなる。

※即ち以下と同じになる。

(1) a <> b OR a IS NULL
(2) a <> b OR b IS NULL
(3) a <> b AND b IS NOT NULL
(4) (a >= 1111 OR b >= 2222) AND a >= b

 結論

NULL値が含まれるデータに対するWHERE条件は、数学的な式の結果と異なるので、誤解をし易い。特に、NOTが含まれる条件は、解釈の際に1手間増えるというだけでなく、誤解する確率を上げる事になるので、もし同じ条件でNOTを使わない記述が可能な場合は、理由がなければ使わない方が良いと言えるであろう。

railsに導入できるMarkdown用エディタの紹介

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

社会人2年目も中盤にさしかかっている中西です。

今回は、railsに導入可能なMarkdown用のエディタについて紹介します。

環境

Rails 4.1.4

Ruby 2.1.2

Markdownとは

Markdownとは、ジョン・グルーバー(John Gruber)によって2004年に開発され、その後、多くの開発者の手を経ながら発展してきた文章の書き方です。

「書きやすくて読みやすいプレーンテキストとして記述した文書を、妥当なXHTML(もしくはHTML)文書へと変換できるフォーマット」として作成されています。

このMarkdown文章を書く場合のルール(記法)をMarkdown記法と呼びます。

詳しい記法については、下記を参照してください。

Daring Fireball: Markdown: Syntax

Markdown記法 · 日本語Markdownユーザー会

Markdown用エディタ

Markdownにもとづいた文章を、HTMLへ変換するgemはたくさんの種類が存在しています。

また、Markdown記法で入力を行えるエディタも存在しています。

しかし、Markdown記法での入力をサポートするようなエディタとなると、なかなか見つかりません。

今回は、そんなMarkdown記法での入力をサポートするエディタであり、railsに簡単に導入できるgemである「pagedown-bootstrap-rails」を紹介します。

pagedown-bootstrap-railsとは

「pagedown-bootstrap-rails」というgemは、「pagedown-bootstrap」をもとにrails用にgem化されたものです。

Markdown記法での入力をサポートするために、主要なMarkdown記法をボタン1つで適用することができます。

また、実際の表示がどうなるのか分かるように、入力内容をリアルタイムでプレビュー表示をしてくれます。

導入方法

まず下記のように、Gemfileのgemの宣言を追加します。

Gemfile
gem 'bootstrap-sass'
gem 'font-awesome-rails'
gem 'simple_form'
gem 'pagedown-bootstrap-rails'

「pagedown-bootstrap-rails」以外のgemについては、前提条件として必要となります。

次に、css及びjsを追加します。

application.css
/*= require pagedown_bootstrap */
application.js
//= require pagedown_bootstrap
//= require pagedown_init

sccの場合は下記のようになります。

application.css.scss
@import "pagedown_bootstrap";

SimpleFormをもちいて表示の変換部分を作成します。

app/inputs/pagedown_input.rb
class PagedownInput < SimpleForm::Inputs::TextInput
  def input(wrapper_options)
    out = "\n"
    html_options = input_html_options.merge(class: 'wmd-input', id: "wmd-input-#{attribute_name}")
    out << "#{@builder.text_area(attribute_name, merge_options(html_options, wrapper_options)) }"
    if input_html_options[:preview]
      out << ""
    end
    out.html_safe
  end

  private

  def merge_options(html_opts, wrapper_opts)
    html_opts.merge(wrapper_opts) { |_key, first, second| first + ' ' + second }
  end
end

後は、エディタを表示したい部分に、下記のように記述するだけでエディタが表示されます。

<%= simple_form_for(@article) do |f| %>
  <%= f.input :body, as: :pagedown, input_html: { preview: true, rows: 20 } %>
<% end %>

[マークダウン用エディタ.png:image]

まとめ

今回は、Markdown記法での入力をサポートするエディタである、「pagedown-bootstrap-rails」を紹介しました。

railsでブログサイト等を作成するときに、Markdown記法で記事を作成したい場合にはぜひ導入を検討してみてください。

参考

日本Markdownユーザー会

pagedown-bootstrap-rails

to_xml メソッドのエチュード

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

rails に xmlを出力するときに便利な to_xml メソッドがありますが

とある要件に対応する為に

ちょっと加工が必要だったことがあったのでメモです。

おもに困ったこと

1. エンティティ名が to_json のときと違う。エンティティー名に _ があるときに – にされてしまう。

2. タグの属性に type=“値のクラス” が入ってしまう。

3. 文字コードが変えられない。 <?xml version=”1.0″ encoding=”UTF-8”?> というタグが入ってしまう。

環境

CentOS Linux release 7.1.1503 (Core)

ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]

Rails 4.2.2

やっつけソース

def xml_source(object, xml_char) # xml内容作成の定義。
  <<-end_of_xml_source
<?xml version=\"1.0\" encoding=\"#{xml_char}\"?>
#{object.to_xml(dasherize: false, skip_types: true, skip_instruct: true).gsub('"', '"').gsub("'", ''')}
  end_of_xml_source
end
xml_source(object, xml_char).encode(xml_char, invalid: :replace, undef: :replace)

解説

1. to_xml メソッドの引数に dasharize: false を指定することで解決。

2. 同じく skip_types: true を指定することで解決。

3. 同じくskip_instruct: true を指定することでヘッダのタグを表示しなくできる。所望のヘッダタグの取り付けと実際の文字コードの変換はxml 出力後に行う。文字コードの変換には encode メソッドを使用した。変換不可能な文字は置換。

他に対応した点

nil の値があると <エンティティ名 nil=“true”> のようなタグが発行されてしまう為、データに nil があったら ” に変換。

xml出力のときだけ出したくなかった文字は to_xml後にgsub で変換。

CentOS5のsubversionを1.8にしたのでgit-svnのバージョンも上げる(yum)

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

先日CentOS5にSubversion1.8をrpmでインストールしたのですが、
git-svnもそれに合わせたバージョンを入れる必要がありました。

wandiscoが提供するリポジトリをyumリポジトリに追加すれば、
Subversion1.8に合わせたgit-svnをyumでインストールできます。

git-svnインストール時にSubversion関連も一式インストールされるので、
一度Subversionをアンインストールしてからyumでインストールしてみました。・環境・手順

  1. リポジトリを追加
  2. GPGキーを取り込む
  3. yumでインストール

・おまけ

■ 環境

CentOS5.11 x86_64

■ 手順

1. リポジトリを追加

/etc/yum.repos.d/wandisco.repo を作成。
gitとsvnの両方とも設定しておきます。
(subversion-perlがsvnの方に入ってるので必要。
最初gitの方だけ設定していて依存関係でおこられました。)

[wandisco-git]
name=WANDisco Repository - git-2.0 centos5
baseurl=http://opensource.wandisco.com/centos/5/git/$basearch/
enabled=0
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-WANdisco


[wandisco-svn]

name=WANDisco Repository – snv-1.8 centos5 baseurl=http://opensource.wandisco.com/centos/5/svn-1.8/RPMS/$basearch/ enabled=0 gpgcheck=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-WANdisco

2. GPGキーを取り込む

# rpm --import http://opensource.wandisco.com/RPM-GPG-KEY-WANdisco

3. yumでインストール

一度Subversion関連をアンインストール。(しなくてもいいです)

# yum remove subversion apr

リポジトリを指定してインストール

# yum install --enablerepo=wandisco-svn,wandisco-git --disablerepo=base,extras,updates,epel git-svn
Loaded plugins: fastestmirror, security
Loading mirror speeds from cached hostfile
Setting up Install Process
Resolving Dependencies
--> Running transaction check
---> Package git-svn.x86_64 0:2.0.0-1.WANdisco.191 set to be updated
--> Processing Dependency: git = 2.0.0-1.WANdisco.191 for package: git-svn
--> Processing Dependency: perl(Git::SVN) for package: git-svn
--> Processing Dependency: perl(Git::SVN::Log) for package: git-svn
--> Processing Dependency: perl(Git::SVN::Fetcher) for package: git-svn
--> Processing Dependency: subversion for package: git-svn
--> Processing Dependency: perl(Git::SVN::Ra) for package: git-svn
--> Processing Dependency: perl(Git::SVN::Utils) for package: git-svn
--> Processing Dependency: perl(Git::SVN::Editor) for package: git-svn
--> Processing Dependency: perl(Git) for package: git-svn
--> Processing Dependency: perl(Git::SVN::Prompt) for package: git-svn
--> Processing Dependency: perl(Git::SVN::Migration) for package: git-svn
--> Running transaction check
---> Package git.x86_64 0:2.0.0-1.WANdisco.191 set to be updated
---> Package perl-Git.x86_64 0:2.0.0-1.WANdisco.191 set to be updated
--> Processing Dependency: perl(SVN::Client) for package: perl-Git
--> Processing Dependency: perl(SVN::Delta) for package: perl-Git
--> Processing Dependency: perl(SVN::Core) for package: perl-Git
--> Processing Dependency: perl(SVN::Ra) for package: perl-Git
---> Package subversion.x86_64 0:1.8.13-1 set to be updated
--> Processing Dependency: apr-util >= 1.5.3 for package: subversion
--> Processing Dependency: apr >= 1.5.0 for package: subversion
--> Processing Dependency: libapr-1.so.0()(64bit) for package: subversion
--> Processing Dependency: libserf-1.so.1()(64bit) for package: subversion
--> Processing Dependency: libaprutil-1.so.0()(64bit) for package: subversion
--> Running transaction check
---> Package apr.x86_64 0:1.5.0-1.WANdisco.2 set to be updated
---> Package apr-util.x86_64 0:1.5.3-2.WANdisco.8 set to be updated
--> Processing Dependency: apr-util-ldap = 1.5.3-2.WANdisco.8 for package: apr-util
--> Processing Dependency: apr-util-pgsql = 1.5.3-2.WANdisco.8 for package: apr-util
--> Processing Dependency: apr-util-sqlite = 1.5.3-2.WANdisco.8 for package: apr-util
---> Package serf.x86_64 0:1.3.7-1 set to be updated
---> Package subversion-perl.x86_64 0:1.8.13-1 set to be updated
--> Running transaction check
---> Package apr-util-ldap.x86_64 0:1.5.3-2.WANdisco.8 set to be updated
---> Package apr-util-pgsql.x86_64 0:1.5.3-2.WANdisco.8 set to be updated
---> Package apr-util-sqlite.x86_64 0:1.5.3-2.WANdisco.8 set to be updated
--> Finished Dependency Resolution

Dependencies Resolved

================================================================================
 Package             Arch       Version                  Repository        Size
================================================================================
Installing:
 git-svn             x86_64     2.0.0-1.WANdisco.191     wandisco-git     459 k
Installing for dependencies:
 apr                 x86_64     1.5.0-1.WANdisco.2       wandisco-svn      98 k
 apr-util            x86_64     1.5.3-2.WANdisco.8       wandisco-svn      81 k
 apr-util-ldap       x86_64     1.5.3-2.WANdisco.8       wandisco-svn     6.4 k
 apr-util-pgsql      x86_64     1.5.3-2.WANdisco.8       wandisco-svn      11 k
 apr-util-sqlite     x86_64     1.5.3-2.WANdisco.8       wandisco-svn     8.4 k
 git                 x86_64     2.0.0-1.WANdisco.191     wandisco-git      11 M
 perl-Git            x86_64     2.0.0-1.WANdisco.191     wandisco-git      66 k
 serf                x86_64     1.3.7-1                  wandisco-svn      47 k
 subversion          x86_64     1.8.13-1                 wandisco-svn     2.7 M
 subversion-perl     x86_64     1.8.13-1                 wandisco-svn     1.4 M

Transaction Summary
================================================================================
Install      11 Package(s)
Upgrade       0 Package(s)

Total download size: 15 M
Is this ok [y/N]:


  

Subversion1.8に合わせたgit-svnやgit等、一式インストールできました。

参考サイト
CentOS 6でsubversionのバージョンを上げる
リポジトリを指定してyum installする

■ おまけ

Subversion1.8だけ入れたい場合

/etc/yum.repos.d/wandisco.repoにsvnの設定だけして
GPGキー取り込み後、以下を実行すれば一式インストールされます。

# yum install --enablerepo=wandisco-svn --disablerepo=base,extras,updates,epel subversion

シェルスクリプトをダウンロード(登録制)する方法もあるようです。
Subversion 1.8系をCentOSにInstall (YUM経由)
WANdisco Subversion Download | WANdisco CentOS 5

rpmでgit-svnを入れたい場合

以下のものをインストールすればOKでした。(Subversion1.8前提)

http://opensource.wandisco.com/rhel/5/git/x86_64/git-2.0.0-1.WANdisco.191.x86_64.rpm
http://opensource.wandisco.com/rhel/5/git/x86_64/perl-Git-2.0.0-1.WANdisco.191.x86_64.rpm
http://opensource.wandisco.com/rhel/5/git/x86_64/git-svn-2.0.0-1.WANdisco.191.x86_64.rpm
http://opensource.wandisco.com/rhel/5/svn-1.8/RPMS/x86_64/subversion-perl-1.8.10-6.x86_64.rpm
  
# rpm -ivh http://opensource.wandisco.com/rhel/5/git/x86_64/git-2.0.0-1.WANdisco.191.x86_64.rpm http://opensource.wandisco.com/rhel/5/git/x86_64/perl-Git-2.0.0-1.WANdisco.191.x86_64.rpm http://opensource.wandisco.com/rhel/5/git/x86_64/git-svn-2.0.0-1.WANdisco.191.x86_64.rpm http://opensource.wandisco.com/rhel/5/svn-1.8/RPMS/x86_64/subversion-perl-1.8.10-6.x86_64.rpm
  

Oracleで誤ってデータを消してしまった際のリカバリ

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Oracleで誤ってデータを消してコミットしてしまっても、まだ諦めてはいけません。

OracleにはフラッシュバッククエリというUNDO表領域を参照して過去データを取り出す機能があります。

 うっかりWhere句を忘れて・・・

先日、とあるレコードを変更しようとして、うっかりWhere句による絞り込みを忘れ全レコードが更新されてしまうという失態を犯してしまいました・・・。

トランザクション貼っとけ!という意見はごもっともでありますが、ついうっかりは誰しもあるもの。

 フラッシュバッククエリで復旧

しかし調べて見ると、Oracleにはフラッシュバッククエリなる過去データを参照する機能があるとのこと!

早速以下のようにUpdateして事なきを得ました。

update users u set u.name = 
(select name from users as of timestamp (systimestamp - interval '1' hour) 
where u.id = users.id)

上記は1時間前のデータを参照しています。

ちなみに、3分前は

as of timestamp (systimestamp - interval '3' minute )

1日前は

as of timestamp (systimestamp - interval '1' day )

指定した日付、時間

as of timestamp to_timestamp('2015-07-24 00:00:00', 'yyyy-mm-dd hh:mi:ss')

と指定できるようです。

 最後に

UNDO表領域はロールバックデータとしても使われ、インサートなどすると古いUNDO表領域が無くなる恐れがありますので、速やかに復旧することをおすすめします。

また、表をTruncateしたり、再作成してしまった場合は、過去データを参照できないのでご注意ください。

Tomcat起動時のスタックオーバーフローへの対処

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Tomcat起動時にスタックオーバーフローが発生した際の対象方法をご紹介します。

 Tomcat起動が起動しない・・・

ある日、これまで正常に起動していたTomcatが起動しなくなりました。

ログを見ると以下の出力。

Cannot load JDBC driver class 'oracle.jdbc.OracleDriver'
java.lang.StackOverflowError
        at java.util.Stack.empty(Stack.java:96)
        at sun.misc.URLClassPath.getLoader(URLClassPath.java:283)
        at sun.misc.URLClassPath.getResource(URLClassPath.java:168)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:194)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
        at sun.misc.Launcher$ExtClassLoader.findClass(Launcher.java:229)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:295)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
        at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1595)
...

StackOverflowErrorが発生しているようです。

 スタックとは?

JVMのメモリ構造はスタックとヒープに大別されます。

ヒープはオブジェクトのインスタンスなどが保存される広大な領域で、GCの対象です。

一方スタックはメソッド起動時にローカル変数などを保存する領域です。

あまりスタックが足りなくなる場合は無いのですが、意図しないケースだと再帰メソッドの終了条件の書き忘れなどで発生します。

ただ、今回の場合はアプリ起動時にローカル変数をキャッシュするようにしたことによるスタックサイズの増加でした。

そのため、対処としては最大スタックサイズを増やすしかなさそうです。

 最大スタックサイズの設定

最大スタックサイズの設定はJVMの起動パラメータの

-Xss512k

の値で変更します。

では、どれくらい増やせばよいのか・・・?

大きければいいという訳ではありません。最大スタックサイズを非常に大きな値に設定すると、

パフォーマンスが低下する可能性があります。

まずは現在の設定値 or デフォルト値の2倍程度にして様子をみるのがいいでしょう。

 まとめ

通常スタックサイズが足りなくなることは少ないかと思いますが、もし足りなくなったら上記設定で対処することができます。

もちろんその前に、無限ループなどが発生していないか確認するのをお忘れなく!

CentOS5のsvnをWin側からTortoiseSVN1.8で管理する

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

ホストOS(Win)からゲストOS(CentOS5)にSambaで接続して、

Win側からはTortoiseSVN1.8で管理したかったのですが、

Subversion1.6ではうまくいかなかったので、rpmで1.8をインストールしました。

yumでインストールしようとすると1.6が入ってしまいますが

それぞれのバージョンを合わせないと共存できないようです。

1.7以降であれば大丈夫な気がしつつも、

今回はEclipseでSVNクライアント1.8を選択したいので

1.8にしました。

▼作業コピーが1.6のフォーマットだと、「作業コピーをアップグレード」が完了するまで更新やコミットができない。

▼「作業コピーを新しい1.8形式にアップグレード」を選択してフォーマットが最適化されると、

TortoiseSVNでは更新等が可能になるが、ゲスト側では更新ができなくなってしまう。

$ svn up
svn: The path '.' appears to be part of a Subversion 1.7 or greater
working copy.  Please upgrade your Subversion client to use this
working copy.

 やりたいこと

Sambaで接続したゲストOS(CentOS5)にアクセスして、

ホストOS(Win8.1)側からはTortoiseSVN1.8で管理できるようにしたい。

(さらにWin側ではEclipseでSVNクライアント1.8を入れて開発できるように)

 環境

ホストOS Windows8.1 TortoiseSVN1.8 
ゲストOS CentOS5.11(VirtualBox) Subversion1.8 

 手順

1. インストール済みのSubversionがあればアンインストールしておきます

# yum remove subversion
# yum remove apr

2. 適当な場所に保存

# wget http://opensource.wandisco.com/rhel/5/svn-1.8/RPMS/x86_64/subversion-1.8.10-6.x86_64.rpm
# wget http://opensource.wandisco.com/rhel/5/svn-1.8/RPMS/x86_64/apr-1.5.0-1.WANdisco.2.x86_64.rpm
# wget http://opensource.wandisco.com/rhel/5/svn-1.8/RPMS/x86_64/apr-util-1.5.3-2.WANdisco.8.x86_64.rpm
# wget http://opensource.wandisco.com/rhel/5/svn-1.8/RPMS/x86_64/serf-1.3.4-1.x86_64.rpm
# wget http://opensource.wandisco.com/rhel/5/svn-1.8/RPMS/x86_64/apr-util-ldap-1.5.3-2.WANdisco.8.x86_64.rpm http://opensource.wandisco.com/rhel/5/svn-1.8/RPMS/x86_64/apr-util-pgsql-1.5.3-2.WANdisco.8.x86_64.rpm http://opensource.wandisco.com/rhel/5/svn-1.8/RPMS/x86_64/apr-util-sqlite-1.5.3-2.WANdisco.8.x86_64.rpm

3. 保存したパッケージをインストール

# rpm -ivh apr-1.5.0-1.WANdisco.2.x86_64.rpm
# rpm -ivh apr-util-1.5.3-2.WANdisco.8.x86_64.rpm apr-util-ldap-1.5.3-2.WANdisco.8.x86_64.rpm apr-util-pgsql-1.5.3-2.WANdisco.8.x86_64.rpm apr-util-sqlite-1.5.3-2.WANdisco.8.x86_64.rpm
※まとめないと依存関係でおこられます

# rpm -ivh serf-1.3.4-1.x86_64.rpm
# rpm -ivh subversion-1.8.10-6.x86_64.rpm

4. バージョン確認

# svn --version --quiet
1.8.10

これでWin側からもCentOS側からもsvnで管理できるようになりました。

IDCFオブジェクトストレージ使用方法

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

rickNo37です。
IDCフロンティアでオブジェクトストレージを使用する機会があり、
使用しているというブログが少ないので接続確認するまでの方法記載します。

用意するもの

・IDCF契約(仮想サーバ1台以上)
 CentOS7で実施
・オブジェクトストレージ契約(50GB未満の容量は無料)

管理画面上の設定・確認

管理画面よりオブジェクトストレージ画面へ移動
※左上ロゴ横にあるサービス選択より選択
(FireFoxだと契約画面に遷移して遷移したい画面に遷移できない、chromeだといける)

APIユーザーの追加

 リージョン:EAST
 APIユーザー名:メールアドレス

バケットの作成

オブジェクト>BucketAction>バケット作成
 バケット名を入力

オブジェクトを保存

 上記で作成したバケットに画像をドロップ

記録

APIユーザーのエンドポイント、API Key、Secret Keyを後で使用します。

仮想サーバ(IDCFのサーバでなくても可能)

s3cmdインストール

参照
wget http://sourceforge.net/projects/s3tools/files/s3cmd/1.5.2/s3cmd-1.5.2.tar.gz
tar zxvf s3cmd-1.5.2.tar.gz
cd s3cmd-1.5.2
python setup.py install
yum -y install python-dateutil
s3cmd –version
=>s3cmd version 1.5.2

s3cmd設定

s3cmd –configure
Access Key:管理画面でみたAPI Key
Secret Key:管理画面でみたSecret Key
Default Region [US]:ap-northeast-1 ←東京らしい
Encryption password:
Path to GPG program [/bin/gpg]:
Use HTTPS protocol [No]:Yes
HTTP Proxy server name:
Test access with supplied credentials? [Y/n] n
Save settings? [y/N] y
Configuration saved to ‘/root/.s3cfg’

s3cmdアカウント設定

cd ~
vim .s3cfg
—————
host_base = 管理画面エンドポイント
host_bucket = %(bucket)s.管理画面エンドポイント
signature_v2 = True
—————

コマンド実行

s3cmd ls バケット参照
s3cmd setacl –acl-public s3://バケット名/オブジェクト名
コマンド参照

最近人気な記事