投稿日 2010年6月30日 水曜日 カテゴリ CakePHP, PHP 投稿者 sugimotoコメント(0) » 

sugimoto です。最近、CakePHPを使ってます。

しばらくRails を使っていたこともあり、わかりやすい所もある反面、衝撃的に違うところがあったりして試行錯誤な毎日です。

先日、連結テーブルに「並び順」カラムを持たせて、hasManyAndBelongsToなリレーションの順番をつけようとしたところ、うまく動きませんでした。

プロジェクトとユーザーを以下のようなテーブルで関連つけていました
projects
users
projects_users

このとき、「各プロジェクトの参加者ごとに並び順を設定したい」という要望があり、 projects_users に position カラムを持たせて並び順を設定することにしました。

positionカラムの更新をするために ProjectsUser という中途半端なmodel クラスを作ったところ、問題発生。

projects_controller のuses 句で ProjectsUser を設定しているにもかかわらず、ProjectsUser の関数が呼べず、controller内での $this->ProjectsUser の実体がなぜか AppModel となっていました。

AppController など、ソースを確認したところ、controller のイニシャライズ時、以下のようなロジックでした。

  1. Projectモデルのインスタンス を作成
  2. Projectモデルで設定されているリレーションに該当するモデルのインスタンスを作成(Userなど)
  3. リレーションテーブルを扱うのインスタンス ProjectsUserを作成
  4. その際、デフォルト実装である AppModel のインスタンスとして作成
  5. 上記作成したインスタンスはすべてキャッシュ
  6. ProjectsUserを作成するが、すでにキャッシュされているためそれを使用

つまり、上記処理がcontroller の uses句内で宣言された順に処理されているため、ProjectsUserをロードするとき、先に処理したProjectモデルのリレーションとして作成されたProjectsUserが優先されていたわけです。

今日の格言

リレーショナルテーブルのモデルを作ったら、uses 句内では必ず先に宣言すること。

ソフトウェアエンジニアのためのバグトラッキングシステム : Ciklone

ソフトウェアエンジニアのためのバグトラッキングシステム

ソフトウェアエンジニアのためのバグトラッキングシステム

投稿日 2010年6月28日 月曜日 カテゴリ Ruby on Rails 投稿者 morimotoComments Off 

どうもお久しぶりです。

morimotoです。

今日は複雑なActiveRecordの条件句を作成する際に(もしかしたら)楽になるのではないかと思いconditionを生成するクラスを作ってみました。

  class ARCond
    module OPERATION
      EQUAL            = '='
      NOT_EQUAL        = '<>'
      IN               = 'IN'
      GREATER          = '>'
      GREATER_OR_EQUAL = '>='
      LESS             = '< '
      LESS_OR_EQUAL    = '<='
    end

    attr_reader :conditions, :parameters, :separator, :table_name

    def initialize(separator="AND", table_name=nil)
      @conditions = []
      @parameters = []
      @separator  = separator
      @table_name = table_name
    end

    # column = ?
    def equal(column, value, table=nil)
      add(column, value, OPERATION::EQUAL, table)
    end
    # column <> ?
    def not_equal(column, value, table=nil)
      add(column, value, OPERATION::NOT_EQUAL, table)
    end
    # column IN (?,?,?...)
    def in(column, value, table=nil)
      add(column, value, OPERATION::IN, table)
    end
    # column > ?
    def greater(column, value, table=nil)
      add(column, value, OPERATION::GREATER, table)
    end
    # column >= ?
    def greater_or_equal(column, value, table=nil)
      add(column, value, OPERATION::GREATER_OR_EQUAL, table)
    end
    # column < ?
    def less(column, value, table=nil)
      add(column, value, OPERATION::LESS, table)
    end
    # column <= ?
    def less_or_equal(column, value, table=nil)
      add(column, value, OPERATION::LESS_OR_EQUAL, table)
    end

    def << (other)
      cond = nil
      param = []
      if other.kind_of? ARCond
        c = other.build
        cond = c.delete_at(0)
        param = c
      elsif other.kind_of? String
        cond = other
      elsif other.kind_of? Array
        cond = other.delete_at(0)
        param = other
      end
      unless cond.blank?
        @conditions << cond
        @parameters.concat(param)
      end
      return self.build
    end

    # [conditions, param, param, param,...]
    def build
      [join_conditions].concat(@parameters)
    end

    private
    def join_conditions
      sep = " #{@separator} "
      "(#{@conditions.join(sep)})"
    end

    def column_fullname(column, table=nil)
      unless column =~ /^[\w]+\.[\w]+$/
        if table_name = table.blank? ? @table_name : table
          return "#{table_name}.#{column}"
        end
      end
      column
    end

    def add(column, value, operation, table=nil)
      parts = [column_fullname(column, table), operation]
      param = [value].flatten
      parts << ((operation == OPERATION::IN) ? "(#{param.map{'?'}.join(',')})" : "?")
      self << [parts.join(' ')].concat(param)
    end
  end

使い方の例)

# 基本スタイル
c1 = ARCond.new("AND")
c1.equal("col1", true)
  # => ["(col1 = ?)", true]
c1.not_equal("col2", nil)
  # => ["(col1 = ? AND col2 <> ?)", true, nil]
c1.in("col3", [31,32,33])
  # => ["(col1 = ? AND col2 <> ? AND col3 IN (?,?,?))", true, nil, 31, 32, 33]



# 連結文字を変更する
c2 = ARCond.new("OR")

# 指定した連結文字で結合されていく
c2.greater("col4", 100)
  # => ["(col4 > ?)", 100]
c2.less("col4", 200)
  # => ["(col4 > ? OR col4 < ?)", 100, 200]

# 配列みたいに追加していく
c1 << c2
  # => ["(col1 = ? AND col2 <> ? AND col3 IN (?,?,?) AND (col4 > ? OR col4 < ?))", true, nil, 31, 32, 33, 100, 200]



# 引数なしはANDで連結
c3 = ARCond.new()

# いつもどおりの配列の conditions もくっつけれる
c3 << ["col5 = ? AND col6 IN (?,?)", 11,22,33]
  # => ["(col5 = ? AND col6 IN (?,?))", 11, 22, 33]

# 任意文字列もくっつけれる
c3 < < "col7 > col8"
  # => ["(col5 = ? AND col6 IN (?,?) AND col7 > col8)", 11, 22, 33]


# テーブル名を指定する
c4 = ARCond.new("OR", "sample")

# カラム名の頭にテーブル名が付与される
c4.greater_or_equal("col9", 300)
  # => ["(sample.col9 >= ?)", 300]
c4.less_or_equal("col9", 400)
  # => ["(sample.col9 >= ? OR sample.col9 < = ?)", 300, 400]

# くっつけるときにテーブル名を指定する
c4.equal("col10", false, "banana")
  # => ["(sample.col9 >= ? OR sample.col9 < = ? OR banana.col10 = ?)", 300, 400, false]

c3 << c4
  # => ["(col5 = ? AND col6 IN (?,?) AND col7 > col8 AND (sample.col9 >= ? OR sample.col9 < = ? OR banana.col10 = ?))", 11, 22, 33, 300, 400, false]

c1 << c3
  # => ["(col1 = ? AND col2 <> ? AND col3 IN (?,?,?) AND (col4 > ? OR col4 < ?) AND (col5 = ? AND col6 IN (?,?) AND col7 > col8 AND (sample.col9 >= ? OR sample.col9 < = ? OR banana.col10 = ?)))", true, nil, 31, 32, 33, 100, 200, 11, 22, 33, 300, 400, false]


# 最終的に使いたいタイミングで build してあげたらよい
c1.build
  # => ["(col1 = ? AND col2 <> ? AND col3 IN (?,?,?) AND (col4 > ? OR col4 < ?) AND (col5 = ? AND col6 IN (?,?) AND col7 > col8 AND (sample.col9 >= ? OR sample.col9 < = ? OR banana.col10 = ?)))", true, nil, 31, 32, 33, 100, 200, 11, 22, 33, 300, 400, false]

作っておいてなんですが、テーブルが複数あったり、集計クエリが絡んできたりと、複雑になればなるほど自分でwhere句を書いたほうが早い気がします。

以上、morimoto でした。

投稿日 2010年5月24日 月曜日 カテゴリ ソフトウェア開発, 読書 投稿者 syojiComments Off 
オープンソースソフトウェアの育て方
プロジェクトが失敗に終わる可能性は非常に高く、 おそらく90–95%くらい

「オープンソースソフトウェアの育て方」という書籍があります。副題にフリーソフトウェアプロジェクトを成功させるコツとあるように、著者がオープンソースプロジェクトでの経験を元に実例を交えて説明されています。バージョン管理システムで有名なSubversionプロジェクトでの実際の経験から書かれています。 実践的な内容なので、ぜひソフトウェアエンジニアの方には読んで欲しい内容です。 (技術的な側面よりもオープンソースプロジェクトをうまく運営するための考え方やプロジェクト運営方法についての説明が多くなっています。)

さらに、うれしいことにウェブで全文を公開しているためだれでも読むことが出来ます(当然、日本語で)300ページにもなる専門的でためになる文書を公開された作者の方と翻訳者の方に感謝しなければいけません。

本の内容で特にビジネスアプリケーション開発の困難な点と共通する部分が多く(同じソフト開発なので当たり前ですが)さらに多くの課題に対処するための方法も参考になります。 「3. 技術的な問題」で紹介されているツールとその運用方法は、ビジネスアプリケーションの現場でも十分有効に使えるので、新入社員などに読ませるのも良いと思います。紹介されているツール群は若干古いですが、どのようなツールを、どのような場面で、どのように使っているのかを知る上でとても分かりやすいです。

また、「6.コミュニケーション」などは自分たちの開発でも学ぶべきコトが多いと思った部分で、読んでおくべき章だと思います。

ソフトウェアエンジニアに求められる能力として、はじめに思いついたことは、「文章を作成する力」です。コミュニケーション能力や提案力、プログラミング能力などよく言われる能力も必要であると思いますが、自分の考えを正確に正しく伝えるための書く力はインターネットが仕事に欠かせないツールになったことで重要であると考えています。

そのためには書く(まとめる)内容以前に考える力が重要になってきますが。。。

http://subversion.tigris.org/
投稿日 2010年5月6日 木曜日 カテゴリ ZABBIX, ツール 投稿者 sugimotoコメント(0) » 

tt_graphic

sugimotoです。

Webサービスの運用ではサーバーやサービスの監視が欠かせないと思います。 オープングルーヴでも突然のサーバー停止や、サービス停止、定期処理の失敗などに備え、監視システムを使って障害発生時にはメール通知するようにしています。

GW中に出かける途中で、監視システムとして運用しているZABBIXから警告メールが飛んできました。

パソコンを持たずに出かけていて、長距離バスに乗っていたんですが、iPhoneにインストールしていたTouchTermを使いました。

TouchTermはiPhoneアプリとして動作するSSHターミナルです。 アプリケーション内で作成したSSHキーのパブリックキーをあらかじめサーバーにおいておくことで、サーバーにSSH経由でログインすることができます。

iPhoneの画面とキーでも十分にサーバー上のログや状況の確認が可能で、問題の箇所をすぐに特定、対応することができました。

iPhoneの画面とキーを使っての操作のため、長時間操作や大きな設定変更は難しいですが、緊急時の一時的な対応には十分使えるツールです。

ソフトウェアエンジニアのためのバグトラッキングシステム : Ciklone

ソフトウェアエンジニアのためのバグトラッキングシステム

ソフトウェアエンジニアのためのバグトラッキングシステム

投稿日 2010年3月16日 火曜日 カテゴリ Wiki, プロジェクト管理 投稿者 syojiComments Off 

社内での仕事術 #1

社内での仕事術について紹介したいと思います。 ソフトウェア開発は一つ一つの案件をプロジェクトとしてすすめるため、はじめにプロジェクトチームを作ります。

プロジェクトチームは提案内容や得意分野により主担当がかわります。 プロジェクトでは複数のメンバーが集まって仕事をすることになるため、情報共有はとても重要。

オープングルーヴではどのようにしているのか、ツールを使った情報共有#1として「Wikiを仕事で使う」について書きたいと思います。

Wikiとは「ウィキ」と言いますが、ウェブブラウザを使ってページの作成・編集ができるコンテンツサービスです。一人でメモ書きとして利用している方もいると思いますが、けっこう書込のためにページを開く。という動作が面倒になりがちということはあると思います。

弊社で利用する場合は、複数のメンバーでプロジェクトを進める上でガリガリ書き込みます。これはあるルールを決めているためですが、そのルールのおかげでWikiがなくてはならいツールになっています。

ルール : プロジェクトの成果物(中間成果物)はWikiで一元管理

Wikiのメリット

  • 会議をしながら議事録(画面を見ながらみんなで確認)
  • 顧客向けの議事録
  • 顧客との打合せで出来る議事録はWikiをPDF化やメールで共有
  • 設計書(技術メモ、検討メモ)、技術方式に対する他チームのコメント
  • 開発環境構築メモなど、開発に関わる情報源
  • 世代管理機能、ページ単位で履歴を確認し、追加された・削除されたがカラー表示される(下図)

Wikiによる備忘録・ルール

Wikiによる備忘録・ルール

Wikiの世代管理(履歴)

Wikiの世代管理(履歴)

などなど、メールでも同様のことはできますが、プロジェクトのポータルとして利用でき、大切な文書が埋もれない・・・(メールは探すのが大変) プロジェクトメンバーで使うことで、ガリガリ更新され、すぐにWikiが必須の情報共有ツールになりました。

デメリットは…

しかし、良い面ばかりではないです。新しく加わったメンバーなどにとっては使ったことがないツールのため、慣れるまで大変かも知れません。 「Wikiを知らない人や初めて使う人にとって慣れ親しんだインターフェースではない。」ということです。ファイル名がない、特殊なフォーマット・・・

Wikiを仕事で使いたい人へ セキュアで、1プロジェクト無料のcikloneを評価してください。
次のページ »