Project

General

Profile

Actions

wiki 編集機能の追加

プラグインに wiki 編集機能を付ける方法の Tips です。
プラグイン開発ガイド では簡単な wiki 編集機能は付けました。ここでは他の wiki のように以下の機能も追加します。

  • プレビュー
  • 添付ファイル

wiki 編集機能だけの場合の説明はプラグイン開発ガイドを見てください。

サンプルコード

サンプルはプラグイン開発ガイドのコードを改造したものです。

フォーム

表示

プレビュー

プレビューでは新しくページを開くことなく、ページの内容を変更する必要があります。こういう処理には JavaScript が必要になります。しかし、 Rails ではこれを簡単に行える link_to_remote という関数が用意されてます。 Rails では _remote と付くのは JavaScript 実行用のもので、 link_to_remote では JavaScript を実行するリンクが作成できます。

:update オプションを使った link_to_remote では、リンクをクリックするとアクションを実行し、その結果をページの指定した場所に挿入します。

表示

プレビュー用のリンクを新規作成(new.html.erb)と編集(edit.html.erb)のフォーム送信ボタンの横に付けます。 wiki 編集機能を改良した new.html.erb は次のようになります。 edit.html.erb もほぼ同じように修正します。

<h2><%=l(:label_foos_new)%></h2>

<% labelled_tabular_form_for :foo, @foo,
                             {:html => {:multipart => true, :id => 'foo-form'}} do |f| %>
    <%= render :partial => 'foos/form', :locals => {:form => f} %>
    <%= f.submit l(:button_create) %>
    <%= link_to_remote l(:label_preview), 
                       { :url => {:action => 'preview', :id => @project },
                         :method => 'post',
                         :update => 'preview',
                         :with => "Form.serialize('foo-form')",
                         :complete => "Element.scrollTo('preview')" 
                       }, :accesskey => accesskey(:preview) %>
<% end %>
<div id="preview" class="wiki"></div>

変更点は 3 つです。

  • フォームタグに ID を要素を付ける。
    • {:html => {:multipart => true, :id => 'foo-form'}}
  • link_to_remote でプレビュー用のリンクを付ける
  • プレビューの表示場所を付ける
    • <div id="preview" class="wiki"></div>

multipart も追加していますが、これは次で説明する添付ファイル用のものです。

link_to_remote は引数は以下のものを渡します。

  1. 表示名
  2. オプション
  3. html オプション

表示名には Redmine で定義されたプレビューのラベルを使い、 html オプションとしてプレビュー用のアクセスキーを設定しています。アクセスキーを付けるとどう変わるのかはよく分かりませんが、 Redmine のチケット、ニュース等は付いているの一応付けています。

link_to_remote の主な指定はオプションで行います。

オプション 説明
:url アクションを指定するための url です。 preview アクションは今回新たに追加します。
:method get または post を指定します。文字数が 256 を超える可能性があるので post を指定しています。
:update 結果の挿入先の html 要素の ID を指定します。
:with リンクと一緒に実行する JavaScript を記述します。リンクを実行したときにフォームの内容を params 変数に格納するための処理を行っています。 フォームに ID を追加したのはここで使用するためです。
:complete アクション実行後の JavaScript の処理を指定します。処理が完了したら、スクロールしてプレビューの内容が表示されるようにしています。

コントローラ

コントローラ( foos_controller.rb )に link_to_remote から呼ばれる preview を追加します。

  def preview
    @text = params[:foo][:description]
    render :partial => 'common/preview'
  end

2 行目でフォームの説明(description)フィールドの内容を @text に入れ、3 行目で挿入する部分描画を行っています。 code/preview は Redmine で用意されているビュー用のテンプレートファイルで以下のような内容です。

<fieldset class="preview"><legend><%= l(:label_preview) %></legend>
<%= textilizable @text, :attachments => @attachements, :object => @previewed %>
</fieldset>

(@attachements のつづりが間違っている気がしますが、 1.2.0 ではこうなってました)

preview アクションの権限

アクションを追加した場合には忘れずに init.rb で権限を指定していないとエラーになってしまいます。

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

添付ファイル

添付ファイルを使えるようにするにはいろいろやることがあります。

  • モデル
    • 添付ファイルを使えるように指定
    • プロジェクトメソッドの追加
  • ビュー
    • フォーム
      • マルチパートにする
      • 添付ファイル用のフィールドを追加
    • 表示
      • wiki 解析で添付ファイルを使うように指定
      • 添付ファイルの表示
  • コントロール
    • attachments ヘルパーのインクルード
    • 添付ファイルの保存

モデル

class Foo < ActiveRecord::Base
  unloadable

  belongs_to :project

  acts_as_attachable :delete_permission => :manage_foos

  # :

  def project
    Project.find(:first, :conditions => "projects.id = #{project_id}")
  end

end

acts_as_attachable メソッドを書くことにより、 foo クラスで添付ファイルが使えるようになります。 acts_as_attachable は Redmine が使用している Rails のプラグインで他のプラグインと同様に vendor/plugins 以下にデフォルトで置かれているものです。
引数はオプションで、ここでは添付ファイルを削除するのにサンプルデータの管理権限が必要なようにしています。

添付ファイルを使用する場合、 プロジェクトのオブジェクトを返すプロジェクトメソッドが必要となります。なぜ、必要なのかは実は私もよく分かりません。分かりませんが作っておかないと正常に動作しないのでとりあえず付けておきましょう。

belongs_to はモデルクラスの関係を記述しています。ここでの記述で foo は project に属していることになります。
project メソッドは自分の project_id メンバを使って、 コントローラの時と同じ ようにプロジェクトオブジェクトを取得しています。

ビュー

フォーム

まず、 プレビューで書いたコードのようにしてフォームはマルチパート(multipart)にしておく必要があります。これは http の決まりのようなものです。

また、新規作成と編集で共通して使うフォーム( _form.html.erb ) に以下の行を追加します。ここも Redmine で使われているものをそのまま部分描画として使用します。

<p><label><%=l(:label_attachment_plural)%></label><%= render :partial => 'attachments/form' %></p>

表示

wiki 解析結果の表示も少し変更する必要があります。

<% unless @foo.description.blank? %>
  <p><strong><%=l(:field_description)%></strong></p>
  <div class="wiki">
    <%= textilizable @foo.description, :attachments => @foo.attachments %>
  </div>
<% end %>

<% if @foo.attachments.any? %>
    <hr />
    <%= link_to_attachments @foo %>
<% end %>

wiki 解析時に添付ファイルも考慮するように textilizable のオプションで添付ファイルを渡しています。
また、 link_to_attachments で添付ファイルの情報とリンクを説明の下に追加しています。

コントロール

添付ファイルを扱うメソッドは Attachments ヘルパーで定義されています。これを使うためにモジュールを include する必要があります。

  helper :attachments

データの保存が終わった後、添付ファイルも保存する必要があります。 @foo.save が成功した後に以下の行を new, edit それぞれのメソッドで追加します。

        Attachment.attach_files(@foo, params[:attachments])
        render_attachment_warning_if_needed(@foo)

1 行目が添付ファイルを保存する処理で、 2 行目がそのエラー処理を行っています。

Updated by Mitsuyoshi Yoshida over 9 years ago · 4 revisions