项目

常规

个人资料

操作

插件教程 » 历史 » 修订版66

上一页 | 修订版66/119 (diff) | 下一页
Etienne Massip, 2012-05-25 11:13


插件教程

注意:要跟随本教程,您需要运行Redmine devel r1786 或更高版本。

创建新的插件

您可能需要设置RAILS_ENV变量,以便使用以下命令

$ export RAILS_ENV="production" 

在Windows上

set RAILS_ENV=production

可以使用Redmine插件生成器创建新的插件。
此生成器的语法是

ruby script/generate redmine_plugin <plugin_name>

因此,打开命令提示符,并"cd"到您的redmine目录,然后执行以下命令

% ruby script/generate redmine_plugin Polls

插件结构在vendor/plugins/redmine_polls中创建

      create  vendor/plugins/redmine_polls/app/controllers
      create  vendor/plugins/redmine_polls/app/helpers
      create  vendor/plugins/redmine_polls/app/models
      create  vendor/plugins/redmine_polls/app/views
      create  vendor/plugins/redmine_polls/db/migrate
      create  vendor/plugins/redmine_polls/lib/tasks
      create  vendor/plugins/redmine_polls/assets/images
      create  vendor/plugins/redmine_polls/assets/javascripts
      create  vendor/plugins/redmine_polls/assets/stylesheets
      create  vendor/plugins/redmine_polls/lang
      create  vendor/plugins/redmine_polls/config/locales
      create  vendor/plugins/redmine_polls/test
      create  vendor/plugins/redmine_polls/README.rdoc
      create  vendor/plugins/redmine_polls/init.rb
      create  vendor/plugins/redmine_polls/config/locales/en.yml
      create  vendor/plugins/redmine_polls/test/test_helper.rb

编辑vendor/plugins/redmine_polls/init.rb以调整插件信息(名称、作者、描述和版本)

require 'redmine'

Redmine::Plugin.register :redmine_polls do
  name 'Polls plugin'
  author 'John Smith'
  description 'A plugin for managing polls'
  version '0.0.1'
end

然后重新启动应用程序,并将您的浏览器指向https://127.0.0.1:3000/admin/plugins
登录后,您应该在插件列表中看到您的新插件

生成模型

目前插件不存储任何内容。让我们为我们的插件创建一个简单的Poll模型。语法是

   ruby script/generate redmine_plugin_model <plugin_name> <model_name> [<fields>]

因此,转到命令提示符并运行

   ruby script/generate redmine_plugin_model polls poll question:string yes:integer no:integer

这创建了一个Poll模型和相应的迁移文件。

请注意,您可能需要重命名您的迁移。实际Redmine插件引擎(Engines)不支持带时间戳的迁移。如果您的迁移名称带有时间戳,请使用"001"、"002"等来重命名它。

mv vendor/plugins/redmine_polls/db/migrate/20091009211553_create_polls.rb vendor/plugins/redmine_polls/db/migrate/001_create_polls.rb

如果您已经在插件_schema_info中创建了带有时间戳版本号的数据库表记录,您必须将其更改为反映您的新版本号,否则迁移会挂起。

使用以下命令迁移数据库

rake db:migrate_plugins

注意,每个插件都有自己的迁移集。

让我们在控制台添加一些投票,这样我们就有东西可以工作了。控制台是您可以交互式工作并检查Redmine环境的地方,非常适合探索。但现在我们只需要创建两个投票对象

script/console
>> Poll.create(:question => "Can you see this poll")
>> Poll.create(:question => "And can you see this other poll")
>> exit

编辑您的插件目录中的 vendor/plugins/redmine_polls/app/models/poll.rb,以添加一个 #vote 方法,该方法将由我们的控制器调用

class Poll < ActiveRecord::Base
  def vote(answer)
    increment(answer == 'yes' ? :yes : :no)
  end
end

生成控制器

警告:从 1.4.0 版本开始,Redmine 将不再提供默认的通配符路由(':controller/:action/:id')。插件必须在它们正确的 config/routes.rb 文件中声明所需的路由。

目前,该插件没有任何功能。所以让我们为我们的插件创建一个控制器。
我们可以使用插件控制器生成器来做到这一点。语法是

ruby script/generate redmine_plugin_controller <plugin_name> <controller_name> [<actions>]

因此,返回到命令提示符并运行

% ruby script/generate redmine_plugin_controller Polls polls index vote
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/polls
      create  test/functional/
      create  app/controllers/polls_controller.rb
      create  test/functional/polls_controller_test.rb
      create  app/helpers/polls_helper.rb
      create  app/views/polls/index.html.erb
      create  app/views/polls/vote.html.erb

创建了一个名为 PollsController 的控制器,包含 2 个操作(#index#vote)。

编辑 redmine_polls 目录中的 vendor/plugins/redmine_polls/app/controllers/polls_controller.rb,以实现这两个操作。

class PollsController < ApplicationController
  unloadable

  def index
    @polls = Poll.find(:all)
  end

  def vote
    poll = Poll.find(params[:id])
    poll.vote(params[:answer])
    if poll.save
      flash[:notice] = 'Vote saved.'
      redirect_to :action => 'index'
    end
  end
end

然后编辑 vendor/plugins/redmine_polls/app/views/polls/index.html.erb,它将显示现有的投票。

<h2>Polls</h2>

<% @polls.each do |poll| %>
  <p>
  <%= poll[:question] %>?
  <%= link_to 'Yes', { :action => 'vote', :id => poll[:id], :answer => 'yes' }, :method => :post %> (<%= poll[:yes] %>) /
  <%= link_to 'No', { :action => 'vote', :id => poll[:id], :answer => 'no' }, :method => :post %> (<%= poll[:no] %>)
  </p>
<% end %>

您可以删除 vendor/plugins/redmine_polls/app/views/polls/vote.html.erb,因为相应的操作没有执行渲染。

现在,重新启动应用程序并将浏览器指向 https://127.0.0.1:3000/polls
您应该看到两个投票,并且您应该能够为它们投票。

请注意,如果您不在生产模式下运行应用程序,则投票结果将在每个请求后重置,因为我们的“模型”在这个例子中存储在类变量中。

翻译

翻译文件 *.yml 的位置取决于正在运行的Redmine版本

版本 路径
< 0.9 .../redmine_polls/lang
>= 0.9 .../redmine_polls/config/locales

如果您希望您的插件在两个版本上都能工作,您需要在这两个位置都有相同的翻译文件。

扩展菜单

我们的控制器运行良好,但用户必须知道URL才能查看投票。使用Redmine插件API,您可以扩展标准菜单。
所以让我们向应用程序菜单添加一个新项目。

扩展应用程序菜单

编辑插件目录根目录中的 vendor/plugins/redmine_polls/init.rb,在插件注册块末尾添加以下行

Redmine::Plugin.register :redmine_polls do
  [...]

  menu :application_menu, :polls, { :controller => 'polls', :action => 'index' }, :caption => 'Polls'
end

语法是

menu(menu_name, item_name, url, options={})

您可以扩展以下五个菜单

  • :top_menu - 顶部左边的菜单
  • :account_menu - 顶部右边的菜单,包含登录/注销链接
  • :application_menu - 用户不在项目内时显示的主要菜单
  • :project_menu - 用户在项目内时显示的主要菜单
  • :admin_menu - 在管理页面上显示的菜单(只能在设置之后、插件之前插入)

可用的选项是

  • :param - 用于项目 id 的参数键(默认为 :id
  • :if - 在渲染项目之前被调用的Proc,只有当它返回true时才显示项目
  • :caption - 菜单标题可以是
    • 一个本地化的字符串Symbol
    • 一个String
    • 一个可以接受项目作为参数的Proc
  • :before:after - 指定菜单项应插入的位置(例如,:after => :activity
  • :first:last - 如果设置为true,项目将保持在菜单的开始/结束位置(例如,:last => true
  • :html - 传递给 link_to 渲染菜单项时的HTML选项的hash

在我们的例子中,我们已向应用程序菜单添加了一个空的项目。
重新启动应用程序并转到 https://127.0.0.1:3000

现在您可以通过点击欢迎屏幕上的“投票”标签来访问投票。

扩展项目菜单

现在,让我们假设投票是在项目级别定义的(即使在我们的示例投票模型中不是这样)。因此,我们希望将“投票”标签添加到项目菜单中。
打开 init.rb 并用这两行替换刚刚添加的行

Redmine::Plugin.register :redmine_polls do
  [...]

  permission :polls, { :polls => [:index, :vote] }, :public => true
  menu :project_menu, :polls, { :controller => 'polls', :action => 'index' }, :caption => 'Polls', :after => :activity, :param => :project_id
end

第二行将我们的“投票”标签添加到项目菜单中,位于活动标签之后。
第一行是必需的,它声明我们的两个来自 PollsController 的操作是公开的。我们稍后会更详细地解释这一点。

再次重启应用程序,并转到您的一个项目

如果您点击“投票”标签,您应该会注意到项目菜单不再显示。
为了使项目菜单可见,您必须初始化控制器实例变量 @project

编辑您的 PollsController 以实现这一点

def index
  @project = Project.find(params[:project_id])
  @polls = Poll.find(:all) # @project.polls
end

由于在上述菜单项声明中的 :param => :project_id 选项,项目 ID 可在 :project_id 参数中找到。

现在,您应该会在查看投票时看到项目菜单。

添加新权限

到目前为止,任何人都可以为投票投票。让我们通过更改权限声明使其更具可配置性。
我们将声明两个基于项目的权限,一个用于查看投票,另一个用于投票。这些权限不再公开(移除了 :public => true 选项)。

编辑 vendor/plugins/redmine_polls/init.rb 并用这两行替换之前的权限声明


  permission :view_polls, :polls => :index
  permission :vote_polls, :polls => :vote

重启应用程序,并转到 https://127.0.0.1:3000/roles/report

现在,您可以将这些权限分配给现有的角色。

当然,需要在 PollsController 中添加一些代码,以便根据当前用户的权限实际保护操作。
为此,我们只需添加 :authorize 过滤器,并确保在调用此过滤器之前正确设置了 Herve Harster 实例变量。

以下是 #index 操作的示例

class PollsController < ApplicationController
  unloadable

  before_filter :find_project, :authorize, :only => :index

  [...]

  def index
    @polls = Poll.find(:all) # @project.polls
  end

  [...]

  private

  def find_project
    # @project variable must be set before calling the authorize filter
    @project = Project.find(params[:project_id])
  end
end

#vote 操作之前使用类似的方式检索当前项目。
在此之后,查看和投票将仅对管理员用户或在项目中具有适当角色的用户可用。

如果您想以多语言方式显示您的权限符号,则需要在一个语言文件中添加必要的文本标签。
只需在您的 Redmine 版本的正确翻译目录中创建一个 *.yml 文件,并填充类似于下面的标签


  permission_view_polls: View Polls
  permission_vote_polls: Vote Polls

在此示例中,创建的文件被称为 en.yml,但所有其他支持的语言文件也是可能的。
如上例所示,标签由权限符号 :view_polls:vote_polls 组成,并在前面添加了 permission_

重启您的应用程序并指向权限部分。

创建项目模块

目前,投票功能已添加到您的所有项目中。但您可能只想在某些项目中启用投票。
因此,让我们创建一个“投票”项目模块。这是通过将权限声明包裹在 #project_module 调用中来完成的。

编辑 init.rb 并更改权限声明

  project_module :polls do
    permission :view_polls, :polls => :index
    permission :vote_polls, :polls => :vote
  end

重启应用程序,并转到您的一个项目设置。
点击“模块”标签。您应该会在模块列表的末尾看到“投票”模块(默认情况下禁用)

您现在可以按项目级别启用/禁用投票。

改进插件视图

添加样式表

让我们首先为我们的插件视图添加一个样式表。
在目录 vendor/plugins/redmine_polls/assets/stylesheets 中创建一个名为 voting.css 的文件

a.vote { font-size: 120%; }
a.vote.yes { color: green; }
a.vote.no  { color: red; }

当启动应用程序时,Rails Engines 会自动将插件资源复制到 public/plugin_assets/redmine_polls/,以便通过您的 Web 服务器提供。因此,对插件样式表或 JavaScript 的任何更改都需要重启应用程序。

然后,在 vendor/plugins/redmine_polls/app/views/polls/index.html.erb 的末尾追加以下行,以便 Redmine 将您的样式表包含在页面标题中

<% content_for :header_tags do %>
    <%= stylesheet_link_tag 'voting', :plugin => 'redmine_polls' %>
<% end %>

请注意,在调用 stylesheet_link_tag 辅助函数时需要 :plugin => 'redmine_polls' 选项。

可以使用与 javascript_include_tag 辅助函数相同的方式在插件视图中包含 JavaScript。

设置页面标题

您可以使用 html_title 辅助函数在视图中设置 HTML 标题。
示例

<% html_title "Polls" %>

测试您的插件

test/test_helper.rb:

以下是我的测试辅助文件的正文

require File.expand_path(File.dirname(__FILE__) + '/../../../../test/test_helper')

示例测试:

requirements_controller_test.rb 的内容

require File.dirname(__FILE__) + '/../test_helper'
require 'requirements_controller'

class RequirementsControllerTest < ActionController::TestCase
  fixtures :projects, :versions, :users, :roles, :members, :member_roles, :issues, :journals, :journal_details,
           :trackers, :projects_trackers, :issue_statuses, :enabled_modules, :enumerations, :boards, :messages,
           :attachments, :custom_fields, :custom_values, :time_entries

  def setup
    @skill = Skill.new(:skill_name => 'Java')
    @project = Project.find(1)
    @request    = ActionController::TestRequest.new
    @response   = ActionController::TestResponse.new
    User.current = nil
  end

  def test_routing
    assert_routing(
      {:method => :get, :path => '/requirements'},
      :controller => 'requirements', :action => 'index'
    )
  end
end

初始化测试数据库:

我发现通过以下 rake 调用直接初始化测试数据库是最容易的

rake db:drop db:create db:migrate db:migrate_plugins redmine:load_default_data RAILS_ENV=test

运行测试:

要执行 requirements_controller_test.rb,我使用了以下命令

rake test:engines:all PLUGIN=redmine_requirements

使用权限进行测试

如果您的插件需要项目成员资格,请在功能测试的开始处添加以下内容

def test_index
  @request.session[:user_id] = 2
  ...
end

如果您的插件需要特定的权限,可以将该权限添加到用户角色中(在 fixtures 中查找适用于用户的角色)

def test_index
  Role.find(1).add_permission! :my_permission
  ...
end

您可以通过以下方式启用/禁用特定模块

def test_index
  Project.find(1).enabled_module_names = [:mymodule]
  ...
end

艾蒂安·马西普更新 大约12年前 · 66次修订