ホーム ブログ ページ 44

MybatisでOracleにListを一括insert

0

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

MybatisでOracleにList<object>を一括insert

主キーIDは自動増加ではないパターン

mybatisを利用して、OracleDBにList<object>を一括insert方法を紹介します。

主キーIDは自動増加ではないパターン

 mapperメソッド定義:

int insertBatch(@Param (“itemList” ) List<objectclass> itemList);

itemListを一括DBにinsertします。

 NGパターン

<insert id=”insertBatch” parametertype=”java.util.List”>

insert into TABLEAAA (C1, C2)

values

<foreach collection=”itemList” item=”item” index=”index” separator=”,”>

(#{item.c1},#{item.c2})

</foreach>

</insert>

書き方は大丈夫そうな感じですが、実は下記エラーが発生します。

Cause: java.sql.BatchUpdateException : ORA-00933: SQLコマンドが正しく終了されていません。

; bad SQL grammar []; nested exception is java.sql.BatchUpdateException: ORA-00933: SQLコマンドが正しく終了されていません。

Oracleの場合は特別です。

 OKパターン1

INSERT ALLを利用します。

<insert id=”insertBatch” parametertype=”java.util.List”>

INSERT ALL

<foreach collection=”itemList” item=”item”>

INTO TABLEAAA (C1, C2) values (#{item.c1},#{item.c2})

</foreach>

SELECT * FROM dual

</insert>

 OKパターン2

union allを利用します。

<insert id=”insertBatch” parametertype=”java.util.List”>

insert into TABLEAAA (C1, C2)

<foreach collection=”itemList” item=”item” separator=”union all”>

(select #{item.c1},#{item.c2} from dual)

</foreach>

</insert>

MybatisでOracleにListを一括update

0

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

MybatisでOracleにList<object>を一括update

mybatisを利用して、OracleDBにList<object>を一括update方法を紹介します。

 mapperメソッド定義:

int updateBatch(@Param (“itemList” ) List<objectclass> itemList);

itemListを一括DBにupdateします。

 NGパターン

      <update id="updateBatch" parametertype="java.util.List">
             <foreach collection="itemList" item="item" separator=";">
                  update TABLEAAA
                   <set>
                        C1 = #{item.c1},
                        C2 = #{item.c2}
                   </set>
                  WHERE ID = #{item.id}
             </foreach>
      </update>

書き方は大丈夫そうな感じですが、実はエラーが発生します。

Oracleの場合は特別です。

 OKパターン

      <update id="updateBatch" parametertype="java.util.List">
            begin
             <foreach collection="itemList" item="item" separator=";">
                  update TABLEAAA
                   <set>
                        C1 = #{item.c1},
                        C2 = #{item.c2}
                   </set>
                  WHERE ID = #{item.id}
             </foreach>
            ;end;
      </update>

Active Record のカラム名にエイリアスを使えるようにする Utusemi gem

0

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

Active Record のカラム名にエイリアスを利用できるようにするための gem「Utusemi」を紹介します。

 はじめに

Utusemi は Active Record のカラム名にエイリアスを利用できるようにするための Ruby on Rails 3, 4 向けの gem です。

Ruby on Rails にはモデルのインスタンスに対してエイリアスを張るための alias_attribute というメソッドが存在します。Utusemi は、これに加えてモデルクラスの where メソッドや order メソッドでもエイリアスが使えるようにするための gem になります。

カラム名へのエイリアスは以下のようなケースで利用されることが想定されます。

  1. カラム名が長いので実装上は短く済ませたい
  2. 既存のコードを変えずに DB のカラム名変更に対応したい
  3. gem で用意されている固定カラム名をアプリケーションの特定カラム名にマッピングさせたい

では早速インストールの仕方から紹介していきます。

 インストール方法

他の gem と同じように Bundler を使ってインストールするのがおすすめです。

この場合は Gemfile に下記の1行を追記し、bundle install を実行します。

gem 'utusemi'

また、Bundler を利用しない場合は下記のコマンドでもインストールできます。

gem install utusmei

 設定ファイルの書き方

エイリアス先のカラムとエイリアス元のカラムを設定していきます。

例として、下記のコードを config/initializer/utusemi.rb に設置します。

Utusemi.configure do
  map :sample do
    name :first_name
  end
end

 使い方

上記で設定したエイリアスの設定名を utusemi メソッドに渡すことで、エイリアスを有効にできます。

irb> User.utusemi(:sample).where(name: 'John')
SELECT "users".* FROM "users" WHERE "users"."first_name" = 'John'

例では sample というエイリアス設定を有効にすることで、User モデルの first_name カラムに対して name という名前でアクセスしています。

また、utusemi メソッドを介して取得したインスタンスでもエイリアスが有効です。

irb> user = User.utusemi(:sample).where(name: 'John').first
irb> user.name
#=> "John"

 詳細なメソッドの説明

ActiveRecord::Base.utusemi

モデルクラスに対するエイリアスを設定します。

「使い方」の項で紹介した例では、このメソッドを利用しています。

引数にはエイリアス設定名のシンボルまたは文字列を渡します。

引数を省略した場合はモデル名の小文字単数形をエイリアス設定名として利用します。

irb> Utusemi.configure do
  map(:user) { nickname :first_name }
end

irb> User.utusemi.where(nickname: 'John')
SELECT "users".* FROM "users" WHERE "users"."first_name" = 'John'

ActiveRecord::Base.utusemi!

モデルクラスに対してエイリアスを設定する、破壊的メソッドです。

ActiveRecord::Base.utusemi! を1度でも呼び出したモデルは、その後もエイリアスが有効な状態となります。

irb> User.where(name: 'John')
SQL:Error: Unknown column 'users.name' ...

irb> User.utusemi!(:sample)
irb> User.where(name: 'John')
SELECT "users".* FROM "users" WHERE "users"."first_name" = 'John'

ActiveRecord::Base#utusemi

モデルインスタンスに対するエイリアスを設定します。

irb> user = User.first

irb> user.name
NoMethodError: undefined method `name' for #<user:...>

irb> user.utusemi(:sample).name
#=> "John"

ActiveRecord::Base#utusemi!

モデルインスタンスに対してエイリアスを設定する、破壊的メソッドです。

ActiveRecord::Base#utusemi! を1度でも呼び出したインスタンスは、その後もエイリアスが有効な状態となります。

irb> user = User.first

irb> user.name
NoMethodError: undefined method `name' for #<user:...>

irb> user.utusemi(:sample)
irb> user.name
#=> "John"

 関連モデルに対するエイリアス

エイリアスの有効状態は関連モデルにも引き継がれます。

例として、User モデルに対して Blog モデルが複数紐付いている場合を詳細します。

app/models/user.rb

class User < ActiveRecord::Base
  has_many :blogs
end

app/models/blog.rb

class Blog < ActiveRecord::Base
  belongs_to :user
end

config/initializers/utusemi.rb

Utusemi.configure do
  map :user do
    name :first_name
  end

  map :blog do
    url_path :permanent_link_url
  end
end

このようなファイル構成となっているとき、次のような書き方ができます。

irb> user = User.first
irb> user.utusemi.blogs.where(url_path: 'path-to-link')
SELECT "blogs".* FROM "blogs" WHERE "blogs"."user_id" = 1 AND "blogs"."permanent_link_url" = 'path-to-link'

 リンク

https://github.com/hyoshida/utusemi

【GAIQ】2014年8月1日時点の出題傾向

0

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


新たにGoogleアナリティクスIQ(GAIQ)を取得しました。

個人的に100%を狙っていましたが…結果は95%。残念…。

ともあれ、無事合格できたので一安心です。

2014年8月4日現在、日本のGAIQの合格者は506名。

増えましたね。

1年半前に確認した際は100名程だったかと思います。

GAIQの認知度、問題傾向の共有が進み

受験しようという方も増えているのだと思います。

今回はGAIQの概要紹介と、

私が受けた現時点での問題の傾向を簡単にお伝えしたいと思います。

 GAIQとは

「Google アナリティクス IQ(以下、GAIQ)はGoogleが実施している個人認定資格です。Google アナリティクスの「導入」から「分析」「レポーティング」にいたるまでの総合的な知識を確認するものでテストに合格するとGoogleから認定証が発行されます。」

 受験概要

受験費用:US50ドル(テストセンターにてクレジットカード決済)

受験言語:英語

問題数:70問

出題形式:テスト画面での選択チェック方式

テスト時間:90分

※テスト開始後は中断が可能。中断中は経過時間のカウントも停止します。

ただし、テスト開始後120時間(5日間)以内に終了しないといけません。

合格正解率:80%

 出題傾向(2014年8月1日現在)

私の場合は下記のような問題の傾向でした。

※分け方が適切ではないかもしれませんが…ザックリと。

・解析環境 …特定条件の場合のビュー構成/GAの利用規約…など

・フィルタ …ビューやレポートに適用するフィルタの内容

・マーケティング …ROIの考え方やデジタルアナリティクスとは…など

・ディメンション …ディメンションの定義や使用方法

・レポート …特定条件の場合の閲覧対象レポート/レポートの定義…など

・指標 …指標定義…など

・eコマース …eコマース機能導入方法/取得される指標に関して

・adwords …アトリビューションモデルやadwordsの評価指標に関して

・GTM …GTM導入の意義など

ちなみに、ユニバーサルアナリティクスに特化した問題は

現時点では見られませんでした。

正式リリースして数か月。

GAIQにもそろそろ採用されるんじゃないかと思うので

問題傾向も大きく変わることを懸念していたのですが…

まだ大丈夫のようです。

でも近い将来、

ユニバーサルアナリティクスの問題も増えていくのでしょうね。

(分からない英単語が増える予感…)

他の方のブログ等でウォッチしていきたと思います。

 気になる問題

一つ、回答に困った問題がありましたのでご紹介します。

You have defined goal X such that 
any PDF download qualifies as a goal conversion.
A user comes to your site once and downloads five PDFs. 
How many goal conversions will be recorded?

A) 2
B) 0
C) 1
D) 5

※私の翻訳※

あなたのサイトではPDFダウンロードを目標Xとして目標設定してます。
一回のサイト訪問で5回ダウンロードしました。
目標完了数はどのように記録されるでしょう。

A) 2
B) 0
C) 1
D) 5

PDFにはGoogleアナリティクスのタグを設置することができないので

リンクにイベントトラッキング、もしくはバーチャルページビューを仕掛けることになると思います。

例えば、

イベントトラッキングを指定しており、それを目標設定しているなら目標完了数は「5」。

バーチャルページビューを指定しており、URLを目標設定しているなら「1」になると思います。

この問題ではどちらの機能を導入しているか

明確な記述はないと思うので、どちらかの判断に迷いました。

私はGoogleアナリティクスのヘルプ等でよく

イベントトラッキングの導入例としてPDFダウンロードが挙げられているので、

恐らくイベントトラッキングが導入されているのだろうと見越し、「5」にしましたが…。

皆様はどちらだと思いますか?

もしかして翻訳に不足があるかもしれません…。

その際はご指摘いただけますと幸いです_(_ _)_

 受験してみての感想

私は事前の勉強は特に行いませんでした。

なにせ有難い一時停止機能があるので…

分からない単語や問題は都度、

Google翻訳やGoogleアナリティクスのヘルプページで調べていました。

ただ、私の場合、従来のGA・ユニバーサルアナリティクス・GTMの機能を

予め十分理解した上で挑んだつもりです。

それでも多少は戸惑いました。

やはり、少し不安がある、という方はアナリティクスアカデミーでの勉強をお勧めします。

※アナリティクスアカデミー

https://analyticsacademy.withgoogle.com/explorer

有効期限が切れて受けなおす方、

初めて受ける方に対して、少しでも参考になれば幸いです。

以上、最新GAIQのレポートでした。

Google アナリティクス セミナー インターフェイス編

Google アナリティクスのレポート画面が把握できていない方向けの講座。

レポート画面の解説や既存機能の活用法、マルチチャネルなどの新レポートのインターフェイスを解説します。

Google アナリティクス セミナー 分析手法編

インターフェイスは把握しているが、数値の意味や考え方がよく分からないという方向けの講座です。 アクセス解析を用いた課題抽出やサイト改善の考え方を解説します。

Google アナリティクス セミナー 徹底設定編

現状のGoogle アナリティクスで取得可能な数値に物足りない方向けの講座。

外部サイトへの誘導やソーシャルボタン連携、eコマース機能などのカスタマイズ方法をレクチャーします。

MacでのOWASP ZAPのプロキシ設定

0

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

今回はMacでOWASP ZAPのプロキシ設定を行う手順をご紹介します。

 概要

【環境】
Mac OS X 10.7.5
OWASP ZAP 2.2.2

OWASP ZAPはWEBサイトの脆弱性を診断することができる、オープンソースのツールです。

このOWASP ZAPにはプロキシを利用する手動クロールと、OWASPが自動でリンクを辿って自動クロールする動的スキャンがあります。

ただ、動的スキャンだけでは検出できない項目もあるので、より細かい診断は手動クロールがおすすめです。

この手動クロール、仕組みとしてはブラウザでのリクエストを全てローカルの8080ポート(デフォルト)で起動しているOWASP ZAPを経由して行い、診断を行うというものです。

HTTPSのサイトはこの手動クロールでは診断できないのでご注意ください。

 プロキシ設定

プロキシの設定方法は以下になります。

1. [システム環境設定]
2. [ネットワーク]
3. [(任意のデバイス)]
4. [プロキシ]
5. [Web プロキシ (HTTP)]をチェック
5-1. Webプロキシサーバ [localhost] : [8080]
6. [OK]
7. [適用]
8. ブラウザ再起動

以上で設定は完了です。

OWASP ZAPの画面を見ると、左上の[サイト]にブラウザでアクセスしたサイトのURLが表示されていくかと思います。

注意点としては、設定したPC全体のWebアクセス(HTTP)がOWASP ZAP経由となってしまいますので、ブラウザ以外でHTTPを利用する他のアプリが利用不可能となります。

診断が終わったら忘れずに設定をもとに戻すようにしましょう。

以上です。簡単に設定ができ、脆弱性診断ができるOWASP ZAPおすすめです。

PHP技術者認定試験(初級)合格経験

0

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

PHP技術者認定試験(初級)合格経験

 【試験難易度】

初心者向けの試験です。

PHPプログラミングの基本知識を問う試験です。

試験の合格率は70%ぐらいです。

ちなみに、上級の合格率:11%ぐらいです。

 【使用教材】

初めてのPHP5増補改訂版(買ったけど、いらない感じでした。)

徹底攻略PHP5技術者認定[初級]試験公式問題集(会社の本棚にある)

http://www.phpexam.jp/material/

 【勉強方法】

問題集を中心として勉強した。

問題をやって、回答をしっかり覚えました

問題の回答は教材見たいです。表にしているので、覚えやすいです。

問題集に出た関数は必ず覚えてください。

ITPROの問題をやりませんでした。

開発環境を構築して、気になるところを実行してみた。

実際動かしたら、印象が深いです。

 【感想】

初心者レベルです。

問題集をしっかり把握すれば、合格できます。

PHPはスクリプト言語なので、Javaと違って、Rubyと似ている。

Ruby&Rails技術者はJava技術者より取りやすいと思います。

audio.js使う時、要注意

0

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

部分android機種の標準ブラウザにはにaudio.jsがうまく動かないaudio.jsは、みなさんご存知のようにMP3音声ファイルの再生にとても便利なjsプラグインです。

しかし、部分android機種の標準ブラウザにはにaudio.jsがうまく動かない現象があります。

うまく動かないというのは、
①曲再生のシークンは、曲再生後、瞬間終了
②曲再生時間は0のまま
③前進、バックの操作が効かない
のことです。

jsの中身を確認すると、loadProgressファンクションには、下記のif分があります。
      if(this.element.buffered!=null&&this.element.buffered.length){
        if(!this.loadStartedCalled)this.loadStartedCalled=this.loadStarted();
        this.loadedPercent=this.element.buffered.end(this.element.buffered.length-1)/this.duration;
        this.settings.loadProgress.apply(this,[this.loadedPercent])
      }

if分岐に入って、this.loadStarted()が呼ばれると、曲の再生時間this.duration(②)がセットされます。
さらにthis.loadedPercent(①)が正しく計算されます。
さらに前進、バック時(③)、this.loadedPercentを使うので、前進、バック動作は正しく動作します。

androidの部分機種には、this.element.bufferedが取れなくて、if分に入れず、動作がおかしくなります。

あまり強引な解決方法ですが、

if(this.element.buffered!=null&&this.element.buffered.length){
:
}
//追加
else userAgentを判断して、androidかつ標準ブラウザの場合{
 //↑同じ処理
}

但し、androidかつ標準ブラウザの判断は難しい。
最初、/(android)/i.test(navigator.userAgent)&&!(/(chrome)/i.test(navigator.userAgent))
で、androidかつchrome以外で、行けるかなと思っていましたが、
どうも、一部機種には、標準ブラウザでもuserAgentに”chrome”という文字が入っています。

残念ですが、完璧の解決方法が見つかりません。audio.js使う時、注意しましょう。

[Rails4]Bootstrap導入とassets:precompileでglyphiconが表示されない不具合対応

0

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

Rails4にBootstrapを導入するのは、とても簡単です。
だが、いざ本番環境にデプロイしたら、glyphiconが表示されないという不具合に見舞われました。
自分がベストだと思う導入方法と対処方法をメモします。
対象バージョンはbootstrap-sass-3.2.0.0です。バージョンアップで解消される事を期待したい。

●Bootstrapを追加

turbolinksと相性が悪いらしいので、turbolinksを外してbootstrap-sassを追加します。

編集:Gemfile

# gem 'turbolinks'

# Use Bootstrap
gem 'bootstrap-sass'

$ bundle install =========================================== Installing bootstrap-sass 3.1.1.1 =========================================== ※「Your bundle is complete!」と表示されればOK

●Bootstrapの適用順番を明示

JSとCSSは、デフォルトだと名前順に適用されるので、先に読まれるように明示します。
aとかで始まる名前のJS/CSSだとBootstrapの設定を上書けない為です。(CSSは後勝ちなので)

編集:app/assets/javascripts/application.js

//= require turbolinks
//= require bootstrap

編集:app/assets/stylesheets/application.css

 *= require bootstrap
 *= require_tree .
 *= require_self

●assets:precompileでglyphiconが表示されない不具合対応

本番環境ではassets:precompileして、public/assets以下をApacheから直接返すようにしていますが、gems/bootstrap-sass-3.2.0.0/assets/stylesheets/bootstrap/_glyphicons.scssで「url(」と定義されている為、precompile時にcssにハッシュ値が入らず、アイコンが表示できません。
SCSSで画像などを表示するには「image-url(」と定義して、Railsに変換してもらう必要があります。開発環境では「url(」でも表示されるので、開発段階では気付き難いので厄介です。

作成:app/assets/stylesheets/bootstrap_override.scss

//### assets:precompileでglyphiconが表示されない不具合対応 ###
@font-face{
  font-family:'Glyphicons Halflings';
  src: image-url("bootstrap/glyphicons-halflings-regular.eot");
  src: image-url("bootstrap/glyphicons-halflings-regular.eot?#iefix") format("embedded-opentype"),
       image-url("bootstrap/glyphicons-halflings-regular.woff") format("woff"),
       image-url("bootstrap/glyphicons-halflings-regular.ttf") format("truetype"),
       image-url("bootstrap/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") format("svg")
}

編集:app/assets/stylesheets/application.css

 *= require bootstrap
 *= require bootstrap_override

論理削除Gem(Paranoia)を自分好みにカスタマイズ

0

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

DBのユニーク規制が、データの整合性を保つ最後の砦だと考えている。
実装に注意したり、DBを直接書き換える場合に、注意すれば良いのだけれど、やっぱりバグやヒューマンエラーは付き物。
バグやヒューマンエラーを考えると論理削除を使って、定期的にクリーニングがベストかな。
論理削除のGemを探しましたが、日付を使う物が多く、かつNULLが使われるので、複合キーでのユニーク規制が掛からない。
フラグを使う物もあったけど、0・1では一度削除したものと同じものを再度削除出来なくなる。
辿り着いたのは、初期値0で、削除時にIDと同じ値を設定するというDB設計。
ただ、これを満たすGemが見つからないので、良さそうなParanoiaの一部を修正する(モンキーパッチを充てる)事にしました。

また、JOINされるケースでSQLが「WHERE “.`deleted` = 0」となり、「Mysql2::Error: Column ‘deleted’ in where clause is ambiguous:」で落ちる問題も対応しました。
このバージョンの組み合わせだから動かない、という事なんだろうか?(謎)

前提:Rails 4、Paranoia 2.0.2

●Paranoia追加

編集:Gemfile

# Use Paranoia
gem 'paranoia', '2.0.2' # モンキーパッチ:config/initializers/extensions/paranoia.rb

$ bundle install
===========================================
Installing paranoia 2.0.2
===========================================
※「Your bundle is complete!」と表示されればOK

●Paranoiaカスタマイズ

作成:config/initializers/extensions/paranoia.rb

module Paranoia
  module Query
    def only_deleted
      # with_deleted.where.not(paranoia_column => nil)
      with_deleted.where.not(paranoia_column => 0)
    end
  end

  def restore!(opts = {})
    ActiveRecord::Base.transaction do
      run_callbacks(:restore) do
        # update_column paranoia_column, nil
        update_column paranoia_column, 0
        restore_associated_records if opts[:recursive]
      end
    end
  end

  private

  def touch_paranoia_column(with_transaction=false)
    if with_transaction
      # with_transaction_returning_status { touch(paranoia_column) }
      with_transaction_returning_status { update_attribute(paranoia_column, id) }
    else
      # touch(paranoia_column)
      update_attribute(paranoia_column, id)
    end
  end
end

class ActiveRecord::Base
  def self.acts_as_paranoid(options={})
    alias :really_destroy! :destroy
    alias :destroy! :destroy
    alias :delete! :delete
    include Paranoia
    class_attribute :paranoia_column

    # self.paranoia_column = options[:column] || :deleted_at
    self.paranoia_column = options[:column] || :deleted
    # default_scope { where(paranoia_column => nil) }
    def self.default_scope
      where(arel_table[paranoia_column].eq 0)
    end

    before_restore {
      self.class.notify_observers(:before_restore, self) if self.class.respond_to?(:notify_observers)
    }
    after_restore {
      self.class.notify_observers(:after_restore, self) if self.class.respond_to?(:notify_observers)
    }
  end
end

●ベースモデル作成

$ rails g model base
===========================================
invoke active_record
create db/migrate/20140707233955_create_bases.rb
create app/models/base.rb
invoke rspec
create spec/models/base_spec.rb
invoke factory_girl
create spec/factories/bases.rb
===========================================
※エラーが表示されなければOK
削除:db/migrate/20140707233955_create_bases.rb
削除:spec/factories/bases.rb
編集:app/models/base.rb

class Base < ActiveRecord::Base
  self.abstract_class = true
  acts_as_paranoid
end

●テストモデル作成

$ rails g model test
===========================================
invoke active_record
create db/migrate/20140707234352_create_tests.rb
create app/models/test.rb
invoke rspec
create spec/models/test_spec.rb
invoke factory_girl
create spec/factories/tests.rb
===========================================
※エラーが表示されなければOK
編集:db/migrate/20140707234352_create_tests.rb

class Tests < ActiveRecord::Migration
  def change
	create_table :tests do |t|
      t.string :name, null: false
      t.timestamps
      t.integer :deleted, null: false, default: 0
    end
    add_index :tests, [:name, :deleted], unique: true
  end
end

$ rake db:migrate
※エラーが表示されなければOK
編集:app/models/test.rb

class Test < ActiveRecord::Base
class Test < Base
end

○動作確認

$ rails cTest.create(name: ‘test’)
test = Test.find_by_name(‘test’)
test.blank?
=> false
test.destroy
=> UPDATE文
test = Test.find_by_name(‘test’)
test.blank?
=> true
exit

●テストモデル削除

削除:app/models/test.rb
削除:db/migrate/20140707234352_create_tests.rb
削除:spec/models/test_spec.rb
削除:spec/factories/tests.rb
$ rake db:migrate:reset
※エラーが表示されなければOK

jQuery flotr2 〜グラフ〜

0

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

rick No33です。
今回は、jQueryのプラグインflotr2を使用して簡単にきれいなグラフを作成します

環境

jQuery 2.1.1

インストール

http://humblesoftware.com/flotr2/よりダウンロード

手順

ダウンロードした中のflotr2.min.jsを読み込む

<!– 出力先 –>
<div id=”graph1″ style=”width:800px;height:300px;”></div>

<!– グラフ作成 –>
<script>
$(document).ready(function(){
var graph=[{data: [[1,10], [2,20], [3, 5]], label: “グラフ1”, yaxis: 1}, {data: [[1,30], [2,1], [3, 15]], label: “グラフ2”, yaxis: 1}];
var option={
title: “グラフ名”,
legend: {
position: “se” //ラベル表示位置(右下)
},
xaxis: {
title: “x軸名”,
ticks: [[1,”1個目”], [2, “2個目”], [3, “3個目”]]
}
}
Flotr.draw($(#graph1)[0], graph, options);
})
</script>

これだけです。 他にも色々グラフがあるので試してみてください。

[Ruby] 複数サーバの同じファイルをtail -fするプログラムを作ってみよう

0

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

複数サーバの同じファイルをtail -fするプログラムを作ってみよう

 この記事について

サーバでの作業にはかかせないログの監視。

tail -fは多くの方が利用されていると思います。

台数が少なければいいのですが、増えてくると一台ずつ

サーバにログインして→”tail -f <パス名>”とタイプして・・・

が面倒になってきます。

今回はこの手間を省くスクリプトを作成しようというのがテーマです。

 net/ssh/multi

今回使うrubygemsライブラリはnet-ssh-multiです。

複数のサーバにログインして同じ操作を行うことができるものです。

 プログラム作成

いきなりですが、以下のように作成しました。

#!/usr/bin/env ruby
#-*- coding: utf-8 -*-
require 'rubygems'
require "net/ssh/multi"
SSH_CONFIG = File.join(ENV['HOME'], ".ssh/config")

def main(hosts, paths)
  Net::SSH::Multi.start do |session|
    hosts.each do |host|
      connect_host(session, host)
    end
    tail_f(session, paths)
    session.loop
  end
rescue Interrupt
end

def connect_host(session, host)
  option = {}
  option[:config] = SSH_CONFIG if SSH_CONFIG && File.exists?(SSH_CONFIG)
  session.use host, option
end

def tail_f(session, paths)
  session.open_channel do |channel|
    channel.on_data do |ch, data|
      data.each_line do |line|
        puts ["[#{ch[:host]}]", line].join("\t")
      end
    end
    channel.exec "tail -f #{paths.join(" ")}"
  end
end    

if __FILE__ == $0
  raise "usage: mtailf <host ,host,...> <file file file...>" if ARGV.length < 2
  hosts = ARGV[0].split(/\s*,\s*/)
  paths = ARGV[1 .. -1]
  main(hosts, paths)
end

ポイントを説明していきます。

SSH_CONFIG = File.join(ENV['HOME'], ".ssh/config")

ssh_configの設定が使えるようにssh/configファイルの場所を指定しておきます。

def main(hosts, paths)
  Net::SSH::Multi.start do |session|
    hosts.each do |host|
      connect_host(session, host)
    end
    tail_f(session, paths)
    session.loop
  end
rescue Interrupt
end

mainメソッドです。

Net::SSH::Multiのブロック内でサーバへのコネクションをはり、

tailコマンドを実行しています。

tail -f はctrl+cを押すまで処理が続くので

session.loop

を実行しています。

def connect_host(session, host)
  option = {}
  option[:config] = SSH_CONFIG if SSH_CONFIG && File.exists?(SSH_CONFIG)
  session.use host, option
end

サーバへの接続です。

session.use で接続します。

def tail_f(session, paths)
  session.open_channel do |channel|
    channel.on_data do |ch, data|
      data.each_line do |line|
        puts ["[#{ch[:host]}]", line].join("\t")
      end
    end
    channel.exec "tail -f #{paths.join(" ")}"
  end
end

リモートホストに対してtail -fを実行している部分です。

channel.execでコマンドを実行して

ホストから応答があったら

channel.on_data

のブロックが実行されるかんじです。

JavaScriptっぽいですね。

ch変数にはホスト名も含まれているので

コンソールに出力する際には

puts [“[#{ch[:host]}]”, line].join(“\t”)

として、どのホストからの出力なのかがわかるようにしています。

 使い方

上記のプログラムを作成したら

ファイル名はmtailf とします。

そして

chmod 755 mtailf

と実行可能なようにパーミッションを設定します。

net-ssh-multiをインストールします。

gem install net-ssh-multi

ここまでが初期設定で、実際に使うときには

mtailf user@host01,user@host02 /path/to/file

のようにします。

引数は

第一引数→ホスト名をカンマ区切りで

第二引数以降→表示するファイルパス

以下は出力イメージです。

[host01]   ファイル行・・・・・・・・・・・
[host02]   ファイル行・・・・・・・・・・・
・
・
・
・

終了方法は

tail -fと同様に

ctrl+c です。

このコマンド打つのも面倒!となったら・・・・・・

aliasとか設定しましょう!

【LiveValidation】ブラウザ上でバリデーションを行う【RAILS/JS】

0

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

LiveValidation.jsを使用するとブラウザ上でバリデーションを行えます。

 動作環境

Ruby 1.8.7,1.9.3

Rails 2.3.15

prototype.jsがある

 1.「LiveValidation.js」をダウンロード

ここからダウンロードできます

 2.ダウンロードしたものをRailsのpublicディレクトリに配置(prototype.jsと同じ階層)

 3.Viewで使ってみる

JSを読み込み、テキストフィールド等のIDに対するscriptを書くだけ

	~~~~~~~~~~~
	~~~~~~~~~~~
	<%= javascript_include_tag "livevalidation_prototype" %>
	~~~~~~~~~~~
	~~~~~~~~~~~
	
	<%= :text_field, :product, :name, :id => '/product_name'/ %> 
	この下に↓を追加
	<script type="text/javascript">
	        var product_name = new LiveValidation('product_name', { validMessage: 'OKです', wait: 500 });
	        product_name.add(Validate.Presence, {failureMessage: "未入力です"});
	        //product_name.add(Validate.Length, { minimum: 3, maximum: 255,
	tooLowMessage: '3文字以上で', tooHighMessage: '255文字以下で' });
	        //product_name.add(Validate.Numericality, { minimum: 3, maximum: 255,
	tooLowMessage: '数字は3から', tooHighMessage: '数字は255まで' });
	        //product_name.add(Validate.Format, {pattern: /^会社名$/i, 
	failureMessage: "'会社名'と入力してください" } );
	</script>
	
	

Rails3系だとProduct.validatorsでバリデーションの設定がとれるのでペルパーとかを作成してもっとスマートにできそうです。

MyBatis Generator紹介

0

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

MyBatis Generator紹介

 MyBatis Generatorとは

データベースのスキーマを元にMyBatisが使用する各種ファイルを自動生成するためのツールです。

MyBatisを使う場合は基本的にSQLを手書きする必要がありますが、大量のXMLとJavaBeanファイルを手で書くのはミスの原因にもなりますし健康にも良くありません。

テーブルが多くて、カラム数が多い場合、MyBatis Generatorを使えば、効率はすごくアップしますし、ミスも少ないです。

 ダウンロード先:

https://code.google.com/p/mybatis/downloads/list?can=1&q=Product%3DGenerator

 使い方

●ファイル置き場:

D:\mybatis\generator
 ・src(保存先)
 ・mybatis-generator-core-1.3.2.jar(実行ファイル)
 ・generator.xml(設定ファイル)

●設定ファイル:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorconfiguration>
	-->
	<classpathentry location="D:\lib\ojdbc6.jar" />
	<context id="DB2Tables" targetruntime="MyBatis3">
		<commentgenerator>
			<property name="suppressAllComments" value="true" />
		</commentgenerator>
		-->
		<jdbcconnection driverclass="oracle.jdbc.driver.OracleDriver" connectionurl="jdbc:oracle:thin:@192.168.111.111:1521:XE" userid="xxxx" password="xxxx">
		</jdbcconnection>
		<javatyperesolver>
			<property name="forceBigDecimals" value="false" />
		</javatyperesolver>
		-->
		<javamodelgenerator targetpackage="com.test.webapp.model" targetproject="D:\mybatis\generator\src">
			<property name="enableSubPackages" value="true" />
			<property name="trimStrings" value="true" />
		</javamodelgenerator>
		-->
		<sqlmapgenerator targetpackage="com.test.webapp.mapping" targetproject="D:\mybatis\generator\src">
			<property name="enableSubPackages" value="true" />
		</sqlmapgenerator>
		-->
		<javaclientgenerator type="XMLMAPPER" targetpackage="com.test.webapp.persistence" targetproject="D:\mybatis\generator\src">
			<property name="enableSubPackages" value="true" />
		</javaclientgenerator>
		-->
		-->
			<generatedkey column="id" sqlstatement="SELECT TEST_TABELE_SEQ.nextval FROM dual" type="pre" />
		
	</context>
</generatorconfiguration>

●実行

コマンド:

java -jar D:\myibatis\generator\mybatis-generator-core-1.3.2.jar -configfile generator.xml -overwrite

●結果:

下記ファイルが作成されます。

TestTableMapper.xml

TestTable.java

TestTableMapper.java

RewriteRuleとWordPressのRedirectionで日本語URLを扱う方法

0

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

WordPressのページ構成変更に伴い日本語URLを日本語URLにリダイレクトしようした時にハマったのでメモしておきます。
最終的には、WordPressのRedirectionプラグインを使う事にしましたが、RewriteRuleでも成功しています。
書き方が違うので注意が必要です。

RewriteRuleを使う場合

Apacheの設定ファイルまたは.htaccessでmod_rewriteを有効にしてある前提です。
「http://example.com/ほげ」にアクセスされた場合に「http://example.com/ほげほげ」にリダイレクトする例です。
RewriteRule ^/\xe3\x81\xbb\xe3\x81\x92$ /\%e3\%81\%bb\%e3\%81\%92\%e3\%81\%bb\%e3\%81\%92 [NE,R=301,L]
「ほげ」をUTF-8でURLエンコードしたのはこれ「%e3%81%bb%e3%81%92」です。
転送元のURIは「%」を「\x」に、転送先のURIは「%」を「\%」とエスケープしてあげる必要があります。
また、最後に「NE」を追加して、エスケープしないようにしてあげる必要があります。
面倒ですね。

WordPressのRedirectionプラグインを使う場合

WordPressにRedirectionプラグインがインストール&有効化されている前提です。
RewriteRuleと同様に「http://example.com/ほげ」にアクセスされた場合に「http://example.com/ほげほげ」にリダイレクトする例です。
ソースURL:/%e3%81%bb%e3%81%92
ターゲットURL:/\%e3\%81\%bb\%e3\%81\%92\%e3\%81\%bb\%e3\%81\%92
「ほげ」をUTF-8でURLエンコードしたのはこれ「%e3%81%bb%e3%81%92」です。
転送元のURIはそのまま(RewriteRuleと異なる)で、転送先のURIは「%」を「\%」(RewriteRuleと同様)とエスケープしてあげる必要があります。
やはり面倒ですね。

MyBatisでwhere要素を使った時になぜか先頭の「AND」が取り除かれなかった時の話

0

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

仕事でMyBatisを使っているのですが、select文を書いてる際にWHERE句を編集したらSQLがエラーになりました。
ひょっとしたら同じ事でコケる人もいるかもしれないので原因を書いておきます。

MyBatisでSQLを定義するXMLのwhere要素には、中の文字列の先頭がAND|ORだったらそれを取り除く機能があるのですが、今回なぜかそれが機能しませんでした。

よくチェックすると、文字列のANDの後が半角スペースでなく、タブで入っていました。
タブを半角スペースに置き換えたところ、正常にSQLが流れるようになりました。

インデントにタブを使っていると同様の事態に引っかかるかもしれません。
どうしてもタブで書きたいという場合はwhere要素を使わずに
prefixOverrides=”AND★|OR★”(★をタブに置き換える)
とするとうまくいくかもしれません。

参考:
http://mybatis.github.io/mybatis-3/ja/dynamic-sql.html

システムのせいでタグがエスケープしても取り除かれてしまうので色々省略して書いてます。

続・たった1コマンドでネットショップ構築できちゃうelecoma-vagrant

0

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

通販サイトをたった1コマンドで簡単に構築できる「elecoma-vagrant」のしくみについて紹介します。

■ 概要

以前の記事」で紹介した「elecoma-vagrant」のに利用されている chef + vagrant の技術について、スライドにまとめました。

『オープンソースカンファレンス2014 Tokyo/Spring』のブースにてデモを交えて解説する予定ですので、是非お越し下さい!

■ 本編(スライド)

xinetd(ザイネットディー) 〜sshのIP制限とアクセスログの記録〜

0

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

rick No32です。
今回は、xinetdといわれるサービスを管理し、必用なときに起動させるデーモンです。
このxinetdでsshのIP制限とアクセスログの記録を行います。

インストール

yum -y install xinetd
> xinetd.x86_64 2:2.3.14-20.el5_10
ls /etc
> xinetd.confとxinetd.dフォルダが作成される

SSH設定

// 自動起動
chkconfig xinetd on
service sshd stop
chkconfig sshd off
cd /etc/xinetd.d/
vim ssh
————————
// 設定するサービス名を指定(/etc/servicesファイルに定義されたサービス名を指定)
service ssh
{
// サービスの停止指定
// no=サービスを起動する
disable =no
// サービスが使用するソケットタイプ
// stream=TCP
// dgram=UDP
// raw=IPダイレクトアクセス
// seqpacket=sequenced packet
socket_type =stream
// マルチスレッド
// yes=1つしかsshを受け付けない
// no=リミットまで受け付ける
wait =no
// サービスを実行するユーザ名
user =root
// 起動するサービスを絶対パスで指定
server =/usr/sbin/sshd
// サービスに渡す引数
server_args =-i
// 接続に成功した場合に記録するログの種類を指定(下記をスペース区切りで繋げられる)
// PID=サービスのプロセスID
// HOST=リモートホストのIPアドレス
// USERID=リモートホストの認証ユーザ名(マルチスレッド+TCPでのみ有効)
// EXIT=サービス終了シグナルを受けたのかを記録
// DURATION=セッション周期(秒)
log_on_success += DURATION HOST USERID
// 接続に失敗した場合に記録するログの種類を指定
// HOST=リモートホストのIPアドレス
// USERID=リモートホストの認証ユーザ名(マルチスレッド+TCPでのみ有効)
// ATTEMPT=起動に失敗した場合の記録
// RECORD=サービスが起動しなかった場合の諸事情を記録
//  設定するとエラー Bad log_on_failure flag: RECORD [file=/etc/xinetd.d/ssh] [line=10]
log_on_failure += HOST USERID
}
———————–
/etc/init.d/xinetd start

共通設定

vim /etc/xinetd.conf
defaults
{
// ログ出力方法を定義
log_type = SYSLOG daemon info
log_on_failure = HOST
log_on_success = PID HOST DURATION EXIT
// 毎秒ごとの可能な接続数上限の設定
// 第1引数=1秒間で処理可能な数
// 第2引数=上限を超えた後サービスが停止し再開するまでの時間
cps = 50 10
// 起動できるデーモンの数
instances = 50
// 同じクライアントからの接続数制限
per_source = 10
v6only = no
groups = yes
umask = 002
}

ログ出力

基本は
/var/log/messages
に出力される
別ファイルに出したい場合は
log_type = FILE ファイル名
を指定するとファイルにログが吐出される(log_typeは型も含めて2つで問題ない)

IP制限

個別指定に
lonly_from = 192.168.7.{23,91}
のようにすると23と91だけ許可になる

注意点

selinuxは停止しておかないと接続できない可能性があります。

[Ruby] コンソールアプリで表を出力しよう

0

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

コンソールアプリで表を出力しよう

 この記事について

メンテナンスや日々の確認のために

ちょっとしたスクリプトを書くことがあります。

データなどを確認したい場面では

タブ区切りでのテキストを出力していましたが

データ量が大きくなると視認性が悪くなります。

そこでコンソール上でも表を出力したい!

となります。

※記事内でソースコードを変更する箇所がありますが、利用する場合は自己責任でお願いします。

 formatador

rubygemsでインストールができる

formatador

を使うこととします。

簡単な使い方は以下の通りです。

#-*- coding: utf-8 -*-
require "rubygems"
require "formatador"

data = [
  {:name => "taro", :age => 30},
  {:name => "hanako", :age => 25}
]

Formatador.display_compact_table(data, [:name, :age])
#第2引数で列順を指定
  +--------+-----+
  | name   | age |
  +--------+-----+
  | taro   | 30  |
  | hanako | 25  |
  +--------+-----+

実行すると上記のように表が出力されます。

 日本語表示でずれる

スクリプト上のdataを以下のように変更して出力してみます。

data = [
  {:name => "太郎", :age => 30},
  {:name => "花子", :age => 25}
]
  +------+-----+
  | name | age |
  +------+-----+
  | 太郎   | 30  |
  | 花子   | 25  |
  +------+-----+

ずれました。

マルチバイト文字に対応させてみます。

formatador-0.2.4/lib/formatador/table.rb

を以下のように修正しました。

--- table.rb.org 
+++ table.rb 
@@ -1,3 +1,9 @@
+class String
+  def width
+    chars.inject(0){|s,c| s += c.bytesize > 1 ? 2 : 1}
+  end
+end
+
class Formatador
   def display_table(hashes, keys = nil, &block)
     new_hashes = hashes.inject([]) do |accum,item|
@@ -14,7 +20,7 @@
     # Calculate Widths
     if hashes.empty? && keys
       keys.each do |key|
-        widths[key] = key.to_s.length
+        widths[key] = key.to_s.width
       end
     else
       hashes.each do |hash|
@@ -52,7 +58,7 @@
     # Display data row
     columns = []
     headers.each do |header|
-      columns << "[bold]#{header}[/]#{' ' * (widths[header] - header.to_s.length)}"
+      columns << "[bold]#{header}[/]#{' ' * (widths[header] - header.to_s.width)}"
     end
     display_line("| #{columns.join(' | ')} |")
     display_line(split)
@@ -80,7 +86,7 @@
   private

   def length(value)
-    value.to_s.gsub(PARSE_REGEX, '').length
+    value.to_s.gsub(PARSE_REGEX, '').width
   end

   def calculate_datum(header, hash)

再度出力してみます。

  +------+-----+
  | name | age |
  +------+-----+
  | 太郎 | 30  |
  | 花子 | 25  |
  +------+-----+

ずれなくなりました!

環境

ruby 1.9.3p484

formatador 0.2.4

少人数チームにおけるプロジェクト管理のベストプラクティス

0

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

Redmine+Git+GitLab+Jenkinsを使ったプロジェクト管理について、自らの経験して実際にかなり利便性が高いと思えた内容をフロー化してスライドにまとめてみました。

■ 概要

チケット管理ツール(Redmine), バージョン管理ツール(Git), Git管理ツール(GitLab), CIツール(Jenkins) を総合的に利用した少人数チームでのプロジェクト管理について、自らの経験して実際にかなり利便性が高いと思えた内容をフロー化してスライドにまとめてみました。

前置きが長くても仕方がないので早速下記スライドをご覧ください。

■ 本編(スライド)

■ 関連リンク

Comableのページ: hyoshida/comable

Ruby技術者認定試験(Gold)合格経験

0

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

Ruby技術者認定試験(Gold)合格経験

 【使用教材】

Ruby リファレンスマニュアル(オンラインのドキュメント)

Ruby公式資格教科書 Ruby技術者認定試験Silver/Gold対応

メタプログラミングRuby

 【勉強方法】

Ruby公式資格教科書

教科書のとおりに、Gold範囲をしっかり読む。

ガイドの説明をしっかり読んだほうが効率的です。

3章、4章、5-9~5-12は重要です

2章 実行環境 2,3問ぐらい

* コマンドラインオプション

* 組み込み変数/定数

3章 文法 15問ぐらい

* 変数と定数

* 演算子

* ブロック

* 例外処理

* 大域脱出

4章 オブジェクト指向 (試験の肝の部分です)25問くらい。

* メソッドの詳細

* メソッドの可視性

* クラスの詳細

* クラスの継承

* モジュールの詳細

5-9~5-12 組み込みライブラリ 10問くらい。

* よく使用されるクラス(Object、Kernel、Module等)

* よく使用されるモジュール(Enumerable、Comparable等)

* 数値

* 正規表現

正規表現は基本的な使い方以外にも、 *? や +? などの最短マッチも出題されます。

6章 標準添付ライブラリ 2,3問ぐらい

* よく使用されるライブラリ(socket、rdoc等)

メタプログラミングRuby 

 オブジェクト指向について、教科書がない内容があります。

 自分はヨドバシで立って読みました。

irbで試す(重要)

自分が試した注意点を共有します。

—————————————————————————-

クラスメソッドはクラスしか呼び出さない。

class C

def self.m

p “2”

end

end

C.new.m # undefined method `m’ for #<c:0x1fd7a80> (NoMethodError)

C.m # 2

—————————————————————————-

モジュールをクラスに extend すれば、モジュールのインスタンスメソッドがクラスメソッドになる

module Foo

def foo

p “foo”

end

end

class Hoge

extend Foo

end

Hoge.new.foo #undefined method `foo’ for #<hoge:0x1f07868> (NoMethodError)

Hoge.foo # foo

—————————————————————————-

initialize を定義しない場合は親クラスの initialize が自動で呼ばれます

class M1

def initialize

p “m1”

end

end

class M2 < M1

end

M2.new  #m1

—————————————————————————-

super と super() は動作が異なります

super は現在のメソッドがオーバーライドしているメソッドを呼び出します。

括弧と引数が省略された場合には現在のメソッドの引数がそのまま引き 渡されます。

引数を渡さずにオーバーライドしたメソッドを呼び出すには super() と括弧を明示します。

例:

class Foo

def foo(arg=nil)

p arg

end

end

class Bar < Foo

def foo(arg)

super(5) # 5 を引数にして呼び出す

super(arg) # 5 を引数にして呼び出す

super # 5 を引数にして呼び出す super(arg) の略記法

arg = 1

super # 1 を引数にして呼び出す super(arg) の略記法

super() # 引数なしで呼び出す nil

end

end

Bar.new.foo 5

—————————————————————————-

インスタンス変数

class Sample

@value = “hello”

def value

@value

end

end

Sample.new.value #=> nil

Sample.class_eval { @value } #=> “hello”

クラス定義の中で初期化した、@valueは Sampleクラスオブジェクトのインスタンス変数で、

メソッド定義の中で、初期化した、@valueはSampleクラスオブジェクトのインスタンスのインスタンス変数になる。

インスタンス変数はクラス内で全メソッドで共通して使用することが出来ます。最初にどこかのメソッドで使用された時点でインスタンス変数は作成され、一度作成されたインスタンス変数は他のメソッドで値を取り出したり格納したりすることが出来るようになります。

class Foo

@v1=1

def self.read; @v1;end

def write; @v1=2;end

def read; @v1;end

end

=> nil

irb(main):017:0> obj=Foo.new

=> #<foo:0x000000174ce908>

irb(main):018:0> obj.write

=> 2

irb(main):019:0> obj.read

=> 2

irb(main):020:0> Foo.read

=> 1

—————————————————————————-

クラスとsuperクラス

irb(main):032:0* foo=Foo.new

=> #<foo:0x0000001d9caf78>

irb(main):033:0> foo.class

=> Foo

irb(main):034:0> foo.superclass

NoMethodError: undefined method `superclass’ for #<foo:0x0000001d9caf78>

from (irb):34

from /home/search/ruby/bin/irb:12:in `<main>’

irb(main):035:0> Foo.class

=> Class

irb(main):036:0> Foo.superclass

=> Object

irb(main):037:0> Class.class

=> Class

irb(main):038:0> Class.superclass

=> Module

irb(main):007:0> Module.superclass

=> Object

—————————————————————————-

クラス変数。トップレベル:object 全てのクラスの親クラス。

クラス変数は、親と子共有で使う

irb(main):001:0> @@v1=1

=> 1

irb(main):002:0> class Foo

irb(main):003:1> @@v1=2

irb(main):004:1> end

=> 2

irb(main):005:0> p @@v1

2

=> 2

—————————————————————————-

Object extend

irb(main):001:0> module M

irb(main):002:1> def m;”aa”;end

irb(main):003:1> end

=> nil

irb(main):004:0> obj=Object.new

=> #<object:0x00000011384670>

irb(main):005:0> obj.extend M

=> #<object:0x00000011384670>

irb(main):006:0> obj.m

=> “aa”

irb(main):007:0> class C

irb(main):008:1> extend M

irb(main):009:1> end

=> C

irb(main):010:0> C.m

=> “aa”

irb(main):011:0> c.new.m

NameError: undefined local variable or method `c’ for main:Object

from (irb):11

from /home/search/ruby/bin/irb:12:in `<main>’

—————————————————————————-

以下の2つのコード、include の位置を変えると表示される結果が異なります。

コード1

module M

@@x = 100

end

class A

@@x = 500

include M

end

module M

puts @@x # 100 と表示される

end

class A

puts @@x # 100 と表示される

end

コード2

module M

@@x = 100

end

class A

include M

@@x = 500

end

module M

puts @@x # 500 と表示される

end

class A

puts @@x # 500 と表示される

end

—————————————————————————-

モジュールで定義されたクラス変数(モジュール変数)は、そのモジュールをインクルードしたクラス間でも共有されます。

module Foo

@@foo = 1

end

class Bar

include Foo

p @@foo += 1 # => 2

end

class Baz

include Foo

p @@foo += 1 # => 3

end

—————————————————————————-

親クラスに、子クラスで既に定義されている同名のクラス変数を追加した場合には、 子クラスのクラス変数は子クラスで保存されます。

上書きされません。

class Foo

end

class Bar < Foo

@@v = :bar

end

class Foo

@@v = :foo

end

class Bar

p @@v #=> :bar

end

class Foo

p @@v #=> :foo

end

—————————————————————————-

トップレベルで定義すれば、Object中に定義され、親なので、子供も共有。下記は同じになる。

@@v=1

class Foo

end

class Bar < Foo

@@v = :bar

end

class Foo

@@v = :foo

end

class Bar

p @@v #=> :foo

end

class Foo

p @@v #=> :foo

end

p @@v #=> :foo

irb(main):002:0> @@v=1

=> 1

irb(main):003:0> class Foo

irb(main):004:1> @@v=2

irb(main):005:1> end

=> 2

irb(main):006:0> @@v

=> 2

irb(main):001:0> class Foo

irb(main):002:1> @@v=1

irb(main):003:1> end

=> 1

irb(main):004:0> p @@v

NameError: uninitialized class variable @@v in Object

from (irb):4

from /usr/bin/irb:12:in `<main>’

—————————————————————————-

irb(main):007:0> Module.class

=> Class

irb(main):008:0> Class.class

=> Class

irb(main):009:0> Class.superclass

=> Module

irb(main):005:0> Class.ancestors

=> [Class, Module, Object, Kernel]

irb(main):010:0> Module.superclass

=> Object

irb(main):001:0> module Foo

irb(main):002:1> @@foo = 1

irb(main):003:1> end

=> 1

irb(main):004:0> Foo.class

=> Module

irb(main):006:0> Foo.ancestors

=> [Foo]

irb(main):001:0> class Foo

irb(main):002:1> end

=> nil

irb(main):003:0> Foo.class

=> Class

irb(main):004:0> Foo.ancestors

=> [Foo, Object, Kernel]

—————————————————————————-

可変引数

可変長引数のデフォルト値は指定できません。

引数は配列として扱われる。

可変長引数は一つのメソッドは一つしか指定できません。

def foo(*args)

p args

end

def bar(*args)

foo(args)

end

def hoge(*args)

foo(*args)

end

実行結果は以下のとおり

bar(1, 2, 3, 4, 5) #=> [[1, 2, 3, 4, 5]]

hoge(1, 2, 3, 4, 5) #=> [1, 2, 3, 4, 5]

foo, bar = [1, 2] # foo = 1; bar = 2

foo, bar = 1, 2 # foo = 1; bar = 2

foo, bar = 1 # foo = 1; bar = nil

foo, bar, baz = 1, 2 # foo = 1; bar = 2; baz = nil

foo, bar = 1, 2, 3 # foo = 1; bar = 2

foo = 1, 2, 3 # foo = [1, 2, 3]

*foo = 1, 2, 3 # foo = [1, 2, 3]

foo,*bar = 1, 2, 3 # foo = 1; bar = [2, 3]

—————————————————————————-

合格者の合格経験を見る

http://rochefort.hatenablog.com/category/gold

 【感想】

Silverよりかなり難しいですが、試験内容は上記です。

ですので、重要な部分を理解して、irbで注意点などしっかり把握すれば、合格できます。

PHP5技術者認定初級試験を受験しました

0

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

所属のSaaS部の案件の多くは ruby や java といった言語を使用していますが、php の案件も増えています。昨年、アピリッツの資格支援の対象にPHP技術者認定試験が加えられたこともあり、先週2014年1月25日に PHP5技術者認定初級試験を受験しましたので報告します。

 試験対策について

業務で php を使っていれば初級試験の試験範囲はほぼ網羅できていると考えらますが、

試験ですので、試験特有の罠にかからないように試験用の学習はする必要があると考えましょう。要するに試験問題をひと通り解いて問題の作り方のパターンや引っ掛けの選択肢のパターンを把握しましょう。LPIC Level 1や Ruby Silver もそうですが初級の試験は回答の選択肢だけ見て問題文を見ずに正解を出すといった裏技が使えることがありま…。

 実務学習での盲点

・ セキュリティー対策やDB接続、出力バッファの制御の箇所は業務ではフレームワーク任せにしていたた為、知識が曖昧になっており失点しておりました。実害なく自分の弱点が把握できるのが試験の良いところです。セキュリティー対策として14種類の攻撃方法への対応方法を今学習しています。

・ PHPのオブジェクト指向の傾向についての出題があり、いくつか耳慣れない用語が登場しました。オブジェクト指向についての一般的な知識も整理しておくと良いです。

 試験概要・出題範囲

下記サイトで確認できます。書籍教材の紹介のリンクもあります。

http://www.phpexam.jp/summary/novice/

 学習サイト

下記を利用させて頂きました。

http://jibun.atmarkit.co.jp/scenter/ittrain/122_today_q.html

rubyの学習サイト「ミニツク」程ではありませんが初級試験対策の心強い味方です。

 書籍教材

『徹底攻略 PHP5技術者認定[初級]試験 公式問題集』が社内にありましたので利用させて頂きました。

上記サイトと重複する内容もありますが通信環境が不要なのが書籍の便利なところです。

 申し込み

PHP5技術者認定初級試験はプロメトリック社で受験を申し込みます。

http://it.prometric-jp.com/testlist/php/index.html

 注意点

試験は php-5.1がベースです。

現在 安定版は 5.5.8, 5.4.24, 5.3.28 となっており、記述方法の進化や関数の入れ替えがあったりします。詳細については下記にURLを記載しましたPHPマニュアルをご参照ください。

SQLも出題されます。

insert, update, delete 文や where, order by, limit 句 sum() 関数といった基本的なものは理解しておきます。

プロメトリック社の試験場での受験です。

3営業日以上前に申し込みが必要(以前、LPIC認定試験を受けたピアソンVUEは前日でも申し込み可でした)

2つの身分証明書(1つは顔写真入り)の提示が必要です。

 Doruby参考記事

下記を参考にさせて頂きました。

お金をかけずにRuby技術者認定試験(Silver)に合格する方法

http://doruby.kbmj.com/hyoshida/20131115/_Ruby_Silver_1

※ Ruby Silver の取得方法ですがプロメトリック社の受験時の注意点も参考になります。

 PHPマニュアル

http://jp2.php.net/manual/ja/

PHP 5.4.x から PHP 5.5.x への移行

http://jp2.php.net/manual/ja/migration55.php

PHP 5.3.x から PHP 5.4.x への移行

http://jp2.php.net/manual/ja/migration54.php

PHP 5.2.x から PHP 5.3.x への移行

http://jp2.php.net/manual/ja/migration53.php

PHP 5.1.x から PHP 5.2.x への移行

http://jp2.php.net/manual/ja/migration52.php

最近人気な記事