プロジェクト

全般

プロフィール

操作

GuideForProject » 履歴 » リビジョン 1

リビジョン 1/10 | 次 »
Mitsuyoshi Yoshida, 2011/06/25 23:37


プロジェクトで利用可能にする

プラグインをプロジェクトごとに使用できるようするためにはプロジェクトモジュールとしての登録とプロジェクトメニューへの項目の追加が必要となります。

モジュールと permission の設定

モジュールの登録ではモジュール名とアクションごとの実行する権限(permission)を指定します。

権限 アクション
データの表示 index, view
データの管理 new, edit, destory

権限の指定は init.rb の Redmine::Plugin::register メソッドで行います。次の記述をブロック内に追加してください。

  project_module :standard do
    permission :view_foos, :foos => [:index, :show]
    permission :manage_foos, :foos => [:new, :edit, :destroy],
               :require => :member
  end

project_module メソッドの引数でモジュール名(standard)を指定し、ブロック内で permission メソッドを呼び出して権限の指定をしています。

permission メソッドの書式は次の形です。

permission(name, hash, options={})

第一引数で権限の名前を指定します。
第二引数にはコントローラ名をキー、アクション名の配列を値としたハッシュを渡します。サンプルではコントローラは一つしかありませんが、複数あることもあるので、ハッシュで指定できるようになっています。
第三引数はオプションです。

Rails では次のようなスタイルがよくとられるので慣れておきましょう。
  • メソッドのオプション的な指定は最後の引数でシンボル名をキーとしたハッシュを使ってまとめて渡す
  • ハッシュが一つのペアしか持たないや最後の引数などで括弧 {} が省略できる場合は省略する

このオプションの :require の指定を使って、データ管理の権限(:manage_foos)ではプロジェクトメンバー以外の Non member や Anonymous(ログインしていない人)では使えないようにしています。

それでは Redmine を起動して、プラグインをプロジェクトで使用できるようにしましょう。

まず、管理メニューにあるロールと権限の 権限レポート でチェックをいれて権限を与えます。

次にプラグインを使いたいプロジェクトの設定で Standard モジュールを有効にします。

このときの表示は指定したモジュール名などがほぼそのまま表示されているだけですが、これを日本語に変更する方法は国際化のところで説明します。

プラグインメニューへの追加

プロジェクトでモジュールを有効にしてもまだ何も変わりません。実際にこのプラグインを使えるようにするためにはプロジェクトメニューに項目を追加する必要があります。
プロジェクトメニューにはこのプラグインで最初に表示させたいページに対応するアクションを追加します。サンプルでは foos コントロールの index アクションとなります。

メニュー項目の追加も init.rb で行います。先ほどの記述の後に以下を加えます。

  menu :project_menu, :standard, { :controller => 'foos', :action => 'index' }

メニューの項目の追加は menu メソッドを使います。

menu(menu, item, url, options={})

第 1 引数はメニューの名前です。ここではプロジェクトメニューを指定します。指定できるメニューは サンプル仕様 で説明した 4 つです。

メニュー メニュー名
トップメニュー :top_menu
アカウントメニュー :account_menu
プロジェクトメニュー :project_menu
アプリケーションメニュー :application_menu

第 2 引数はメニューの項目名です。
第 3 引数はメニューをクリックしたときのリンク先の URL を指定します。
第 4 引数はオプションでここでは省略しています。

Rails での URL の指定方法

前節のメニューで行った URL の指定方法は link_to などでの他の Rails のリンクの指定方法と同じです。
URL の指定方法についてもう少し詳しく説明しましょう。

URL として文字列を指定すると単純にその文字列が url として使用されますが、ハッシュで指定するとそれを元に URL を生成します。

指定するキーはコントローラ名(:controller)、アクション名(:action)と ID名(:id) で、そのキーの値を使って次のようなアドレスとなります。

サーバアドレス/コントローラ名/アクション名/ID名

ID 名は省略可能で省略されると ID 名の部分はなくなります。ただし、ここで省略しているのはプロジェクトメニューから呼ばれると自動的に ID 名はプロジェクトの識別名になるためです。サンプルのアドレスは以下のようになります。(プロジェクトの識別名は demo にしています)

http://127.0.0.1:3000/foos/index/demo

このアドレスの指定によりコントロールのアクションが実行されることになります。この場合は FoosController の index メソッドが呼ばれます。
ID は param というハッシュクラスの変数に格納されてます。param は $ マークは付いてませんが、グローバル変数のようなものだと考えてください。

プロジェクトの識別名は :id を使わずに :project_id に入れて、config/routes.rb でアドレスの表示を変える方法もあります。サンプルでは :id を使った方が簡単だと思ったのでこちらの方法をとっています。

index ページの表示

Redmine を再起動してモジュールを追加したプロジェクトを開いてみましょう。プロジェクトメニューに Standard が追加されています。

このメニューをクリックして下さい。 index.html.erb の内容のページが表示されます。

コントローラの index メソッドの中にはまだ何も書いていません。それにもかかわらず、 index ページが表示されています。これはコントローラのアクションが実行されるとアクション名のメソッドが実行され、デフォルトの状態ではアクション名に対応する views のファイルが表示されるためです。
スケルトンとして生成されたファイルは index.html.erb ですが、検索されるファイルはアクション名の後は .rhtml, .erb のような Erb の html を表す拡張子であれば何でもかまいません。

@project の設定

ただし、表示されたページよく見ると何か変なことに気づくと思います。これは他のプロジェクトメニューと違いプロジェクトが開かれていないためです。このページをプロジェクトに属するものするためには FoosController クラスのインスタンス変数 @project に値を設定する必要があります。

FoosController クラスの末尾に次のような @project を設定する find_project メソッドの定義を追加します。外から呼ばれることはありませんので、private メソッドにしています。

class FoosController < ApplicationController
  unloadable
    # :
private
  def find_project
    @project = Project.find(params[:id])
  rescue ActiveRecord::RecordNotFound
    render_404
  end
end

params[:id] にはプロジェクトの識別名が入っています。
Project はプロジェクト用のモデルクラスです。 find メソッドは引数にプロジェクト識別名を渡すと、データベースから識別名が一致するプロジェクトを探し、Project のオブジェクトを返すクラスメソッドです。

Project クラスも ActiveRecord::Base クラスを継承して作成されており、データがみつからないと ActiveRecord::RecordNotFound の例外が発生します。コントローラ内で例外が発生すると通常の http サーバの場合 Internal Error のページになってしまいます。(WEBrick では詳細なエラー情報の画面になります。)
この例外をキャッチして render_404 を実行しています。 これはファイルが見つかりませんといった http の 404 エラーのページを表示するメソッドです。

定義した find_project メソッドを index メソッドの中で呼び出せばプロジェクト内のページとして表示されます。

before_filter

アクションは index だけではありません。他のアクションのメソッドでも同様に find_project を呼び出す必要があります。じゃ、 index の find_project をコピーして、他のメソッドにもペーストしていって ... と思った人はちょっと待ってください。 それでは同じことを何度も書く羽目になります。 Rails には DRY という繰り返し禁止の方針がありました。何か繰り返しを避ける方法があるはずです。

実際、避ける方法は用意されています。それは before_filter です。これでメソッドを指定するとそのメソッドはアクションのメソッドの前に呼ばれるようになります。
こちらはコントローラクラスの先頭の方に追加します。

class FoosController < ApplicationController
  unloadable
  before_filter :find_project
    # :

authorize

before_filter はカンマで区切って複数のメソッドを指定することが出来ます。もう一つ追加してみましょう。

class FoosController < ApplicationController
  unloadable
  before_filter :find_project, :authorize
    # :

追加した authorize はページを開いた時にログインしていない場合はログインのページ行く Redmine のメソッドです。通常、プロジェクトメニューから開かれるので、ログインしていることが多いと思いますが、ブラウザで前に開いていたページをもう一度開くといった設定がしてある場合などでは直接ページが指定されることもあります。そういったときにもちゃんとログインできるようにすべてのアクションの前に実行しておく必要があります。

権限の設定で index や show では設定によってはログインしてなくても、表示できる場合があるのではと疑問を持った方もいると思いますが、そういう場合も Redmine がログインしないように上手く処理してくれます。

権限の判定には現在のプロジェクトの情報が必要となります。before_filter は追加した順に実行されますので必ず find_project, authorize の順で記述して下さい。

ここまで設定して、もう一度 [Standard] のメニューを選択してみてください。今度はプロジェクトのページとして開かれているはずです。

まだ、少し変なところがあります。メニュー項目が選択状態になっていませんね。これを解決するにはコントローラ内で menu_item を使ってメニュー項目を指定します。

  menu_item :メニュー項目のシンボル

このメソッドで指定しなくてもメニュー項目が選択状態になることがあります。実はどうしたらそうなるのかは私もよく分かりません。とりあえず、選択状態にならないときはこのメソッドで指定してみてください。

これまでの記述を追加したコントローラのファイルの中身は次のようになります。

class FoosController < ApplicationController
  unloadable
  menu_item :standard
  before_filter :find_project, :authorize

  def index
  end

  def new
  end

  def show
  end

  def edit
  end

private
  def find_project
    @project = Project.find(params[:id])
  rescue ActiveRecord::RecordNotFound
    render_404
  end
end

これでプロジェクトメニューにきちんと登録できるようになりました。


^ << >>


Updated by Mitsuyoshi Yoshida , ほぼ13年前に更新
Access count: 36641 :since 2009-10-30

Mitsuyoshi Yoshida さんがほぼ13年前に更新 · 1件の履歴