ホーム ブログ ページ 41

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://バケット名/オブジェクト名
コマンド参照

【Rails】RailsにAdminLTEを導入【AdminLTE】

0

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

RailsにAdminLTEを導入する手順を紹介します。

1. AdminLTEのダウンロード

ここからダウンロード (2015/03/31現在)

2. ダウンロードしたファイルを解凍し、設置

「dist」と「plgins」のフォルダを使用。下記に設置します。 ※/lib/にパスが通っている必要がある

RAILS_ROOT/lib/assets/adminlte/

3. 読み込む必要があるjsとcssをapplication.jsとapplication.cssに記入(導入するファイルは解凍したフォルダのindex.htmlを参考すると良い)

$ vim app/assets/javascripts/application.js

・
・
・
//= require jquery
//= require jquery_ujs
//= require bootstrap
//= require adminlte/dist/js/app.js                         ここら辺から読み込む必要があるファイルを記述
//= require adminlte/dist/js/raphael-min
//= require adminlte/plugins/morris/morris.min
//= require adminlte/plugins/sparkline/jquery.sparkline
//= require adminlte/plugins/jvectormap/jquery-jvectormap-1.2.2.min
//= require adminlte/plugins/jvectormap/jquery-jvectormap-world-mill-en
//= require adminlte/plugins/knob/jquery.knob
//= require adminlte/plugins/daterangepicker/daterangepicker
//= require adminlte/plugins/datepicker/bootstrap-datepicker
//= require adminlte/plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.all.min
//= require adminlte/plugins/slimScroll/jquery.slimscroll.min
・
・
・

$ vim app/assets/stylesheets/application.css

 ・
 ・
 ・
 *= require adminlte     ←このファイルにAdminLTEの読み込むcssをまとめる
 ・
 ・
 ・

$ vim app/assets/stylesheets/adminlte.css.scss

@import url('https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css');
@import url('http://code.ionicframework.com/ionicons/2.0.0/css/ionicons.min.css');
@import 'dist/css/AdminLTE.min';
@import 'dist/css/skins/_all-skins.min';
@import 'plugins/iCheck/flat/blue';
@import 'plugins/morris/morris';
@import 'plugins/jvectormap/jquery-jvectormap-1.2.2.css';
@import 'plugins/datepicker/datepicker3';
@import 'plugins/daterangepicker/daterangepicker-bs3';
@import 'plugins/bootstrap-wysihtml5/bootstrap3-wysihtml5.min';

以上で完了

flashのメッセージ以外の使い道

0

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

社会人2年目になった、まだまだ技術的に新人域を抜けきっていない気がする中西です。

今回は、flashが使えるのは、メッセージだけでないことについて紹介します。

環境

Rails 4.1.4

Ruby 2.1.2

flashに渡せる値

flashトとは、セッションに一時的にメッセージを入れておける機能です。

エラー等のメッセージを値として渡し、リダイレクト先でそのメッセージを表示する使い方が多いと思います。

test_controller.rb
flash[:notice] = "テストメッセージです。"
flash[:error] = "エラーが発生しました。"
redirect_to test_path
test/show.html.slim
= flash[:notice]
= flash[:error]

しかし、flashの実態はHashです。

そのため、そのため、任意のキーを使用することができます。

したがって、メッセージの他に、独自に設定したキーで、名前やフラグを値として渡すこともできます。

 名前の例

test_controller.rb
flash[:test_name] = "welcome"
redirect_to test_path
test/show.html.slim
- if flash[:test_name]
  = link_to "#{flash[:test_name]}", "http://www.test.#{flash[:test_name]}"

 flagの例

test_controller.rb
flash[:test_view_flag] = true
redirect_to test_path
test/show.html.slim
- if flash[:test_view_flag]
  | テスト経由

まとめ

flashを一時的なsessionとしてうまく使うと、様々なことができそうです。

参照

http://guides.rubyonrails.org/action_controller_overview.html#the-flash

http://thepugautomatic.com/2012/08/the-rails-flash/

CentOS MuninとプラグインのInstall方法

0

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

rickNo36です。
最近CentOS7でmunin入れたのでインストール方法を記載します。

環境

CentOS7
Apache(yumにてinstall済)

Muninインストール

yum install epel-release
yum install munin munin-node
systemctl start munin-node
apachectl configtest
systemctl restart httpd.service

アクセス

http://xxx/munin
これだけ、とても簡単

ラグイン追加

設定されているplugin
/etc/munin/plugins
用意されているplugin
/usr/share/munin/plugins

追加例:Apache

# アクセス数
ln -s /usr/share/munin/plugins/apache_accesses /etc/munin/plugins/apache_accesses
# プロセス数
ln -s /usr/share/munin/plugins/apache_processes /etc/munin/plugins/apache_processes
# データ転送量
ln -s /usr/share/munin/plugins/apache_volume /etc/munin/plugins/apache_volume
cd /etc/httpd/conf
vim httpd.conf
———————
nclude conf.modules.d/*.conf
下記追加
ExtendedStatus On

SetHandler server-status
Require local

———————
vim extra/httpd-vhosts.conf
———————

ServerName hoge

RewriteEngine On
RewriteRule ^/balancer-manager$ /balancer-manager/ [L]
RewriteRule ^/server-status$ /server-status/ [L]
RewriteRule ^(.*)$ [R=404,L]

SetHandler server-status
Order deny,allow
Deny from all
Allow from 127.0.0.1

SetHandler balancer-manager
Order Deny,Allow
Deny from all
Allow from 127.0.0.1

———————
systemctl restart httpd.service
systemctl restart munin-node

Rails4 + Mongoidでデータ収集するあれこれ

0

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

MongoDBのObjectId型を物検索するのににこれたたいいかか、

  1. ObjectId型の_idを着する
  2. $ whereディレクター
  3. 分類の指定方法
  4. モンゴイドのセレクション展開の指定方法
  5. 集合体group_by?

 ObjectId型の_idを着検索する

▼サンプル

> db.members.find();
{"_id":ObjectId( "54daf7307da4107a3694f5af")、 "name": "hoge"、 "count":1、 "status":1123、 "created_at":ISODate( "2015-02-11T12:20:18.766Z" )、 "updated_at":ISODate( "2015-02-11T12:20:18.766Z")、 "deleted_at":0}

MongoDBの_idはObjectId型要素ので、

ざに「/ ^ 54d /」九なぷあり勝しませんでした。

文字列型に変換して「ObjectId( “」からなっ一致するようにすししししますがううーん。

Member.where( '$ where' => 'function(){return this._id.match(/ ^ ObjectId \(\ "%s /)}'%Regexp.escape(@ search.id))

とたたら定的に変換する

http://docs.mongodb.org/manual/reference/method/ObjectId.valueOf/

ObjectId.valueOf()を外とカッコ内の文字列をしてせます。

ObjectId( "54daf7307da4107a3694f5af")。valueOf()=> "54daf7307da4107a3694f5af"

をしたばば↓このように書けます。(※ももするばができます)

Member.where( '$ where' => 'function(){return this._id.valueOf()。match(/ ^%s /);}'%Regexp.escape(@ search.id))
Member.where( '$ where' => 'this._id.valueOf()。match(/ ^%s /)'%Regexp.escape(@ search.id))

省略、検索条件が$ where省略の属性は$ whereも省略可能。

Member.where( 'this._id.valueOf()。match(/ ^%s /)'%Regexp.escape(@ search.id))

使いまわすそうえる、モデルの方でスコープにPlanskお実行かと。

コントローラ
Member.id(@ search.id)

モデル
scope:id、->(id){'this._id.valueOf()。match(/ ^%s /)'%Regexp.escape(id)if id.present?}

mongoシェルメソッド

http://docs.mongodb.org/manual/reference/method/

IntegerもtoString()で文字列に変換すし、正規表現での検索が可能です。

 $ where

ここ$ whereです。

http://docs.mongodb.org/manual/reference/operator/query/where/

た内でjavascriptを実行したいいは$ whereをするようにとのこと。

公式のコメント通りですが、ざ解説

使いろろはえくらありようです。

  • 陳ができない
  • 絶された内でありない(表レベルであること)
  • $ whereBEGINの条件と國可能。先に$ whereBEGINの変形を評価する。(その結婚が0の属性$ where内は評価されない)
  • ファル3微妙
  • ず$ whereえずにありならそっちをててね
  • でできてなら、$ whereEVERの条件もいして、$ whereでで立てをすると、でなるのできる

検索条件の指定方法

ももな指定方法がますます。

モンゴイドの選択

http://mongoid.org/en/origin/docs/selection.html#standard

http://mongoid.org/en/origin/docs/selection.html#symbol

▼名前に「ほ」をするもの

(文字列型のフィールドフィールド正規表現表現が有効です)

Member.where(name:/ ho /)

▼1と3コンポーネント

Member.where(:status.all => [1,3])

▼1と3をこれ

Member.where(:status.in => [1,3])

▼1と3をこれないもの

Member.where(:status.nin => [1,3])

▼ステータスがnilfalseRefer

Member.where(:status.exists => true)

▼ステータスが1

Member.where(:status.gt => 1)

▼ステータスが1>

Member.where(:status.gte => 1)

▼ステータスが3

Member.where(:status.lt => 3)

▼ステータスが3

Member.where(:category.lte => 3)

▼ステータスが1

Member.where(:category.ne => 1)

▼updated_atg2015-02-1110:15:00.000円

Member.where(:updated_at.gte => '2015-02-11 10:15') 

▼updated_atが2015-02-1110:15:01.000前前

 ミリ秒表ので、「2015-02-11 10:15.725」等男勝表1秒後のdatetimeで

Member.where(:updated_at.lt => Time.at(Time.parse( '2015-02-11 10:15')。to_i + 1))

モンゴイドのセレクション展開の選択方法

Model.where()の術モンゴイドのセレクションダブルモデル、

なりのように指定する、MongoDBのシェルとありのくらがいようです。

db = Mongoid :: Sessions.default
コレクション= db [:models]
collection.find()

矯正

Model.collection.find()

※「Mongoid :: Sessions.default」はconfig / mongoid.ymlの設定内容?

もはもももをあります。

mongoDBdb.models.find({count:{‘$ gte’ => 1}})
RailsModel.where(:count.gte => 1)モンゴイド::基準
RailsModel.collection.find(count:{‘$ gte’ => 1})原付::クエリ

オブジェクトオブジェクトオブジェクトオブジェクトオブジェクトオブジェクト。

基準= Model.where(:count.gte => 1)

ppcriteria.class
 => Mongoid :: Criteria

ppcriteria.class.ancestors
 => [Mongoid :: Criteria、
 Mongoid :: Sessions :: Options、
 Mongoid :: Criteria :: Scopable、
 Mongoid :: Criteria :: Modified、
 Mongoid :: Criteria :: Marshalable、
 Mongoid :: Criteria :: Inspectable、
 Mongoid :: Criteria :: Findable、
 Origin :: Queryable、
 Origin ::オプション、
 Origin :: Selectable、
 Origin :: Aggregable、
 起源::マージ可能、
 Mongoid :: Contextual、
 可算、
 オブジェクト、
 Delayed :: MessageSending、
 Mongoid :: Extensions :: Object、
 BSON :: Object、
 Origin :: Extensions :: Object、
 ActiveSupport :: Dependencies :: Loadable、
 PP :: ObjectMixin、
 V8 :: Conversion :: Object、
 JSON :: Ext :: Generator :: GeneratorMethods :: Object、
 カーネル、
 BasicObject]
moped = Model.collection.find(count:{'$ gte' => 1})

pp moped.class
 =>原付::クエリ

pp moped.class.ancestors
 => [Moped :: Query、
 Mongoid :: QueryCache :: Query、
 Mongoid :: QueryCache :: Cacheable、
 可算、
 オブジェクト、
 Delayed :: MessageSending、
 Mongoid :: Extensions :: Object、
 BSON :: Object、
 Origin :: Extensions :: Object、
 ActiveSupport :: Dependencies :: Loadable、
 PP :: ObjectMixin、
 V8 :: Conversion :: Object、
 JSON :: Ext :: Generator :: GeneratorMethods :: Object、
 カーネル、
 BasicObject]

 aggregatedegroup_byする

MongoDBのシェルがされて↓ここにあるメソッドもメソッドを…

http://docs.mongodb.org/manual/reference/method/

data = Member.collection.aggregate({'$ group' => {'_id' => '$ count'、 'count' => {'$ sum' => 1}}})

=> [{"_ id" => 3、 "count" => 1}、{"_ id" => 2.0、 "count" => 2}、{"_ id" => 1.0、 "count" => 1} ]

できました!

pp data.class
 =>配列

pp data.class.ancestors
 => [配列、
 Mongoid :: Extensions :: Array、
 BSON :: Array、
 BSON :: Encodable、
 Origin :: Extensions :: Array、
 カラム化、
 V8 :: Conversion :: Array、
 JSON :: Ext :: Generator :: GeneratorMethods :: Array、
 可算、
 オブジェクト、
 Delayed :: MessageSending、
 Mongoid :: Extensions :: Object、
 BSON :: Object、
 Origin :: Extensions :: Object、
 ActiveSupport :: Dependencies :: Loadable、
 PP :: ObjectMixin、
 V8 :: Conversion :: Object、
 JSON :: Ext :: Generator :: GeneratorMethods :: Object、
 カーネル、
 BasicObject]

SQL特徴group_byとは別ですが、比較にらない

Enumerable#group_byがますます。

(Mongoid :: CriteriaもMoped :: QueryもEnumerableファンを実装してます)

Member.where(:count.gte => 1).group_by {| member | member.status}
Member.collection.find(count:{'$ gte' => 1})。group_by {| member | member [:status]}

jsファイルを渡して、言いからコマンドは

mongo sample_dev〜 / mongo / batch.js

SQLとの比較表も定にありました。

決定に。

http://docs.mongodb.org/manual/reference/sql-comparison/

浮動小数点誤差対策

0

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

小数の計算が必要な場面というのは多々ある。Rubyでは、例えば「1.5」と書けばFloatクラスのオブジェクトになるが、Floatクラスで注意しなければならないのが、浮動小数点誤差である。

この浮動小数点誤差に関して、原因、注意点、対策方法を纏める。

 浮動小数点誤差が発生する必要条件

Floatクラスのオブジェクトは内部的に2進数にて表現される。

2進数で表現した場合に無限小数となる数の演算は全て、浮動小数点誤差が発生する可能性がある。

「2進数で表現した場合に有限小数となる」とは、既約数で表現した場合の分母に2以外の素因数がない事である。

以下に例を示す。

1.5 = 3/2 … 分母を素因数分解すると2^1なので浮動小数点誤差は発生しない。

0.75 = 3/4 … 分母を素因数分解すると2^2なので浮動小数点誤差は発生しない。

0.1 = 1/10 … 分母を素因数分解すると2^1 * 5^1 なので浮動小数点誤差が発生する可能性がある。

 浮動小数点誤差が発生しがちな計算の例

浮動小数点誤差が発生しがちな計算は、例えば消費税の計算がある。

浮動小数点誤差の知識はあったとしても、意識していないと、225円の商品の税込み価格計算で「225 * 1.08」の様に書いてしまいがちである。

この計算は「243.0」を期待しているが、実際は「243.00000000000003」となる。

この結果の問題点は、税込価格が端数切り上げで計算している場合に、本来の価格より1円高くなってしまう点である。

(225 * 1.08).ceil

=> 244

 浮動小数点誤差に対する対策

対策1 : 演算の順序を工夫する

小数は分数で表現できる。分数は除算で表現できる。

整数の集合は、加算・減算・乗算において閉じているので、

除算を最後の1回のみ行う様に式を置き換える。

(225 * 108 / 100.0).ceil

=> 243

デメリット

・有効になる場面が限られている。

・複雑な演算には向かない。

対策2 : BigDecimalクラスを使用する

人間が数値として表現できる数は殆どが10進法の有限小数または整数である。

10進法で表記した各桁の精度を落とさずに演算が可能なBigDecimalクラスを使用すれば、有効桁数がそれ程多くない数同士の加算・減算・乗算では誤差は発生しない。

(恐らく電卓と同じ様なロジックになっていると思われる)

(225 * BigDecimal(“1.08”)).ceil

=> 243

デメリット

・分子の素因数に2, 5以外の数を持つ既約有理数による除算は誤差が発生する可能性がある。

・String型に変換する必要がある。

・遅い。

対策3 : Rationalクラスを使用する

有理数の集合は四則演算において閉じている(0による除算を除く)ので、

既約有理数の分母分子の精度を落とさずに演算が可能なRationalクラスを使用すれば、有理数同士の四則演算では0による除算を除いて誤差は発生しない。

(225 * 1.08r).ceil

=> 243

デメリット

・数値的に求めるには型変換をしなければならない。

 Rationalクラスを使用する場合の注意点

Rationalクラスは丸め誤差の影響を考えなくて良い便利なクラスであるが、RationalオブジェクトとFloatオブジェクトの四則演算を行う場合、RationalオブジェクトはFloatオブジェクトに暗黙型変換されて演算される為、注意が必要となる。

(例えば、「225.0 * 1.08r」は「225.0 * 1.08」と同じになってしまう)

つまり型の優先度としては、Rationalは、Integerより強く、Floatより弱い様である。

Rationalクラスの利点を活用するのであれば、Floatオブジェクトをto_rメソッドによってRationalオブジェクトにしてから演算を行う必要がある。

テストデータ作成時の注意点

0

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

テストデータで決定する数値は無作為に決定していると、予期せぬ矛盾が発生する事がある。

その注意点を記述する。

 問題点

例えば商品のテストデータを作成する場合を考える。

商品の値段は当然自然数である。

これは税抜価格であっても税込価格であっても当てはまるが、1点異なる部分がある。

税抜価格は単純に決定された値であり、この値を導いている値はないのに対して、税込価格は税抜価格から導かれて決定する。

つまり税込価格は税抜価格の関数になっている。

この関数をfとした場合、f(x)は

f(x) = floor(1.08x)

と表現できる。このfはN→Nの写像になっており、下記の様にF(y)を定義すると、Fはfの逆関数になる

F(y) = ceil(y/1.08)

テストデータとして、税込価格を決定する場合、ランダムに自然数が発生する様なプログラムでは、例えば1700という値になる可能性がある。これを関数Fによって

F(1700) = 1575

と税抜価格を算出したとすると、実際のf(1575)は1701の為、誤差が発生する。

 原因

この誤差はfの逆関数が存在する事と矛盾する様に見えるが、そうではなく、この写像fがN→Nにおいて全射でない点が問題である。

このfの定義域はN全体であるが、値域はN全体ではなく、1700というのが値域外の数値である事が原因である。

(つまり f(x) = 1700 を満足するxは存在しない)

 結論

テストデータを作成する際は、それを導いている値があるかないかを意識する必要がある。

導いている値がある場合、その関数の写像において全射であるかを考え、

全射でない場合は、値域外の数値にならない様、データを工夫する必要がある。

最近人気な記事